summaryrefslogtreecommitdiff
path: root/sys-kernel/linux-sources-redcore/files/5.14-k10temp-frugalware.patch
diff options
context:
space:
mode:
Diffstat (limited to 'sys-kernel/linux-sources-redcore/files/5.14-k10temp-frugalware.patch')
-rw-r--r--sys-kernel/linux-sources-redcore/files/5.14-k10temp-frugalware.patch242
1 files changed, 242 insertions, 0 deletions
diff --git a/sys-kernel/linux-sources-redcore/files/5.14-k10temp-frugalware.patch b/sys-kernel/linux-sources-redcore/files/5.14-k10temp-frugalware.patch
new file mode 100644
index 00000000..73c4cd1d
--- /dev/null
+++ b/sys-kernel/linux-sources-redcore/files/5.14-k10temp-frugalware.patch
@@ -0,0 +1,242 @@
+diff -Naur linux-5.12/drivers/hwmon/k10temp.c linux-5.12-p/drivers/hwmon/k10temp.c
+--- linux-5.12/drivers/hwmon/k10temp.c 2021-04-25 22:49:08.000000000 +0200
++++ linux-5.12-p/drivers/hwmon/k10temp.c 2021-04-26 15:49:17.205409281 +0200
+@@ -11,6 +11,13 @@
+ * convert raw register values is from https://github.com/ocerman/zenpower.
+ * The information is not confirmed from chip datasheets, but experiments
+ * suggest that it provides reasonable temperature values.
++ * - Register addresses to read chip voltage and current are also from
++ * https://github.com/ocerman/zenpower, and not confirmed from chip
++ * datasheets. Current calibration is board specific and not typically
++ * shared by board vendors. For this reason, current values are
++ * normalized to report 1A/LSB for core current and and 0.25A/LSB for SoC
++ * current. Reported values can be adjusted using the sensors configuration
++ * file.
+ */
+
+ #include <linux/bitops.h>
+@@ -80,17 +87,34 @@
+ /* F17h thermal registers through SMN */
+ #define F17H_M01H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0xc)
+ #define F17H_M01H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
++
++/* ZEN2 SP3/TR */
+ #define F17H_M31H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
+ #define F17H_M31H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
+
++/* ZEN2 Ryzen Desktop */
++#define F17H_M71H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x10)
++#define F17H_M71H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0xc)
++
++/* Renoir is different */
++#define F17H_RN_SVI 0x0006F000
++#define F17H_RN_SVI_TEL_PLANE0 (F17H_RN_SVI + 0x38)
++#define F17H_RN_SVI_TEL_PLANE1 (F17H_RN_SVI + 0x3C)
++
++/* fixme: figure these */
+ #define F17H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
+ #define F17H_M01H_CFACTOR_ISOC 250000 /* 0.25A / LSB */
+ #define F17H_M31H_CFACTOR_ICORE 1000000 /* 1A / LSB */
+ #define F17H_M31H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
+
+ /* F19h thermal registers through SMN */
+-#define F19H_M01_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
+-#define F19H_M01_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
++/* ZEN3 SP3/TR */
++#define F19H_M01H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
++#define F19H_M01H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
++
++/* ZEN3 Ryzen Desktop */
++#define F19H_M21H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x10)
++#define F19H_M21H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0xc)
+
+ #define F19H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
+ #define F19H_M01H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
+@@ -102,7 +126,10 @@
+ int temp_offset;
+ u32 temp_adjust_mask;
+ u32 show_temp;
++ u32 svi_addr[2];
+ bool is_zen;
++ bool show_current;
++ int cfactor[2];
+ };
+
+ #define TCTL_BIT 0
+@@ -127,6 +154,16 @@
+ { 0x17, "AMD Ryzen Threadripper 29", 27000 }, /* 29{20,50,70,90}[W]X */
+ };
+
++static bool is_threadripper(void)
++{
++ return strstr(boot_cpu_data.x86_model_id, "Threadripper");
++}
++
++static bool is_epyc(void)
++{
++ return strstr(boot_cpu_data.x86_model_id, "EPYC");
++}
++
+ static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval)
+ {
+ pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, regval);
+@@ -191,6 +228,16 @@
+ "Tccd8",
+ };
+
++static const char *k10temp_in_label[] = {
++ "Vcore",
++ "Vsoc",
++};
++
++static const char *k10temp_curr_label[] = {
++ "Icore",
++ "Isoc",
++};
++
+ static int k10temp_read_labels(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+@@ -199,6 +246,50 @@
+ case hwmon_temp:
+ *str = k10temp_temp_label[channel];
+ break;
++ case hwmon_in:
++ *str = k10temp_in_label[channel];
++ break;
++ case hwmon_curr:
++ *str = k10temp_curr_label[channel];
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return 0;
++}
++
++static int k10temp_read_curr(struct device *dev, u32 attr, int channel,
++ long *val)
++{
++ struct k10temp_data *data = dev_get_drvdata(dev);
++ u32 regval;
++
++ switch (attr) {
++ case hwmon_curr_input:
++ amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
++ data->svi_addr[channel], &regval);
++ *val = DIV_ROUND_CLOSEST(data->cfactor[channel] *
++ (regval & 0xff),
++ 1000);
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return 0;
++}
++
++static int k10temp_read_in(struct device *dev, u32 attr, int channel, long *val)
++{
++ struct k10temp_data *data = dev_get_drvdata(dev);
++ u32 regval;
++
++ switch (attr) {
++ case hwmon_in_input:
++ amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
++ data->svi_addr[channel], &regval);
++ regval = (regval >> 16) & 0xff;
++ *val = DIV_ROUND_CLOSEST(155000 - regval * 625, 100);
++ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -257,6 +348,10 @@
+ switch (type) {
+ case hwmon_temp:
+ return k10temp_read_temp(dev, attr, channel, val);
++ case hwmon_in:
++ return k10temp_read_in(dev, attr, channel, val);
++ case hwmon_curr:
++ return k10temp_read_curr(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+@@ -305,6 +400,11 @@
+ return 0;
+ }
+ break;
++ case hwmon_in:
++ case hwmon_curr:
++ if (!data->show_current)
++ return 0;
++ break;
+ default:
+ return 0;
+ }
+@@ -430,16 +530,43 @@
+ data->is_zen = true;
+
+ switch (boot_cpu_data.x86_model) {
++ /* FIXME: those looks wrong too */
+ case 0x1: /* Zen */
+ case 0x8: /* Zen+ */
+ case 0x11: /* Zen APU */
+ case 0x18: /* Zen+ APU */
++ data->show_current = !is_threadripper() && !is_epyc();
++ data->svi_addr[0] = F17H_M01H_SVI_TEL_PLANE0;
++ data->svi_addr[1] = F17H_M01H_SVI_TEL_PLANE1;
++ data->cfactor[0] = F17H_M01H_CFACTOR_ICORE;
++ data->cfactor[1] = F17H_M01H_CFACTOR_ISOC;
+ k10temp_get_ccd_support(pdev, data, 4);
+ break;
+- case 0x31: /* Zen2 Threadripper */
+- case 0x71: /* Zen2 */
++ case 0x31: /* Zen2 SP3/TR */
++ data->show_current = !is_threadripper() && !is_epyc();
++ data->cfactor[0] = F17H_M31H_CFACTOR_ICORE;
++ data->cfactor[1] = F17H_M31H_CFACTOR_ISOC;
++ data->svi_addr[0] = F17H_M31H_SVI_TEL_PLANE0;
++ data->svi_addr[1] = F17H_M31H_SVI_TEL_PLANE1;
+ k10temp_get_ccd_support(pdev, data, 8);
+ break;
++ case 0x60: /* Renoir APUs */
++ data->show_current = true;
++ /* FIXME */
++ data->cfactor[0] = F17H_M31H_CFACTOR_ICORE;
++ data->cfactor[1] = F17H_M31H_CFACTOR_ISOC;
++ data->svi_addr[0] = F17H_RN_SVI_TEL_PLANE0;
++ data->svi_addr[1] = F17H_RN_SVI_TEL_PLANE1;
++ k10temp_get_ccd_support(pdev, data, 4); /* probably not needed */
++ break;
++ case 0x71: /* ZEN2 Ryzen Desktop */
++ data->show_current = true;
++ data->cfactor[0] = F17H_M31H_CFACTOR_ICORE;
++ data->cfactor[1] = F17H_M31H_CFACTOR_ISOC;
++ data->svi_addr[0] = F17H_M71H_SVI_TEL_PLANE0;
++ data->svi_addr[1] = F17H_M71H_SVI_TEL_PLANE1;
++ k10temp_get_ccd_support(pdev, data, 4);
++ break;
+ }
+ } else if (boot_cpu_data.x86 == 0x19) {
+ data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
+@@ -449,9 +576,21 @@
+
+ switch (boot_cpu_data.x86_model) {
+ case 0x0 ... 0x1: /* Zen3 SP3/TR */
+- case 0x21: /* Zen3 Ryzen Desktop */
++ data->show_current = true;
++ data->svi_addr[0] = F19H_M01H_SVI_TEL_PLANE0;
++ data->svi_addr[1] = F19H_M01H_SVI_TEL_PLANE1;
++ data->cfactor[0] = F19H_M01H_CFACTOR_ICORE;
++ data->cfactor[1] = F19H_M01H_CFACTOR_ISOC;
+ k10temp_get_ccd_support(pdev, data, 8);
+ break;
++ case 0x21: /* ZEN3 Ryzen Desktop */
++ data->show_current = true;
++ data->svi_addr[0] = F19H_M21H_SVI_TEL_PLANE0;
++ data->svi_addr[1] = F19H_M21H_SVI_TEL_PLANE1;
++ data->cfactor[0] = F19H_M01H_CFACTOR_ICORE;
++ data->cfactor[1] = F19H_M01H_CFACTOR_ISOC;
++ k10temp_get_ccd_support(pdev, data, 2);
++ break;
+ }
+ } else {
+ data->read_htcreg = read_htcreg_pci;