{"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");
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)
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]);
}
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);
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);
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 */
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;
{
struct amd_pmc_dev *pdev = &pmc;
int rc;
- u8 msg;
u32 arg = 1;
/* Reset and Start SMU logging - to monitor the s0i3 stats */
}
}
- 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;
{
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);
.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;
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);
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);
/* 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
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;
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;
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 {
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);