@@ -40,10 +40,16 @@
#define AMD_PMC_STB_INDEX_DATA 0xFC
#define AMD_PMC_STB_PMI_0 0x03E30600
#define AMD_PMC_STB_PREDEF 0xC6000001
+#define AMD_STB_REGISTER_MESSAGE 0xA20
+#define AMD_STB_REGISTER_RESPONSE 0xA80
+#define AMD_STB_REGISTER_ARGUMENT 0xA88
/* STB message port and Parameters */
#define PMC_MSG_PORT_PEP 0
#define PMC_MSG_PORT_STB 1
+#define STB_SPILL_TO_DRAM 0xBE
+#define STB_TELEMETRY_BYTES_MAX 0x100000
+#define STB_TELEMETRY_DRAMBYTES_MAX 0x1000000
/* Base address of SMU for mapping physical address to virtual address */
#define AMD_PMC_SMU_INDEX_ADDRESS 0xB8
@@ -99,6 +105,13 @@ enum amd_pmc_def {
MSG_OS_HINT_RN,
};
+enum stb_arg {
+ FIX_SIZE = 0x01,
+ STB_ADDR_LOW,
+ STB_ADDR_HIGH,
+ STB_SAMPLES,
+};
+
struct amd_pmc_bit_map {
const char *name;
u32 bit_mask;
@@ -123,6 +136,7 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = {
struct amd_pmc_dev {
void __iomem *regbase;
void __iomem *smu_virt_addr;
+ void __iomem *stb_virt_addr;
void __iomem *fch_virt_addr;
u32 base_addr;
u32 cpu_id;
@@ -238,6 +252,61 @@ const struct file_operations amd_pmc_stb_debugfs_fops = {
.release = amd_pmc_stb_debugfs_release,
};
+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, phys_addr_low, phys_addr_hi, size, samples;
+ u64 stb_phys_addr;
+
+ amd_pmc_send_cmd(dev, FIX_SIZE, &size, STB_SPILL_TO_DRAM, 1, PMC_MSG_PORT_STB);
+ if (size != STB_TELEMETRY_BYTES_MAX)
+ return -EIO;
+
+ /* Get STB DRAM address */
+ amd_pmc_send_cmd(dev, STB_ADDR_LOW, &phys_addr_low, STB_SPILL_TO_DRAM, 1, PMC_MSG_PORT_STB);
+ amd_pmc_send_cmd(dev, STB_ADDR_HIGH, &phys_addr_hi, STB_SPILL_TO_DRAM, 1, PMC_MSG_PORT_STB);
+ /* Get the number of samples present in the STB buffer */
+ amd_pmc_send_cmd(dev, STB_SAMPLES, &samples, STB_SPILL_TO_DRAM, 1, PMC_MSG_PORT_STB);
+ stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
+
+ dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, STB_TELEMETRY_DRAMBYTES_MAX);
+ if (!dev->stb_virt_addr)
+ return -ENOMEM;
+
+ buf = kzalloc(STB_TELEMETRY_BYTES_MAX, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy_fromio(buf, dev->stb_virt_addr, STB_TELEMETRY_BYTES_MAX);
+
+ filp->private_data = buf;
+
+ return 0;
+}
+
+static ssize_t amd_pmc_stb_debugfs_read_v2(struct file *filp, char __user *buf, size_t size,
+ loff_t *pos)
+{
+ if (!filp->private_data)
+ return -EINVAL;
+
+ return simple_read_from_buffer(buf, size, pos, filp->private_data,
+ STB_TELEMETRY_BYTES_MAX);
+}
+
+static int amd_pmc_stb_debugfs_release_v2(struct inode *inode, struct file *filp)
+{
+ kfree(filp->private_data);
+ return 0;
+}
+
+const struct file_operations amd_pmc_stb_debugfs_fops_v2 = {
+ .owner = THIS_MODULE,
+ .open = amd_pmc_stb_debugfs_open_v2,
+ .read = amd_pmc_stb_debugfs_read_v2,
+ .release = amd_pmc_stb_debugfs_release_v2,
+};
+
static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev,
struct seq_file *s)
{
@@ -352,9 +421,15 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
debugfs_create_file("amd_pmc_idlemask", 0644, dev->dbgfs_dir, dev,
&amd_pmc_idlemask_fops);
/* Enable STB only when the module_param is set */
- if (enable_stb)
- debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
- &amd_pmc_stb_debugfs_fops);
+ if (enable_stb) {
+ if (dev->cpu_id == AMD_CPU_ID_YC) {
+ debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
+ &amd_pmc_stb_debugfs_fops_v2);
+ } else {
+ debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
+ &amd_pmc_stb_debugfs_fops);
+ }
+ }
}
#else
static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
@@ -393,17 +468,27 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
return 0;
}
-static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
+static void amd_pmc_dump_registers(struct amd_pmc_dev *dev, u8 msg_port_stb)
{
- u32 value;
+ u32 value, message, argument, response;
+
+ if (msg_port_stb) {
+ message = AMD_STB_REGISTER_MESSAGE;
+ argument = AMD_STB_REGISTER_ARGUMENT;
+ response = AMD_STB_REGISTER_RESPONSE;
+ } else {
+ message = AMD_PMC_REGISTER_MESSAGE;
+ argument = AMD_PMC_REGISTER_ARGUMENT;
+ response = AMD_PMC_REGISTER_RESPONSE;
+ }
- value = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_RESPONSE);
+ value = amd_pmc_reg_read(dev, response);
dev_dbg(dev->dev, "AMD_PMC_REGISTER_RESPONSE:%x\n", value);
- value = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
+ value = amd_pmc_reg_read(dev, argument);
dev_dbg(dev->dev, "AMD_PMC_REGISTER_ARGUMENT:%x\n", value);
- value = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_MESSAGE);
+ value = amd_pmc_reg_read(dev, message);
dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value);
}
@@ -411,11 +496,22 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg,
u8 msg_port_stb)
{
int rc;
- u32 val;
+ u32 val, message, argument, response;
mutex_lock(&dev->lock);
+
+ if (msg_port_stb) {
+ message = AMD_STB_REGISTER_MESSAGE;
+ argument = AMD_STB_REGISTER_ARGUMENT;
+ response = AMD_STB_REGISTER_RESPONSE;
+ } else {
+ message = AMD_PMC_REGISTER_MESSAGE;
+ argument = AMD_PMC_REGISTER_ARGUMENT;
+ response = AMD_PMC_REGISTER_RESPONSE;
+ }
+
/* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
+ rc = readx_poll_timeout(ioread32, dev->regbase + response,
val, val != 0, PMC_MSG_DELAY_MIN_US,
PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
if (rc) {
@@ -424,16 +520,16 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg,
}
/* Write zero to response register */
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_RESPONSE, 0);
+ amd_pmc_reg_write(dev, response, 0);
/* Write argument into response register */
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, arg);
+ amd_pmc_reg_write(dev, argument, arg);
/* Write message ID to message ID register */
- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
+ amd_pmc_reg_write(dev, message, msg);
/* Wait until we get a valid response */
- rc = readx_poll_timeout(ioread32, dev->regbase + AMD_PMC_REGISTER_RESPONSE,
+ rc = readx_poll_timeout(ioread32, dev->regbase + response,
val, val != 0, PMC_MSG_DELAY_MIN_US,
PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
if (rc) {
@@ -446,7 +542,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg,
if (ret) {
/* PMFW may take longer time to return back the data */
usleep_range(DELAY_MIN_US, 10 * DELAY_MAX_US);
- *data = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
+ *data = amd_pmc_reg_read(dev, argument);
}
break;
case AMD_PMC_RESULT_CMD_REJECT_BUSY:
@@ -467,7 +563,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg,
out_unlock:
mutex_unlock(&dev->lock);
- amd_pmc_dump_registers(dev);
+ amd_pmc_dump_registers(dev, msg_port_stb);
return rc;
}