Module Name:    src
Committed By:   martin
Date:           Tue Oct 11 18:16:21 UTC 2022

Modified Files:
        src/share/man/man4/man4.x86 [netbsd-9]: amdsmn.4
        src/sys/arch/x86/pci [netbsd-9]: amdsmn.c amdzentemp.c

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #1539):

        share/man/man4/man4.x86/amdsmn.4: revision 1.5
        sys/arch/x86/pci/amdsmn.c: revision 1.14
        sys/arch/x86/pci/amdzentemp.c: revision 1.12-1.15

amdzentemp(4): Add Zen 3 support.

amdzentemp(4): Add support for per CCD temperature sensor from FreeBSD.

Fix build failure on i386.

amdsmn(4),amdzentemp(4): Add support for 17h/6xh and 19h/6xh.

amdsmn.4: Now support AMD Family 19h processors.


To generate a diff of this commit:
cvs rdiff -u -r1.3.8.1 -r1.3.8.2 src/share/man/man4/man4.x86/amdsmn.4
cvs rdiff -u -r1.5.2.2 -r1.5.2.3 src/sys/arch/x86/pci/amdsmn.c
cvs rdiff -u -r1.9.2.1 -r1.9.2.2 src/sys/arch/x86/pci/amdzentemp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/man4.x86/amdsmn.4
diff -u src/share/man/man4/man4.x86/amdsmn.4:1.3.8.1 src/share/man/man4/man4.x86/amdsmn.4:1.3.8.2
--- src/share/man/man4/man4.x86/amdsmn.4:1.3.8.1	Fri Apr 24 17:46:44 2020
+++ src/share/man/man4/man4.x86/amdsmn.4	Tue Oct 11 18:16:20 2022
@@ -1,4 +1,4 @@
-.\"	$NetBSD: amdsmn.4,v 1.3.8.1 2020/04/24 17:46:44 martin Exp $
+.\"	$NetBSD: amdsmn.4,v 1.3.8.2 2022/10/11 18:16:20 martin Exp $
 .\"
 .\" Copyright (c) 2018 Ian Clark <mrroos...@gmail.com>
 .\" All rights reserved.
@@ -54,7 +54,7 @@
 .\"
 .\" $FreeBSD: head/share/man/man4/amdsmn.4 323184 2017-09-05 15:13:41Z cem $
 .\"
-.Dd April 20, 2020
+.Dd October 2, 2022
 .Dt AMDSMN 4 x86
 .Os
 .Sh NAME
@@ -66,7 +66,8 @@
 The
 .Nm
 driver provides support for resources on the System Management Network bus
-in AMD Family 17h processors and some later AMD Family 15h processors.
+in AMD Family 19h processors, 17h processors and some later
+AMD Family 15h processors.
 .Sh SEE ALSO
 .Xr amdzentemp 4
 .Sh HISTORY

