diff options
Diffstat (limited to 'drivers/platform/x86/amd/pmc.c')
-rw-r--r-- | drivers/platform/x86/amd/pmc.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index 3cbb01ec10e3..ab05b9ee6655 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -43,6 +43,7 @@ #define AMD_PMC_STB_S2IDLE_PREPARE 0xC6000001 #define AMD_PMC_STB_S2IDLE_RESTORE 0xC6000002 #define AMD_PMC_STB_S2IDLE_CHECK 0xC6000003 +#define AMD_PMC_STB_DUMMY_PC 0xC6000007 /* STB S2D(Spill to DRAM) has different message port offset */ #define STB_SPILL_TO_DRAM 0xBE @@ -104,6 +105,7 @@ #define DELAY_MIN_US 2000 #define DELAY_MAX_US 3000 #define FIFO_SIZE 4096 + enum amd_pmc_def { MSG_TEST = 0x01, MSG_OS_HINT_PCO, @@ -114,6 +116,7 @@ enum s2d_arg { S2D_TELEMETRY_SIZE = 0x01, S2D_PHYS_ADDR_LOW, S2D_PHYS_ADDR_HIGH, + S2D_NUM_SAMPLES, }; struct amd_pmc_bit_map { @@ -246,13 +249,40 @@ static const struct file_operations amd_pmc_stb_debugfs_fops = { static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct file *filp) { struct amd_pmc_dev *dev = filp->f_inode->i_private; - u32 *buf; + u32 *buf, fsize, num_samples, stb_rdptr_offset = 0; + int ret; + + /* Write dummy postcode while reading the STB buffer */ + ret = amd_pmc_write_stb(dev, AMD_PMC_STB_DUMMY_PC); + if (ret) + dev_err(dev->dev, "error writing to STB: %d\n", ret); buf = kzalloc(S2D_TELEMETRY_BYTES_MAX, GFP_KERNEL); if (!buf) return -ENOMEM; - memcpy_fromio(buf, dev->stb_virt_addr, S2D_TELEMETRY_BYTES_MAX); + /* Spill to DRAM num_samples uses separate SMU message port */ + dev->msg_port = 1; + + /* Get the num_samples to calculate the last push location */ + ret = amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &num_samples, STB_SPILL_TO_DRAM, 1); + /* Clear msg_port for other SMU operation */ + dev->msg_port = 0; + if (ret) { + dev_err(dev->dev, "error: S2D_NUM_SAMPLES not supported : %d\n", ret); + return ret; + } + + /* Start capturing data from the last push location */ + if (num_samples > S2D_TELEMETRY_BYTES_MAX) { + fsize = S2D_TELEMETRY_BYTES_MAX; + stb_rdptr_offset = num_samples - fsize; + } else { + fsize = num_samples; + stb_rdptr_offset = 0; + } + + memcpy_fromio(buf, dev->stb_virt_addr + stb_rdptr_offset, fsize); filp->private_data = buf; return 0; @@ -560,13 +590,13 @@ static void amd_pmc_dump_registers(struct amd_pmc_dev *dev) } value = amd_pmc_reg_read(dev, response); - dev_dbg(dev->dev, "AMD_PMC_REGISTER_RESPONSE:%x\n", value); + dev_dbg(dev->dev, "AMD_%s_REGISTER_RESPONSE:%x\n", dev->msg_port ? "S2D" : "PMC", value); value = amd_pmc_reg_read(dev, argument); - dev_dbg(dev->dev, "AMD_PMC_REGISTER_ARGUMENT:%x\n", value); + dev_dbg(dev->dev, "AMD_%s_REGISTER_ARGUMENT:%x\n", dev->msg_port ? "S2D" : "PMC", value); value = amd_pmc_reg_read(dev, message); - dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value); + dev_dbg(dev->dev, "AMD_%s_REGISTER_MESSAGE:%x\n", dev->msg_port ? "S2D" : "PMC", value); } static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret) |