From: Kuppuswamy Sathyanarayanan <[email protected]>

Removed redundant IPC helper functions and refactored the driver to use
generic IPC device driver APIs.

This patch also cleans-up PMC IPC user drivers to use APIs provided
by generic IPC driver.

Signed-off-by: Kuppuswamy Sathyanarayanan 
<[email protected]>
---
 arch/x86/include/asm/intel_pmc_ipc.h          |  37 +--
 drivers/mfd/intel_soc_pmic_bxtwc.c            |  24 +-
 drivers/platform/x86/intel_pmc_ipc.c          | 364 +++++++++-----------------
 drivers/platform/x86/intel_telemetry_pltdrv.c | 114 ++++----
 include/linux/mfd/intel_soc_pmic.h            |   2 +
 5 files changed, 215 insertions(+), 326 deletions(-)

Changes since v1:
 * Removed custom APIs.
 * Cleaned up PMC IPC user drivers to use APIs provided by generic
   IPC driver.

diff --git a/arch/x86/include/asm/intel_pmc_ipc.h 
b/arch/x86/include/asm/intel_pmc_ipc.h
index fac89eb..9fc7c3c 100644
--- a/arch/x86/include/asm/intel_pmc_ipc.h
+++ b/arch/x86/include/asm/intel_pmc_ipc.h
@@ -1,10 +1,15 @@
 #ifndef _ASM_X86_INTEL_PMC_IPC_H_
 #define  _ASM_X86_INTEL_PMC_IPC_H_
 
+#include <linux/platform_data/x86/intel_ipc_dev.h>
+
+#define INTEL_PMC_IPC_DEV              "intel_pmc_ipc"
+#define PMC_PARAM_LEN                  2
+
 /* Commands */
 #define PMC_IPC_PMIC_ACCESS            0xFF
-#define                PMC_IPC_PMIC_ACCESS_READ        0x0
-#define                PMC_IPC_PMIC_ACCESS_WRITE       0x1
+#define        PMC_IPC_PMIC_ACCESS_READ        0x0
+#define        PMC_IPC_PMIC_ACCESS_WRITE       0x1
 #define PMC_IPC_USB_PWR_CTRL           0xF0
 #define PMC_IPC_PMIC_BLACKLIST_SEL     0xEF
 #define PMC_IPC_PHY_CONFIG             0xEE
@@ -28,13 +33,14 @@
 #define PMC_GCR_TELEM_DEEP_S0IX_REG    0x78
 #define PMC_GCR_TELEM_SHLW_S0IX_REG    0x80
 
+static inline void pmc_cmd_init(u32 *cmd, u32 param1, u32 param2)
+{
+       cmd[0] = param1;
+       cmd[1] = param2;
+}
+
 #if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
 
-int intel_pmc_ipc_simple_command(int cmd, int sub);
-int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
-               u32 *out, u32 outlen, u32 dptr, u32 sptr);
-int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
-               u32 *out, u32 outlen);
 int intel_pmc_s0ix_counter_read(u64 *data);
 int intel_pmc_gcr_read(u32 offset, u32 *data);
 int intel_pmc_gcr_write(u32 offset, u32 data);
@@ -42,23 +48,6 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val);
 
 #else
 
