Commit 332ed4e5 authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by Rafael J. Wysocki

thermal: intel: int340x: Capability to map user space to firmware values

To ensure compatibility between user inputs and firmware requirements,
a conversion mechanism is necessary for certain attributes. For instance,
on some platforms, the DLVR frequency must be translated into a predefined
index before being communicated to the firmware. On Lunar Lake platform:
RFI_FREQ_SELECT and RFI_FREQ:
Index 0 corresponds to a DLVR frequency of 2227.2 MHz
Index 1 corresponds to a DLVR frequency of 2140 MHz

Introduce a feature that enables the conversion of values between user
space inputs and firmware-accepted formats. This feature would also
facilitate the reverse process, converting firmware values back into user
friendly display values.

To support this functionality, a model-specific mapping table will be
utilized. When available, this table will provide the necessary
translations between user space values and firmware values, ensuring
seamless communication and accurate settings.
Signed-off-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Link: https://patch.msgid.link/20240619124600.491168-3-srinivas.pandruvada@linux.intel.comSigned-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 822b2a7c
...@@ -19,6 +19,12 @@ struct mmio_reg { ...@@ -19,6 +19,12 @@ struct mmio_reg {
u16 shift; u16 shift;
}; };
struct mapping_table {
const char *attr_name;
const u32 value;
const char *mapped_str;
};
/* These will represent sysfs attribute names */ /* These will represent sysfs attribute names */
static const char * const fivr_strings[] = { static const char * const fivr_strings[] = {
"vco_ref_code_lo", "vco_ref_code_lo",
...@@ -62,6 +68,59 @@ static const struct mmio_reg dlvr_mmio_regs[] = { ...@@ -62,6 +68,59 @@ static const struct mmio_reg dlvr_mmio_regs[] = {
{ 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */ { 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */
}; };
static int match_mapping_table(const struct mapping_table *table, const char *attr_name,
bool match_int_value, const u32 value, const char *value_str,
char **result_str, u32 *result_int)
{
bool attr_matched = false;
int i = 0;
if (!table)
return -EOPNOTSUPP;
while (table[i].attr_name) {
if (strncmp(table[i].attr_name, attr_name, strlen(attr_name)))
goto match_next;
attr_matched = true;
if (match_int_value) {
if (table[i].value != value)
goto match_next;
*result_str = (char *)table[i].mapped_str;
return 0;
}
if (strncmp(table[i].mapped_str, value_str, strlen(table[i].mapped_str)))
goto match_next;
*result_int = table[i].value;
return 0;
match_next:
i++;
}
/* If attribute name is matched, then the user space value is invalid */
if (attr_matched)
return -EINVAL;
return -EOPNOTSUPP;
}
static int get_mapped_string(const struct mapping_table *table, const char *attr_name,
u32 value, char **result)
{
return match_mapping_table(table, attr_name, true, value, NULL, result, NULL);
}
static int get_mapped_value(const struct mapping_table *table, const char *attr_name,
const char *value, unsigned int *result)
{
return match_mapping_table(table, attr_name, false, 0, value, NULL, result);
}
/* These will represent sysfs attribute names */ /* These will represent sysfs attribute names */
static const char * const dvfs_strings[] = { static const char * const dvfs_strings[] = {
"rfi_restriction_run_busy", "rfi_restriction_run_busy",
...@@ -93,12 +152,14 @@ static ssize_t suffix##_show(struct device *dev,\ ...@@ -93,12 +152,14 @@ static ssize_t suffix##_show(struct device *dev,\
struct device_attribute *attr,\ struct device_attribute *attr,\
char *buf)\ char *buf)\
{\ {\
const struct mapping_table *mapping = NULL;\
struct proc_thermal_device *proc_priv;\ struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\ struct pci_dev *pdev = to_pci_dev(dev);\
const struct mmio_reg *mmio_regs;\ const struct mmio_reg *mmio_regs;\
const char **match_strs;\ const char **match_strs;\
int ret, err;\
u32 reg_val;\ u32 reg_val;\
int ret;\ char *str;\
\ \
proc_priv = pci_get_drvdata(pdev);\ proc_priv = pci_get_drvdata(pdev);\
if (table == 1) {\ if (table == 1) {\
...@@ -116,7 +177,12 @@ static ssize_t suffix##_show(struct device *dev,\ ...@@ -116,7 +177,12 @@ static ssize_t suffix##_show(struct device *dev,\
return ret;\ return ret;\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\ ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
return sprintf(buf, "%u\n", ret);\ err = get_mapped_string(mapping, attr->attr.name, ret, &str);\
if (!err)\
return sprintf(buf, "%s\n", str);\
if (err == -EOPNOTSUPP)\
return sprintf(buf, "%u\n", ret);\
return err;\
} }
#define RFIM_STORE(suffix, table)\ #define RFIM_STORE(suffix, table)\
...@@ -124,6 +190,7 @@ static ssize_t suffix##_store(struct device *dev,\ ...@@ -124,6 +190,7 @@ static ssize_t suffix##_store(struct device *dev,\
struct device_attribute *attr,\ struct device_attribute *attr,\
const char *buf, size_t count)\ const char *buf, size_t count)\
{\ {\
const struct mapping_table *mapping = NULL;\
struct proc_thermal_device *proc_priv;\ struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\ struct pci_dev *pdev = to_pci_dev(dev);\
unsigned int input;\ unsigned int input;\
...@@ -150,9 +217,14 @@ static ssize_t suffix##_store(struct device *dev,\ ...@@ -150,9 +217,14 @@ static ssize_t suffix##_store(struct device *dev,\
return ret;\ return ret;\
if (mmio_regs[ret].read_only)\ if (mmio_regs[ret].read_only)\
return -EPERM;\ return -EPERM;\
err = kstrtouint(buf, 10, &input);\ err = get_mapped_value(mapping, attr->attr.name, buf, &input);\
if (err)\ if (err == -EINVAL)\
return err;\ return err;\
if (err == -EOPNOTSUPP) {\
err = kstrtouint(buf, 10, &input);\
if (err)\
return err;\
} \
mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\ mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\ reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
reg_val &= ~mask;\ reg_val &= ~mask;\
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment