From d27a7e299daaf5d984cd671db99424660895586d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Apr 2017 19:05:28 +0300 Subject: platform/x86: intel_scu_ipc: Introduce intel_scu_ipc_raw_command() A new call to SCU intel_scu_ipc_raw_command() writes SPTR and DPTR registers before sending a command. Signed-off-by: Andy Shevchenko --- drivers/platform/x86/intel_scu_ipc.c | 63 ++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'drivers/platform/x86/intel_scu_ipc.c') diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index f9d3eb505a0b..f7cf981502cd 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -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 */ -- cgit v1.2.3