diff options
Diffstat (limited to 'drivers/platform/x86/amd/pmc.c')
-rw-r--r-- | drivers/platform/x86/amd/pmc.c | 170 |
1 files changed, 85 insertions, 85 deletions
diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index 2edaae04a691..5a935db80fab 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <asm/amd_nb.h> #include <linux/acpi.h> #include <linux/bitfield.h> #include <linux/bits.h> @@ -37,8 +38,6 @@ #define AMD_PMC_SCRATCH_REG_YC 0xD14 /* STB Registers */ -#define AMD_PMC_STB_INDEX_ADDRESS 0xF8 -#define AMD_PMC_STB_INDEX_DATA 0xFC #define AMD_PMC_STB_PMI_0 0x03E30600 #define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001 #define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002 @@ -56,8 +55,6 @@ #define S2D_TELEMETRY_DRAMBYTES_MAX 0x1000000 /* Base address of SMU for mapping physical address to virtual address */ -#define AMD_PMC_SMU_INDEX_ADDRESS 0xB8 -#define AMD_PMC_SMU_INDEX_DATA 0xBC #define AMD_PMC_MAPPING_SIZE 0x01000 #define AMD_PMC_BASE_ADDR_OFFSET 0x10000 #define AMD_PMC_BASE_ADDR_LO 0x13B102E8 @@ -97,6 +94,7 @@ #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 PMC_MSG_DELAY_MIN_US 50 #define RESPONSE_REGISTER_LOOP_MAX 20000 @@ -268,6 +266,7 @@ static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) dev->msg_port = 0; if (ret) { dev_err(dev->dev, "error: S2D_NUM_SAMPLES not supported : %d\n", ret); + kfree(buf); return ret; } @@ -342,33 +341,6 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev) return 0; } -static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev, - struct seq_file *s) -{ - u32 val; - - switch (pdev->cpu_id) { - case AMD_CPU_ID_CZN: - val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_CZN); - 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; - default: - return -EINVAL; - } - - if (dev) - dev_dbg(pdev->dev, "SMU idlemask s0i3: 0x%x\n", val); - - if (s) - seq_printf(s, "SMU idlemask : 0x%x\n", val); - - return 0; -} - static int get_metrics_table(struct amd_pmc_dev *pdev, struct smu_metrics *table) { if (!pdev->smu_virt_addr) { @@ -403,6 +375,9 @@ static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev) int rc; u32 val; + if (dev->cpu_id == AMD_CPU_ID_PCO) + return -ENODEV; + rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1); if (rc) return rc; @@ -449,12 +424,31 @@ static ssize_t smu_program_show(struct device *d, struct device_attribute *attr, static DEVICE_ATTR_RO(smu_fw_version); static DEVICE_ATTR_RO(smu_program); +static umode_t pmc_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct amd_pmc_dev *pdev = dev_get_drvdata(dev); + + if (pdev->cpu_id == AMD_CPU_ID_PCO) + return 0; + return 0444; +} + static struct attribute *pmc_attrs[] = { &dev_attr_smu_fw_version.attr, &dev_attr_smu_program.attr, NULL, }; -ATTRIBUTE_GROUPS(pmc); + +static struct attribute_group pmc_attr_group = { + .attrs = pmc_attrs, + .is_visible = pmc_attr_is_visible, +}; + +static const struct attribute_group *pmc_groups[] = { + &pmc_attr_group, + NULL, +}; static int smu_fw_info_show(struct seq_file *s, void *unused) { @@ -521,28 +515,47 @@ static int s0ix_stats_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(s0ix_stats); -static int amd_pmc_idlemask_show(struct seq_file *s, void *unused) +static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev, + struct seq_file *s) { - struct amd_pmc_dev *dev = s->private; + u32 val; int rc; - /* we haven't yet read SMU version */ - if (!dev->major) { - rc = amd_pmc_get_smu_version(dev); - if (rc) - return rc; + switch (pdev->cpu_id) { + case AMD_CPU_ID_CZN: + /* we haven't yet read SMU version */ + 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 + 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; + default: + return -EINVAL; } - if (dev->major > 56 || (dev->major >= 55 && dev->minor >= 37)) { - rc = amd_pmc_idlemask_read(dev, NULL, s); - if (rc) - return rc; - } else { - seq_puts(s, "Unsupported SMU version for Idlemask\n"); - } + if (dev) + dev_dbg(pdev->dev, "SMU idlemask s0i3: 0x%x\n", val); + + if (s) + seq_printf(s, "SMU idlemask : 0x%x\n", val); return 0; } + +static int amd_pmc_idlemask_show(struct seq_file *s, void *unused) +{ + return amd_pmc_idlemask_read(s->private, NULL, s); +} DEFINE_SHOW_ATTRIBUTE(amd_pmc_idlemask); static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev) @@ -812,6 +825,14 @@ static void amd_pmc_s2idle_check(void) dev_err(pdev->dev, "error writing to STB: %d\n", rc); } +static int amd_pmc_dump_data(struct amd_pmc_dev *pdev) +{ + if (pdev->cpu_id == AMD_CPU_ID_PCO) + return -ENODEV; + + return amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0); +} + static void amd_pmc_s2idle_restore(void) { struct amd_pmc_dev *pdev = &pmc; @@ -824,7 +845,7 @@ static void amd_pmc_s2idle_restore(void) dev_err(pdev->dev, "resume failed: %d\n", rc); /* Let SMU know that we are looking for stats */ - amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0); + amd_pmc_dump_data(pdev); rc = amd_pmc_write_stb(pdev, AMD_PMC_STB_S2IDLE_RESTORE); if (rc) @@ -840,7 +861,7 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = { .restore = amd_pmc_s2idle_restore, }; -static int __maybe_unused amd_pmc_suspend_handler(struct device *dev) +static int amd_pmc_suspend_handler(struct device *dev) { struct amd_pmc_dev *pdev = dev_get_drvdata(dev); @@ -866,6 +887,7 @@ static const struct pci_device_id pmc_pci_ids[] = { { 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) }, { } }; @@ -902,17 +924,9 @@ static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data) { int err; - err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_ADDRESS, AMD_PMC_STB_PMI_0); + err = amd_smn_write(0, AMD_PMC_STB_PMI_0, data); if (err) { - dev_err(dev->dev, "failed to write addr in stb: 0x%X\n", - AMD_PMC_STB_INDEX_ADDRESS); - return pcibios_err_to_errno(err); - } - - err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_DATA, data); - if (err) { - dev_err(dev->dev, "failed to write data in stb: 0x%X\n", - AMD_PMC_STB_INDEX_DATA); + dev_err(dev->dev, "failed to write data in stb: 0x%X\n", AMD_PMC_STB_PMI_0); return pcibios_err_to_errno(err); } @@ -923,18 +937,10 @@ static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf) { int i, err; - err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_ADDRESS, AMD_PMC_STB_PMI_0); - if (err) { - dev_err(dev->dev, "error writing addr to stb: 0x%X\n", - AMD_PMC_STB_INDEX_ADDRESS); - return pcibios_err_to_errno(err); - } - for (i = 0; i < FIFO_SIZE; i++) { - err = pci_read_config_dword(dev->rdev, AMD_PMC_STB_INDEX_DATA, buf++); + err = amd_smn_read(0, AMD_PMC_STB_PMI_0, buf++); if (err) { - dev_err(dev->dev, "error reading data from stb: 0x%X\n", - AMD_PMC_STB_INDEX_DATA); + dev_err(dev->dev, "error reading data from stb: 0x%X\n", AMD_PMC_STB_PMI_0); return pcibios_err_to_errno(err); } } @@ -960,31 +966,26 @@ static int amd_pmc_probe(struct platform_device *pdev) } dev->cpu_id = rdev->device; - dev->rdev = rdev; - err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_LO); - if (err) { - dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS); - err = pcibios_err_to_errno(err); + + if (dev->cpu_id == AMD_CPU_ID_SP) { + dev_warn_once(dev->dev, "S0i3 is not supported on this hardware\n"); + err = -ENODEV; goto err_pci_dev_put; } - err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val); + dev->rdev = rdev; + err = amd_smn_read(0, AMD_PMC_BASE_ADDR_LO, &val); if (err) { + dev_err(dev->dev, "error reading 0x%x\n", AMD_PMC_BASE_ADDR_LO); err = pcibios_err_to_errno(err); goto err_pci_dev_put; } base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK; - err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_HI); - if (err) { - dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS); - err = pcibios_err_to_errno(err); - goto err_pci_dev_put; - } - - err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val); + err = amd_smn_read(0, AMD_PMC_BASE_ADDR_HI, &val); if (err) { + dev_err(dev->dev, "error reading 0x%x\n", AMD_PMC_BASE_ADDR_HI); err = pcibios_err_to_errno(err); goto err_pci_dev_put; } @@ -1022,7 +1023,7 @@ err_pci_dev_put: return err; } -static int amd_pmc_remove(struct platform_device *pdev) +static void amd_pmc_remove(struct platform_device *pdev) { struct amd_pmc_dev *dev = platform_get_drvdata(pdev); @@ -1031,7 +1032,6 @@ static int amd_pmc_remove(struct platform_device *pdev) amd_pmc_dbgfs_unregister(dev); pci_dev_put(dev->rdev); mutex_destroy(&dev->lock); - return 0; } static const struct acpi_device_id amd_pmc_acpi_ids[] = { @@ -1054,7 +1054,7 @@ static struct platform_driver amd_pmc_driver = { .pm = pm_sleep_ptr(&amd_pmc_pm), }, .probe = amd_pmc_probe, - .remove = amd_pmc_remove, + .remove_new = amd_pmc_remove, }; module_platform_driver(amd_pmc_driver); |