diff options
| author | Aymeric Wibo <obiwac@FreeBSD.org> | 2026-02-28 15:43:26 +0000 |
|---|---|---|
| committer | Aymeric Wibo <obiwac@FreeBSD.org> | 2026-03-31 04:48:59 +0000 |
| commit | 69124109c5a00bb748cd8d3e9ede7291b34b577c (patch) | |
| tree | 39f97c6d62f5f164b7e9459d345510fbd350871a | |
| parent | 59cb18f35617d3a53f7d7e142b4f91ad7951f5e0 (diff) | |
amdsmu: Cezanne support
Add support for Cezanne chips. The only real difference vs
Rembrandt/Phoenix is the idlemask register.
Also simplify getting IP block count by having this straight in struct
amdsmu_product and remove Strix Point from the list for now, as that
doesn't support S0ix and our driver can't handle that.
Reviewed by: mckusick
Approved by: mckusick
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D55594
| -rw-r--r-- | sys/dev/amdsmu/amdsmu.c | 34 | ||||
| -rw-r--r-- | sys/dev/amdsmu/amdsmu.h | 19 | ||||
| -rw-r--r-- | sys/dev/amdsmu/amdsmu_reg.h | 5 |
3 files changed, 31 insertions, 27 deletions
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c index 9a6873b43517..7b97888887c5 100644 --- a/sys/dev/amdsmu/amdsmu.c +++ b/sys/dev/amdsmu/amdsmu.c @@ -58,9 +58,12 @@ amdsmu_identify(driver_t *driver, device_t parent) static int amdsmu_probe(device_t dev) { + struct amdsmu_softc *sc; + if (resource_disabled("amdsmu", 0)) return (ENXIO); - if (!amdsmu_match(device_get_parent(dev), NULL)) + sc = device_get_softc(dev); + if (!amdsmu_match(device_get_parent(dev), &sc->product)) return (ENXIO); device_set_descf(dev, "AMD System Management Unit"); @@ -154,28 +157,11 @@ static int amdsmu_get_ip_blocks(device_t dev) { struct amdsmu_softc *sc = device_get_softc(dev); - const uint16_t deviceid = pci_get_device(dev); int err; struct amdsmu_metrics *m = &sc->metrics; bool active; char sysctl_descr[32]; - /* Get IP block count. */ - switch (deviceid) { - case PCI_DEVICEID_AMD_REMBRANDT_ROOT: - sc->ip_block_count = 12; - break; - case PCI_DEVICEID_AMD_PHOENIX_ROOT: - sc->ip_block_count = 21; - break; - /* TODO How many IP blocks does Strix Point (and the others) have? */ - case PCI_DEVICEID_AMD_STRIX_POINT_ROOT: - default: - sc->ip_block_count = nitems(amdsmu_ip_blocks_names); - } - KASSERT(sc->ip_block_count <= nitems(amdsmu_ip_blocks_names), - ("too many IP blocks for array")); - /* Get and print out IP blocks. */ err = amdsmu_cmd(dev, SMU_MSG_GET_SUP_CONSTRAINTS, 0, &sc->active_ip_blocks); @@ -184,13 +170,13 @@ amdsmu_get_ip_blocks(device_t dev) return (err); } device_printf(dev, "Active IP blocks: "); - for (size_t i = 0; i < sc->ip_block_count; i++) { + for (size_t i = 0; i < sc->product->ip_block_count; i++) { active = (sc->active_ip_blocks & (1 << i)) != 0; sc->ip_blocks_active[i] = active; if (!active) continue; printf("%s%s", amdsmu_ip_blocks_names[i], - i + 1 < sc->ip_block_count ? " " : "\n"); + i + 1 < sc->product->ip_block_count ? " " : "\n"); } /* Create a sysctl node for IP blocks. */ @@ -203,7 +189,7 @@ amdsmu_get_ip_blocks(device_t dev) } /* Create a sysctl node for each IP block. */ - for (size_t i = 0; i < sc->ip_block_count; i++) { + for (size_t i = 0; i < sc->product->ip_block_count; i++) { /* Create the sysctl node itself for the IP block. */ snprintf(sysctl_descr, sizeof sysctl_descr, "Metrics about the %s AMD IP block", @@ -293,7 +279,7 @@ amdsmu_fetch_idlemask(device_t dev) { struct amdsmu_softc *sc = device_get_softc(dev); - sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK); + sc->idlemask = amdsmu_read4(sc, sc->product->idlemask_reg); } static void @@ -301,6 +287,10 @@ amdsmu_suspend(device_t dev, enum power_stype stype) { if (stype != POWER_STYPE_SUSPEND_TO_IDLE) return; + /* + * XXX It seems that Cezanne needs a special workaround here for + * firmware versions < 64.53. See amd_pmc_verify_czn_rtc() in Linux. + */ if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL) != 0) device_printf(dev, "failed to hint to SMU to enter sleep"); } diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h index 857fa21cba4e..4286d515ae77 100644 --- a/sys/dev/amdsmu/amdsmu.h +++ b/sys/dev/amdsmu/amdsmu.h @@ -25,10 +25,20 @@ static const struct amdsmu_product { uint16_t amdsmu_vendorid; uint16_t amdsmu_deviceid; + int16_t idlemask_reg; + size_t ip_block_count; } amdsmu_products[] = { - { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT }, - { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT }, - { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_STRIX_POINT_ROOT }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_CEZANNE_ROOT, + SMU_REG_IDLEMASK_CEZANNE, 12 }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT, + SMU_REG_IDLEMASK_PHOENIX, 12 }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT, + SMU_REG_IDLEMASK_PHOENIX, 21 }, + /* + * XXX Strix Point (PCI_DEVICEID_AMD_STRIX_POINT_ROOT) doesn't support + * S0i3 and thus doesn't have an idlemask. Since our driver doesn't + * yet understand this, don't attach to Strix Point for the time being. + */ }; static const char *const amdsmu_ip_blocks_names[] = { @@ -59,6 +69,8 @@ static const char *const amdsmu_ip_blocks_names[] = { CTASSERT(nitems(amdsmu_ip_blocks_names) <= 32); struct amdsmu_softc { + const struct amdsmu_product *product; + struct sysctl_ctx_list *sysctlctx; struct sysctl_oid *sysctlnode; @@ -76,7 +88,6 @@ struct amdsmu_softc { uint32_t active_ip_blocks; struct sysctl_oid *ip_blocks_sysctlnode; - size_t ip_block_count; struct sysctl_oid *ip_block_sysctlnodes[ nitems(amdsmu_ip_blocks_names)]; bool ip_blocks_active[ diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h index d45fa60941d5..6afbcf006535 100644 --- a/sys/dev/amdsmu/amdsmu_reg.h +++ b/sys/dev/amdsmu/amdsmu_reg.h @@ -16,6 +16,7 @@ * out? Also, there are way more of these. I couldn't find a centralized place * which lists them though. */ +#define PCI_DEVICEID_AMD_CEZANNE_ROOT 0x1630 #define PCI_DEVICEID_AMD_REMBRANDT_ROOT 0x14B5 #define PCI_DEVICEID_AMD_PHOENIX_ROOT 0x14E8 #define PCI_DEVICEID_AMD_STRIX_POINT_ROOT 0x14A4 @@ -32,7 +33,9 @@ #define SMU_REG_MESSAGE 0x538 #define SMU_REG_RESPONSE 0x980 #define SMU_REG_ARGUMENT 0x9BC -#define SMU_REG_IDLEMASK 0xD14 + +#define SMU_REG_IDLEMASK_CEZANNE 0x94 +#define SMU_REG_IDLEMASK_PHOENIX 0xD14 enum amdsmu_res { SMU_RES_WAIT = 0x00, |
