git: 69124109c5a0 - main - amdsmu: Cezanne support
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 31 Mar 2026 04:51:26 UTC
The branch main has been updated by obiwac:
URL: https://cgit.FreeBSD.org/src/commit/?id=69124109c5a00bb748cd8d3e9ede7291b34b577c
commit 69124109c5a00bb748cd8d3e9ede7291b34b577c
Author: Aymeric Wibo <obiwac@FreeBSD.org>
AuthorDate: 2026-02-28 15:43:26 +0000
Commit: Aymeric Wibo <obiwac@FreeBSD.org>
CommitDate: 2026-03-31 04:48:59 +0000
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
---
sys/dev/amdsmu/amdsmu.c | 34 ++++++++++++----------------------
sys/dev/amdsmu/amdsmu.h | 19 +++++++++++++++----
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,