aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorTom Jones <thj@FreeBSD.org>2026-04-24 12:47:04 +0000
committerTom Jones <thj@FreeBSD.org>2026-05-01 10:24:50 +0000
commit9c77fb6aaa366cbabc80ee1b834bcfe4df135491 (patch)
tree82c5bc78c90a96c96f1361ddbf5394c06f8dd1f5 /sys/dev
parent9c18d55a768a3e60ecaba1325e9a3e00a25dee26 (diff)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/amdsmu/amdsmu.c18
-rw-r--r--sys/dev/amdsmu/amdsmu.h98
-rw-r--r--sys/dev/amdsmu/amdsmu_reg.h7
3 files changed, 92 insertions, 31 deletions
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c
index 7b97888887c5..5029336af9cb 100644
--- a/sys/dev/amdsmu/amdsmu.c
+++ b/sys/dev/amdsmu/amdsmu.c
@@ -30,11 +30,21 @@ amdsmu_match(device_t dev, const struct amdsmu_product **product_out)
const uint16_t vendorid = pci_get_vendor(dev);
const uint16_t deviceid = pci_get_device(dev);
+ const uint32_t model = CPUID_TO_MODEL(cpu_id);
+
for (size_t i = 0; i < nitems(amdsmu_products); i++) {
const struct amdsmu_product *prod = &amdsmu_products[i];
if (vendorid == prod->amdsmu_vendorid &&
deviceid == prod->amdsmu_deviceid) {
+
+ /*
+ * Some Krackan Point devices have different ip blocks
+ * based on CPU model.
+ */
+ if (prod->model != 0x00 && model != prod->model)
+ continue;
+
if (product_out != NULL)
*product_out = prod;
return (true);
@@ -105,7 +115,7 @@ amdsmu_cmd(device_t dev, enum amdsmu_msg msg, uint32_t arg, uint32_t *ret)
amdsmu_write4(sc, SMU_REG_RESPONSE, SMU_RES_WAIT);
/* Write out command to registers. */
- amdsmu_write4(sc, SMU_REG_MESSAGE, msg);
+ amdsmu_write4(sc, sc->product->amdsmu_msg, msg);
amdsmu_write4(sc, SMU_REG_ARGUMENT, arg);
/* Wait for SMU response and handle it. */
@@ -175,7 +185,7 @@ amdsmu_get_ip_blocks(device_t dev)
sc->ip_blocks_active[i] = active;
if (!active)
continue;
- printf("%s%s", amdsmu_ip_blocks_names[i],
+ printf("%s%s", sc->product->ip_blocks_names[i],
i + 1 < sc->product->ip_block_count ? " " : "\n");
}
@@ -193,10 +203,10 @@ amdsmu_get_ip_blocks(device_t dev)
/* Create the sysctl node itself for the IP block. */
snprintf(sysctl_descr, sizeof sysctl_descr,
"Metrics about the %s AMD IP block",
- amdsmu_ip_blocks_names[i]);
+ sc->product->ip_blocks_names[i]);
sc->ip_block_sysctlnodes[i] = SYSCTL_ADD_NODE(sc->sysctlctx,
SYSCTL_CHILDREN(sc->ip_blocks_sysctlnode), OID_AUTO,
- amdsmu_ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr);
+ sc->product->ip_blocks_names[i], CTLFLAG_RD, NULL, sysctl_descr);
if (sc->ip_block_sysctlnodes[i] == NULL) {
device_printf(dev,
"could not add sysctl node for \"%s\"\n", sysctl_descr);
diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h
index 4286d515ae77..0e7c4df37a43 100644
--- a/sys/dev/amdsmu/amdsmu.h
+++ b/sys/dev/amdsmu/amdsmu.h
@@ -14,7 +14,11 @@
#include <sys/bus.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
-#include <machine/bus.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/cputypes.h>
+#include <machine/specialreg.h>
#include <x86/cputypes.h>
#include <dev/amdsmu/amdsmu_reg.h>
@@ -22,26 +26,7 @@
#define SMU_RES_READ_PERIOD_US 50
#define SMU_RES_READ_MAX 20000
-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_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[] = {
+static const char *amdsmu_ip_blocks_names[] = {
"DISPLAY",
"CPU",
"GFX",
@@ -66,7 +51,69 @@ static const char *const amdsmu_ip_blocks_names[] = {
"VPE",
};
-CTASSERT(nitems(amdsmu_ip_blocks_names) <= 32);
+static const char *amdsmu_ip_blocks_names_v2[] = {
+ "DISPLAY",
+ "CPU",
+ "GFX",
+ "VDD",
+ "VDD_CCX",
+ "ACP",
+ "VCN_0",
+ "VCN_1",
+ "ISP",
+ "NBIO",
+ "DF",
+ "USB3_0",
+ "USB3_1",
+ "LAPIC",
+ "USB3_2",
+ "USB4_RT0",
+ "USB4_RT1",
+ "USB4_0",
+ "USB4_1",
+ "MPM",
+ "JPEG_0",
+ "JPEG_1",
+ "IPU",
+ "UMSCH",
+ "VPE",
+};
+
+#define IP_MAX_BLOCK_NAMES 32
+
+CTASSERT(nitems(amdsmu_ip_blocks_names) <= IP_MAX_BLOCK_NAMES);
+CTASSERT(nitems(amdsmu_ip_blocks_names_v2) <= IP_MAX_BLOCK_NAMES);
+
+static const struct amdsmu_product {
+ uint16_t amdsmu_vendorid;
+ uint16_t amdsmu_deviceid;
+ uint32_t model;
+ int16_t idlemask_reg;
+ size_t ip_block_count;
+ const char **ip_blocks_names;
+ uint32_t amdsmu_msg;
+} amdsmu_products[] = {
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_CEZANNE_ROOT, 0x00,
+ SMU_REG_IDLEMASK_CEZANNE, 12 , amdsmu_ip_blocks_names,
+ SMU_REG_MSG_CEZANNE},
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT, 0x00,
+ SMU_REG_IDLEMASK_PHOENIX, 12 , amdsmu_ip_blocks_names,
+ SMU_REG_MSG_CEZANNE},
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT, 0x00,
+ SMU_REG_IDLEMASK_PHOENIX, 21 , amdsmu_ip_blocks_names,
+ SMU_REG_MSG_CEZANNE},
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x00,
+ SMU_REG_IDLEMASK_KRACKAN, 22, amdsmu_ip_blocks_names,
+ SMU_REG_MSG_KRACKAN },
+ { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x70,
+ SMU_REG_IDLEMASK_KRACKAN, 25, amdsmu_ip_blocks_names_v2,
+ SMU_REG_MSG_KRACKAN },
+ /*
+ * 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.
+ */
+};
struct amdsmu_softc {
const struct amdsmu_product *product;
@@ -88,14 +135,13 @@ struct amdsmu_softc {
uint32_t active_ip_blocks;
struct sysctl_oid *ip_blocks_sysctlnode;
- struct sysctl_oid *ip_block_sysctlnodes[
- nitems(amdsmu_ip_blocks_names)];
- bool ip_blocks_active[
- nitems(amdsmu_ip_blocks_names)];
+ struct sysctl_oid *ip_block_sysctlnodes[IP_MAX_BLOCK_NAMES];
+ bool ip_blocks_active[IP_MAX_BLOCK_NAMES];
bus_space_handle_t metrics_space;
struct amdsmu_metrics metrics;
uint32_t idlemask;
+ uint32_t smu_msg;
};
static inline uint32_t
diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h
index 6afbcf006535..c71082072b60 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_KRACKAN_POINT_ROOT 0x1122
#define PCI_DEVICEID_AMD_CEZANNE_ROOT 0x1630
#define PCI_DEVICEID_AMD_REMBRANDT_ROOT 0x14B5
#define PCI_DEVICEID_AMD_PHOENIX_ROOT 0x14E8
@@ -28,14 +29,18 @@
#define SMU_PHYSBASE_ADDR_HI 0x13B102EC
#define SMU_MEM_SIZE 0x1000
+
#define SMU_REG_SPACE_OFF 0x10000
-#define SMU_REG_MESSAGE 0x538
#define SMU_REG_RESPONSE 0x980
#define SMU_REG_ARGUMENT 0x9BC
#define SMU_REG_IDLEMASK_CEZANNE 0x94
#define SMU_REG_IDLEMASK_PHOENIX 0xD14
+#define SMU_REG_IDLEMASK_KRACKAN 0xF14
+
+#define SMU_REG_MSG_CEZANNE 0x538
+#define SMU_REG_MSG_KRACKAN 0x938
enum amdsmu_res {
SMU_RES_WAIT = 0x00,