-static inline int intel_pmc_ipc_simple_command(int cmd, int sub)
-{
-       return -EINVAL;
-}
-
-static inline int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen,
-               u32 *out, u32 outlen, u32 dptr, u32 sptr)
-{
-       return -EINVAL;
-}
-
-static inline int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
-               u32 *out, u32 outlen)
-{
-       return -EINVAL;
-}
-
 static inline int intel_pmc_s0ix_counter_read(u64 *data)
 {
        return -EINVAL;
diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c 
b/drivers/mfd/intel_soc_pmic_bxtwc.c
index 15bc052..368cbe2 100644
--- a/drivers/mfd/intel_soc_pmic_bxtwc.c
+++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
@@ -268,9 +268,11 @@ static int regmap_ipc_byte_reg_read(void *context, 
unsigned int reg,
 {
        int ret;
        int i2c_addr;
-       u8 ipc_in[2];
-       u8 ipc_out[4];
+       u8 ipc_in[2] = {0};
+       u8 ipc_out[4] = {0};
        struct intel_soc_pmic *pmic = context;
+       u32 cmd[PMC_PARAM_LEN] = {PMC_IPC_PMIC_ACCESS,
+               PMC_IPC_PMIC_ACCESS_READ};
 
        if (!pmic)
                return -EINVAL;
@@ -284,9 +286,8 @@ static int regmap_ipc_byte_reg_read(void *context, unsigned 
int reg,
 
        ipc_in[0] = reg;
        ipc_in[1] = i2c_addr;
-       ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
-                       PMC_IPC_PMIC_ACCESS_READ,
-                       ipc_in, sizeof(ipc_in), (u32 *)ipc_out, 1);
+       ret = ipc_dev_raw_cmd(pmic->ipc_dev, cmd, PMC_PARAM_LEN, (u32 *)ipc_in,
+                       1, (u32 *)ipc_out, 1, 0, 0);
        if (ret) {
                dev_err(pmic->dev, "Failed to read from PMIC\n");
                return ret;
@@ -301,8 +302,10 @@ static int regmap_ipc_byte_reg_write(void *context, 
unsigned int reg,
 {
        int ret;
        int i2c_addr;
-       u8 ipc_in[3];
+       u8 ipc_in[3] = {0};
        struct intel_soc_pmic *pmic = context;
+       u32 cmd[PMC_PARAM_LEN] = {PMC_IPC_PMIC_ACCESS,
+               PMC_IPC_PMIC_ACCESS_WRITE};
 
        if (!pmic)
                return -EINVAL;
@@ -317,9 +320,8 @@ static int regmap_ipc_byte_reg_write(void *context, 
unsigned int reg,
        ipc_in[0] = reg;
        ipc_in[1] = i2c_addr;
        ipc_in[2] = val;
-       ret = intel_pmc_ipc_command(PMC_IPC_PMIC_ACCESS,
-                       PMC_IPC_PMIC_ACCESS_WRITE,
-                       ipc_in, sizeof(ipc_in), NULL, 0);
+       ret = ipc_dev_raw_cmd(pmic->ipc_dev, cmd, PMC_PARAM_LEN, (u32 *)ipc_in,
+                       1, NULL, 0, 0, 0);
        if (ret) {
                dev_err(pmic->dev, "Failed to write to PMIC\n");
                return ret;
@@ -445,6 +447,10 @@ static int bxtwc_probe(struct platform_device *pdev)
        if (!pmic)
                return -ENOMEM;
 
+       pmic->ipc_dev = intel_ipc_dev_get(INTEL_PMC_IPC_DEV);
+       if (IS_ERR_OR_NULL(pmic->ipc_dev))
+               return PTR_ERR(pmic->ipc_dev);
+
        ret = platform_get_irq(pdev, 0);
        if (ret < 0) {
                dev_err(&pdev->dev, "Invalid IRQ\n");
diff --git a/drivers/platform/x86/intel_pmc_ipc.c 
b/drivers/platform/x86/intel_pmc_ipc.c
index 222262f..7723755 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -47,18 +47,8 @@
  * The ARC handles the interrupt and services it, writing optional data to
  * the IPC1 registers, updates the IPC_STS response register with the status.
  */
-#define IPC_CMD                        0x0
-#define                IPC_CMD_MSI             0x100
 #define                IPC_CMD_SIZE            16
 #define                IPC_CMD_SUBCMD          12
-#define IPC_STATUS             0x04
-#define                IPC_STATUS_IRQ          0x4
-#define                IPC_STATUS_ERR          0x2
-#define                IPC_STATUS_BUSY         0x1
-#define IPC_SPTR               0x08
-#define IPC_DPTR               0x0C
-#define IPC_WRITE_BUFFER       0x80
-#define IPC_READ_BUFFER                0x90
 
 /* Residency with clock rate at 19.2MHz to usecs */
 #define S0IX_RESIDENCY_IN_USECS(d, s)          \
@@ -69,14 +59,9 @@
 })
 
 /*
- * 16-byte buffer for sending data associated with IPC command.
+ * 16-byte(4 dwords) buffer for sending data associated with IPC command.
  */
-#define IPC_DATA_BUFFER_SIZE   16
-
-#define IPC_LOOP_CNT           3000000
-#define IPC_MAX_SEC            3
-
-#define IPC_TRIGGER_MODE_IRQ           true
+#define IPC_DATA_BUFFER_SIZE   4
 
 /* exported resources from IFWI */
 #define PLAT_RESOURCE_IPC_INDEX                0
@@ -117,13 +102,31 @@
 #define PMC_CFG_NO_REBOOT_EN           (1 << 4)
 #define PMC_CFG_NO_REBOOT_DIS          (0 << 4)
 
+/* IPC PMC commands */
+#define        IPC_DEV_PMC_CMD_MSI                     BIT(8)
+#define        IPC_DEV_PMC_CMD_SIZE                    16
+#define        IPC_DEV_PMC_CMD_SUBCMD                  12
+#define        IPC_DEV_PMC_CMD_STATUS                  BIT(2)
+#define        IPC_DEV_PMC_CMD_STATUS_IRQ              BIT(2)
+#define        IPC_DEV_PMC_CMD_STATUS_ERR              BIT(1)
+#define        IPC_DEV_PMC_CMD_STATUS_ERR_MASK         GENMASK(7, 0)
+#define        IPC_DEV_PMC_CMD_STATUS_BUSY             BIT(0)
+
+/*IPC PMC reg offsets */
+#define IPC_DEV_PMC_STATUS_OFFSET              0x04
+#define IPC_DEV_PMC_SPTR_OFFSET                        0x08
+#define IPC_DEV_PMC_DPTR_OFFSET                        0x0C
+#define IPC_DEV_PMC_WRBUF_OFFSET               0x80
+#define IPC_DEV_PMC_RBUF_OFFSET                        0x90
+
 static struct intel_pmc_ipc_dev {
        struct device *dev;
+       struct intel_ipc_dev *pmc_ipc_dev;
+       struct intel_ipc_dev_ops ops;
+       struct intel_ipc_dev_cfg cfg;
        void __iomem *ipc_base;
-       bool irq_mode;
        int irq;
        int cmd;
-       struct completion cmd_complete;
 
        /* gcr */
        void __iomem *gcr_mem_base;
@@ -133,23 +136,10 @@ static struct intel_pmc_ipc_dev {
        u8 telem_res_inval;
 } ipcdev;
 
-static char *ipc_err_sources[] = {
-       [IPC_ERR_NONE] =
-               "no error",
-       [IPC_ERR_CMD_NOT_SUPPORTED] =
-               "command not supported",
-       [IPC_ERR_CMD_NOT_SERVICED] =
-               "command not serviced",
-       [IPC_ERR_UNABLE_TO_SERVICE] =
-               "unable to service",
-       [IPC_ERR_CMD_INVALID] =
-               "command invalid",
-       [IPC_ERR_CMD_FAILED] =
-               "command failed",
-       [IPC_ERR_EMSECURITY] =
-               "Invalid Battery",
-       [IPC_ERR_UNSIGNEDKERNEL] =
-               "Unsigned kernel",
+static struct regmap_config pmc_regmap_config = {
+        .reg_bits = 32,
+        .reg_stride = 4,
+        .val_bits = 32,
 };
 
 static struct regmap_config gcr_regmap_config = {
@@ -163,37 +153,6 @@ static struct regmap_config gcr_regmap_config = {
 /* Prevent concurrent calls to the PMC */
 static DEFINE_MUTEX(ipclock);
 
-static inline void ipc_send_command(u32 cmd)
-{
-       ipcdev.cmd = cmd;
-       if (ipcdev.irq_mode) {
-               reinit_completion(&ipcdev.cmd_complete);
-               cmd |= IPC_CMD_MSI;
-       }
-       writel(cmd, ipcdev.ipc_base + IPC_CMD);
-}
-
-static inline u32 ipc_read_status(void)
-{
-       return readl(ipcdev.ipc_base + IPC_STATUS);
-}
-
-static inline void ipc_data_writel(u32 data, u32 offset)
-{
-       writel(data, ipcdev.ipc_base + IPC_WRITE_BUFFER + offset);
-}
-
-static inline u8 __maybe_unused ipc_data_readb(u32 offset)
-{
-       return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
-}
-
-static inline u32 ipc_data_readl(u32 offset)
-{
-       return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
-}
-
-
 /**
  * intel_pmc_gcr_read() - Read PMC GCR register
  * @offset:    offset of GCR register from GCR address base
@@ -259,160 +218,98 @@ static int update_no_reboot_bit(void *priv, bool set)
                                    PMC_CFG_NO_REBOOT_MASK, value);
 }
 
-static int intel_pmc_ipc_check_status(void)
+static int pre_simple_cmd_fn(u32 *cmd_list, u32 cmdlen)
 {
-       int status;
-       int ret = 0;
-
-       if (ipcdev.irq_mode) {
-               if (0 == wait_for_completion_timeout(
-                               &ipcdev.cmd_complete, IPC_MAX_SEC * HZ))
-                       ret = -ETIMEDOUT;
-       } else {
-               int loop_count = IPC_LOOP_CNT;
-
-               while ((ipc_read_status() & IPC_STATUS_BUSY) && --loop_count)
-                       udelay(1);
-               if (loop_count == 0)
-                       ret = -ETIMEDOUT;
-       }
-
-       status = ipc_read_status();
-       if (ret == -ETIMEDOUT) {
-               dev_err(ipcdev.dev,
-                       "IPC timed out, TS=0x%x, CMD=0x%x\n",
-                       status, ipcdev.cmd);
-               return ret;
-       }
+       if (!cmd_list || cmdlen != PMC_PARAM_LEN)
+               return -EINVAL;
 
-       if (status & IPC_STATUS_ERR) {
-               int i;
-
-               ret = -EIO;
-               i = (status >> IPC_CMD_SIZE) & 0xFF;
-               if (i < ARRAY_SIZE(ipc_err_sources))
-                       dev_err(ipcdev.dev,
-                               "IPC failed: %s, STS=0x%x, CMD=0x%x\n",
-                               ipc_err_sources[i], status, ipcdev.cmd);
-               else
-                       dev_err(ipcdev.dev,
-                               "IPC failed: unknown, STS=0x%x, CMD=0x%x\n",
-                               status, ipcdev.cmd);
-               if ((i == IPC_ERR_UNSIGNEDKERNEL) || (i == IPC_ERR_EMSECURITY))
-                       ret = -EACCES;
-       }
+       cmd_list[0] |= (cmd_list[1] << IPC_CMD_SUBCMD);
 
-       return ret;
+       return 0;
 }
 
-/**
- * intel_pmc_ipc_simple_command() - Simple IPC command
- * @cmd:       IPC command code.
- * @sub:       IPC command sub type.
- *
- * Send a simple IPC command to PMC when don't need to specify
- * input/output data and source/dest pointers.
- *
- * Return:     an IPC error code or 0 on success.
- */
-int intel_pmc_ipc_simple_command(int cmd, int sub)
+static int pre_raw_cmd_fn(u32 *cmd_list, u32 cmdlen, u32 *in, u32 inlen,
+               u32 *out, u32 outlen, u32 dptr, u32 sptr)
 {
        int ret;
 
-       mutex_lock(&ipclock);
-       if (ipcdev.dev == NULL) {
-               mutex_unlock(&ipclock);
-               return -ENODEV;
-       }
-       ipc_send_command(sub << IPC_CMD_SUBCMD | cmd);
-       ret = intel_pmc_ipc_check_status();
-       mutex_unlock(&ipclock);
+       if (inlen > IPC_DATA_BUFFER_SIZE || outlen > IPC_DATA_BUFFER_SIZE)
+               return -EINVAL;
 
-       return ret;
-}
-EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command);
+       ret = pre_simple_cmd_fn(cmd_list, cmdlen);
+       if (ret < 0)
+               return ret;
 
-/**
- * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers
- * @cmd:       IPC command code.
- * @sub:       IPC command sub type.
- * @in:                input data of this IPC command.
- * @inlen:     input data length in bytes.
- * @out:       output data of this IPC command.
- * @outlen:    output data length in dwords.
- * @sptr:      data writing to SPTR register.
- * @dptr:      data writing to DPTR register.
- *
- * Send an IPC command to PMC with input/output data and source/dest pointers.
- *
- * Return:     an IPC error code or 0 on success.
- */
-int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
-                         u32 outlen, u32 dptr, u32 sptr)
-{
-       u32 wbuf[4] = { 0 };
-       int ret;
-       int i;
+       cmd_list[0] |= (inlen << IPC_CMD_SIZE);
 
-       if (inlen > IPC_DATA_BUFFER_SIZE || outlen > IPC_DATA_BUFFER_SIZE / 4)
-               return -EINVAL;
+       return 0;
+}
 
-       mutex_lock(&ipclock);
-       if (ipcdev.dev == NULL) {
-               mutex_unlock(&ipclock);
-               return -ENODEV;
-       }
-       memcpy(wbuf, in, inlen);
-       writel(dptr, ipcdev.ipc_base + IPC_DPTR);
-       writel(sptr, ipcdev.ipc_base + IPC_SPTR);
-       /* The input data register is 32bit register and inlen is in Byte */
-       for (i = 0; i < ((inlen + 3) / 4); i++)
-               ipc_data_writel(wbuf[i], 4 * i);
-       ipc_send_command((inlen << IPC_CMD_SIZE) |
-                       (sub << IPC_CMD_SUBCMD) | cmd);
-       ret = intel_pmc_ipc_check_status();
-       if (!ret) {
-               /* out is read from 32bit register and outlen is in 32bit */
-               for (i = 0; i < outlen; i++)
-                       *out++ = ipc_data_readl(4 * i);
-       }
-       mutex_unlock(&ipclock);
+static int pmc_ipc_err_code(int status)
+{
+       return ((status >> IPC_DEV_PMC_CMD_SIZE) &
+                       IPC_DEV_PMC_CMD_STATUS_ERR_MASK);
+}
 
-       return ret;
+static int pmc_ipc_busy_check(int status)
+{
+       return status | IPC_DEV_PMC_CMD_STATUS_BUSY;
 }
-EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd);
 
-/**
- * intel_pmc_ipc_command() -  IPC command with input/output data
- * @cmd:       IPC command code.
- * @sub:       IPC command sub type.
- * @in:                input data of this IPC command.
- * @inlen:     input data length in bytes.
- * @out:       output data of this IPC command.
- * @outlen:    output data length in dwords.
- *
- * Send an IPC command to PMC with input/output data.
- *
- * Return:     an IPC error code or 0 on success.
- */
-int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
-                         u32 *out, u32 outlen)
+static u32 pmc_ipc_enable_msi(u32 cmd)
 {
-       return intel_pmc_ipc_raw_cmd(cmd, sub, in, inlen, out, outlen, 0, 0);
+       return cmd | IPC_DEV_PMC_CMD_MSI;
 }
-EXPORT_SYMBOL_GPL(intel_pmc_ipc_command);
 
-static irqreturn_t ioc(int irq, void *dev_id)
+static struct intel_ipc_dev *intel_pmc_ipc_dev_create(
+               struct device *pmc_dev,
+               void __iomem *base,
+               int irq)
 {
-       int status;
+       struct intel_ipc_dev_ops *ops;
+       struct intel_ipc_dev_cfg *cfg;
+       struct regmap *cmd_regs;
+
+       cfg = devm_kzalloc(pmc_dev, sizeof(*cfg), GFP_KERNEL);
+       if (!cfg)
+               return ERR_PTR(-ENOMEM);
+
+       ops = devm_kzalloc(pmc_dev, sizeof(*ops), GFP_KERNEL);
+       if (!ops)
+               return ERR_PTR(-ENOMEM);
+
+        cmd_regs = devm_regmap_init_mmio_clk(pmc_dev, NULL, base,
+                       &pmc_regmap_config);
+        if (IS_ERR(cmd_regs)) {
+                dev_err(pmc_dev, "cmd_regs regmap init failed\n");
+                return ERR_CAST(cmd_regs);;
+        }
 
-       if (ipcdev.irq_mode) {
-               status = ipc_read_status();
-               writel(status | IPC_STATUS_IRQ, ipcdev.ipc_base + IPC_STATUS);
-       }
-       complete(&ipcdev.cmd_complete);
+       /* set IPC dev ops */
+       ops->to_err_code = pmc_ipc_err_code;
+       ops->busy_check = pmc_ipc_busy_check;
+       ops->enable_msi = pmc_ipc_enable_msi;
+       ops->pre_raw_cmd_fn = pre_raw_cmd_fn;
+       ops->pre_simple_cmd_fn = pre_simple_cmd_fn;
 
-       return IRQ_HANDLED;
+       /* set cfg options */
+       if (irq > 0)
+               cfg->mode = IPC_DEV_MODE_IRQ;
+       else
+               cfg->mode = IPC_DEV_MODE_POLLING;
+
+       cfg->chan_type = IPC_CHANNEL_IA_PMC;
+       cfg->irq = irq;
+       cfg->use_msi = true;
+       cfg->cmd_regs = cmd_regs;
+       cfg->data_regs = cmd_regs;
+       cfg->wrbuf_reg = IPC_DEV_PMC_WRBUF_OFFSET;
+       cfg->rbuf_reg = IPC_DEV_PMC_RBUF_OFFSET;
+       cfg->sptr_reg = IPC_DEV_PMC_SPTR_OFFSET;
+       cfg->dptr_reg = IPC_DEV_PMC_DPTR_OFFSET;
+       cfg->status_reg = IPC_DEV_PMC_STATUS_OFFSET;
+
+       return devm_intel_ipc_dev_create(pmc_dev, INTEL_PMC_IPC_DEV, cfg, ops);
 }
 
 static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -422,13 +319,12 @@ static int ipc_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
        int len;
 
        ipcdev.dev = &pci_dev_get(pdev)->dev;
-       ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
 
        ret = pci_enable_device(pdev);
        if (ret)
                goto release_device;
 
-       ret = pci_request_regions(pdev, "intel_pmc_ipc");
+       ret = pci_request_regions(pdev, INTEL_PMC_IPC_DEV);
        if (ret)
                goto disable_device;
 
@@ -440,15 +336,6 @@ static int ipc_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
                goto free_pci_resources;
        }
 
-       init_completion(&ipcdev.cmd_complete);
-
-       if (devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc",
-                               &ipcdev)) {
-               dev_err(&pdev->dev, "Failed to request irq\n");
-               ret = -EBUSY;
-               goto free_pci_resources;
-       }
-
        ipcdev.ipc_base = devm_ioremap_nocache(&pdev->dev, pci_resource, len);
        if (!ipcdev.ipc_base) {
                dev_err(&pdev->dev, "Failed to ioremap ipc base\n");
@@ -456,6 +343,15 @@ static int ipc_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
                goto free_pci_resources;
        }
 
+       ipcdev.pmc_ipc_dev = intel_pmc_ipc_dev_create(&pdev->dev,
+                       ipcdev.ipc_base, pdev->irq);
+       if (IS_ERR(ipcdev.pmc_ipc_dev)) {
+               dev_err(ipcdev.dev,
+                               "Failed to create PMC IPC device\n");
+               ret = PTR_ERR(ipcdev.pmc_ipc_dev);
+               goto free_pci_resources;
+       }
+
        return 0;
 
 free_pci_resources:
@@ -495,19 +391,19 @@ static ssize_t intel_pmc_ipc_simple_cmd_store(struct 
device *dev,
                                              struct device_attribute *attr,
                                              const char *buf, size_t count)
 {
-       int subcmd;
-       int cmd;
+       struct intel_pmc_ipc_dev *pmc_priv = dev_get_drvdata(dev);
+       int cmd[2];
        int ret;
 
-       ret = sscanf(buf, "%d %d", &cmd, &subcmd);
+       ret = sscanf(buf, "%d %d", &cmd[0], &cmd[2]);
        if (ret != 2) {
                dev_err(dev, "Error args\n");
                return -EINVAL;
        }
 
-       ret = intel_pmc_ipc_simple_command(cmd, subcmd);
+       ret = ipc_dev_simple_cmd(pmc_priv->pmc_ipc_dev, cmd, 2);
        if (ret) {
-               dev_err(dev, "command %d error with %d\n", cmd, ret);
+               dev_err(dev, "command %d error with %d\n", cmd[0], ret);
                return ret;
        }
        return (ssize_t)count;
@@ -517,22 +413,23 @@ static ssize_t intel_pmc_ipc_northpeak_store(struct 
device *dev,
                                             struct device_attribute *attr,
                                             const char *buf, size_t count)
 {
+       struct intel_pmc_ipc_dev *pmc_priv = dev_get_drvdata(dev);
        unsigned long val;
-       int subcmd;
+       int cmd[2] = {PMC_IPC_NORTHPEAK_CTRL, 0};
        int ret;
 
        if (kstrtoul(buf, 0, &val))
                return -EINVAL;
 
        if (val)
-               subcmd = 1;
-       else
-               subcmd = 0;
-       ret = intel_pmc_ipc_simple_command(PMC_IPC_NORTHPEAK_CTRL, subcmd);
+               cmd[1] = 1;
+
+       ret = ipc_dev_simple_cmd(pmc_priv->pmc_ipc_dev, cmd, 2);
        if (ret) {
-               dev_err(dev, "command north %d error with %d\n", subcmd, ret);
+               dev_err(dev, "command north %d error with %d\n", cmd[1], ret);
                return ret;
        }
+
        return (ssize_t)count;
 }
 
@@ -782,14 +679,14 @@ MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids);
 
 static int ipc_plat_probe(struct platform_device *pdev)
 {
-       int ret;
+       int ret, irq;
 
        ipcdev.dev = &pdev->dev;
-       ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
-       init_completion(&ipcdev.cmd_complete);
 
-       ipcdev.irq = platform_get_irq(pdev, 0);
-       if (ipcdev.irq < 0) {
+       dev_set_drvdata(&pdev->dev, &ipcdev);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
                dev_err(&pdev->dev, "Failed to get irq\n");
                return -EINVAL;
        }
@@ -813,12 +710,6 @@ static int ipc_plat_probe(struct platform_device *pdev)
                return ret;
        }
 
-       if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND,
-                            "intel_pmc_ipc", &ipcdev)) {
-               dev_err(&pdev->dev, "Failed to request irq\n");
-               return -EBUSY;
-       }
-
        ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group);
        if (ret) {
                dev_err(&pdev->dev, "Failed to create sysfs group %d\n",
@@ -826,6 +717,13 @@ static int ipc_plat_probe(struct platform_device *pdev)
                return ret;
        }
 
+       ipcdev.pmc_ipc_dev = intel_pmc_ipc_dev_create(&pdev->dev,
+                       ipcdev.ipc_base, irq);
+       if (IS_ERR(ipcdev.pmc_ipc_dev)) {
+               dev_err(&pdev->dev, "Failed to create PMC IPC device\n");
+               return PTR_ERR(ipcdev.pmc_ipc_dev);
+       }
+
        return 0;
 }
 
diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c 
b/drivers/platform/x86/intel_telemetry_pltdrv.c
index 2e91ce0..77e10f5 100644
--- a/drivers/platform/x86/intel_telemetry_pltdrv.c
+++ b/drivers/platform/x86/intel_telemetry_pltdrv.c
@@ -57,10 +57,6 @@
 #define IOSS_TELEM_TRACE_CTL_WRITE     0x6
 #define IOSS_TELEM_EVENT_CTL_READ      0x7
 #define IOSS_TELEM_EVENT_CTL_WRITE     0x8
-#define IOSS_TELEM_EVT_CTRL_WRITE_SIZE 0x4
-#define IOSS_TELEM_READ_WORD           0x1
-#define IOSS_TELEM_WRITE_FOURBYTES     0x4
-#define IOSS_TELEM_EVT_WRITE_SIZE      0x3
 
 #define TELEM_INFO_SRAMEVTS_MASK       0xFF00
 #define TELEM_INFO_SRAMEVTS_SHIFT      0x8
@@ -99,7 +95,7 @@ struct telem_ssram_region {
 };
 
 static struct telemetry_plt_config *telm_conf;
-static struct intel_ipc_dev *punit_bios_ipc_dev;
+static struct intel_ipc_dev *punit_bios_ipc_dev, *pmc_ipc_dev;
 
 /*
  * The following counters are programmed by default during setup.
@@ -233,17 +229,16 @@ static int telemetry_check_evtid(enum telemetry_unit 
telem_unit,
 static inline int telemetry_plt_config_ioss_event(u32 evt_id, int index)
 {
        u32 write_buf;
-       int ret;
+       u32 cmd[PMC_PARAM_LEN] = {0};
 
        write_buf = evt_id | TELEM_EVENT_ENABLE;
        write_buf <<= BITS_PER_BYTE;
        write_buf |= index;
 
-       ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                   IOSS_TELEM_EVENT_WRITE, (u8 *)&write_buf,
-                                   IOSS_TELEM_EVT_WRITE_SIZE, NULL, 0);
+       pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_EVENT_WRITE);
 
-       return ret;
+       return ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, &write_buf,
+                       1, NULL, 0, 0, 0);
 }
 
 static inline int telemetry_plt_config_pss_event(u32 evt_id, int index)
@@ -253,6 +248,7 @@ static inline int telemetry_plt_config_pss_event(u32 
evt_id, int index)
 
        write_buf = evt_id | TELEM_EVENT_ENABLE;
        punit_cmd_init(cmd, IPC_PUNIT_BIOS_WRITE_TELE_EVENT, index, 0);
+
        return ipc_dev_raw_cmd(punit_bios_ipc_dev, cmd, PUNIT_PARAM_LEN,
                        &write_buf, 1, NULL, 0, 0, 0);
 }
@@ -264,15 +260,16 @@ static int telemetry_setup_iossevtconfig(struct 
telemetry_evtconfig evtconfig,
        int ret, index, idx;
        u32 *ioss_evtmap;
        u32 telem_ctrl;
+       u32 cmd[PMC_PARAM_LEN] = {0};
 
        num_ioss_evts = evtconfig.num_evts;
        ioss_period = evtconfig.period;
        ioss_evtmap = evtconfig.evtmap;
 
        /* Get telemetry EVENT CTL */
-       ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                   IOSS_TELEM_EVENT_CTL_READ, NULL, 0,
-                                   &telem_ctrl, IOSS_TELEM_READ_WORD);
+       pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_EVENT_CTL_READ);
+       ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, NULL, 0,
+                       &telem_ctrl, 1, 0, 0);
        if (ret) {
                pr_err("IOSS TELEM_CTRL Read Failed\n");
                return ret;
@@ -280,12 +277,9 @@ static int telemetry_setup_iossevtconfig(struct 
telemetry_evtconfig evtconfig,
 
        /* Disable Telemetry */
        TELEM_DISABLE(telem_ctrl);
-
-       ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                   IOSS_TELEM_EVENT_CTL_WRITE,
-                                   (u8 *)&telem_ctrl,
-                                   IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
-                                   NULL, 0);
+       pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_EVENT_CTL_WRITE);
+       ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, &telem_ctrl,
+                       1, NULL, 0, 0, 0);
        if (ret) {
                pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
                return ret;
@@ -296,12 +290,10 @@ static int telemetry_setup_iossevtconfig(struct 
telemetry_evtconfig evtconfig,
        if (action == TELEM_RESET) {
                /* Clear All Events */
                TELEM_CLEAR_EVENTS(telem_ctrl);
-
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                           IOSS_TELEM_EVENT_CTL_WRITE,
-                                           (u8 *)&telem_ctrl,
-                                           IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
-                                           NULL, 0);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_EVENT_CTL_WRITE);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN,
+                               &telem_ctrl, 1, NULL, 0, 0, 0);
                if (ret) {
                        pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
                        return ret;
@@ -326,11 +318,10 @@ static int telemetry_setup_iossevtconfig(struct 
telemetry_evtconfig evtconfig,
                /* Clear All Events */
                TELEM_CLEAR_EVENTS(telem_ctrl);
 
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                           IOSS_TELEM_EVENT_CTL_WRITE,
-                                           (u8 *)&telem_ctrl,
-                                           IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
-                                           NULL, 0);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_EVENT_CTL_WRITE);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN,
+                               &telem_ctrl, 1, NULL, 0, 0, 0);
                if (ret) {
                        pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
                        return ret;
@@ -378,10 +369,9 @@ static int telemetry_setup_iossevtconfig(struct 
telemetry_evtconfig evtconfig,
        TELEM_ENABLE_PERIODIC(telem_ctrl);
        telem_ctrl |= ioss_period;
 
-       ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                   IOSS_TELEM_EVENT_CTL_WRITE,
-                                   (u8 *)&telem_ctrl,
-                                   IOSS_TELEM_EVT_CTRL_WRITE_SIZE, NULL, 0);
+       pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_EVENT_CTL_WRITE);
+       ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, &telem_ctrl,
+                       1, NULL, 0, 0, 0);
        if (ret) {
                pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n");
                return ret;
@@ -573,8 +563,9 @@ static int telemetry_setup(struct platform_device *pdev)
        u32 cmd[PUNIT_PARAM_LEN] = {0};
        int ret;
 
-       ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_INFO_READ,
-                                   NULL, 0, &read_buf, IOSS_TELEM_READ_WORD);
+       pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY, IOSS_TELEM_INFO_READ);
+       ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, NULL, 0,
+                       &read_buf, 1, 0, 0);
        if (ret) {
                dev_err(&pdev->dev, "IOSS TELEM_INFO Read Failed\n");
                return ret;
@@ -677,9 +668,10 @@ static int telemetry_plt_set_sampling_period(u8 
pss_period, u8 ioss_period)
                }
 
                /* Get telemetry EVENT CTL */
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                           IOSS_TELEM_EVENT_CTL_READ, NULL, 0,
-                                           &telem_ctrl, IOSS_TELEM_READ_WORD);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_EVENT_CTL_READ);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, NULL, 0,
+                               &telem_ctrl, 1, 0, 0);
                if (ret) {
                        pr_err("IOSS TELEM_CTRL Read Failed\n");
                        goto out;
@@ -687,12 +679,10 @@ static int telemetry_plt_set_sampling_period(u8 
pss_period, u8 ioss_period)
 
                /* Disable Telemetry */
                TELEM_DISABLE(telem_ctrl);
-
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                           IOSS_TELEM_EVENT_CTL_WRITE,
-                                           (u8 *)&telem_ctrl,
-                                           IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
-                                           NULL, 0);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_EVENT_CTL_WRITE);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN,
+                               &telem_ctrl, 1, NULL, 0, 0, 0);
                if (ret) {
                        pr_err("IOSS TELEM_CTRL Event Disable Write Failed\n");
                        goto out;
@@ -704,11 +694,10 @@ static int telemetry_plt_set_sampling_period(u8 
pss_period, u8 ioss_period)
                TELEM_ENABLE_PERIODIC(telem_ctrl);
                telem_ctrl |= ioss_period;
 
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                                           IOSS_TELEM_EVENT_CTL_WRITE,
-                                           (u8 *)&telem_ctrl,
-                                           IOSS_TELEM_EVT_CTRL_WRITE_SIZE,
-                                           NULL, 0);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_EVENT_CTL_WRITE);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN,
+                               &telem_ctrl, 1, NULL, 0, 0, 0);
                if (ret) {
                        pr_err("IOSS TELEM_CTRL Event Enable Write Failed\n");
                        goto out;
@@ -1006,9 +995,10 @@ static int telemetry_plt_get_trace_verbosity(enum 
telemetry_unit telem_unit,
                break;
 
        case TELEM_IOSS:
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                               IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp,
-                               IOSS_TELEM_READ_WORD);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_TRACE_CTL_READ);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, NULL, 0,
+                               &temp, 1, 0, 0);
                if (ret) {
                        pr_err("IOSS TRACE_CTL Read Failed\n");
                        goto out;
@@ -1061,9 +1051,10 @@ static int telemetry_plt_set_trace_verbosity(enum 
telemetry_unit telem_unit,
                break;
 
        case TELEM_IOSS:
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                               IOSS_TELEM_TRACE_CTL_READ, NULL, 0, &temp,
-                               IOSS_TELEM_READ_WORD);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY,
+                               IOSS_TELEM_TRACE_CTL_READ);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, NULL, 0,
+                               &temp, 1, 0, 0);
                if (ret) {
                        pr_err("IOSS TRACE_CTL Read Failed\n");
                        goto out;
@@ -1071,10 +1062,9 @@ static int telemetry_plt_set_trace_verbosity(enum 
telemetry_unit telem_unit,
 
                TELEM_CLEAR_VERBOSITY_BITS(temp);
                TELEM_SET_VERBOSITY_BITS(temp, verbosity);
-
-               ret = intel_pmc_ipc_command(PMC_IPC_PMC_TELEMTRY,
-                               IOSS_TELEM_TRACE_CTL_WRITE, (u8 *)&temp,
-                               IOSS_TELEM_WRITE_FOURBYTES, NULL, 0);
+               pmc_cmd_init(cmd, PMC_IPC_PMC_TELEMTRY, 
IOSS_TELEM_TRACE_CTL_WRITE);
+               ret = ipc_dev_raw_cmd(pmc_ipc_dev, cmd, PMC_PARAM_LEN, &temp,
+                               1, NULL, 0, 0, 0);
                if (ret) {
                        pr_err("IOSS TRACE_CTL Verbosity Set Failed\n");
                        goto out;
@@ -1119,6 +1109,10 @@ static int telemetry_pltdrv_probe(struct platform_device 
*pdev)
        if (IS_ERR_OR_NULL(punit_bios_ipc_dev))
                return PTR_ERR(punit_bios_ipc_dev);
 
+       pmc_ipc_dev = intel_ipc_dev_get(INTEL_PMC_IPC_DEV);
+       if (IS_ERR_OR_NULL(pmc_ipc_dev))
+               return PTR_ERR(pmc_ipc_dev);
+
        telm_conf = (struct telemetry_plt_config *)id->driver_data;
 
        res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/include/linux/mfd/intel_soc_pmic.h 
b/include/linux/mfd/intel_soc_pmic.h
index 5aacdb0..7cc39b6 100644
--- a/include/linux/mfd/intel_soc_pmic.h
+++ b/include/linux/mfd/intel_soc_pmic.h
@@ -20,6 +20,7 @@
 #define __INTEL_SOC_PMIC_H__
 
 #include <linux/regmap.h>
+#include <linux/platform_data/x86/intel_ipc_dev.h>
 
 struct intel_soc_pmic {
        int irq;
@@ -31,6 +32,7 @@ struct intel_soc_pmic {
        struct regmap_irq_chip_data *irq_chip_data_chgr;
        struct regmap_irq_chip_data *irq_chip_data_crit;
        struct device *dev;
+       struct intel_ipc_dev *ipc_dev;
 };
 
 #endif /* __INTEL_SOC_PMIC_H__ */
-- 
2.7.4

Reply via email to