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