diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2017-04-05 19:05:28 +0300 |
---|---|---|
committer | Darren Hart (VMware) <dvhart@infradead.org> | 2017-04-13 20:16:04 +0300 |
commit | d27a7e299daaf5d984cd671db99424660895586d (patch) | |
tree | 4a33f58fa3494d6bc25fd6dd8f195e8d06a1adaf /drivers/platform/x86/intel_scu_ipc.c | |
parent | 74bc77a3db0f68609c4c7641e010fd85e4c77a36 (diff) | |
download | linux-d27a7e299daaf5d984cd671db99424660895586d.tar.xz |
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 <andriy.shevchenko@linux.intel.com>
Diffstat (limited to 'drivers/platform/x86/intel_scu_ipc.c')
-rw-r--r-- | drivers/platform/x86/intel_scu_ipc.c | 63 |
1 files changed, 63 insertions, 0 deletions
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 */ |