get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/809927/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 809927,
    "url": "http://patchwork.ozlabs.org/api/patches/809927/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/rtc-linux/patch/90f4d15c9ca0430f6ac4cfafe0eaf6ece6c8761c.1504588701.git.sathyanarayanan.kuppuswamy@linux.intel.com/",
    "project": {
        "id": 9,
        "url": "http://patchwork.ozlabs.org/api/projects/9/?format=api",
        "name": "Linux RTC development",
        "link_name": "rtc-linux",
        "list_id": "linux-rtc.vger.kernel.org",
        "list_email": "linux-rtc@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<90f4d15c9ca0430f6ac4cfafe0eaf6ece6c8761c.1504588701.git.sathyanarayanan.kuppuswamy@linux.intel.com>",
    "list_archive_url": null,
    "date": "2017-09-05T05:37:27",
    "name": "[RFC,v3,7/7] platform/x86: intel_scu_ipc: Use generic Intel IPC device calls",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": false,
    "hash": "d398f2dfd47f13cea4932b973147a43be7a2f569",
    "submitter": {
        "id": 66129,
        "url": "http://patchwork.ozlabs.org/api/people/66129/?format=api",
        "name": "Kuppuswamy Sathyanarayanan",
        "email": "sathyanarayanan.kuppuswamy@linux.intel.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/rtc-linux/patch/90f4d15c9ca0430f6ac4cfafe0eaf6ece6c8761c.1504588701.git.sathyanarayanan.kuppuswamy@linux.intel.com/mbox/",
    "series": [
        {
            "id": 1490,
            "url": "http://patchwork.ozlabs.org/api/series/1490/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/rtc-linux/list/?series=1490",
            "date": "2017-09-05T05:37:20",
            "name": "PMC/PUNIT IPC driver cleanup",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/1490/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/809927/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/809927/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<linux-rtc-owner@vger.kernel.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=linux-rtc-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xmb9R6sW0z9sNq\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue,  5 Sep 2017 15:38:35 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1750969AbdIEFic (ORCPT <rfc822;incoming@patchwork.ozlabs.org>);\n\tTue, 5 Sep 2017 01:38:32 -0400",
            "from mga01.intel.com ([192.55.52.88]:3891 \"EHLO mga01.intel.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S1754140AbdIEFiQ (ORCPT <rfc822;linux-rtc@vger.kernel.org>);\n\tTue, 5 Sep 2017 01:38:16 -0400",
            "from orsmga005.jf.intel.com ([10.7.209.41])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t04 Sep 2017 22:38:14 -0700",
            "from skuppusw-desk.jf.intel.com ([10.7.198.92])\n\tby orsmga005.jf.intel.com with ESMTP; 04 Sep 2017 22:38:13 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.41,478,1498546800\"; d=\"scan'208\";a=\"145505111\"",
        "From": "sathyanarayanan.kuppuswamy@linux.intel.com",
        "To": "a.zummo@towertech.it, x86@kernel.org, wim@iguana.be,\n\tmingo@redhat.com, alexandre.belloni@free-electrons.com,\n\tqipeng.zha@intel.com, hpa@zytor.com, dvhart@infradead.org,\n\ttglx@linutronix.de, lee.jones@linaro.org, andy@infradead.org,\n\tsouvik.k.chakravarty@intel.com",
        "Cc": "linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org,\n\tsathyaosid@gmail.com, Kuppuswamy Sathyanarayanan \n\t<sathyanarayanan.kuppuswamy@linux.intel.com>",
        "Subject": "[RFC v3 7/7] platform/x86: intel_scu_ipc: Use generic Intel IPC\n\tdevice calls",
        "Date": "Mon,  4 Sep 2017 22:37:27 -0700",
        "Message-Id": "<90f4d15c9ca0430f6ac4cfafe0eaf6ece6c8761c.1504588701.git.sathyanarayanan.kuppuswamy@linux.intel.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<cover.1504588701.git.sathyanarayanan.kuppuswamy@linux.intel.com>",
        "References": "<cover.1504588701.git.sathyanarayanan.kuppuswamy@linux.intel.com>",
        "Sender": "linux-rtc-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<linux-rtc.vger.kernel.org>",
        "X-Mailing-List": "linux-rtc@vger.kernel.org"
    },
    "content": "From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>\n\nRemoved redundant IPC helper functions and refactored the driver to use\ngeneric IPC device driver APIs.\n\nThis patch also cleans-up SCU IPC user drivers to use APIs provided\nby generic IPC driver.\n\nSigned-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>\n---\n arch/x86/include/asm/intel_scu_ipc.h    |  23 +-\n arch/x86/platform/intel-mid/intel-mid.c |  12 +-\n drivers/platform/x86/Kconfig            |   1 +\n drivers/platform/x86/intel_scu_ipc.c    | 483 +++++++++++++-------------------\n drivers/rtc/rtc-mrst.c                  |  15 +-\n drivers/watchdog/intel-mid_wdt.c        |  12 +-\n drivers/watchdog/intel_scu_watchdog.c   |  17 +-\n 7 files changed, 251 insertions(+), 312 deletions(-)",
    "diff": "diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h\nindex 81d3d87..5842534 100644\n--- a/arch/x86/include/asm/intel_scu_ipc.h\n+++ b/arch/x86/include/asm/intel_scu_ipc.h\n@@ -14,9 +14,19 @@\n #define IPCMSG_COLD_BOOT\t0xF3\n \n #define IPCMSG_VRTC\t\t0xFA\t /* Set vRTC device */\n-\t/* Command id associated with message IPCMSG_VRTC */\n-\t#define IPC_CMD_VRTC_SETTIME      1 /* Set time */\n-\t#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */\n+\n+/* Command id associated with message IPCMSG_VRTC */\n+#define IPC_CMD_VRTC_SETTIME      1 /* Set time */\n+#define IPC_CMD_VRTC_SETALARM     2 /* Set alarm */\n+\n+#define INTEL_SCU_IPC_DEV\t\"intel_scu_ipc\"\n+#define SCU_PARAM_LEN\t\t2\n+\n+static inline void scu_cmd_init(u32 *cmd, u32 param1, u32 param2)\n+{\n+\tcmd[0] = param1;\n+\tcmd[1] = param2;\n+}\n \n /* Read single register */\n int intel_scu_ipc_ioread8(u16 addr, u8 *data);\n@@ -45,13 +55,6 @@ int intel_scu_ipc_writev(u16 *addr, u8 *data, int len);\n /* Update single register based on the mask */\n int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);\n \n-/* Issue commands to the SCU with or without data */\n-int intel_scu_ipc_simple_command(int cmd, int sub);\n-int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,\n-\t\t\t  u32 *out, int outlen);\n-int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,\n-\t\t\t      u32 *out, int outlen, u32 dptr, u32 sptr);\n-\n /* I2C control api */\n int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);\n \ndiff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c\nindex 12a2725..27541e9 100644\n--- a/arch/x86/platform/intel-mid/intel-mid.c\n+++ b/arch/x86/platform/intel-mid/intel-mid.c\n@@ -22,6 +22,7 @@\n #include <linux/irq.h>\n #include <linux/export.h>\n #include <linux/notifier.h>\n+#include <linux/platform_data/x86/intel_ipc_dev.h>\n \n #include <asm/setup.h>\n #include <asm/mpspec_def.h>\n@@ -68,18 +69,23 @@ static void *(*get_intel_mid_ops[])(void) = INTEL_MID_OPS_INIT;\n enum intel_mid_cpu_type __intel_mid_cpu_chip;\n EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);\n \n+static struct intel_ipc_dev *ipc_dev;\n+\n static void intel_mid_power_off(void)\n {\n+\tu32 cmds[SCU_PARAM_LEN] = {IPCMSG_COLD_OFF, 1};\n \t/* Shut down South Complex via PWRMU */\n \tintel_mid_pwr_power_off();\n \n \t/* Only for Tangier, the rest will ignore this command */\n-\tintel_scu_ipc_simple_command(IPCMSG_COLD_OFF, 1);\n+\tipc_dev_simple_cmd(ipc_dev, cmds, SCU_PARAM_LEN);\n };\n \n static void intel_mid_reboot(void)\n {\n-\tintel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);\n+\tu32 cmds[SCU_PARAM_LEN] = {IPCMSG_COLD_BOOT, 0};\n+\n+\tipc_dev_simple_cmd(ipc_dev, cmds, SCU_PARAM_LEN);\n }\n \n static unsigned long __init intel_mid_calibrate_tsc(void)\n@@ -206,6 +212,8 @@ void __init x86_intel_mid_early_setup(void)\n \tx86_init.mpparse.find_smp_config = x86_init_noop;\n \tx86_init.mpparse.get_smp_config = x86_init_uint_noop;\n \tset_bit(MP_BUS_ISA, mp_bus_not_pci);\n+\n+\tipc_dev = intel_ipc_dev_get(INTEL_SCU_IPC_DEV);\n }\n \n /*\ndiff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig\nindex 82479ca..e4e5822 100644\n--- a/drivers/platform/x86/Kconfig\n+++ b/drivers/platform/x86/Kconfig\n@@ -850,6 +850,7 @@ config INTEL_VBTN\n config INTEL_SCU_IPC\n \tbool \"Intel SCU IPC Support\"\n \tdepends on X86_INTEL_MID\n+\tselect REGMAP_MMIO\n \tdefault y\n \t---help---\n \t  IPC is used to bridge the communications between kernel and SCU on\ndiff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c\nindex f7cf981..78013e4 100644\n--- a/drivers/platform/x86/intel_scu_ipc.c\n+++ b/drivers/platform/x86/intel_scu_ipc.c\n@@ -24,6 +24,8 @@\n #include <linux/pci.h>\n #include <linux/interrupt.h>\n #include <linux/sfi.h>\n+#include <linux/regmap.h>\n+#include <linux/platform_data/x86/intel_ipc_dev.h>\n #include <asm/intel-mid.h>\n #include <asm/intel_scu_ipc.h>\n \n@@ -39,6 +41,25 @@\n #define IPC_CMD_PCNTRL_R      1 /* Register read */\n #define IPC_CMD_PCNTRL_M      2 /* Register read-modify-write */\n \n+/* IPC dev register offsets */\n+/*\n+ * IPC Read Buffer (Read Only):\n+ * 16 byte buffer for receiving data from SCU, if IPC command\n+ * processing results in response data\n+ */\n+#define IPC_DEV_SCU_RBUF_OFFSET\t\t\t0x90\n+#define IPC_DEV_SCU_WRBUF_OFFSET\t\t0x80\n+#define IPC_DEV_SCU_SPTR_OFFSET\t\t\t0x08\n+#define IPC_DEV_SCU_DPTR_OFFSET\t\t\t0x0C\n+#define IPC_DEV_SCU_STATUS_OFFSET\t\t0x04\n+\n+/* IPC dev commands */\n+/* IPC command register IOC bit */\n+#define\tIPC_DEV_SCU_CMD_MSI\t\t\tBIT(8)\n+#define\tIPC_DEV_SCU_CMD_STATUS_ERR\t\tBIT(1)\n+#define\tIPC_DEV_SCU_CMD_STATUS_ERR_MASK\t\tGENMASK(7, 0)\n+#define\tIPC_DEV_SCU_CMD_STATUS_BUSY\t\tBIT(0)\n+\n /*\n  * IPC register summary\n  *\n@@ -59,6 +80,11 @@\n #define IPC_WWBUF_SIZE    20\t\t/* IPC Write buffer Size */\n #define IPC_RWBUF_SIZE    20\t\t/* IPC Read buffer Size */\n #define IPC_IOC\t          0x100\t\t/* IPC command register IOC bit */\n+#define\tIPC_CMD_SIZE            16\n+#define\tIPC_CMD_SUBCMD          12\n+#define\tIPC_RWBUF_SIZE_DWORD    5\n+#define\tIPC_WWBUF_SIZE_DWORD    5\n+\n \n #define PCI_DEVICE_ID_LINCROFT\t\t0x082a\n #define PCI_DEVICE_ID_PENWELL\t\t0x080e\n@@ -93,140 +119,49 @@ static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {\n \n struct intel_scu_ipc_dev {\n \tstruct device *dev;\n+\tstruct intel_ipc_dev *ipc_dev;\n \tvoid __iomem *ipc_base;\n \tvoid __iomem *i2c_base;\n-\tstruct completion cmd_complete;\n+\tstruct regmap *ipc_regs;\n+\tstruct regmap *i2c_regs;\n \tu8 irq_mode;\n };\n \n-static struct intel_scu_ipc_dev  ipcdev; /* Only one for now */\n+static struct regmap_config ipc_regmap_config = {\n+        .reg_bits = 32,\n+        .reg_stride = 4,\n+        .val_bits = 32,\n+};\n \n-/*\n- * IPC Read Buffer (Read Only):\n- * 16 byte buffer for receiving data from SCU, if IPC command\n- * processing results in response data\n- */\n-#define IPC_READ_BUFFER\t\t0x90\n+static struct regmap_config i2c_regmap_config = {\n+        .reg_bits = 32,\n+        .reg_stride = 4,\n+        .val_bits = 32,\n+\t.fast_io = true,\n+};\n+\n+static struct intel_scu_ipc_dev  ipcdev; /* Only one for now */\n \n #define IPC_I2C_CNTRL_ADDR\t0\n #define I2C_DATA_ADDR\t\t0x04\n \n-static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */\n-\n-/*\n- * Send ipc command\n- * Command Register (Write Only):\n- * A write to this register results in an interrupt to the SCU core processor\n- * Format:\n- * |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)|\n- */\n-static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)\n-{\n-\tif (scu->irq_mode) {\n-\t\treinit_completion(&scu->cmd_complete);\n-\t\twritel(cmd | IPC_IOC, scu->ipc_base);\n-\t}\n-\twritel(cmd, scu->ipc_base);\n-}\n-\n-/*\n- * Write ipc data\n- * IPC Write Buffer (Write Only):\n- * 16-byte buffer for sending data associated with IPC command to\n- * SCU. Size of the data is specified in the IPC_COMMAND_REG register\n- */\n-static inline void ipc_data_writel(struct intel_scu_ipc_dev *scu, u32 data, u32 offset)\n-{\n-\twritel(data, scu->ipc_base + 0x80 + offset);\n-}\n-\n-/*\n- * Status Register (Read Only):\n- * Driver will read this register to get the ready/busy status of the IPC\n- * block and error status of the IPC command that was just processed by SCU\n- * Format:\n- * |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)|\n- */\n-static inline u8 ipc_read_status(struct intel_scu_ipc_dev *scu)\n-{\n-\treturn __raw_readl(scu->ipc_base + 0x04);\n-}\n-\n-/* Read ipc byte data */\n-static inline u8 ipc_data_readb(struct intel_scu_ipc_dev *scu, u32 offset)\n-{\n-\treturn readb(scu->ipc_base + IPC_READ_BUFFER + offset);\n-}\n-\n-/* Read ipc u32 data */\n-static inline u32 ipc_data_readl(struct intel_scu_ipc_dev *scu, u32 offset)\n-{\n-\treturn readl(scu->ipc_base + IPC_READ_BUFFER + offset);\n-}\n-\n-/* Wait till scu status is busy */\n-static inline int busy_loop(struct intel_scu_ipc_dev *scu)\n-{\n-\tu32 status = ipc_read_status(scu);\n-\tu32 loop_count = 100000;\n-\n-\t/* break if scu doesn't reset busy bit after huge retry */\n-\twhile ((status & BIT(0)) && --loop_count) {\n-\t\tudelay(1); /* scu processing time is in few u secods */\n-\t\tstatus = ipc_read_status(scu);\n-\t}\n-\n-\tif (status & BIT(0)) {\n-\t\tdev_err(scu->dev, \"IPC timed out\");\n-\t\treturn -ETIMEDOUT;\n-\t}\n-\n-\tif (status & BIT(1))\n-\t\treturn -EIO;\n-\n-\treturn 0;\n-}\n-\n-/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */\n-static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)\n-{\n-\tint status;\n-\n-\tif (!wait_for_completion_timeout(&scu->cmd_complete, 3 * HZ)) {\n-\t\tdev_err(scu->dev, \"IPC timed out\\n\");\n-\t\treturn -ETIMEDOUT;\n-\t}\n-\n-\tstatus = ipc_read_status(scu);\n-\tif (status & BIT(1))\n-\t\treturn -EIO;\n-\n-\treturn 0;\n-}\n-\n-static int intel_scu_ipc_check_status(struct intel_scu_ipc_dev *scu)\n-{\n-\treturn scu->irq_mode ? ipc_wait_for_interrupt(scu) : busy_loop(scu);\n-}\n-\n /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */\n static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)\n {\n \tstruct intel_scu_ipc_dev *scu = &ipcdev;\n \tint nc;\n \tu32 offset = 0;\n-\tint err;\n+\tint err = -EIO;\n \tu8 cbuf[IPC_WWBUF_SIZE];\n \tu32 *wbuf = (u32 *)&cbuf;\n+\tu32 cmd[SCU_PARAM_LEN] = {0};\n+\t/* max rbuf size is 20 bytes */\n+\tu8 rbuf[IPC_RWBUF_SIZE] = {0};\n+\tu32 rbuflen = DIV_ROUND_UP(count, 4);\n \n \tmemset(cbuf, 0, sizeof(cbuf));\n \n-\tmutex_lock(&ipclock);\n-\n-\tif (scu->dev == NULL) {\n-\t\tmutex_unlock(&ipclock);\n-\t\treturn -ENODEV;\n-\t}\n+\tscu_cmd_init(cmd, op, id);\n \n \tfor (nc = 0; nc < count; nc++, offset += 2) {\n \t\tcbuf[offset] = addr[nc];\n@@ -234,30 +169,30 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id)\n \t}\n \n \tif (id == IPC_CMD_PCNTRL_R) {\n-\t\tfor (nc = 0, offset = 0; nc < count; nc++, offset += 4)\n-\t\t\tipc_data_writel(scu, wbuf[nc], offset);\n-\t\tipc_command(scu, (count * 2) << 16 | id << 12 | 0 << 8 | op);\n+\t\terr = ipc_dev_raw_cmd(scu->ipc_dev, cmd, SCU_PARAM_LEN,\n+\t\t\t\t(u8 *)wbuf, count * 2, (u32 *)rbuf,\n+\t\t\t\tIPC_RWBUF_SIZE_DWORD, 0, 0);\n \t} else if (id == IPC_CMD_PCNTRL_W) {\n \t\tfor (nc = 0; nc < count; nc++, offset += 1)\n \t\t\tcbuf[offset] = data[nc];\n-\t\tfor (nc = 0, offset = 0; nc < count; nc++, offset += 4)\n-\t\t\tipc_data_writel(scu, wbuf[nc], offset);\n-\t\tipc_command(scu, (count * 3) << 16 | id << 12 | 0 << 8 | op);\n+\t\terr = ipc_dev_raw_cmd(scu->ipc_dev, cmd, SCU_PARAM_LEN,\n+\t\t\t\t(u8 *)wbuf, count * 3, NULL, 0, 0, 0);\n+\n \t} else if (id == IPC_CMD_PCNTRL_M) {\n \t\tcbuf[offset] = data[0];\n \t\tcbuf[offset + 1] = data[1];\n-\t\tipc_data_writel(scu, wbuf[0], 0); /* Write wbuff */\n-\t\tipc_command(scu, 4 << 16 | id << 12 | 0 << 8 | op);\n+\t\terr = ipc_dev_raw_cmd(scu->ipc_dev, cmd, SCU_PARAM_LEN,\n+\t\t\t\t(u8 *)wbuf, 4, NULL, 0, 0, 0);\n \t}\n \n-\terr = intel_scu_ipc_check_status(scu);\n \tif (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */\n \t\t/* Workaround: values are read as 0 without memcpy_fromio */\n \t\tmemcpy_fromio(cbuf, scu->ipc_base + 0x90, 16);\n-\t\tfor (nc = 0; nc < count; nc++)\n-\t\t\tdata[nc] = ipc_data_readb(scu, nc);\n+\t\tregmap_bulk_read(scu->ipc_regs, IPC_DEV_SCU_RBUF_OFFSET,\n+\t\t\t\t\trbuf, rbuflen);\n+\t\tmemcpy(data, rbuf, count);\n \t}\n-\tmutex_unlock(&ipclock);\n+\n \treturn err;\n }\n \n@@ -422,138 +357,6 @@ int intel_scu_ipc_update_register(u16 addr, u8 bits, u8 mask)\n }\n EXPORT_SYMBOL(intel_scu_ipc_update_register);\n \n-/**\n- *\tintel_scu_ipc_simple_command\t-\tsend a simple command\n- *\t@cmd: command\n- *\t@sub: sub type\n- *\n- *\tIssue a simple command to the SCU. Do not use this interface if\n- *\tyou must then access data as any data values may be overwritten\n- *\tby another SCU access by the time this function returns.\n- *\n- *\tThis function may sleep. Locking for SCU accesses is handled for\n- *\tthe caller.\n- */\n-int intel_scu_ipc_simple_command(int cmd, int sub)\n-{\n-\tstruct intel_scu_ipc_dev *scu = &ipcdev;\n-\tint err;\n-\n-\tmutex_lock(&ipclock);\n-\tif (scu->dev == NULL) {\n-\t\tmutex_unlock(&ipclock);\n-\t\treturn -ENODEV;\n-\t}\n-\tipc_command(scu, sub << 12 | cmd);\n-\terr = intel_scu_ipc_check_status(scu);\n-\tmutex_unlock(&ipclock);\n-\treturn err;\n-}\n-EXPORT_SYMBOL(intel_scu_ipc_simple_command);\n-\n-/**\n- *\tintel_scu_ipc_command\t-\tcommand with data\n- *\t@cmd: command\n- *\t@sub: sub type\n- *\t@in: input data\n- *\t@inlen: input length in dwords\n- *\t@out: output data\n- *\t@outlein: output length in dwords\n- *\n- *\tIssue a command to the SCU which involves data transfers. Do the\n- *\tdata copies under the lock but leave it for the caller to interpret\n- */\n-int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,\n-\t\t\t  u32 *out, int outlen)\n-{\n-\tstruct intel_scu_ipc_dev *scu = &ipcdev;\n-\tint i, err;\n-\n-\tmutex_lock(&ipclock);\n-\tif (scu->dev == NULL) {\n-\t\tmutex_unlock(&ipclock);\n-\t\treturn -ENODEV;\n-\t}\n-\n-\tfor (i = 0; i < inlen; i++)\n-\t\tipc_data_writel(scu, *in++, 4 * i);\n-\n-\tipc_command(scu, (inlen << 16) | (sub << 12) | cmd);\n-\terr = intel_scu_ipc_check_status(scu);\n-\n-\tif (!err) {\n-\t\tfor (i = 0; i < outlen; i++)\n-\t\t\t*out++ = ipc_data_readl(scu, 4 * i);\n-\t}\n-\n-\tmutex_unlock(&ipclock);\n-\treturn err;\n-}\n-EXPORT_SYMBOL(intel_scu_ipc_command);\n-\n-#define IPC_SPTR\t\t0x08\n-#define IPC_DPTR\t\t0x0C\n-\n-/**\n- * intel_scu_ipc_raw_command() - IPC command with data and pointers\n- * @cmd:\tIPC command code.\n- * @sub:\tIPC command sub type.\n- * @in:\t\tinput data of this IPC command.\n- * @inlen:\tinput data length in dwords.\n- * @out:\toutput data of this IPC command.\n- * @outlen:\toutput data length in dwords.\n- * @sptr:\tdata writing to SPTR register.\n- * @dptr:\tdata writing to DPTR register.\n- *\n- * Send an IPC command to SCU with input/output data and source/dest pointers.\n- *\n- * Return:\tan IPC error code or 0 on success.\n- */\n-int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,\n-\t\t\t      u32 *out, int outlen, u32 dptr, u32 sptr)\n-{\n-\tstruct intel_scu_ipc_dev *scu = &ipcdev;\n-\tint inbuflen = DIV_ROUND_UP(inlen, 4);\n-\tu32 inbuf[4];\n-\tint i, err;\n-\n-\t/* Up to 16 bytes */\n-\tif (inbuflen > 4)\n-\t\treturn -EINVAL;\n-\n-\tmutex_lock(&ipclock);\n-\tif (scu->dev == NULL) {\n-\t\tmutex_unlock(&ipclock);\n-\t\treturn -ENODEV;\n-\t}\n-\n-\twritel(dptr, scu->ipc_base + IPC_DPTR);\n-\twritel(sptr, scu->ipc_base + IPC_SPTR);\n-\n-\t/*\n-\t * SRAM controller doesn't support 8-bit writes, it only\n-\t * supports 32-bit writes, so we have to copy input data into\n-\t * the temporary buffer, and SCU FW will use the inlen to\n-\t * determine the actual input data length in the temporary\n-\t * buffer.\n-\t */\n-\tmemcpy(inbuf, in, inlen);\n-\n-\tfor (i = 0; i < inbuflen; i++)\n-\t\tipc_data_writel(scu, inbuf[i], 4 * i);\n-\n-\tipc_command(scu, (inlen << 16) | (sub << 12) | cmd);\n-\terr = intel_scu_ipc_check_status(scu);\n-\tif (!err) {\n-\t\tfor (i = 0; i < outlen; i++)\n-\t\t\t*out++ = ipc_data_readl(scu, 4 * i);\n-\t}\n-\n-\tmutex_unlock(&ipclock);\n-\treturn err;\n-}\n-EXPORT_SYMBOL_GPL(intel_scu_ipc_raw_command);\n-\n /* I2C commands */\n #define IPC_I2C_WRITE 1 /* I2C Write command */\n #define IPC_I2C_READ  2 /* I2C Read command */\n@@ -575,48 +378,143 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)\n \tstruct intel_scu_ipc_dev *scu = &ipcdev;\n \tu32 cmd = 0;\n \n-\tmutex_lock(&ipclock);\n-\tif (scu->dev == NULL) {\n-\t\tmutex_unlock(&ipclock);\n-\t\treturn -ENODEV;\n-\t}\n \tcmd = (addr >> 24) & 0xFF;\n \tif (cmd == IPC_I2C_READ) {\n-\t\twritel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);\n+\t\tregmap_write(scu->i2c_regs, IPC_I2C_CNTRL_ADDR, addr);\n \t\t/* Write not getting updated without delay */\n \t\tmdelay(1);\n-\t\t*data = readl(scu->i2c_base + I2C_DATA_ADDR);\n+\t\tregmap_read(scu->i2c_regs, I2C_DATA_ADDR, data);\n \t} else if (cmd == IPC_I2C_WRITE) {\n-\t\twritel(*data, scu->i2c_base + I2C_DATA_ADDR);\n+\t\tregmap_write(scu->i2c_regs, I2C_DATA_ADDR, *data);\n \t\tmdelay(1);\n-\t\twritel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);\n+\t\tregmap_write(scu->i2c_regs, IPC_I2C_CNTRL_ADDR, addr);\n \t} else {\n \t\tdev_err(scu->dev,\n \t\t\t\"intel_scu_ipc: I2C INVALID_CMD = 0x%x\\n\", cmd);\n \n-\t\tmutex_unlock(&ipclock);\n \t\treturn -EIO;\n \t}\n-\tmutex_unlock(&ipclock);\n \treturn 0;\n }\n EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl);\n \n-/*\n- * Interrupt handler gets called when ioc bit of IPC_COMMAND_REG set to 1\n- * When ioc bit is set to 1, caller api must wait for interrupt handler called\n- * which in turn unlocks the caller api. Currently this is not used\n- *\n- * This is edge triggered so we need take no action to clear anything\n- */\n-static irqreturn_t ioc(int irq, void *dev_id)\n+static int pre_simple_cmd_fn(u32 *cmd_list, u32 cmdlen)\n {\n-\tstruct intel_scu_ipc_dev *scu = dev_id;\n+\tif (!cmd_list || cmdlen != SCU_PARAM_LEN)\n+\t\treturn -EINVAL;\n \n-\tif (scu->irq_mode)\n-\t\tcomplete(&scu->cmd_complete);\n+\tcmd_list[0] |= (cmd_list[1] << IPC_CMD_SUBCMD);\n \n-\treturn IRQ_HANDLED;\n+\treturn 0;\n+}\n+\n+static int pre_cmd_fn(u32 *cmd_list, u32 cmdlen, u32 *in, u32 inlen,\n+\t\tu32 *out, u32 outlen)\n+{\n+\tint ret;\n+\n+\tif (inlen > IPC_WWBUF_SIZE_DWORD || outlen > IPC_RWBUF_SIZE_DWORD)\n+\t\treturn -EINVAL;\n+\n+\tret = pre_simple_cmd_fn(cmd_list, cmdlen);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tcmd_list[0] |= (inlen << IPC_CMD_SIZE);\n+\n+\treturn 0;\n+}\n+\n+static int pre_raw_cmd_fn(u32 *cmd_list, u32 cmdlen, u8 *in, u32 inlen,\n+\t\tu32 *out, u32 outlen, u32 dptr, u32 sptr)\n+{\n+\tint ret;\n+\n+\tif (inlen > IPC_WWBUF_SIZE || outlen > IPC_RWBUF_SIZE_DWORD)\n+\t\treturn -EINVAL;\n+\n+\tret = pre_simple_cmd_fn(cmd_list, cmdlen);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tcmd_list[0] |= (inlen << IPC_CMD_SIZE);\n+\n+\treturn 0;\n+}\n+\n+static int scu_ipc_err_code(int status)\n+{\n+\tif (status & IPC_DEV_SCU_CMD_STATUS_ERR)\n+\t\treturn (status & IPC_DEV_SCU_CMD_STATUS_ERR_MASK);\n+\telse\n+\t\treturn 0;\n+}\n+\n+static int scu_ipc_busy_check(int status)\n+{\n+\treturn status | IPC_DEV_SCU_CMD_STATUS_BUSY;\n+}\n+\n+static u32 scu_ipc_enable_msi(u32 cmd)\n+{\n+\treturn cmd | IPC_DEV_SCU_CMD_MSI;\n+}\n+\n+static struct intel_ipc_dev *intel_scu_ipc_dev_create(\n+\t\tstruct device *dev,\n+\t\tvoid __iomem *base,\n+\t\tint irq)\n+{\n+\tstruct intel_ipc_dev_ops *ops;\n+\tstruct intel_ipc_dev_cfg *cfg;\n+\tstruct regmap *ipc_regs;\n+\tstruct intel_scu_ipc_dev *scu = dev_get_drvdata(dev);\n+\n+\tcfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);\n+\tif (!cfg)\n+\t\treturn ERR_PTR(-ENOMEM);\n+\n+\tops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);\n+\tif (!ops)\n+\t\treturn ERR_PTR(-ENOMEM);\n+\n+        ipc_regs = devm_regmap_init_mmio_clk(dev, NULL, base,\n+\t\t\t&ipc_regmap_config);\n+        if (IS_ERR(ipc_regs)) {\n+                dev_err(dev, \"ipc_regs regmap init failed\\n\");\n+                return ERR_CAST(ipc_regs);;\n+        }\n+\n+\tscu->ipc_regs = ipc_regs;\n+\n+\t/* set IPC dev ops */\n+\tops->to_err_code = scu_ipc_err_code;\n+\tops->busy_check = scu_ipc_busy_check;\n+\tops->enable_msi = scu_ipc_enable_msi;\n+\tops->pre_cmd_fn = pre_cmd_fn;\n+\tops->pre_raw_cmd_fn = pre_raw_cmd_fn;\n+\tops->pre_simple_cmd_fn = pre_simple_cmd_fn;\n+\n+\t/* set cfg options */\n+\tif (scu->irq_mode)\n+\t\tcfg->mode = IPC_DEV_MODE_IRQ;\n+\telse\n+\t\tcfg->mode = IPC_DEV_MODE_POLLING;\n+\n+\tcfg->chan_type = IPC_CHANNEL_IA_SCU;\n+\tcfg->irq = irq;\n+\tcfg->use_msi = true;\n+\tcfg->support_sptr = true;\n+\tcfg->support_dptr = true;\n+\tcfg->cmd_regs = ipc_regs;\n+\tcfg->data_regs = ipc_regs;\n+\tcfg->wrbuf_reg = IPC_DEV_SCU_WRBUF_OFFSET;\n+\tcfg->rbuf_reg = IPC_DEV_SCU_RBUF_OFFSET;\n+\tcfg->sptr_reg = IPC_DEV_SCU_SPTR_OFFSET;\n+\tcfg->dptr_reg = IPC_DEV_SCU_DPTR_OFFSET;\n+\tcfg->status_reg = IPC_DEV_SCU_STATUS_OFFSET;\n+\n+\treturn devm_intel_ipc_dev_create(dev, INTEL_SCU_IPC_DEV, cfg, ops);\n }\n \n /**\n@@ -650,25 +548,34 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n \tif (err)\n \t\treturn err;\n \n-\tinit_completion(&scu->cmd_complete);\n-\n \tscu->ipc_base = pcim_iomap_table(pdev)[0];\n \n-\tscu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len);\n+\tscu->i2c_base = devm_ioremap_nocache(&pdev->dev, pdata->i2c_base,\n+\t\t\tpdata->i2c_len);\n \tif (!scu->i2c_base)\n \t\treturn -ENOMEM;\n \n-\terr = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, \"intel_scu_ipc\",\n-\t\t\t       scu);\n-\tif (err)\n-\t\treturn err;\n+\tpci_set_drvdata(pdev, scu);\n+\n+        scu->i2c_regs = devm_regmap_init_mmio_clk(&pdev->dev, NULL,\n+\t\t\tscu->i2c_base, &i2c_regmap_config);\n+        if (IS_ERR(scu->i2c_regs)) {\n+                dev_err(&pdev->dev, \"i2c_regs regmap init failed\\n\");\n+                return PTR_ERR(scu->i2c_regs);;\n+        }\n+\n+\tscu->ipc_dev = intel_scu_ipc_dev_create(&pdev->dev, scu->ipc_base,\n+\t\t\tpdev->irq);\n+\tif (IS_ERR(scu->ipc_dev)) {\n+\t\tdev_err(&pdev->dev, \"Failed to create SCU IPC device\\n\");\n+\t\treturn PTR_ERR(scu->ipc_dev);\n+\t}\n \n \t/* Assign device at last */\n \tscu->dev = &pdev->dev;\n \n \tintel_scu_devices_create();\n \n-\tpci_set_drvdata(pdev, scu);\n \treturn 0;\n }\n \ndiff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c\nindex 7334c44..a2d87e8 100644\n--- a/drivers/rtc/rtc-mrst.c\n+++ b/drivers/rtc/rtc-mrst.c\n@@ -36,6 +36,7 @@\n #include <linux/module.h>\n #include <linux/init.h>\n #include <linux/sfi.h>\n+#include <linux/platform_data/x86/intel_ipc_dev.h>\n \n #include <asm/intel_scu_ipc.h>\n #include <asm/intel-mid.h>\n@@ -46,6 +47,7 @@ struct mrst_rtc {\n \tstruct device\t\t*dev;\n \tint\t\t\tirq;\n \tstruct resource\t\t*iomem;\n+\tstruct intel_ipc_dev\t*ipc_dev;\n \n \tu8\t\t\tenabled_wake;\n \tu8\t\t\tsuspend_ctrl;\n@@ -110,10 +112,11 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)\n \n static int mrst_set_time(struct device *dev, struct rtc_time *time)\n {\n-\tint ret;\n \tunsigned long flags;\n \tunsigned char mon, day, hrs, min, sec;\n \tunsigned int yrs;\n+\tstruct mrst_rtc\t*mrst = dev_get_drvdata(dev);\n+\tu32 cmds[SCU_PARAM_LEN] = {IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME};\n \n \tyrs = time->tm_year;\n \tmon = time->tm_mon + 1;   /* tm_mon starts at zero */\n@@ -137,8 +140,7 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time)\n \n \tspin_unlock_irqrestore(&rtc_lock, flags);\n \n-\tret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME);\n-\treturn ret;\n+\treturn ipc_dev_simple_cmd(mrst->ipc_dev, cmds, SCU_PARAM_LEN);\n }\n \n static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)\n@@ -210,6 +212,7 @@ static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)\n \tstruct mrst_rtc\t*mrst = dev_get_drvdata(dev);\n \tunsigned char hrs, min, sec;\n \tint ret = 0;\n+\tu32 cmds[SCU_PARAM_LEN] = {IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM};\n \n \tif (!mrst->irq)\n \t\treturn -EIO;\n@@ -229,7 +232,7 @@ static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)\n \n \tspin_unlock_irq(&rtc_lock);\n \n-\tret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM);\n+\tret = ipc_dev_simple_cmd(mrst->ipc_dev, cmds, SCU_PARAM_LEN);\n \tif (ret)\n \t\treturn ret;\n \n@@ -329,6 +332,10 @@ static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,\n \tif (!iomem)\n \t\treturn -ENODEV;\n \n+\tmrst_rtc.ipc_dev = intel_ipc_dev_get(INTEL_SCU_IPC_DEV);\n+\tif (IS_ERR_OR_NULL(mrst_rtc.ipc_dev))\n+\t\treturn PTR_ERR(mrst_rtc.ipc_dev);\n+\n \tiomem = request_mem_region(iomem->start, resource_size(iomem),\n \t\t\t\t   driver_name);\n \tif (!iomem) {\ndiff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c\nindex 72c108a..a73559b 100644\n--- a/drivers/watchdog/intel-mid_wdt.c\n+++ b/drivers/watchdog/intel-mid_wdt.c\n@@ -18,6 +18,7 @@\n #include <linux/platform_device.h>\n #include <linux/watchdog.h>\n #include <linux/platform_data/intel-mid_wdt.h>\n+#include <linux/platform_data/x86/intel_ipc_dev.h>\n \n #include <asm/intel_scu_ipc.h>\n #include <asm/intel-mid.h>\n@@ -29,6 +30,8 @@\n #define MID_WDT_TIMEOUT_MAX\t\t170\n #define MID_WDT_DEFAULT_TIMEOUT\t\t90\n \n+static struct intel_ipc_dev *scu_ipc_dev;\n+\n /* SCU watchdog messages */\n enum {\n \tSCU_WATCHDOG_START = 0,\n@@ -38,7 +41,10 @@ enum {\n \n static inline int wdt_command(int sub, u32 *in, int inlen)\n {\n-\treturn intel_scu_ipc_command(IPC_WATCHDOG, sub, in, inlen, NULL, 0);\n+\tu32 cmds[SCU_PARAM_LEN] = {IPC_WATCHDOG, sub};\n+\n+\treturn ipc_dev_cmd(scu_ipc_dev, cmds, SCU_PARAM_LEN, in,\n+\t\t\tinlen, NULL, 0);\n }\n \n static int wdt_start(struct watchdog_device *wd)\n@@ -129,6 +135,10 @@ static int mid_wdt_probe(struct platform_device *pdev)\n \tif (!wdt_dev)\n \t\treturn -ENOMEM;\n \n+\tscu_ipc_dev = intel_ipc_dev_get(INTEL_SCU_IPC_DEV);\n+\tif (IS_ERR_OR_NULL(scu_ipc_dev))\n+\t\treturn PTR_ERR(scu_ipc_dev);\n+\n \twdt_dev->info = &mid_wdt_info;\n \twdt_dev->ops = &mid_wdt_ops;\n \twdt_dev->min_timeout = MID_WDT_TIMEOUT_MIN;\ndiff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c\nindex 0caab62..9457c7a 100644\n--- a/drivers/watchdog/intel_scu_watchdog.c\n+++ b/drivers/watchdog/intel_scu_watchdog.c\n@@ -49,6 +49,7 @@\n #include <asm/intel_scu_ipc.h>\n #include <asm/apb_timer.h>\n #include <asm/intel-mid.h>\n+#include <linux/platform_data/x86/intel_ipc_dev.h>\n \n #include \"intel_scu_watchdog.h\"\n \n@@ -94,6 +95,8 @@ MODULE_PARM_DESC(force_boot,\n \n static struct intel_scu_watchdog_dev watchdog_device;\n \n+static struct intel_ipc_dev *scu_ipc_dev;\n+\n /* Forces restart, if force_reboot is set */\n static void watchdog_fire(void)\n {\n@@ -128,18 +131,14 @@ static int watchdog_set_ipc(int soft_threshold, int threshold)\n \tu32\t*ipc_wbuf;\n \tu8\t cbuf[16] = { '\\0' };\n \tint\t ipc_ret = 0;\n+\tu32 cmds[SCU_PARAM_LEN] = {IPC_SET_WATCHDOG_TIMER, 0};\n \n \tipc_wbuf = (u32 *)&cbuf;\n \tipc_wbuf[0] = soft_threshold;\n \tipc_wbuf[1] = threshold;\n \n-\tipc_ret = intel_scu_ipc_command(\n-\t\t\tIPC_SET_WATCHDOG_TIMER,\n-\t\t\t0,\n-\t\t\tipc_wbuf,\n-\t\t\t2,\n-\t\t\tNULL,\n-\t\t\t0);\n+\tipc_ret = ipc_dev_cmd(scu_ipc_dev, cmds, SCU_PARAM_LEN, ipc_wbuf,\n+\t\t\t2, NULL, 0);\n \n \tif (ipc_ret != 0)\n \t\tpr_err(\"Error setting SCU watchdog timer: %x\\n\", ipc_ret);\n@@ -460,6 +459,10 @@ static int __init intel_scu_watchdog_init(void)\n \tif (check_timer_margin(timer_margin))\n \t\treturn -EINVAL;\n \n+\tscu_ipc_dev = intel_ipc_dev_get(INTEL_SCU_IPC_DEV);\n+\tif (IS_ERR_OR_NULL(scu_ipc_dev))\n+\t\treturn PTR_ERR(scu_ipc_dev);\n+\n \twatchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);\n \n \tif (watchdog_device.timer_tbl_ptr == NULL) {\n",
    "prefixes": [
        "RFC",
        "v3",
        "7/7"
    ]
}