Commit f6045de1 authored by Sanket Goswami's avatar Sanket Goswami Committed by Hans de Goede

platform/x86: amd-pmc: Export Idlemask values based on the APU

IdleMask is the metric used by the PM firmware to know the status of each
of the Hardware IP blocks monitored by the PM firmware.

Knowing this value is key to get the information of s2idle suspend/resume
status. This value is mapped to PMC scratch registers, retrieve them
accordingly based on the CPU family and the underlying firmware support.
Co-developed-by: default avatarShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: default avatarShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: default avatarSanket Goswami <Sanket.Goswami@amd.com>
Reviewed-by: default avatarMario Limonciello <mario.limonciello@amd.com>
Link: https://lore.kernel.org/r/20210916124002.2529-1-Sanket.Goswami@amd.comReviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 9cfe0202
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#define AMD_PMC_REGISTER_RESPONSE 0x980 #define AMD_PMC_REGISTER_RESPONSE 0x980
#define AMD_PMC_REGISTER_ARGUMENT 0x9BC #define AMD_PMC_REGISTER_ARGUMENT 0x9BC
/* PMC Scratch Registers */
#define AMD_PMC_SCRATCH_REG_CZN 0x94
#define AMD_PMC_SCRATCH_REG_YC 0xD14
/* Base address of SMU for mapping physical address to virtual address */ /* Base address of SMU for mapping physical address to virtual address */
#define AMD_PMC_SMU_INDEX_ADDRESS 0xB8 #define AMD_PMC_SMU_INDEX_ADDRESS 0xB8
#define AMD_PMC_SMU_INDEX_DATA 0xBC #define AMD_PMC_SMU_INDEX_DATA 0xBC
...@@ -110,6 +114,10 @@ struct amd_pmc_dev { ...@@ -110,6 +114,10 @@ struct amd_pmc_dev {
u32 base_addr; u32 base_addr;
u32 cpu_id; u32 cpu_id;
u32 active_ips; u32 active_ips;
/* SMU version information */
u16 major;
u16 minor;
u16 rev;
struct device *dev; struct device *dev;
struct mutex lock; /* generic mutex lock */ struct mutex lock; /* generic mutex lock */
#if IS_ENABLED(CONFIG_DEBUG_FS) #if IS_ENABLED(CONFIG_DEBUG_FS)
...@@ -202,6 +210,66 @@ static int s0ix_stats_show(struct seq_file *s, void *unused) ...@@ -202,6 +210,66 @@ static int s0ix_stats_show(struct seq_file *s, void *unused)
} }
DEFINE_SHOW_ATTRIBUTE(s0ix_stats); DEFINE_SHOW_ATTRIBUTE(s0ix_stats);
static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev)
{
int rc;
u32 val;
rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1);
if (rc)
return rc;
dev->major = (val >> 16) & GENMASK(15, 0);
dev->minor = (val >> 8) & GENMASK(7, 0);
dev->rev = (val >> 0) & GENMASK(7, 0);
dev_dbg(dev->dev, "SMU version is %u.%u.%u\n", dev->major, dev->minor, dev->rev);
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:
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 amd_pmc_idlemask_show(struct seq_file *s, void *unused)
{
struct amd_pmc_dev *dev = s->private;
int rc;
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");
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(amd_pmc_idlemask);
static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev) static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
{ {
debugfs_remove_recursive(dev->dbgfs_dir); debugfs_remove_recursive(dev->dbgfs_dir);
...@@ -214,6 +282,8 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) ...@@ -214,6 +282,8 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
&smu_fw_info_fops); &smu_fw_info_fops);
debugfs_create_file("s0ix_stats", 0644, dev->dbgfs_dir, dev, debugfs_create_file("s0ix_stats", 0644, dev->dbgfs_dir, dev,
&s0ix_stats_fops); &s0ix_stats_fops);
debugfs_create_file("amd_pmc_idlemask", 0644, dev->dbgfs_dir, dev,
&amd_pmc_idlemask_fops);
} }
#else #else
static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev) static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
...@@ -350,6 +420,8 @@ static int __maybe_unused amd_pmc_suspend(struct device *dev) ...@@ -350,6 +420,8 @@ static int __maybe_unused amd_pmc_suspend(struct device *dev)
amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_RESET, 0); amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_RESET, 0);
amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_START, 0); amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_START, 0);
/* Dump the IdleMask before we send hint to SMU */
amd_pmc_idlemask_read(pdev, dev, NULL);
msg = amd_pmc_get_os_hint(pdev); msg = amd_pmc_get_os_hint(pdev);
rc = amd_pmc_send_cmd(pdev, 1, NULL, msg, 0); rc = amd_pmc_send_cmd(pdev, 1, NULL, msg, 0);
if (rc) if (rc)
...@@ -372,6 +444,9 @@ static int __maybe_unused amd_pmc_resume(struct device *dev) ...@@ -372,6 +444,9 @@ static int __maybe_unused amd_pmc_resume(struct device *dev)
if (rc) if (rc)
dev_err(pdev->dev, "resume failed\n"); dev_err(pdev->dev, "resume failed\n");
/* Dump the IdleMask to see the blockers */
amd_pmc_idlemask_read(pdev, dev, NULL);
return 0; return 0;
} }
...@@ -458,6 +533,7 @@ static int amd_pmc_probe(struct platform_device *pdev) ...@@ -458,6 +533,7 @@ static int amd_pmc_probe(struct platform_device *pdev)
if (err) if (err)
dev_err(dev->dev, "SMU debugging info not supported on this platform\n"); dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
amd_pmc_get_smu_version(dev);
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
amd_pmc_dbgfs_register(dev); amd_pmc_dbgfs_register(dev);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment