Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x86/pci amdzentemp(4): Add support for per CCD temp...
details: https://anonhg.NetBSD.org/src/rev/892aaeea371c
branches: trunk
changeset: 1021586:892aaeea371c
user: nonaka <nonaka%NetBSD.org@localhost>
date: Sun Jun 06 08:45:18 2021 +0000
description:
amdzentemp(4): Add support for per CCD temperature sensor from FreeBSD.
diffstat:
sys/arch/x86/pci/amdzentemp.c | 194 ++++++++++++++++++++++++++++++++++++-----
1 files changed, 169 insertions(+), 25 deletions(-)
diffs (truncated from 321 to 300 lines):
diff -r 477a7c733319 -r 892aaeea371c sys/arch/x86/pci/amdzentemp.c
--- a/sys/arch/x86/pci/amdzentemp.c Sun Jun 06 05:06:44 2021 +0000
+++ b/sys/arch/x86/pci/amdzentemp.c Sun Jun 06 08:45:18 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: amdzentemp.c,v 1.12 2021/06/05 01:38:22 nonaka Exp $ */
+/* $NetBSD: amdzentemp.c,v 1.13 2021/06/06 08:45:18 nonaka Exp $ */
/* $OpenBSD: kate.c,v 1.2 2008/03/27 04:52:03 cnst Exp $ */
/*
@@ -53,7 +53,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.12 2021/06/05 01:38:22 nonaka Exp $ ");
+__KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.13 2021/06/06 08:45:18 nonaka Exp $ ");
#include <sys/param.h>
#include <sys/bus.h>
@@ -76,6 +76,7 @@
#define AMD_CURTMP_RANGE_ADJUST 49000000 /* in microKelvins (ie, 49C) */
#define AMD_CURTMP_RANGE_CHECK __BIT(19)
#define F10_TEMP_CURTMP __BITS(31,21) /* XXX same as amdtemp.c */
+#define F10_TEMP_CURTMP_MASK 0x7ff
#define F15M60_CURTMP_TJSEL __BITS(17,16)
/*
@@ -96,7 +97,17 @@
*/
#define AMD_17H_CUR_TMP 0x59800
+/*
+ * The following register set was discovered experimentally by Ondrej Čerman
+ * and collaborators, but is not (yet) documented in a PPR/OSRR (other than
+ * the M70H PPR SMN memory map showing [0x59800, +0x314] as allocated to
+ * SMU::THM). It seems plausible and the Linux sensor folks have adopted it.
+ */
+#define AMD_17H_CCD_TMP_BASE 0x59954
+#define AMD_17H_CCD_TMP_VALID __BIT(11)
+
struct amdzentemp_softc {
+ device_t sc_dev;
struct sysmon_envsys *sc_sme;
device_t sc_smn;
envsys_data_t *sc_sensor;
@@ -105,15 +116,33 @@
int32_t sc_offset;
};
+enum {
+ NOSENSOR = 0,
+ CORE0_SENSOR0,
+ CCD_BASE,
+ CCD0 = CCD_BASE,
+ CCD1,
+ CCD2,
+ CCD3,
+ CCD4,
+ CCD5,
+ CCD6,
+ CCD7,
+ CCD_MAX,
+ NUM_CCDS = CCD_MAX - CCD_BASE
+};
+
static int amdzentemp_match(device_t, cfdata_t, void *);
static void amdzentemp_attach(device_t, device_t, void *);
static int amdzentemp_detach(device_t, int);
-static void amdzentemp_init(struct amdzentemp_softc *);
-static void amdzentemp_setup_sensors(struct amdzentemp_softc *, int);
+static void amdzentemp_init(struct amdzentemp_softc *, int, int);
+static void amdzentemp_setup_sensors(struct amdzentemp_softc *);
static void amdzentemp_family15_refresh(struct sysmon_envsys *, envsys_data_t *);
static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *);
+static int amdzentemp_probe_ccd_sensors(struct amdzentemp_softc *, int, int);
+static void amdzentemp_setup_ccd_sensors(struct amdzentemp_softc *);
CFATTACH_DECL_NEW(amdzentemp, sizeof(struct amdzentemp_softc),
amdzentemp_match, amdzentemp_attach, amdzentemp_detach, NULL);
@@ -124,9 +153,9 @@
struct pci_attach_args *pa __diagused = aux;
KASSERT(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD);
-
+
cfdata_t parent_cfdata = device_cfdata(parent);
-
+
/* Got AMD family 17h system management network */
return parent_cfdata->cf_name &&
memcmp(parent_cfdata->cf_name, "amdsmn", 6) == 0;
@@ -137,18 +166,20 @@
{
struct amdzentemp_softc *sc = device_private(self);
struct cpu_info *ci = curcpu();
- int family;
+ int family, model;
int error;
size_t i;
+ sc->sc_dev = self;
+
family = CPUID_TO_FAMILY(ci->ci_signature);
+ model = CPUID_TO_MODEL(ci->ci_signature);
aprint_naive("\n");
- aprint_normal(": AMD CPU Temperature Sensors (Family%xh)",
- family);
+ aprint_normal(": AMD CPU Temperature Sensors (Family%xh)", family);
sc->sc_smn = parent;
- amdzentemp_init(sc);
+ amdzentemp_init(sc, family, model);
aprint_normal("\n");
@@ -156,12 +187,14 @@
sc->sc_sensor_len = sizeof(envsys_data_t) * sc->sc_numsensors;
sc->sc_sensor = kmem_zalloc(sc->sc_sensor_len, KM_SLEEP);
- amdzentemp_setup_sensors(sc, device_unit(self));
+ amdzentemp_setup_sensors(sc);
/*
* Set properties in sensors.
*/
for (i = 0; i < sc->sc_numsensors; i++) {
+ if (sc->sc_sensor[i].private == NOSENSOR)
+ continue;
if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i]))
goto bad;
}
@@ -223,10 +256,10 @@
static void
-amdzentemp_init(struct amdzentemp_softc *sc)
+amdzentemp_init(struct amdzentemp_softc *sc, int family, int model)
{
- sc->sc_numsensors = 1;
+ sc->sc_numsensors = 1 + amdzentemp_probe_ccd_sensors(sc, family, model);
sc->sc_offset = 0;
if (strstr(cpu_brand_string, "AMD Ryzen 5 1600X")
@@ -241,24 +274,28 @@
}
static void
-amdzentemp_setup_sensors(struct amdzentemp_softc *sc, int dv_unit)
+amdzentemp_setup_sensors(struct amdzentemp_softc *sc)
{
sc->sc_sensor[0].units = ENVSYS_STEMP;
sc->sc_sensor[0].state = ENVSYS_SVALID;
sc->sc_sensor[0].flags = ENVSYS_FHAS_ENTROPY;
+ sc->sc_sensor[0].private = CORE0_SENSOR0;
snprintf(sc->sc_sensor[0].desc, sizeof(sc->sc_sensor[0].desc),
- "cpu%u temperature", dv_unit);
+ "cpu%u temperature", device_unit(sc->sc_dev));
+
+ if (sc->sc_numsensors > 1)
+ amdzentemp_setup_ccd_sensors(sc);
}
static void
amdzentemp_family15_refresh(struct sysmon_envsys *sme,
- envsys_data_t *edata)
+ envsys_data_t *edata)
{
struct amdzentemp_softc *sc = sme->sme_cookie;
uint32_t val, temp;
int error;
-
+
error = amdsmn_read(sc->sc_smn, AMD_15H_M60H_REPTMP_CTRL, &val);
if (error) {
edata->state = ENVSYS_SINVALID;
@@ -286,26 +323,133 @@
}
static void
-amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
+amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct amdzentemp_softc *sc = sme->sme_cookie;
uint32_t temp;
- int error;
-
- error = amdsmn_read(sc->sc_smn, AMD_17H_CUR_TMP, &temp);
- if (error) {
+ bool minus49;
+ int i, error;
+
+ switch (edata->private) {
+ case CORE0_SENSOR0:
+ /* Tctl */
+ error = amdsmn_read(sc->sc_smn, AMD_17H_CUR_TMP, &temp);
+ if (error) {
+ edata->state = ENVSYS_SINVALID;
+ return;
+ }
+ minus49 = (temp & AMD_CURTMP_RANGE_CHECK) ? true : false;
+ temp = __SHIFTOUT(temp, F10_TEMP_CURTMP);
+ break;
+ case CCD_BASE ... (CCD_MAX - 1):
+ /* Tccd */
+ i = edata->private - CCD_BASE;
+ error = amdsmn_read(sc->sc_smn,
+ AMD_17H_CCD_TMP_BASE + (i * sizeof(temp)), &temp);
+ if (error || !ISSET(temp, AMD_17H_CCD_TMP_VALID)) {
+ edata->state = ENVSYS_SINVALID;
+ return;
+ }
+ minus49 = true;
+ temp &= F10_TEMP_CURTMP_MASK;
+ break;
+ default:
edata->state = ENVSYS_SINVALID;
return;
}
edata->state = ENVSYS_SVALID;
- /* From C to uK. */
- edata->value_cur = ((temp >> 21) * 125000) + 273150000;
+ /* From C to uK. */
+ edata->value_cur = (temp * 125000) + 273150000;
/* adjust for possible offset of 49K */
- if (temp & AMD_CURTMP_RANGE_CHECK)
+ if (minus49)
edata->value_cur -= AMD_CURTMP_RANGE_ADJUST;
edata->value_cur += sc->sc_offset;
}
+static int
+amdzentemp_probe_ccd_sensors17h(struct amdzentemp_softc *sc, int model)
+{
+ int maxreg;
+
+ switch (model) {
+ case 0x00 ... 0x2f: /* Zen1, Zen+ */
+ maxreg = 4;
+ break;
+ case 0x30 ... 0x3f: /* Zen2 TR (Castle Peak)/EPYC (Rome) */
+ case 0x60 ... 0x7f: /* Zen2 Ryzen (Renoir APU, Matisse) */
+ case 0x90 ... 0x9f: /* Zen2 Ryzen (Van Gogh APU) */
+ maxreg = 8;
+ break;
+ default:
+ aprint_error_dev(sc->sc_dev,
+ "Unrecognized Family 17h Model: %02xh\n", model);
+ return 0;
+ }
+
+ return maxreg;
+}
+
+static int
+amdzentemp_probe_ccd_sensors19h(struct amdzentemp_softc *sc, int model)
+{
+ int maxreg;
+
+ switch (model) {
+ case 0x00 ... 0x0f: /* Zen3 EPYC "Milan" */
+ case 0x20 ... 0x2f: /* Zen3 Ryzen "Vermeer" */
+ maxreg = 8;
+ break;
+ default:
+ aprint_error_dev(sc->sc_dev,
+ "Unrecognized Family 19h Model: %02xh\n", model);
+ return 0;
+ }
+
+ return maxreg;
+}
+
+static int
+amdzentemp_probe_ccd_sensors(struct amdzentemp_softc *sc, int family, int model)
+{
+ int nccd;
+
+ switch (family) {
+ case 0x17:
+ nccd = amdzentemp_probe_ccd_sensors17h(sc, model);
+ break;
+ case 0x19:
+ nccd = amdzentemp_probe_ccd_sensors19h(sc, model);
+ break;
+ default:
+ return 0;
+ }
+
+ return nccd;
+}
+
+static void
+amdzentemp_setup_ccd_sensors(struct amdzentemp_softc *sc)
+{
+ envsys_data_t *edata;
+ uint32_t temp;
Home |
Main Index |
Thread Index |
Old Index