diff mbox series

[2/3] thermal: intel: int340x: Capability to map user space to firmware values

Message ID 20240619124600.491168-3-srinivas.pandruvada@linux.intel.com
State Accepted
Commit 332ed4e5c4a347f79acc2a45575700cbf22ff9fe
Headers show
Series Lunar Lake DLVR support | expand

Commit Message

Srinivas Pandruvada June 19, 2024, 12:45 p.m. UTC
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: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 .../int340x_thermal/processor_thermal_rfim.c  | 80 ++++++++++++++++++-
 1 file changed, 76 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
index e56db75a94fb..c9c77bca2014 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
@@ -19,6 +19,12 @@  struct mmio_reg {
 	u16 shift;
 };
 
+struct mapping_table {
+	const char *attr_name;
+	const u32 value;
+	const char *mapped_str;
+};
+
 /* These will represent sysfs attribute names */
 static const char * const fivr_strings[] = {
 	"vco_ref_code_lo",
@@ -62,6 +68,59 @@  static const struct mmio_reg dlvr_mmio_regs[] = {
 	{ 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 */
 static const char * const dvfs_strings[] = {
 	"rfi_restriction_run_busy",
@@ -93,12 +152,14 @@  static ssize_t suffix##_show(struct device *dev,\
 			      struct device_attribute *attr,\
 			      char *buf)\
 {\
+	const struct mapping_table *mapping = NULL;\
 	struct proc_thermal_device *proc_priv;\
 	struct pci_dev *pdev = to_pci_dev(dev);\
 	const struct mmio_reg *mmio_regs;\
 	const char **match_strs;\
+	int ret, err;\
 	u32 reg_val;\
-	int ret;\
+	char *str;\
 \
 	proc_priv = pci_get_drvdata(pdev);\
 	if (table == 1) {\
@@ -116,7 +177,12 @@  static ssize_t suffix##_show(struct device *dev,\
 		return ret;\
 	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
 	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)\
@@ -124,6 +190,7 @@  static ssize_t suffix##_store(struct device *dev,\
 			       struct device_attribute *attr,\
 			       const char *buf, size_t count)\
 {\
+	const struct mapping_table *mapping = NULL;\
 	struct proc_thermal_device *proc_priv;\
 	struct pci_dev *pdev = to_pci_dev(dev);\
 	unsigned int input;\
@@ -150,9 +217,14 @@  static ssize_t suffix##_store(struct device *dev,\
 		return ret;\
 	if (mmio_regs[ret].read_only)\
 		return -EPERM;\
-	err = kstrtouint(buf, 10, &input);\
-	if (err)\
+	err = get_mapped_value(mapping, attr->attr.name, buf, &input);\
+	if (err == -EINVAL)\
 		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);\
 	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
 	reg_val &= ~mask;\