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 --- arch/x86/include/asm/intel_scu_ipc.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_scu_ipc.h b/arch/x86/include/asm/intel_scu_ipc.h index 4fb1d0abef95..81d3d8776fd9 100644 --- a/arch/x86/include/asm/intel_scu_ipc.h +++ b/arch/x86/include/asm/intel_scu_ipc.h @@ -3,6 +3,9 @@ #include +#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); -- cgit v1.2.3 From 496702068597ff29092e724301f77b91864454b3 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 9 Apr 2017 15:00:17 -0700 Subject: platform/x86: intel_pmc_ipc: Add pmc gcr read/write/update api's This patch adds API's to read/write/update PMC GC registers. PMC dependent devices like iTCO_wdt, Telemetry has requirement to acces GCR registers. These API's can be used for this purpose. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Andy Shevchenko --- arch/x86/include/asm/intel_pmc_ipc.h | 21 +++++++ drivers/platform/x86/intel_pmc_ipc.c | 115 +++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_pmc_ipc.h b/arch/x86/include/asm/intel_pmc_ipc.h index 4291b6a5ddf7..8402efef10ad 100644 --- a/arch/x86/include/asm/intel_pmc_ipc.h +++ b/arch/x86/include/asm/intel_pmc_ipc.h @@ -23,6 +23,9 @@ #define IPC_ERR_EMSECURITY 6 #define IPC_ERR_UNSIGNEDKERNEL 7 +/* GCR reg offsets from gcr base*/ +#define PMC_GCR_PMC_CFG_REG 0x08 + #if IS_ENABLED(CONFIG_INTEL_PMC_IPC) int intel_pmc_ipc_simple_command(int cmd, int sub); @@ -31,6 +34,9 @@ int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, 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); +int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val); #else @@ -56,6 +62,21 @@ static inline int intel_pmc_s0ix_counter_read(u64 *data) return -EINVAL; } +static inline int intel_pmc_gcr_read(u32 offset, u32 *data) +{ + return -EINVAL; +} + +static inline int intel_pmc_gcr_write(u32 offset, u32 data) +{ + return -EINVAL; +} + +static inline int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) +{ + return -EINVAL; +} + #endif /*CONFIG_INTEL_PMC_IPC*/ #endif diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index 0a3359240227..a0c773b3910e 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -128,6 +128,7 @@ static struct intel_pmc_ipc_dev { /* gcr */ resource_size_t gcr_base; int gcr_size; + void __iomem *gcr_mem_base; bool has_gcr_regs; /* punit */ @@ -199,6 +200,119 @@ static inline u64 gcr_data_readq(u32 offset) return readq(ipcdev.ipc_base + offset); } +static inline int is_gcr_valid(u32 offset) +{ + if (!ipcdev.has_gcr_regs) + return -EACCES; + + if (offset > PLAT_RESOURCE_GCR_SIZE) + return -EINVAL; + + return 0; +} + +/** + * intel_pmc_gcr_read() - Read PMC GCR register + * @offset: offset of GCR register from GCR address base + * @data: data pointer for storing the register output + * + * Reads the PMC GCR register of given offset. + * + * Return: negative value on error or 0 on success. + */ +int intel_pmc_gcr_read(u32 offset, u32 *data) +{ + int ret; + + mutex_lock(&ipclock); + + ret = is_gcr_valid(offset); + if (ret < 0) { + mutex_unlock(&ipclock); + return ret; + } + + *data = readl(ipcdev.gcr_mem_base + offset); + + mutex_unlock(&ipclock); + + return 0; +} +EXPORT_SYMBOL_GPL(intel_pmc_gcr_read); + +/** + * intel_pmc_gcr_write() - Write PMC GCR register + * @offset: offset of GCR register from GCR address base + * @data: register update value + * + * Writes the PMC GCR register of given offset with given + * value. + * + * Return: negative value on error or 0 on success. + */ +int intel_pmc_gcr_write(u32 offset, u32 data) +{ + int ret; + + mutex_lock(&ipclock); + + ret = is_gcr_valid(offset); + if (ret < 0) { + mutex_unlock(&ipclock); + return ret; + } + + writel(data, ipcdev.gcr_mem_base + offset); + + mutex_unlock(&ipclock); + + return 0; +} +EXPORT_SYMBOL_GPL(intel_pmc_gcr_write); + +/** + * intel_pmc_gcr_update() - Update PMC GCR register bits + * @offset: offset of GCR register from GCR address base + * @mask: bit mask for update operation + * @val: update value + * + * Updates the bits of given GCR register as specified by + * @mask and @val. + * + * Return: negative value on error or 0 on success. + */ +int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) +{ + u32 new_val; + int ret = 0; + + mutex_lock(&ipclock); + + ret = is_gcr_valid(offset); + if (ret < 0) + goto gcr_ipc_unlock; + + new_val = readl(ipcdev.gcr_mem_base + offset); + + new_val &= ~mask; + new_val |= val & mask; + + writel(new_val, ipcdev.gcr_mem_base + offset); + + new_val = readl(ipcdev.gcr_mem_base + offset); + + /* check whether the bit update is successful */ + if ((new_val & mask) != (val & mask)) { + ret = -EIO; + goto gcr_ipc_unlock; + } + +gcr_ipc_unlock: + mutex_unlock(&ipclock); + return ret; +} +EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); + static int intel_pmc_ipc_check_status(void) { int status; @@ -747,6 +861,7 @@ static int ipc_plat_get_res(struct platform_device *pdev) ipcdev.ipc_base = addr; ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET; + ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE; dev_info(&pdev->dev, "ipc res: %pR\n", res); -- cgit v1.2.3 From 62a7b9c859d09af860c71cfbea4381061975ca72 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Sun, 9 Apr 2017 15:00:21 -0700 Subject: platform/x86: intel_pmc_ipc: use gcr mem base for S0ix counter read To maintain the uniformity in accessing GCR registers, this patch modifies the S0ix counter read function to use GCR address base instead of ipc address base. Signed-off-by: Kuppuswamy Sathyanarayanan Reviewed-by: Rajneesh Bhardwaj Tested-by: Shanth Murthy Signed-off-by: Andy Shevchenko --- arch/x86/include/asm/intel_pmc_ipc.h | 2 ++ drivers/platform/x86/intel_pmc_ipc.c | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/intel_pmc_ipc.h b/arch/x86/include/asm/intel_pmc_ipc.h index 8402efef10ad..fac89eb78a6b 100644 --- a/arch/x86/include/asm/intel_pmc_ipc.h +++ b/arch/x86/include/asm/intel_pmc_ipc.h @@ -25,6 +25,8 @@ /* GCR reg offsets from gcr base*/ #define PMC_GCR_PMC_CFG_REG 0x08 +#define PMC_GCR_TELEM_DEEP_S0IX_REG 0x78 +#define PMC_GCR_TELEM_SHLW_S0IX_REG 0x80 #if IS_ENABLED(CONFIG_INTEL_PMC_IPC) diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index 0a39b0f17bbe..e4d4dfe3e1d1 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -57,10 +57,6 @@ #define IPC_WRITE_BUFFER 0x80 #define IPC_READ_BUFFER 0x90 -/* PMC Global Control Registers */ -#define GCR_TELEM_DEEP_S0IX_OFFSET 0x1078 -#define GCR_TELEM_SHLW_S0IX_OFFSET 0x1080 - /* Residency with clock rate at 19.2MHz to usecs */ #define S0IX_RESIDENCY_IN_USECS(d, s) \ ({ \ @@ -202,7 +198,7 @@ static inline u32 ipc_data_readl(u32 offset) static inline u64 gcr_data_readq(u32 offset) { - return readq(ipcdev.ipc_base + offset); + return readq(ipcdev.gcr_mem_base + offset); } static inline int is_gcr_valid(u32 offset) @@ -902,8 +898,8 @@ int intel_pmc_s0ix_counter_read(u64 *data) if (!ipcdev.has_gcr_regs) return -EACCES; - deep = gcr_data_readq(GCR_TELEM_DEEP_S0IX_OFFSET); - shlw = gcr_data_readq(GCR_TELEM_SHLW_S0IX_OFFSET); + deep = gcr_data_readq(PMC_GCR_TELEM_DEEP_S0IX_REG); + shlw = gcr_data_readq(PMC_GCR_TELEM_SHLW_S0IX_REG); *data = S0IX_RESIDENCY_IN_USECS(deep, shlw); -- cgit v1.2.3