From: Shyam Sundar S K Date: Tue, 9 Jun 2026 14:39:51 +0000 (+0530) Subject: platform/x86/amd/pmc: Use per-SoC cpu_info struct for SMU mailbox and IP info X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=c3a2521bcc8e4913a246132f276e5ce1251dd1cd;p=thirdparty%2Fkernel%2Flinux.git platform/x86/amd/pmc: Use per-SoC cpu_info struct for SMU mailbox and IP info Replace the scattered per-field assignments in amd_pmc_get_ip_info() with a single amd_pmc_cpu_info struct capturing all SoC-specific parameters such as SMU offsets, IP block table, and OS hint. Define static const instances per SoC variant and embed them as driver_data in the PCI ID table via PCI_DEVICE_DATA(). Consolidate pci_match_id() into amd_pmc_set_cpu_info(), which assigns driver_data directly to cpu_info, the switch falls through only for 1Ah M20H/M60H variants requiring boot_cpu_data.x86_model detection to distinguish the M70 sub-variant. Add scratch_reg to amd_pmc_cpu_info and populate it for each SoC variant, allowing amd_pmc_idlemask_read() to drop its cpu_id switch in favour of a single cpu_info->scratch_reg lookup. Move dev->cpu_id assignment into amd_pmc_set_cpu_info() so it is valid before the switch statement. Handle SP/SHP directly in the switch since their NULL driver_data bypasses the early return, and remove the duplicate check from probe. Remove amd_pmc_get_os_hint() and use cpu_info->os_hint directly at call sites and rename AMD_CPU_ID_* to PCI_DEVICE_ID_AMD_CPU_ID_* with backward compatibility aliases. Reviewed-by: Mario Limonciello (AMD) Co-developed-by: Sanket Goswami Signed-off-by: Sanket Goswami Signed-off-by: Shyam Sundar S K Link: https://patch.msgid.link/20260609143952.2999707-2-Shyam-sundar.S-k@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c index cae3fcafd4d7b..92e36a6161a95 100644 --- a/drivers/platform/x86/amd/pmc/pmc.c +++ b/drivers/platform/x86/amd/pmc/pmc.c @@ -85,6 +85,89 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = { {"VPE", BIT(21)}, }; +/* CPU info structures for different SoC variants */ +static const struct amd_pmc_cpu_info amd_pco_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MESSAGE, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = 12, + .ips_ptr = soc15_ip_blk, + .os_hint = MSG_OS_HINT_PCO, +}; + +static const struct amd_pmc_cpu_info amd_czn_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MESSAGE, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = 12, + .scratch_reg = AMD_PMC_SCRATCH_REG_CZN, + .ips_ptr = soc15_ip_blk, + .os_hint = MSG_OS_HINT_RN, +}; + +static const struct amd_pmc_cpu_info amd_vg_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MESSAGE, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = 12, + .ips_ptr = soc15_ip_blk, + .os_hint = MSG_OS_HINT_RN, +}; + +static const struct amd_pmc_cpu_info amd_yc_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MESSAGE, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = 12, + .scratch_reg = AMD_PMC_SCRATCH_REG_YC, + .ips_ptr = soc15_ip_blk, + .os_hint = MSG_OS_HINT_RN, +}; + +static const struct amd_pmc_cpu_info amd_ps_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MESSAGE, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = 21, + .scratch_reg = AMD_PMC_SCRATCH_REG_YC, + .ips_ptr = soc15_ip_blk, + .os_hint = MSG_OS_HINT_RN, +}; + +static const struct amd_pmc_cpu_info amd_1ah_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MSG_1AH_20H, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = ARRAY_SIZE(soc15_ip_blk), + .scratch_reg = AMD_PMC_SCRATCH_REG_1AH, + .ips_ptr = soc15_ip_blk, + .os_hint = MSG_OS_HINT_RN, +}; + +static const struct amd_pmc_cpu_info amd_1ah_m70_cpu_info = { + .smu_msg = AMD_PMC_REGISTER_MSG_1AH_20H, + .smu_arg = AMD_PMC_REGISTER_ARGUMENT, + .smu_rsp = AMD_PMC_REGISTER_RESPONSE, + .num_ips = ARRAY_SIZE(soc15_ip_blk_v2), + .scratch_reg = AMD_PMC_SCRATCH_REG_1AH, + .ips_ptr = soc15_ip_blk_v2, + .os_hint = MSG_OS_HINT_RN, +}; + +static const struct pci_device_id pmc_pci_ids[] = { + { PCI_DEVICE_DATA(AMD, CPU_ID_PCO, &amd_pco_cpu_info) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_CZN, &amd_czn_cpu_info) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_VG, &amd_vg_cpu_info) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_YC, &amd_yc_cpu_info) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_CB, &amd_yc_cpu_info) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_PS, &amd_ps_cpu_info) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_SP, NULL) }, + { PCI_DEVICE_DATA(AMD, CPU_ID_SHP, NULL) }, + { PCI_DEVICE_DATA(AMD, 1AH_M20H_ROOT, NULL) }, + { PCI_DEVICE_DATA(AMD, 1AH_M60H_ROOT, NULL) }, + { } +}; + static bool disable_workarounds; module_param(disable_workarounds, bool, 0644); MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs"); @@ -101,35 +184,40 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3 iowrite32(val, dev->regbase + reg_offset); } -static void amd_pmc_get_ip_info(struct amd_pmc_dev *dev) +static int amd_pmc_set_cpu_info(struct amd_pmc_dev *dev, struct pci_dev *rdev) { + const struct pci_device_id *id; + + id = pci_match_id(pmc_pci_ids, rdev); + if (!id) + return -ENODEV; + + dev->cpu_id = rdev->device; + + if (id->driver_data) { + dev->cpu_info = (const struct amd_pmc_cpu_info *)id->driver_data; + return 0; + } + + /* Special case: 1Ah M20H/M60H needs x86_model detection */ switch (dev->cpu_id) { - case AMD_CPU_ID_PCO: - case AMD_CPU_ID_RN: - case AMD_CPU_ID_VG: - case AMD_CPU_ID_YC: - case AMD_CPU_ID_CB: - dev->num_ips = 12; - dev->ips_ptr = soc15_ip_blk; - dev->smu_msg = 0x538; - break; - case AMD_CPU_ID_PS: - dev->num_ips = 21; - dev->ips_ptr = soc15_ip_blk; - dev->smu_msg = 0x538; - break; case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: - if (boot_cpu_data.x86_model == 0x70) { - dev->num_ips = ARRAY_SIZE(soc15_ip_blk_v2); - dev->ips_ptr = soc15_ip_blk_v2; - } else { - dev->num_ips = ARRAY_SIZE(soc15_ip_blk); - dev->ips_ptr = soc15_ip_blk; - } - dev->smu_msg = 0x938; + if (boot_cpu_data.x86_model == 0x70) + dev->cpu_info = &amd_1ah_m70_cpu_info; + else + dev->cpu_info = &amd_1ah_cpu_info; break; + case AMD_CPU_ID_SP: + case AMD_CPU_ID_SHP: + dev_warn_once(dev->dev, "S0i3 is not supported on this hardware\n"); + return -ENODEV; + default: + dev_err(dev->dev, "Unknown CPU ID: 0x%x\n", dev->cpu_id); + return -ENODEV; } + + return 0; } static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) @@ -296,9 +384,9 @@ static int smu_fw_info_show(struct seq_file *s, void *unused) table.timeto_resume_to_os_lastcapture); seq_puts(s, "\n=== Active time (in us) ===\n"); - for (idx = 0 ; idx < dev->num_ips ; idx++) { - if (dev->ips_ptr[idx].bit_mask & dev->active_ips) - seq_printf(s, "%-8s : %lld\n", dev->ips_ptr[idx].name, + for (idx = 0 ; idx < dev->cpu_info->num_ips ; idx++) { + if (dev->cpu_info->ips_ptr[idx].bit_mask & dev->active_ips) + seq_printf(s, "%-8s : %lld\n", dev->cpu_info->ips_ptr[idx].name, table.timecondition_notmet_lastcapture[idx]); } @@ -347,32 +435,22 @@ static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev, u32 val; int rc; - switch (pdev->cpu_id) { - case AMD_CPU_ID_CZN: - /* we haven't yet read SMU version */ + /* we haven't yet read SMU version */ + if (pdev->cpu_id == AMD_CPU_ID_CZN) { if (!pdev->major) { rc = amd_pmc_get_smu_version(pdev); if (rc) return rc; } - if (pdev->major > 56 || (pdev->major >= 55 && pdev->minor >= 37)) - val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_CZN); - else + if (!(pdev->major > 56 || (pdev->major >= 55 && pdev->minor >= 37))) return -EINVAL; - break; - case AMD_CPU_ID_YC: - case AMD_CPU_ID_CB: - case AMD_CPU_ID_PS: - val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_YC); - break; - case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: - case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: - val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_1AH); - break; - default: - return -EINVAL; } + if (!pdev->cpu_info->scratch_reg) + return -EINVAL; + + val = amd_pmc_reg_read(pdev, pdev->cpu_info->scratch_reg); + if (dev) pm_pr_dbg("SMU idlemask s0i3: 0x%x\n", val); @@ -425,9 +503,9 @@ static void amd_pmc_dump_registers(struct amd_pmc_dev *dev) argument = dev->stb_arg.arg; response = dev->stb_arg.resp; } else { - message = dev->smu_msg; - argument = AMD_PMC_REGISTER_ARGUMENT; - response = AMD_PMC_REGISTER_RESPONSE; + message = dev->cpu_info->smu_msg; + argument = dev->cpu_info->smu_arg; + response = dev->cpu_info->smu_rsp; } value = amd_pmc_reg_read(dev, response); @@ -452,9 +530,9 @@ int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool r argument = dev->stb_arg.arg; response = dev->stb_arg.resp; } else { - message = dev->smu_msg; - argument = AMD_PMC_REGISTER_ARGUMENT; - response = AMD_PMC_REGISTER_RESPONSE; + message = dev->cpu_info->smu_msg; + argument = dev->cpu_info->smu_arg; + response = dev->cpu_info->smu_rsp; } /* Wait until we get a valid response */ @@ -512,23 +590,6 @@ int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool r return rc; } -static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) -{ - switch (dev->cpu_id) { - case AMD_CPU_ID_PCO: - return MSG_OS_HINT_PCO; - case AMD_CPU_ID_RN: - case AMD_CPU_ID_VG: - case AMD_CPU_ID_YC: - case AMD_CPU_ID_CB: - case AMD_CPU_ID_PS: - case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: - case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: - return MSG_OS_HINT_RN; - } - return -EINVAL; -} - static int amd_pmc_wa_irq1(struct amd_pmc_dev *pdev) { struct device *d; @@ -602,7 +663,6 @@ static void amd_pmc_s2idle_prepare(void) { struct amd_pmc_dev *pdev = &pmc; int rc; - u8 msg; u32 arg = 1; /* Reset and Start SMU logging - to monitor the s0i3 stats */ @@ -617,8 +677,7 @@ static void amd_pmc_s2idle_prepare(void) } } - msg = amd_pmc_get_os_hint(pdev); - rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, false); + rc = amd_pmc_send_cmd(pdev, arg, NULL, pdev->cpu_info->os_hint, false); if (rc) { dev_err(pdev->dev, "suspend failed: %d\n", rc); return; @@ -659,10 +718,8 @@ static void amd_pmc_s2idle_restore(void) { struct amd_pmc_dev *pdev = &pmc; int rc; - u8 msg; - msg = amd_pmc_get_os_hint(pdev); - rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, false); + rc = amd_pmc_send_cmd(pdev, 0, NULL, pdev->cpu_info->os_hint, false); if (rc) dev_err(pdev->dev, "resume failed: %d\n", rc); @@ -709,22 +766,6 @@ static const struct dev_pm_ops amd_pmc_pm = { .suspend = amd_pmc_suspend_handler, }; -static const struct pci_device_id pmc_pci_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_CB) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_YC) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_CZN) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RN) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SHP) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_VG) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) }, - { } -}; - static int amd_pmc_probe(struct platform_device *pdev) { struct amd_pmc_dev *dev = &pmc; @@ -736,17 +777,14 @@ static int amd_pmc_probe(struct platform_device *pdev) dev->dev = &pdev->dev; rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); - if (!rdev || !pci_match_id(pmc_pci_ids, rdev)) { + if (!rdev) { err = -ENODEV; goto err_pci_dev_put; } - dev->cpu_id = rdev->device; - if (dev->cpu_id == AMD_CPU_ID_SP || dev->cpu_id == AMD_CPU_ID_SHP) { - dev_warn_once(dev->dev, "S0i3 is not supported on this hardware\n"); - err = -ENODEV; + err = amd_pmc_set_cpu_info(dev, rdev); + if (err) goto err_pci_dev_put; - } dev->rdev = rdev; err = amd_smn_read(0, AMD_PMC_BASE_ADDR_LO, &val); @@ -778,9 +816,6 @@ static int amd_pmc_probe(struct platform_device *pdev) if (err) goto err_pci_dev_put; - /* Get num of IP blocks within the SoC */ - amd_pmc_get_ip_info(dev); - platform_set_drvdata(pdev, dev); if (IS_ENABLED(CONFIG_SUSPEND)) { err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops); diff --git a/drivers/platform/x86/amd/pmc/pmc.h b/drivers/platform/x86/amd/pmc/pmc.h index fe3f53eb59558..616faddc70b75 100644 --- a/drivers/platform/x86/amd/pmc/pmc.h +++ b/drivers/platform/x86/amd/pmc/pmc.h @@ -17,6 +17,10 @@ /* SMU communication registers */ #define AMD_PMC_REGISTER_RESPONSE 0x980 #define AMD_PMC_REGISTER_ARGUMENT 0x9BC +#define AMD_PMC_REGISTER_MESSAGE 0x538 + +/* SMU communication registers for 1Ah 20h SoC */ +#define AMD_PMC_REGISTER_MSG_1AH_20H 0x938 /* PMC Scratch Registers */ #define AMD_PMC_SCRATCH_REG_CZN 0x94 @@ -90,6 +94,22 @@ struct stb_arg { u32 resp; }; +struct amd_pmc_bit_map { + const char *name; + u32 bit_mask; +}; + +/* SoC-specific information */ +struct amd_pmc_cpu_info { + u32 smu_msg; + u32 smu_arg; + u32 smu_rsp; + u32 num_ips; + u32 scratch_reg; + const struct amd_pmc_bit_map *ips_ptr; + u8 os_hint; +}; + struct amd_pmc_dev { void __iomem *regbase; void __iomem *smu_virt_addr; @@ -99,9 +119,6 @@ struct amd_pmc_dev { u32 cpu_id; u32 dram_size; u32 active_ips; - const struct amd_pmc_bit_map *ips_ptr; - u32 num_ips; - u32 smu_msg; /* SMU version information */ u8 smu_program; u8 major; @@ -116,11 +133,7 @@ struct amd_pmc_dev { bool disable_8042_wakeup; struct amd_mp2_dev *mp2; struct stb_arg stb_arg; -}; - -struct amd_pmc_bit_map { - const char *name; - u32 bit_mask; + const struct amd_pmc_cpu_info *cpu_info; }; struct smu_metrics { @@ -151,20 +164,29 @@ void amd_pmc_quirks_init(struct amd_pmc_dev *dev); void amd_mp2_stb_init(struct amd_pmc_dev *dev); void amd_mp2_stb_deinit(struct amd_pmc_dev *dev); -/* List of supported CPU ids */ -#define AMD_CPU_ID_RV 0x15D0 -#define AMD_CPU_ID_RN 0x1630 -#define AMD_CPU_ID_PCO AMD_CPU_ID_RV -#define AMD_CPU_ID_CZN AMD_CPU_ID_RN -#define AMD_CPU_ID_VG 0x1645 -#define AMD_CPU_ID_YC 0x14B5 -#define AMD_CPU_ID_CB 0x14D8 -#define AMD_CPU_ID_PS 0x14E8 -#define AMD_CPU_ID_SP 0x14A4 -#define AMD_CPU_ID_SHP 0x153A -#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 -#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 -#define PCI_DEVICE_ID_AMD_MP2_STB 0x172c +/* List of supported CPU/device IDs */ +#define PCI_DEVICE_ID_AMD_CPU_ID_PCO 0x15D0 +#define PCI_DEVICE_ID_AMD_CPU_ID_CZN 0x1630 +#define PCI_DEVICE_ID_AMD_CPU_ID_VG 0x1645 +#define PCI_DEVICE_ID_AMD_CPU_ID_YC 0x14B5 +#define PCI_DEVICE_ID_AMD_CPU_ID_CB 0x14D8 +#define PCI_DEVICE_ID_AMD_CPU_ID_PS 0x14E8 +#define PCI_DEVICE_ID_AMD_CPU_ID_SP 0x14A4 +#define PCI_DEVICE_ID_AMD_CPU_ID_SHP 0x153A + +/* Backward compatibility aliases */ +#define AMD_CPU_ID_PCO PCI_DEVICE_ID_AMD_CPU_ID_PCO +#define AMD_CPU_ID_CZN PCI_DEVICE_ID_AMD_CPU_ID_CZN +#define AMD_CPU_ID_VG PCI_DEVICE_ID_AMD_CPU_ID_VG +#define AMD_CPU_ID_YC PCI_DEVICE_ID_AMD_CPU_ID_YC +#define AMD_CPU_ID_CB PCI_DEVICE_ID_AMD_CPU_ID_CB +#define AMD_CPU_ID_PS PCI_DEVICE_ID_AMD_CPU_ID_PS +#define AMD_CPU_ID_SP PCI_DEVICE_ID_AMD_CPU_ID_SP +#define AMD_CPU_ID_SHP PCI_DEVICE_ID_AMD_CPU_ID_SHP + +#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507 +#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122 +#define PCI_DEVICE_ID_AMD_MP2_STB 0x172c int amd_stb_s2d_init(struct amd_pmc_dev *dev); int amd_stb_read(struct amd_pmc_dev *dev, u32 *buf);