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.
This commit is contained in:
martin 2022-10-11 18:16:20 +00:00
parent 9a522ca6be
commit d5badbfc7a
3 changed files with 195 additions and 30 deletions

View File

@ -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 <mrrooster@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

View File

@ -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 <cem@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
@ -87,11 +87,21 @@ static const struct pciid {
.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
.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 *);

View File

@ -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,v 1.9.2.1 2020/04/24 17:46:44 martin Ex
#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,v 1.9.2.1 2020/04/24 17:46:44 martin Ex
*/
#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, 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 +154,9 @@ amdzentemp_match(device_t parent, cfdata_t match, void *aux)
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, device_t self, void *aux)
{
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, device_t self, void *aux)
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, device_t self, void *aux)
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 flags)
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 *sc)
}
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 sysmon_envsys *sme,
}
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