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
This commit is contained in:
Aymeric Wibo
2026-02-28 16:43:26 +01:00
parent 59cb18f356
commit 69124109c5
3 changed files with 31 additions and 27 deletions
+12 -22
View File
@@ -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");
}
+15 -4
View File
@@ -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[
+4 -1
View File
@@ -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,