linux/drivers/platform/x86/intel_pmc_ipc.c
<<
>>
Prefs
   1/*
   2 * intel_pmc_ipc.c: Driver for the Intel PMC IPC mechanism
   3 *
   4 * (C) Copyright 2014-2015 Intel Corporation
   5 *
   6 * This driver is based on Intel SCU IPC driver(intel_scu_opc.c) by
   7 *     Sreedhara DS <sreedhara.ds@intel.com>
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License
  11 * as published by the Free Software Foundation; version 2
  12 * of the License.
  13 *
  14 * PMC running in ARC processor communicates with other entity running in IA
  15 * core through IPC mechanism which in turn messaging between IA core ad PMC.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/delay.h>
  20#include <linux/errno.h>
  21#include <linux/init.h>
  22#include <linux/device.h>
  23#include <linux/pm.h>
  24#include <linux/pci.h>
  25#include <linux/platform_device.h>
  26#include <linux/interrupt.h>
  27#include <linux/pm_qos.h>
  28#include <linux/kernel.h>
  29#include <linux/bitops.h>
  30#include <linux/sched.h>
  31#include <linux/atomic.h>
  32#include <linux/notifier.h>
  33#include <linux/suspend.h>
  34#include <linux/acpi.h>
  35#include <asm/intel_pmc_ipc.h>
  36#include <linux/platform_data/itco_wdt.h>
  37
  38/*
  39 * IPC registers
  40 * The IA write to IPC_CMD command register triggers an interrupt to the ARC,
  41 * The ARC handles the interrupt and services it, writing optional data to
  42 * the IPC1 registers, updates the IPC_STS response register with the status.
  43 */
  44#define IPC_CMD                 0x0
  45#define         IPC_CMD_MSI             0x100
  46#define         IPC_CMD_SIZE            16
  47#define         IPC_CMD_SUBCMD          12
  48#define IPC_STATUS              0x04
  49#define         IPC_STATUS_IRQ          0x4
  50#define         IPC_STATUS_ERR          0x2
  51#define         IPC_STATUS_BUSY         0x1
  52#define IPC_SPTR                0x08
  53#define IPC_DPTR                0x0C
  54#define IPC_WRITE_BUFFER        0x80
  55#define IPC_READ_BUFFER         0x90
  56
  57/*
  58 * 16-byte buffer for sending data associated with IPC command.
  59 */
  60#define IPC_DATA_BUFFER_SIZE    16
  61
  62#define IPC_LOOP_CNT            3000000
  63#define IPC_MAX_SEC             3
  64
  65#define IPC_TRIGGER_MODE_IRQ            true
  66
  67/* exported resources from IFWI */
  68#define PLAT_RESOURCE_IPC_INDEX         0
  69#define PLAT_RESOURCE_IPC_SIZE          0x1000
  70#define PLAT_RESOURCE_GCR_OFFSET        0x1008
  71#define PLAT_RESOURCE_GCR_SIZE          0x4
  72#define PLAT_RESOURCE_BIOS_DATA_INDEX   1
  73#define PLAT_RESOURCE_BIOS_IFACE_INDEX  2
  74#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3
  75#define PLAT_RESOURCE_ISP_DATA_INDEX    4
  76#define PLAT_RESOURCE_ISP_IFACE_INDEX   5
  77#define PLAT_RESOURCE_GTD_DATA_INDEX    6
  78#define PLAT_RESOURCE_GTD_IFACE_INDEX   7
  79#define PLAT_RESOURCE_ACPI_IO_INDEX     0
  80
  81/*
  82 * BIOS does not create an ACPI device for each PMC function,
  83 * but exports multiple resources from one ACPI device(IPC) for
  84 * multiple functions. This driver is responsible to create a
  85 * platform device and to export resources for those functions.
  86 */
  87#define TCO_DEVICE_NAME                 "iTCO_wdt"
  88#define SMI_EN_OFFSET                   0x30
  89#define SMI_EN_SIZE                     4
  90#define TCO_BASE_OFFSET                 0x60
  91#define TCO_REGS_SIZE                   16
  92#define PUNIT_DEVICE_NAME               "intel_punit_ipc"
  93#define TELEMETRY_DEVICE_NAME           "intel_telemetry"
  94#define TELEM_SSRAM_SIZE                240
  95#define TELEM_PMC_SSRAM_OFFSET          0x1B00
  96#define TELEM_PUNIT_SSRAM_OFFSET        0x1A00
  97
  98static const int iTCO_version = 3;
  99
 100static struct intel_pmc_ipc_dev {
 101        struct device *dev;
 102        void __iomem *ipc_base;
 103        bool irq_mode;
 104        int irq;
 105        int cmd;
 106        struct completion cmd_complete;
 107
 108        /* The following PMC BARs share the same ACPI device with the IPC */
 109        resource_size_t acpi_io_base;
 110        int acpi_io_size;
 111        struct platform_device *tco_dev;
 112
 113        /* gcr */
 114        resource_size_t gcr_base;
 115        int gcr_size;
 116
 117        /* punit */
 118        struct platform_device *punit_dev;
 119
 120        /* Telemetry */
 121        resource_size_t telem_pmc_ssram_base;
 122        resource_size_t telem_punit_ssram_base;
 123        int telem_pmc_ssram_size;
 124        int telem_punit_ssram_size;
 125        u8 telem_res_inval;
 126        struct platform_device *telemetry_dev;
 127} ipcdev;
 128
 129static char *ipc_err_sources[] = {
 130        [IPC_ERR_NONE] =
 131                "no error",
 132        [IPC_ERR_CMD_NOT_SUPPORTED] =
 133                "command not supported",
 134        [IPC_ERR_CMD_NOT_SERVICED] =
 135                "command not serviced",
 136        [IPC_ERR_UNABLE_TO_SERVICE] =
 137                "unable to service",
 138        [IPC_ERR_CMD_INVALID] =
 139                "command invalid",
 140        [IPC_ERR_CMD_FAILED] =
 141                "command failed",
 142        [IPC_ERR_EMSECURITY] =
 143                "Invalid Battery",
 144        [IPC_ERR_UNSIGNEDKERNEL] =
 145                "Unsigned kernel",
 146};
 147
 148/* Prevent concurrent calls to the PMC */
 149static DEFINE_MUTEX(ipclock);
 150
 151static inline void ipc_send_command(u32 cmd)
 152{
 153        ipcdev.cmd = cmd;
 154        if (ipcdev.irq_mode) {
 155                reinit_completion(&ipcdev.cmd_complete);
 156                cmd |= IPC_CMD_MSI;
 157        }
 158        writel(cmd, ipcdev.ipc_base + IPC_CMD);
 159}
 160
 161static inline u32 ipc_read_status(void)
 162{
 163        return readl(ipcdev.ipc_base + IPC_STATUS);
 164}
 165
 166static inline void ipc_data_writel(u32 data, u32 offset)
 167{
 168        writel(data, ipcdev.ipc_base + IPC_WRITE_BUFFER + offset);
 169}
 170
 171static inline u8 ipc_data_readb(u32 offset)
 172{
 173        return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
 174}
 175
 176static inline u32 ipc_data_readl(u32 offset)
 177{
 178        return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
 179}
 180
 181static int intel_pmc_ipc_check_status(void)
 182{
 183        int status;
 184        int ret = 0;
 185
 186        if (ipcdev.irq_mode) {
 187                if (0 == wait_for_completion_timeout(
 188                                &ipcdev.cmd_complete, IPC_MAX_SEC * HZ))
 189                        ret = -ETIMEDOUT;
 190        } else {
 191                int loop_count = IPC_LOOP_CNT;
 192
 193                while ((ipc_read_status() & IPC_STATUS_BUSY) && --loop_count)
 194                        udelay(1);
 195                if (loop_count == 0)
 196                        ret = -ETIMEDOUT;
 197        }
 198
 199        status = ipc_read_status();
 200        if (ret == -ETIMEDOUT) {
 201                dev_err(ipcdev.dev,
 202                        "IPC timed out, TS=0x%x, CMD=0x%x\n",
 203                        status, ipcdev.cmd);
 204                return ret;
 205        }
 206
 207        if (status & IPC_STATUS_ERR) {
 208                int i;
 209
 210                ret = -EIO;
 211                i = (status >> IPC_CMD_SIZE) & 0xFF;
 212                if (i < ARRAY_SIZE(ipc_err_sources))
 213                        dev_err(ipcdev.dev,
 214                                "IPC failed: %s, STS=0x%x, CMD=0x%x\n",
 215                                ipc_err_sources[i], status, ipcdev.cmd);
 216                else
 217                        dev_err(ipcdev.dev,
 218                                "IPC failed: unknown, STS=0x%x, CMD=0x%x\n",
 219                                status, ipcdev.cmd);
 220                if ((i == IPC_ERR_UNSIGNEDKERNEL) || (i == IPC_ERR_EMSECURITY))
 221                        ret = -EACCES;
 222        }
 223
 224        return ret;
 225}
 226
 227/**
 228 * intel_pmc_ipc_simple_command() - Simple IPC command
 229 * @cmd:        IPC command code.
 230 * @sub:        IPC command sub type.
 231 *
 232 * Send a simple IPC command to PMC when don't need to specify
 233 * input/output data and source/dest pointers.
 234 *
 235 * Return:      an IPC error code or 0 on success.
 236 */
 237int intel_pmc_ipc_simple_command(int cmd, int sub)
 238{
 239        int ret;
 240
 241        mutex_lock(&ipclock);
 242        if (ipcdev.dev == NULL) {
 243                mutex_unlock(&ipclock);
 244                return -ENODEV;
 245        }
 246        ipc_send_command(sub << IPC_CMD_SUBCMD | cmd);
 247        ret = intel_pmc_ipc_check_status();
 248        mutex_unlock(&ipclock);
 249
 250        return ret;
 251}
 252EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command);
 253
 254/**
 255 * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers
 256 * @cmd:        IPC command code.
 257 * @sub:        IPC command sub type.
 258 * @in:         input data of this IPC command.
 259 * @inlen:      input data length in bytes.
 260 * @out:        output data of this IPC command.
 261 * @outlen:     output data length in dwords.
 262 * @sptr:       data writing to SPTR register.
 263 * @dptr:       data writing to DPTR register.
 264 *
 265 * Send an IPC command to PMC with input/output data and source/dest pointers.
 266 *
 267 * Return:      an IPC error code or 0 on success.
 268 */
 269int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
 270                          u32 outlen, u32 dptr, u32 sptr)
 271{
 272        u32 wbuf[4] = { 0 };
 273        int ret;
 274        int i;
 275
 276        if (inlen > IPC_DATA_BUFFER_SIZE || outlen > IPC_DATA_BUFFER_SIZE / 4)
 277                return -EINVAL;
 278
 279        mutex_lock(&ipclock);
 280        if (ipcdev.dev == NULL) {
 281                mutex_unlock(&ipclock);
 282                return -ENODEV;
 283        }
 284        memcpy(wbuf, in, inlen);
 285        writel(dptr, ipcdev.ipc_base + IPC_DPTR);
 286        writel(sptr, ipcdev.ipc_base + IPC_SPTR);
 287        /* The input data register is 32bit register and inlen is in Byte */
 288        for (i = 0; i < ((inlen + 3) / 4); i++)
 289                ipc_data_writel(wbuf[i], 4 * i);
 290        ipc_send_command((inlen << IPC_CMD_SIZE) |
 291                        (sub << IPC_CMD_SUBCMD) | cmd);
 292        ret = intel_pmc_ipc_check_status();
 293        if (!ret) {
 294                /* out is read from 32bit register and outlen is in 32bit */
 295                for (i = 0; i < outlen; i++)
 296                        *out++ = ipc_data_readl(4 * i);
 297        }
 298        mutex_unlock(&ipclock);
 299
 300        return ret;
 301}
 302EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd);
 303
 304/**
 305 * intel_pmc_ipc_command() -  IPC command with input/output data
 306 * @cmd:        IPC command code.
 307 * @sub:        IPC command sub type.
 308 * @in:         input data of this IPC command.
 309 * @inlen:      input data length in bytes.
 310 * @out:        output data of this IPC command.
 311 * @outlen:     output data length in dwords.
 312 *
 313 * Send an IPC command to PMC with input/output data.
 314 *
 315 * Return:      an IPC error code or 0 on success.
 316 */
 317int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
 318                          u32 *out, u32 outlen)
 319{
 320        return intel_pmc_ipc_raw_cmd(cmd, sub, in, inlen, out, outlen, 0, 0);
 321}
 322EXPORT_SYMBOL_GPL(intel_pmc_ipc_command);
 323
 324static irqreturn_t ioc(int irq, void *dev_id)
 325{
 326        int status;
 327
 328        if (ipcdev.irq_mode) {
 329                status = ipc_read_status();
 330                writel(status | IPC_STATUS_IRQ, ipcdev.ipc_base + IPC_STATUS);
 331        }
 332        complete(&ipcdev.cmd_complete);
 333
 334        return IRQ_HANDLED;
 335}
 336
 337static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 338{
 339        resource_size_t pci_resource;
 340        int ret;
 341        int len;
 342
 343        ipcdev.dev = &pci_dev_get(pdev)->dev;
 344        ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
 345
 346        ret = pci_enable_device(pdev);
 347        if (ret)
 348                return ret;
 349
 350        ret = pci_request_regions(pdev, "intel_pmc_ipc");
 351        if (ret)
 352                return ret;
 353
 354        pci_resource = pci_resource_start(pdev, 0);
 355        len = pci_resource_len(pdev, 0);
 356        if (!pci_resource || !len) {
 357                dev_err(&pdev->dev, "Failed to get resource\n");
 358                return -ENOMEM;
 359        }
 360
 361        init_completion(&ipcdev.cmd_complete);
 362
 363        if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) {
 364                dev_err(&pdev->dev, "Failed to request irq\n");
 365                return -EBUSY;
 366        }
 367
 368        ipcdev.ipc_base = ioremap_nocache(pci_resource, len);
 369        if (!ipcdev.ipc_base) {
 370                dev_err(&pdev->dev, "Failed to ioremap ipc base\n");
 371                free_irq(pdev->irq, &ipcdev);
 372                ret = -ENOMEM;
 373        }
 374
 375        return ret;
 376}
 377
 378static void ipc_pci_remove(struct pci_dev *pdev)
 379{
 380        free_irq(pdev->irq, &ipcdev);
 381        pci_release_regions(pdev);
 382        pci_dev_put(pdev);
 383        iounmap(ipcdev.ipc_base);
 384        ipcdev.dev = NULL;
 385}
 386
 387static const struct pci_device_id ipc_pci_ids[] = {
 388        {PCI_VDEVICE(INTEL, 0x0a94), 0},
 389        {PCI_VDEVICE(INTEL, 0x1a94), 0},
 390        { 0,}
 391};
 392MODULE_DEVICE_TABLE(pci, ipc_pci_ids);
 393
 394static struct pci_driver ipc_pci_driver = {
 395        .name = "intel_pmc_ipc",
 396        .id_table = ipc_pci_ids,
 397        .probe = ipc_pci_probe,
 398        .remove = ipc_pci_remove,
 399};
 400
 401static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev,
 402                                              struct device_attribute *attr,
 403                                              const char *buf, size_t count)
 404{
 405        int subcmd;
 406        int cmd;
 407        int ret;
 408
 409        ret = sscanf(buf, "%d %d", &cmd, &subcmd);
 410        if (ret != 2) {
 411                dev_err(dev, "Error args\n");
 412                return -EINVAL;
 413        }
 414
 415        ret = intel_pmc_ipc_simple_command(cmd, subcmd);
 416        if (ret) {
 417                dev_err(dev, "command %d error with %d\n", cmd, ret);
 418                return ret;
 419        }
 420        return (ssize_t)count;
 421}
 422
 423static ssize_t intel_pmc_ipc_northpeak_store(struct device *dev,
 424                                             struct device_attribute *attr,
 425                                             const char *buf, size_t count)
 426{
 427        unsigned long val;
 428        int subcmd;
 429        int ret;
 430
 431        if (kstrtoul(buf, 0, &val))
 432                return -EINVAL;
 433
 434        if (val)
 435                subcmd = 1;
 436        else
 437                subcmd = 0;
 438        ret = intel_pmc_ipc_simple_command(PMC_IPC_NORTHPEAK_CTRL, subcmd);
 439        if (ret) {
 440                dev_err(dev, "command north %d error with %d\n", subcmd, ret);
 441                return ret;
 442        }
 443        return (ssize_t)count;
 444}
 445
 446static DEVICE_ATTR(simplecmd, S_IWUSR,
 447                   NULL, intel_pmc_ipc_simple_cmd_store);
 448static DEVICE_ATTR(northpeak, S_IWUSR,
 449                   NULL, intel_pmc_ipc_northpeak_store);
 450
 451static struct attribute *intel_ipc_attrs[] = {
 452        &dev_attr_northpeak.attr,
 453        &dev_attr_simplecmd.attr,
 454        NULL
 455};
 456
 457static const struct attribute_group intel_ipc_group = {
 458        .attrs = intel_ipc_attrs,
 459};
 460
 461static struct resource punit_res_array[] = {
 462        /* Punit BIOS */
 463        {
 464                .flags = IORESOURCE_MEM,
 465        },
 466        {
 467                .flags = IORESOURCE_MEM,
 468        },
 469        /* Punit ISP */
 470        {
 471                .flags = IORESOURCE_MEM,
 472        },
 473        {
 474                .flags = IORESOURCE_MEM,
 475        },
 476        /* Punit GTD */
 477        {
 478                .flags = IORESOURCE_MEM,
 479        },
 480        {
 481                .flags = IORESOURCE_MEM,
 482        },
 483};
 484
 485#define TCO_RESOURCE_ACPI_IO            0
 486#define TCO_RESOURCE_SMI_EN_IO          1
 487#define TCO_RESOURCE_GCR_MEM            2
 488static struct resource tco_res[] = {
 489        /* ACPI - TCO */
 490        {
 491                .flags = IORESOURCE_IO,
 492        },
 493        /* ACPI - SMI */
 494        {
 495                .flags = IORESOURCE_IO,
 496        },
 497        /* GCS */
 498        {
 499                .flags = IORESOURCE_MEM,
 500        },
 501};
 502
 503static struct itco_wdt_platform_data tco_info = {
 504        .name = "Apollo Lake SoC",
 505        .version = 3,
 506};
 507
 508#define TELEMETRY_RESOURCE_PUNIT_SSRAM  0
 509#define TELEMETRY_RESOURCE_PMC_SSRAM    1
 510static struct resource telemetry_res[] = {
 511        /*Telemetry*/
 512        {
 513                .flags = IORESOURCE_MEM,
 514        },
 515        {
 516                .flags = IORESOURCE_MEM,
 517        },
 518};
 519
 520static int ipc_create_punit_device(void)
 521{
 522        struct platform_device *pdev;
 523        int ret;
 524
 525        pdev = platform_device_alloc(PUNIT_DEVICE_NAME, -1);
 526        if (!pdev) {
 527                dev_err(ipcdev.dev, "Failed to alloc punit platform device\n");
 528                return -ENOMEM;
 529        }
 530
 531        pdev->dev.parent = ipcdev.dev;
 532        ret = platform_device_add_resources(pdev, punit_res_array,
 533                                            ARRAY_SIZE(punit_res_array));
 534        if (ret) {
 535                dev_err(ipcdev.dev, "Failed to add platform punit resources\n");
 536                goto err;
 537        }
 538
 539        ret = platform_device_add(pdev);
 540        if (ret) {
 541                dev_err(ipcdev.dev, "Failed to add punit platform device\n");
 542                goto err;
 543        }
 544        ipcdev.punit_dev = pdev;
 545
 546        return 0;
 547err:
 548        platform_device_put(pdev);
 549        return ret;
 550}
 551
 552static int ipc_create_tco_device(void)
 553{
 554        struct platform_device *pdev;
 555        struct resource *res;
 556        int ret;
 557
 558        pdev = platform_device_alloc(TCO_DEVICE_NAME, -1);
 559        if (!pdev) {
 560                dev_err(ipcdev.dev, "Failed to alloc tco platform device\n");
 561                return -ENOMEM;
 562        }
 563
 564        pdev->dev.parent = ipcdev.dev;
 565
 566        res = tco_res + TCO_RESOURCE_ACPI_IO;
 567        res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET;
 568        res->end = res->start + TCO_REGS_SIZE - 1;
 569
 570        res = tco_res + TCO_RESOURCE_SMI_EN_IO;
 571        res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET;
 572        res->end = res->start + SMI_EN_SIZE - 1;
 573
 574        res = tco_res + TCO_RESOURCE_GCR_MEM;
 575        res->start = ipcdev.gcr_base;
 576        res->end = res->start + ipcdev.gcr_size - 1;
 577
 578        ret = platform_device_add_resources(pdev, tco_res, ARRAY_SIZE(tco_res));
 579        if (ret) {
 580                dev_err(ipcdev.dev, "Failed to add tco platform resources\n");
 581                goto err;
 582        }
 583
 584        ret = platform_device_add_data(pdev, &tco_info, sizeof(tco_info));
 585        if (ret) {
 586                dev_err(ipcdev.dev, "Failed to add tco platform data\n");
 587                goto err;
 588        }
 589
 590        ret = platform_device_add(pdev);
 591        if (ret) {
 592                dev_err(ipcdev.dev, "Failed to add tco platform device\n");
 593                goto err;
 594        }
 595        ipcdev.tco_dev = pdev;
 596
 597        return 0;
 598err:
 599        platform_device_put(pdev);
 600        return ret;
 601}
 602
 603static int ipc_create_telemetry_device(void)
 604{
 605        struct platform_device *pdev;
 606        struct resource *res;
 607        int ret;
 608
 609        pdev = platform_device_alloc(TELEMETRY_DEVICE_NAME, -1);
 610        if (!pdev) {
 611                dev_err(ipcdev.dev,
 612                        "Failed to allocate telemetry platform device\n");
 613                return -ENOMEM;
 614        }
 615
 616        pdev->dev.parent = ipcdev.dev;
 617
 618        res = telemetry_res + TELEMETRY_RESOURCE_PUNIT_SSRAM;
 619        res->start = ipcdev.telem_punit_ssram_base;
 620        res->end = res->start + ipcdev.telem_punit_ssram_size - 1;
 621
 622        res = telemetry_res + TELEMETRY_RESOURCE_PMC_SSRAM;
 623        res->start = ipcdev.telem_pmc_ssram_base;
 624        res->end = res->start + ipcdev.telem_pmc_ssram_size - 1;
 625
 626        ret = platform_device_add_resources(pdev, telemetry_res,
 627                                            ARRAY_SIZE(telemetry_res));
 628        if (ret) {
 629                dev_err(ipcdev.dev,
 630                        "Failed to add telemetry platform resources\n");
 631                goto err;
 632        }
 633
 634        ret = platform_device_add(pdev);
 635        if (ret) {
 636                dev_err(ipcdev.dev,
 637                        "Failed to add telemetry platform device\n");
 638                goto err;
 639        }
 640        ipcdev.telemetry_dev = pdev;
 641
 642        return 0;
 643err:
 644        platform_device_put(pdev);
 645        return ret;
 646}
 647
 648static int ipc_create_pmc_devices(void)
 649{
 650        int ret;
 651
 652        ret = ipc_create_tco_device();
 653        if (ret) {
 654                dev_err(ipcdev.dev, "Failed to add tco platform device\n");
 655                return ret;
 656        }
 657        ret = ipc_create_punit_device();
 658        if (ret) {
 659                dev_err(ipcdev.dev, "Failed to add punit platform device\n");
 660                platform_device_unregister(ipcdev.tco_dev);
 661        }
 662
 663        if (!ipcdev.telem_res_inval) {
 664                ret = ipc_create_telemetry_device();
 665                if (ret)
 666                        dev_warn(ipcdev.dev,
 667                                "Failed to add telemetry platform device\n");
 668        }
 669
 670        return ret;
 671}
 672
 673static int ipc_plat_get_res(struct platform_device *pdev)
 674{
 675        struct resource *res, *punit_res;
 676        void __iomem *addr;
 677        int size;
 678
 679        res = platform_get_resource(pdev, IORESOURCE_IO,
 680                                    PLAT_RESOURCE_ACPI_IO_INDEX);
 681        if (!res) {
 682                dev_err(&pdev->dev, "Failed to get io resource\n");
 683                return -ENXIO;
 684        }
 685        size = resource_size(res);
 686        ipcdev.acpi_io_base = res->start;
 687        ipcdev.acpi_io_size = size;
 688        dev_info(&pdev->dev, "io res: %pR\n", res);
 689
 690        punit_res = punit_res_array;
 691        /* This is index 0 to cover BIOS data register */
 692        res = platform_get_resource(pdev, IORESOURCE_MEM,
 693                                    PLAT_RESOURCE_BIOS_DATA_INDEX);
 694        if (!res) {
 695                dev_err(&pdev->dev, "Failed to get res of punit BIOS data\n");
 696                return -ENXIO;
 697        }
 698        *punit_res = *res;
 699        dev_info(&pdev->dev, "punit BIOS data res: %pR\n", res);
 700
 701        /* This is index 1 to cover BIOS interface register */
 702        res = platform_get_resource(pdev, IORESOURCE_MEM,
 703                                    PLAT_RESOURCE_BIOS_IFACE_INDEX);
 704        if (!res) {
 705                dev_err(&pdev->dev, "Failed to get res of punit BIOS iface\n");
 706                return -ENXIO;
 707        }
 708        *++punit_res = *res;
 709        dev_info(&pdev->dev, "punit BIOS interface res: %pR\n", res);
 710
 711        /* This is index 2 to cover ISP data register, optional */
 712        res = platform_get_resource(pdev, IORESOURCE_MEM,
 713                                    PLAT_RESOURCE_ISP_DATA_INDEX);
 714        ++punit_res;
 715        if (res) {
 716                *punit_res = *res;
 717                dev_info(&pdev->dev, "punit ISP data res: %pR\n", res);
 718        }
 719
 720        /* This is index 3 to cover ISP interface register, optional */
 721        res = platform_get_resource(pdev, IORESOURCE_MEM,
 722                                    PLAT_RESOURCE_ISP_IFACE_INDEX);
 723        ++punit_res;
 724        if (res) {
 725                *punit_res = *res;
 726                dev_info(&pdev->dev, "punit ISP interface res: %pR\n", res);
 727        }
 728
 729        /* This is index 4 to cover GTD data register, optional */
 730        res = platform_get_resource(pdev, IORESOURCE_MEM,
 731                                    PLAT_RESOURCE_GTD_DATA_INDEX);
 732        ++punit_res;
 733        if (res) {
 734                *punit_res = *res;
 735                dev_info(&pdev->dev, "punit GTD data res: %pR\n", res);
 736        }
 737
 738        /* This is index 5 to cover GTD interface register, optional */
 739        res = platform_get_resource(pdev, IORESOURCE_MEM,
 740                                    PLAT_RESOURCE_GTD_IFACE_INDEX);
 741        ++punit_res;
 742        if (res) {
 743                *punit_res = *res;
 744                dev_info(&pdev->dev, "punit GTD interface res: %pR\n", res);
 745        }
 746
 747        res = platform_get_resource(pdev, IORESOURCE_MEM,
 748                                    PLAT_RESOURCE_IPC_INDEX);
 749        if (!res) {
 750                dev_err(&pdev->dev, "Failed to get ipc resource\n");
 751                return -ENXIO;
 752        }
 753        size = PLAT_RESOURCE_IPC_SIZE;
 754        if (!request_mem_region(res->start, size, pdev->name)) {
 755                dev_err(&pdev->dev, "Failed to request ipc resource\n");
 756                return -EBUSY;
 757        }
 758        addr = ioremap_nocache(res->start, size);
 759        if (!addr) {
 760                dev_err(&pdev->dev, "I/O memory remapping failed\n");
 761                release_mem_region(res->start, size);
 762                return -ENOMEM;
 763        }
 764        ipcdev.ipc_base = addr;
 765
 766        ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET;
 767        ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
 768        dev_info(&pdev->dev, "ipc res: %pR\n", res);
 769
 770        ipcdev.telem_res_inval = 0;
 771        res = platform_get_resource(pdev, IORESOURCE_MEM,
 772                                    PLAT_RESOURCE_TELEM_SSRAM_INDEX);
 773        if (!res) {
 774                dev_err(&pdev->dev, "Failed to get telemetry ssram resource\n");
 775                ipcdev.telem_res_inval = 1;
 776        } else {
 777                ipcdev.telem_punit_ssram_base = res->start +
 778                                                TELEM_PUNIT_SSRAM_OFFSET;
 779                ipcdev.telem_punit_ssram_size = TELEM_SSRAM_SIZE;
 780                ipcdev.telem_pmc_ssram_base = res->start +
 781                                                TELEM_PMC_SSRAM_OFFSET;
 782                ipcdev.telem_pmc_ssram_size = TELEM_SSRAM_SIZE;
 783                dev_info(&pdev->dev, "telemetry ssram res: %pR\n", res);
 784        }
 785
 786        return 0;
 787}
 788
 789#ifdef CONFIG_ACPI
 790static const struct acpi_device_id ipc_acpi_ids[] = {
 791        { "INT34D2", 0},
 792        { }
 793};
 794MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids);
 795#endif
 796
 797static int ipc_plat_probe(struct platform_device *pdev)
 798{
 799        struct resource *res;
 800        int ret;
 801
 802        ipcdev.dev = &pdev->dev;
 803        ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
 804        init_completion(&ipcdev.cmd_complete);
 805
 806        ipcdev.irq = platform_get_irq(pdev, 0);
 807        if (ipcdev.irq < 0) {
 808                dev_err(&pdev->dev, "Failed to get irq\n");
 809                return -EINVAL;
 810        }
 811
 812        ret = ipc_plat_get_res(pdev);
 813        if (ret) {
 814                dev_err(&pdev->dev, "Failed to request resource\n");
 815                return ret;
 816        }
 817
 818        ret = ipc_create_pmc_devices();
 819        if (ret) {
 820                dev_err(&pdev->dev, "Failed to create pmc devices\n");
 821                goto err_device;
 822        }
 823
 824        if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND,
 825                        "intel_pmc_ipc", &ipcdev)) {
 826                dev_err(&pdev->dev, "Failed to request irq\n");
 827                ret = -EBUSY;
 828                goto err_irq;
 829        }
 830
 831        ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group);
 832        if (ret) {
 833                dev_err(&pdev->dev, "Failed to create sysfs group %d\n",
 834                        ret);
 835                goto err_sys;
 836        }
 837
 838        return 0;
 839err_sys:
 840        free_irq(ipcdev.irq, &ipcdev);
 841err_irq:
 842        platform_device_unregister(ipcdev.tco_dev);
 843        platform_device_unregister(ipcdev.punit_dev);
 844        platform_device_unregister(ipcdev.telemetry_dev);
 845err_device:
 846        iounmap(ipcdev.ipc_base);
 847        res = platform_get_resource(pdev, IORESOURCE_MEM,
 848                                    PLAT_RESOURCE_IPC_INDEX);
 849        if (res)
 850                release_mem_region(res->start, PLAT_RESOURCE_IPC_SIZE);
 851        return ret;
 852}
 853
 854static int ipc_plat_remove(struct platform_device *pdev)
 855{
 856        struct resource *res;
 857
 858        sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group);
 859        free_irq(ipcdev.irq, &ipcdev);
 860        platform_device_unregister(ipcdev.tco_dev);
 861        platform_device_unregister(ipcdev.punit_dev);
 862        platform_device_unregister(ipcdev.telemetry_dev);
 863        iounmap(ipcdev.ipc_base);
 864        res = platform_get_resource(pdev, IORESOURCE_MEM,
 865                                    PLAT_RESOURCE_IPC_INDEX);
 866        if (res)
 867                release_mem_region(res->start, PLAT_RESOURCE_IPC_SIZE);
 868        ipcdev.dev = NULL;
 869        return 0;
 870}
 871
 872static struct platform_driver ipc_plat_driver = {
 873        .remove = ipc_plat_remove,
 874        .probe = ipc_plat_probe,
 875        .driver = {
 876                .name = "pmc-ipc-plat",
 877                .acpi_match_table = ACPI_PTR(ipc_acpi_ids),
 878        },
 879};
 880
 881static int __init intel_pmc_ipc_init(void)
 882{
 883        int ret;
 884
 885        ret = platform_driver_register(&ipc_plat_driver);
 886        if (ret) {
 887                pr_err("Failed to register PMC ipc platform driver\n");
 888                return ret;
 889        }
 890        ret = pci_register_driver(&ipc_pci_driver);
 891        if (ret) {
 892                pr_err("Failed to register PMC ipc pci driver\n");
 893                platform_driver_unregister(&ipc_plat_driver);
 894                return ret;
 895        }
 896        return ret;
 897}
 898
 899static void __exit intel_pmc_ipc_exit(void)
 900{
 901        pci_unregister_driver(&ipc_pci_driver);
 902        platform_driver_unregister(&ipc_plat_driver);
 903}
 904
 905MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");
 906MODULE_DESCRIPTION("Intel PMC IPC driver");
 907MODULE_LICENSE("GPL");
 908
 909/* Some modules are dependent on this, so init earlier */
 910fs_initcall(intel_pmc_ipc_init);
 911module_exit(intel_pmc_ipc_exit);
 912