platform/x86: intel_scu_ipc: Introduce intel_scu_ipc_raw_command()
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Wed, 5 Apr 2017 16:05:28 +0000 (19:05 +0300)
committerDarren Hart (VMware) <dvhart@infradead.org>
Thu, 13 Apr 2017 17:16:04 +0000 (10:16 -0700)
A new call to SCU intel_scu_ipc_raw_command() writes SPTR and DPTR
registers before sending a command.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
arch/x86/include/asm/intel_scu_ipc.h
drivers/platform/x86/intel_scu_ipc.c

index 4fb1d0abef953dbf97cb9e002d3b74d88bc40483..81d3d8776fd948824066f841959f48583a4442fa 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <linux/notifier.h>
 
+#define IPCMSG_INDIRECT_READ   0x02
+#define IPCMSG_INDIRECT_WRITE  0x05
+
 #define IPCMSG_COLD_OFF                0x80    /* Only for Tangier */
 
 #define IPCMSG_WARM_RESET      0xF0
@@ -45,7 +48,10 @@ int intel_scu_ipc_update_register(u16 addr, u8 data, u8 mask);
 /* Issue commands to the SCU with or without data */
 int intel_scu_ipc_simple_command(int cmd, int sub);
 int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
-                                                       u32 *out, int outlen);
+                         u32 *out, int outlen);
+int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
+                             u32 *out, int outlen, u32 dptr, u32 sptr);
+
 /* I2C control api */
 int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);
 
index f9d3eb505a0b9111637b7b72bcf557f387080d09..f7cf981502cdcafee779426547547b79aa565039 100644 (file)
@@ -491,6 +491,69 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen,
 }
 EXPORT_SYMBOL(intel_scu_ipc_command);
 
+#define IPC_SPTR               0x08
+#define IPC_DPTR               0x0C
+
+/**
+ * intel_scu_ipc_raw_command() - 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 dwords.
+ * @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 SCU with input/output data and source/dest pointers.
+ *
+ * Return:     an IPC error code or 0 on success.
+ */
+int intel_scu_ipc_raw_command(int cmd, int sub, u8 *in, int inlen,
+                             u32 *out, int outlen, u32 dptr, u32 sptr)
+{
+       struct intel_scu_ipc_dev *scu = &ipcdev;
+       int inbuflen = DIV_ROUND_UP(inlen, 4);
+       u32 inbuf[4];
+       int i, err;
+
+       /* Up to 16 bytes */
+       if (inbuflen > 4)
+               return -EINVAL;
+
+       mutex_lock(&ipclock);
+       if (scu->dev == NULL) {
+               mutex_unlock(&ipclock);
+               return -ENODEV;
+       }
+
+       writel(dptr, scu->ipc_base + IPC_DPTR);
+       writel(sptr, scu->ipc_base + IPC_SPTR);
+
+       /*
+        * SRAM controller doesn't support 8-bit writes, it only
+        * supports 32-bit writes, so we have to copy input data into
+        * the temporary buffer, and SCU FW will use the inlen to
+        * determine the actual input data length in the temporary
+        * buffer.
+        */
+       memcpy(inbuf, in, inlen);
+
+       for (i = 0; i < inbuflen; i++)
+               ipc_data_writel(scu, inbuf[i], 4 * i);
+
+       ipc_command(scu, (inlen << 16) | (sub << 12) | cmd);
+       err = intel_scu_ipc_check_status(scu);
+       if (!err) {
+               for (i = 0; i < outlen; i++)
+                       *out++ = ipc_data_readl(scu, 4 * i);
+       }
+
+       mutex_unlock(&ipclock);
+       return err;
+}
+EXPORT_SYMBOL_GPL(intel_scu_ipc_raw_command);
+
 /* I2C commands */
 #define IPC_I2C_WRITE 1 /* I2C Write command */
 #define IPC_I2C_READ  2 /* I2C Read command */