mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-02-03 09:34:42 +00:00
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 <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
e6749c89b4
commit
4967020685
@ -23,6 +23,9 @@
|
|||||||
#define IPC_ERR_EMSECURITY 6
|
#define IPC_ERR_EMSECURITY 6
|
||||||
#define IPC_ERR_UNSIGNEDKERNEL 7
|
#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)
|
#if IS_ENABLED(CONFIG_INTEL_PMC_IPC)
|
||||||
|
|
||||||
int intel_pmc_ipc_simple_command(int cmd, int sub);
|
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,
|
int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
|
||||||
u32 *out, u32 outlen);
|
u32 *out, u32 outlen);
|
||||||
int intel_pmc_s0ix_counter_read(u64 *data);
|
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
|
#else
|
||||||
|
|
||||||
@ -56,6 +62,21 @@ static inline int intel_pmc_s0ix_counter_read(u64 *data)
|
|||||||
return -EINVAL;
|
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 /*CONFIG_INTEL_PMC_IPC*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -128,6 +128,7 @@ static struct intel_pmc_ipc_dev {
|
|||||||
/* gcr */
|
/* gcr */
|
||||||
resource_size_t gcr_base;
|
resource_size_t gcr_base;
|
||||||
int gcr_size;
|
int gcr_size;
|
||||||
|
void __iomem *gcr_mem_base;
|
||||||
bool has_gcr_regs;
|
bool has_gcr_regs;
|
||||||
|
|
||||||
/* punit */
|
/* punit */
|
||||||
@ -199,6 +200,119 @@ static inline u64 gcr_data_readq(u32 offset)
|
|||||||
return readq(ipcdev.ipc_base + 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)
|
static int intel_pmc_ipc_check_status(void)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
@ -747,6 +861,7 @@ static int ipc_plat_get_res(struct platform_device *pdev)
|
|||||||
ipcdev.ipc_base = addr;
|
ipcdev.ipc_base = addr;
|
||||||
|
|
||||||
ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET;
|
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;
|
ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
|
||||||
dev_info(&pdev->dev, "ipc res: %pR\n", res);
|
dev_info(&pdev->dev, "ipc res: %pR\n", res);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user