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:
+12
-22
@@ -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
@@ -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[
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user