From: Guenter Roeck <linux@roeck-us.net>
To: linux-hwmon@vger.kernel.org
Cc: Clemens Ladisch <clemens@ladisch.de>,
Jean Delvare <jdelvare@suse.com>,
linux-kernel@vger.kernel.org, Guenter Roeck <linux@roeck-us.net>
Subject: [RFT PATCH 4/4] hwmon: (k10temp) Show core and SoC current and voltages on Zen CPUs
Date: Thu, 16 Jan 2020 06:18:00 -0800 [thread overview]
Message-ID: <20200116141800.9828-5-linux@roeck-us.net> (raw)
In-Reply-To: <20200116141800.9828-1-linux@roeck-us.net>
Zen CPUs report core and SoC voltages and currents. Add support for it
to the k10temp driver.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
drivers/hwmon/k10temp.c | 116 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 113 insertions(+), 3 deletions(-)
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 944ba8008bc4..bce862bacbc5 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -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 is also from
+ * https://github.com/ocerman/zenpower, and not confirmed from chip
+ * datasheets. Experiments suggest that reported current and voltage
+ * information is reasonable.
+ * - It is unknown if the mechanism to read CCD1/CCD2 temperature as well as
+ * current and voltage information works on higher-end Ryzen CPUs, or if
+ * additional information is available on those CPUs.
*/
#include <linux/bitops.h>
@@ -70,6 +77,10 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
#define F17H_M70H_CCD1_TEMP 0x00059954
#define F17H_M70H_CCD2_TEMP 0x00059958
+#define F17H_M01H_SVI 0x0005A000
+#define F17H_M01H_SVI_TEL_PLANE0 (F17H_M01H_SVI + 0xc)
+#define F17H_M01H_SVI_TEL_PLANE1 (F17H_M01H_SVI + 0x10)
+
#define CUR_TEMP_SHIFT 21
#define CUR_TEMP_RANGE_SEL_MASK BIT(19)
@@ -82,6 +93,9 @@ struct k10temp_data {
bool show_tdie;
bool show_tccd1;
bool show_tccd2;
+ u32 svi_addr[2];
+ bool show_current;
+ int cfactor[2];
};
struct tctl_offset {
@@ -157,16 +171,76 @@ const char *k10temp_temp_label[] = {
"Tccd2",
};
+const char *k10temp_in_label[] = {
+ "Vcore",
+ "Vsoc",
+};
+
+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)
{
- *str = k10temp_temp_label[channel];
+ switch (type) {
+ 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(struct device *dev, enum hwmon_sensor_types type,
- u32 attr, int channel, long *val)
+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], ®val);
+ *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], ®val);
+ regval = (regval >> 16) & 0xff;
+ *val = 1550 - DIV_ROUND_CLOSEST(625 * regval, 100);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
+ long *val)
{
struct k10temp_data *data = dev_get_drvdata(dev);
u32 regval;
@@ -216,6 +290,21 @@ static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
return 0;
}
+static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ 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;
+ }
+}
+
static umode_t k10temp_is_visible(const void *_data,
enum hwmon_sensor_types type,
u32 attr, int channel)
@@ -290,6 +379,11 @@ static umode_t k10temp_is_visible(const void *_data,
return 0;
}
break;
+ case hwmon_in:
+ case hwmon_curr:
+ if (!data->show_current)
+ return 0;
+ break;
default:
return 0;
}
@@ -338,6 +432,12 @@ static const struct hwmon_channel_info *k10temp_info[] = {
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL),
+ HWMON_CHANNEL_INFO(curr,
+ HWMON_C_INPUT | HWMON_C_LABEL,
+ HWMON_C_INPUT | HWMON_C_LABEL),
NULL
};
@@ -393,8 +493,18 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
case 0x8: /* Zen+ */
case 0x11: /* Zen APU */
case 0x18: /* Zen+ APU */
+ data->show_current = true;
+ data->svi_addr[0] = F17H_M01H_SVI_TEL_PLANE0;
+ data->svi_addr[1] = F17H_M01H_SVI_TEL_PLANE1;
+ data->cfactor[0] = 1039211; /* core */
+ data->cfactor[1] = 360772; /* SoC */
break;
case 0x71: /* Zen2 */
+ data->show_current = true;
+ data->cfactor[0] = 658823; /* core */
+ data->cfactor[1] = 294300; /* SoC */
+ data->svi_addr[0] = F17H_M01H_SVI_TEL_PLANE1;
+ data->svi_addr[1] = F17H_M01H_SVI_TEL_PLANE0;
amd_smn_read(amd_pci_dev_to_node_id(pdev),
F17H_M70H_CCD1_TEMP, ®val);
if (regval & 0xfff)
--
2.17.1
next prev parent reply other threads:[~2020-01-16 14:18 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-16 14:17 [RFT PATCH 0/4] hwmon: k10temp driver improvements Guenter Roeck
2020-01-16 14:17 ` [RFT PATCH 1/4] hwmon: (k10temp) Use bitops Guenter Roeck
2020-01-16 14:17 ` [RFT PATCH 2/4] hmon: (k10temp) Convert to use devm_hwmon_device_register_with_info Guenter Roeck
2020-01-16 14:17 ` [RFT PATCH 3/4] hwmon: (k10temp) Report temperatures per CPU die Guenter Roeck
2020-01-16 14:18 ` Guenter Roeck [this message]
2020-01-16 20:55 ` [RFT PATCH 0/4] hwmon: k10temp driver improvements Darren Salt
2020-01-16 21:11 ` Guenter Roeck
2020-01-16 22:46 ` Bernhard Gebetsberger
2020-01-16 22:52 ` Guenter Roeck
2020-01-17 0:38 ` Ken Moffat
2020-01-17 3:58 ` Guenter Roeck
2020-01-17 4:47 ` Ken Moffat
2020-01-17 14:14 ` Guenter Roeck
2020-01-17 18:58 ` Ken Moffat
2020-01-17 9:46 ` Ondrej Čerman
2020-01-17 18:46 ` Guenter Roeck
2020-01-17 22:48 ` Ondrej Čerman
2020-01-17 9:58 ` Holger Kiehl
2020-01-17 19:15 ` Sebastian Reichel
2020-01-18 8:52 ` Brad Campbell
2020-01-18 17:14 ` Guenter Roeck
2020-01-19 1:59 ` Brad Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200116141800.9828-5-linux@roeck-us.net \
--to=linux@roeck-us.net \
--cc=clemens@ladisch.de \
--cc=jdelvare@suse.com \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).