Index: src/sys/arch/x86/pci/amdsmn.c
diff -u src/sys/arch/x86/pci/amdsmn.c:1.5.2.2 src/sys/arch/x86/pci/amdsmn.c:1.5.2.3
--- src/sys/arch/x86/pci/amdsmn.c:1.5.2.2	Wed Jul 27 14:40:08 2022
+++ src/sys/arch/x86/pci/amdsmn.c	Tue Oct 11 18:16:20 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: amdsmn.c,v 1.5.2.2 2022/07/27 14:40:08 martin Exp $	*/
+/*	$NetBSD: amdsmn.c,v 1.5.2.3 2022/10/11 18:16:20 martin Exp $	*/
 
 /*-
  * Copyright (c) 2017, 2019 Conrad Meyer <c...@freebsd.org>
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amdsmn.c,v 1.5.2.2 2022/07/27 14:40:08 martin Exp $ ");
+__KERNEL_RCSID(0, "$NetBSD: amdsmn.c,v 1.5.2.3 2022/10/11 18:16:20 martin Exp $ ");
 
 /*
  * Driver for the AMD Family 15h (model 60+) and 17h CPU
@@ -88,10 +88,20 @@ static const struct pciid {
 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
 	},
 	{
+		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_6X_RC,
+		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
+		.amdsmn_data_reg = F17H_SMN_DATA_REG,
+	},
+	{
 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_7X_RC,
 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
 	},
+	{
+		.amdsmn_deviceid = PCI_PRODUCT_AMD_F19_6X_RC,
+		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
+		.amdsmn_data_reg = F17H_SMN_DATA_REG,
+	},
 };
 
 static int amdsmn_match(device_t, cfdata_t, void *);

Index: src/sys/arch/x86/pci/amdzentemp.c
diff -u src/sys/arch/x86/pci/amdzentemp.c:1.9.2.1 src/sys/arch/x86/pci/amdzentemp.c:1.9.2.2
--- src/sys/arch/x86/pci/amdzentemp.c:1.9.2.1	Fri Apr 24 17:46:44 2020
+++ src/sys/arch/x86/pci/amdzentemp.c	Tue Oct 11 18:16:20 2022
@@ -1,4 +1,4 @@
-/*      $NetBSD: amdzentemp.c,v 1.9.2.1 2020/04/24 17:46:44 martin Exp $ */
+/*      $NetBSD: amdzentemp.c,v 1.9.2.2 2022/10/11 18:16:20 martin 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.9.2.1 2020/04/24 17:46:44 martin Exp $ ");
+__KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.9.2.2 2022/10/11 18:16:20 martin Exp $ ");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -76,6 +76,7 @@ __KERNEL_RCSID(0, "$NetBSD: amdzentemp.c
 #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,13 +97,40 @@ __KERNEL_RCSID(0, "$NetBSD: amdzentemp.c
  */
 #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;
 	size_t sc_sensor_len;
 	size_t sc_numsensors;
 	int32_t sc_offset;
+	uint32_t sc_ccd_tmp_base;
+};
+
+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
 };
 
 
@@ -110,10 +138,12 @@ static int  amdzentemp_match(device_t, c
 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 +154,9 @@ amdzentemp_match(device_t parent, cfdata
 	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 +167,20 @@ amdzentemp_attach(device_t parent, devic
 {
 	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 +188,14 @@ amdzentemp_attach(device_t parent, devic
 	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;
 	}
@@ -177,6 +211,7 @@ amdzentemp_attach(device_t parent, devic
 		sc->sc_sme->sme_refresh = amdzentemp_family15_refresh;
 		break;
 	case 0x17:
+	case 0x19:
 		sc->sc_sme->sme_refresh = amdzentemp_family17_refresh;
 		break;
 	default:
@@ -222,10 +257,10 @@ amdzentemp_detach(device_t self, int fla
 
 
 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")
@@ -240,24 +275,28 @@ amdzentemp_init(struct amdzentemp_softc 
 }
 
 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;
@@ -285,26 +324,141 @@ amdzentemp_family15_refresh(struct sysmo
 }
 
 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,
+		    sc->sc_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;
+	case 0x60 ... 0x6f: /* Zen4 Ryzen "Raphael" */
+		sc->sc_ccd_tmp_base = 0x59b08;
+		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;
+
+	/* Set default CCD temp sensor base address. */
+	sc->sc_ccd_tmp_base = 0x59954;
+
+	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;
+	size_t i;
+	uint32_t temp;
+	int error;
+
+	for (i = 0; i < sc->sc_numsensors - 1; i++) {
+		error = amdsmn_read(sc->sc_smn,
+		    sc->sc_ccd_tmp_base + (i * sizeof(temp)), &temp);
+		if (error || !ISSET(temp, AMD_17H_CCD_TMP_VALID))
+			continue;
+
+		edata = &sc->sc_sensor[1 + i];
+		edata->units = ENVSYS_STEMP;
+		edata->state = ENVSYS_SVALID;
+		edata->flags = ENVSYS_FHAS_ENTROPY;
+		edata->private = CCD_BASE + i;
+		snprintf(edata->desc, sizeof(edata->desc),
+		    "cpu%u ccd%zu temperature", device_unit(sc->sc_dev), i);
+	}
+}
+
 MODULE(MODULE_CLASS_DRIVER, amdzentemp, "sysmon_envsys,amdsmn");
 
 #ifdef _MODULE

Reply via email to