1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AMD MP2 STB layer 4 * 5 * Copyright (c) 2024, Advanced Micro Devices, Inc. 6 * All Rights Reserved. 7 * 8 * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com> 9 */ 10 11 #include <linux/debugfs.h> 12 #include <linux/device.h> 13 #include <linux/io.h> 14 #include <linux/io-64-nonatomic-lo-hi.h> 15 #include <linux/iopoll.h> 16 #include <linux/pci.h> 17 #include <linux/sizes.h> 18 #include <linux/time.h> 19 20 #include "pmc.h" 21 22 #define VALID_MSG 0xA 23 #define VALID_RESPONSE 2 24 25 #define AMD_C2P_MSG0 0x10500 26 #define AMD_C2P_MSG1 0x10504 27 #define AMD_P2C_MSG0 0x10680 28 #define AMD_P2C_MSG1 0x10684 29 30 #define MP2_RESP_SLEEP_US 500 31 #define MP2_RESP_TIMEOUT_US (1600 * USEC_PER_MSEC) 32 33 #define MP2_STB_DATA_LEN_2KB 1 34 #define MP2_STB_DATA_LEN_16KB 4 35 36 #define MP2_MMIO_BAR 2 37 38 struct mp2_cmd_base { 39 union { 40 u32 ul; 41 struct { 42 u32 cmd_id : 4; 43 u32 intr_disable : 1; 44 u32 is_dma_used : 1; 45 u32 rsvd : 26; 46 } field; 47 }; 48 }; 49 50 struct mp2_cmd_response { 51 union { 52 u32 resp; 53 struct { 54 u32 cmd_id : 4; 55 u32 status : 4; 56 u32 response : 4; 57 u32 rsvd2 : 20; 58 } field; 59 }; 60 }; 61 62 struct mp2_stb_data_valid { 63 union { 64 u32 data_valid; 65 struct { 66 u32 valid : 16; 67 u32 length : 16; 68 } val; 69 }; 70 }; 71 72 static int amd_mp2_wait_response(struct amd_mp2_dev *mp2, u8 cmd_id, u32 command_sts) 73 { 74 struct mp2_cmd_response cmd_resp; 75 76 if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG0, cmd_resp.resp, 77 (cmd_resp.field.response == 0x0 && 78 cmd_resp.field.status == command_sts && 79 cmd_resp.field.cmd_id == cmd_id), MP2_RESP_SLEEP_US, 80 MP2_RESP_TIMEOUT_US)) 81 return cmd_resp.field.status; 82 83 return -ETIMEDOUT; 84 } 85 86 static void amd_mp2_stb_send_cmd(struct amd_mp2_dev *mp2, u8 cmd_id, bool is_dma_used) 87 { 88 struct mp2_cmd_base cmd_base; 89 90 cmd_base.ul = 0; 91 cmd_base.field.cmd_id = cmd_id; 92 cmd_base.field.intr_disable = 1; 93 cmd_base.field.is_dma_used = is_dma_used; 94 95 writeq(mp2->dma_addr, mp2->mmio + AMD_C2P_MSG1); 96 writel(cmd_base.ul, mp2->mmio + AMD_C2P_MSG0); 97 } 98 99 static int amd_mp2_stb_region(struct amd_mp2_dev *mp2) 100 { 101 struct device *dev = &mp2->pdev->dev; 102 unsigned int len = mp2->stb_len; 103 104 if (!mp2->stbdata) { 105 mp2->vslbase = dmam_alloc_coherent(dev, len, &mp2->dma_addr, GFP_KERNEL); 106 if (!mp2->vslbase) 107 return -ENOMEM; 108 109 mp2->stbdata = devm_kzalloc(dev, len, GFP_KERNEL); 110 if (!mp2->stbdata) 111 return -ENOMEM; 112 } 113 114 return 0; 115 } 116 117 static int amd_mp2_process_cmd(struct amd_mp2_dev *mp2, struct file *filp) 118 { 119 struct device *dev = &mp2->pdev->dev; 120 struct mp2_stb_data_valid stb_dv; 121 int status; 122 123 stb_dv.data_valid = readl(mp2->mmio + AMD_P2C_MSG1); 124 125 if (stb_dv.val.valid != VALID_MSG) { 126 dev_dbg(dev, "Invalid STB data\n"); 127 return -EBADMSG; 128 } 129 130 if (stb_dv.val.length != MP2_STB_DATA_LEN_2KB && 131 stb_dv.val.length != MP2_STB_DATA_LEN_16KB) { 132 dev_dbg(dev, "Unsupported length\n"); 133 return -EMSGSIZE; 134 } 135 136 mp2->stb_len = BIT(stb_dv.val.length) * SZ_1K; 137 138 status = amd_mp2_stb_region(mp2); 139 if (status) { 140 dev_err(dev, "Failed to init STB region, status %d\n", status); 141 return status; 142 } 143 144 amd_mp2_stb_send_cmd(mp2, VALID_MSG, true); 145 status = amd_mp2_wait_response(mp2, VALID_MSG, VALID_RESPONSE); 146 if (status == VALID_RESPONSE) { 147 memcpy_fromio(mp2->stbdata, mp2->vslbase, mp2->stb_len); 148 filp->private_data = mp2->stbdata; 149 mp2->is_stb_data = true; 150 } else { 151 dev_err(dev, "Failed to start STB dump, status %d\n", status); 152 return -EOPNOTSUPP; 153 } 154 155 return 0; 156 } 157 158 static int amd_mp2_stb_debugfs_open(struct inode *inode, struct file *filp) 159 { 160 struct amd_pmc_dev *dev = filp->f_inode->i_private; 161 struct amd_mp2_dev *mp2 = dev->mp2; 162 163 if (mp2) { 164 if (!mp2->is_stb_data) 165 return amd_mp2_process_cmd(mp2, filp); 166 167 filp->private_data = mp2->stbdata; 168 169 return 0; 170 } 171 172 return -ENODEV; 173 } 174 175 static ssize_t amd_mp2_stb_debugfs_read(struct file *filp, char __user *buf, size_t size, 176 loff_t *pos) 177 { 178 struct amd_pmc_dev *dev = filp->f_inode->i_private; 179 struct amd_mp2_dev *mp2 = dev->mp2; 180 181 if (!mp2) 182 return -ENODEV; 183 184 if (!filp->private_data) 185 return -EINVAL; 186 187 return simple_read_from_buffer(buf, size, pos, filp->private_data, mp2->stb_len); 188 } 189 190 static const struct file_operations amd_mp2_stb_debugfs_fops = { 191 .owner = THIS_MODULE, 192 .open = amd_mp2_stb_debugfs_open, 193 .read = amd_mp2_stb_debugfs_read, 194 }; 195 196 static void amd_mp2_dbgfs_register(struct amd_pmc_dev *dev) 197 { 198 if (!dev->dbgfs_dir) 199 return; 200 201 debugfs_create_file("stb_read_previous_boot", 0644, dev->dbgfs_dir, dev, 202 &amd_mp2_stb_debugfs_fops); 203 } 204 205 void amd_mp2_stb_deinit(struct amd_pmc_dev *dev) 206 { 207 struct amd_mp2_dev *mp2 = dev->mp2; 208 struct pci_dev *pdev; 209 210 if (mp2 && mp2->pdev) { 211 pdev = mp2->pdev; 212 213 if (mp2->mmio) 214 pci_clear_master(pdev); 215 216 pci_dev_put(pdev); 217 218 if (mp2->devres_gid) 219 devres_release_group(&pdev->dev, mp2->devres_gid); 220 221 dev->mp2 = NULL; 222 } 223 } 224 225 void amd_mp2_stb_init(struct amd_pmc_dev *dev) 226 { 227 struct amd_mp2_dev *mp2 = NULL; 228 struct pci_dev *pdev; 229 int rc; 230 231 mp2 = devm_kzalloc(dev->dev, sizeof(*mp2), GFP_KERNEL); 232 if (!mp2) 233 return; 234 235 pdev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MP2_STB, NULL); 236 if (!pdev) 237 return; 238 239 dev->mp2 = mp2; 240 mp2->pdev = pdev; 241 242 mp2->devres_gid = devres_open_group(&pdev->dev, NULL, GFP_KERNEL); 243 if (!mp2->devres_gid) { 244 dev_err(&pdev->dev, "devres_open_group failed\n"); 245 goto mp2_error; 246 } 247 248 rc = pcim_enable_device(pdev); 249 if (rc) { 250 dev_err(&pdev->dev, "pcim_enable_device failed\n"); 251 goto mp2_error; 252 } 253 254 rc = pcim_iomap_regions(pdev, BIT(MP2_MMIO_BAR), "mp2 stb"); 255 if (rc) { 256 dev_err(&pdev->dev, "pcim_iomap_regions failed\n"); 257 goto mp2_error; 258 } 259 260 mp2->mmio = pcim_iomap_table(pdev)[MP2_MMIO_BAR]; 261 if (!mp2->mmio) { 262 dev_err(&pdev->dev, "pcim_iomap_table failed\n"); 263 goto mp2_error; 264 } 265 266 pci_set_master(pdev); 267 268 rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 269 if (rc) { 270 dev_err(&pdev->dev, "failed to set DMA mask\n"); 271 goto mp2_error; 272 } 273 274 amd_mp2_dbgfs_register(dev); 275 276 return; 277 278 mp2_error: 279 amd_mp2_stb_deinit(dev); 280 } 281