#define AMD_PMC_STB_PMI_0              0x03E30600
 #define AMD_PMC_STB_PREDEF             0xC6000001
 
+/* STB S2D(Spill to DRAM) has different message port offset */
+#define STB_SPILL_TO_DRAM              0xBE
+#define AMD_S2D_REGISTER_MESSAGE       0xA20
+#define AMD_S2D_REGISTER_RESPONSE      0xA80
+#define AMD_S2D_REGISTER_ARGUMENT      0xA88
+
+/* STB Spill to DRAM Parameters */
+#define S2D_TELEMETRY_BYTES_MAX                0x100000
+#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
        MSG_OS_HINT_RN,
 };
 
+enum s2d_arg {
+       S2D_TELEMETRY_SIZE = 0x01,
+       S2D_PHYS_ADDR_LOW,
+       S2D_PHYS_ADDR_HIGH,
+};
+
 struct amd_pmc_bit_map {
        const char *name;
        u32 bit_mask;
 struct amd_pmc_dev {
        void __iomem *regbase;
        void __iomem *smu_virt_addr;
+       void __iomem *stb_virt_addr;
        void __iomem *fch_virt_addr;
+       bool msg_port;
        u32 base_addr;
        u32 cpu_id;
        u32 active_ips;
        .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;
+
+       buf = kzalloc(S2D_TELEMETRY_BYTES_MAX, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       memcpy_fromio(buf, dev->stb_virt_addr, S2D_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,
+                                       S2D_TELEMETRY_BYTES_MAX);
+}
+
+static int amd_pmc_stb_debugfs_release_v2(struct inode *inode, struct file *filp)
+{
+       kfree(filp->private_data);
+       return 0;
+}
+
+static 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)
 {
        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)
 
 static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
 {
-       u32 value;
+       u32 value, message, argument, response;
+
+       if (dev->msg_port) {
+               message = AMD_S2D_REGISTER_MESSAGE;
+               argument = AMD_S2D_REGISTER_ARGUMENT;
+               response = AMD_S2D_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);
 }
 
 static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret)
 {
        int rc;
-       u32 val;
+       u32 val, message, argument, response;
 
        mutex_lock(&dev->lock);
+
+       if (dev->msg_port) {
+               message = AMD_S2D_REGISTER_MESSAGE;
+               argument = AMD_S2D_REGISTER_ARGUMENT;
+               response = AMD_S2D_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) {
        }
 
        /* 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) {
                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:
        { }
 };
 
+static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
+{
+       u32 size, phys_addr_low, phys_addr_hi;
+       u64 stb_phys_addr;
+
+       /* Spill to DRAM feature uses separate SMU message port */
+       dev->msg_port = 1;
+
+       amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, STB_SPILL_TO_DRAM, 1);
+       if (size != S2D_TELEMETRY_BYTES_MAX)
+               return -EIO;
+
+       /* Get STB DRAM address */
+       amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, STB_SPILL_TO_DRAM, 1);
+       amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, STB_SPILL_TO_DRAM, 1);
+
+       stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
+
+       /* Clear msg_port for other SMU operation */
+       dev->msg_port = 0;
+
+       dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, S2D_TELEMETRY_DRAMBYTES_MAX);
+       if (!dev->stb_virt_addr)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data)
 {
        int err;
        if (err)
                dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
 
+       if (enable_stb && dev->cpu_id == AMD_CPU_ID_YC) {
+               err = amd_pmc_s2d_init(dev);
+               if (err)
+                       return err;
+       }
+
        amd_pmc_get_smu_version(dev);
        platform_set_drvdata(pdev, dev);
        amd_pmc_dbgfs_register(dev);