1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PCIe host controller driver for AMD MDB PCIe Bridge 4 * 5 * Copyright (C) 2024-2025, Advanced Micro Devices, Inc. 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/delay.h> 10 #include <linux/gpio.h> 11 #include <linux/interrupt.h> 12 #include <linux/irqdomain.h> 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/of_device.h> 16 #include <linux/pci.h> 17 #include <linux/platform_device.h> 18 #include <linux/resource.h> 19 #include <linux/types.h> 20 21 #include "pcie-designware.h" 22 23 #define AMD_MDB_TLP_IR_STATUS_MISC 0x4C0 24 #define AMD_MDB_TLP_IR_MASK_MISC 0x4C4 25 #define AMD_MDB_TLP_IR_ENABLE_MISC 0x4C8 26 #define AMD_MDB_TLP_IR_DISABLE_MISC 0x4CC 27 28 #define AMD_MDB_TLP_PCIE_INTX_MASK GENMASK(23, 16) 29 30 #define AMD_MDB_PCIE_INTR_INTX_ASSERT(x) BIT((x) * 2) 31 32 /* Interrupt registers definitions. */ 33 #define AMD_MDB_PCIE_INTR_CMPL_TIMEOUT 15 34 #define AMD_MDB_PCIE_INTR_INTX 16 35 #define AMD_MDB_PCIE_INTR_PM_PME_RCVD 24 36 #define AMD_MDB_PCIE_INTR_PME_TO_ACK_RCVD 25 37 #define AMD_MDB_PCIE_INTR_MISC_CORRECTABLE 26 38 #define AMD_MDB_PCIE_INTR_NONFATAL 27 39 #define AMD_MDB_PCIE_INTR_FATAL 28 40 41 #define IMR(x) BIT(AMD_MDB_PCIE_INTR_ ##x) 42 #define AMD_MDB_PCIE_IMR_ALL_MASK \ 43 ( \ 44 IMR(CMPL_TIMEOUT) | \ 45 IMR(PM_PME_RCVD) | \ 46 IMR(PME_TO_ACK_RCVD) | \ 47 IMR(MISC_CORRECTABLE) | \ 48 IMR(NONFATAL) | \ 49 IMR(FATAL) | \ 50 AMD_MDB_TLP_PCIE_INTX_MASK \ 51 ) 52 53 /** 54 * struct amd_mdb_pcie - PCIe port information 55 * @pci: DesignWare PCIe controller structure 56 * @slcr: MDB System Level Control and Status Register (SLCR) base 57 * @intx_domain: INTx IRQ domain pointer 58 * @mdb_domain: MDB IRQ domain pointer 59 * @intx_irq: INTx IRQ interrupt number 60 */ 61 struct amd_mdb_pcie { 62 struct dw_pcie pci; 63 void __iomem *slcr; 64 struct irq_domain *intx_domain; 65 struct irq_domain *mdb_domain; 66 int intx_irq; 67 }; 68 69 static const struct dw_pcie_host_ops amd_mdb_pcie_host_ops = { 70 }; 71 72 static void amd_mdb_intx_irq_mask(struct irq_data *data) 73 { 74 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(data); 75 struct dw_pcie *pci = &pcie->pci; 76 struct dw_pcie_rp *port = &pci->pp; 77 unsigned long flags; 78 u32 val; 79 80 raw_spin_lock_irqsave(&port->lock, flags); 81 val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK, 82 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq)); 83 84 /* 85 * Writing '1' to a bit in AMD_MDB_TLP_IR_DISABLE_MISC disables that 86 * interrupt, writing '0' has no effect. 87 */ 88 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); 89 raw_spin_unlock_irqrestore(&port->lock, flags); 90 } 91 92 static void amd_mdb_intx_irq_unmask(struct irq_data *data) 93 { 94 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(data); 95 struct dw_pcie *pci = &pcie->pci; 96 struct dw_pcie_rp *port = &pci->pp; 97 unsigned long flags; 98 u32 val; 99 100 raw_spin_lock_irqsave(&port->lock, flags); 101 val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK, 102 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq)); 103 104 /* 105 * Writing '1' to a bit in AMD_MDB_TLP_IR_ENABLE_MISC enables that 106 * interrupt, writing '0' has no effect. 107 */ 108 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); 109 raw_spin_unlock_irqrestore(&port->lock, flags); 110 } 111 112 static struct irq_chip amd_mdb_intx_irq_chip = { 113 .name = "AMD MDB INTx", 114 .irq_mask = amd_mdb_intx_irq_mask, 115 .irq_unmask = amd_mdb_intx_irq_unmask, 116 }; 117 118 /** 119 * amd_mdb_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid 120 * @domain: IRQ domain 121 * @irq: Virtual IRQ number 122 * @hwirq: Hardware interrupt number 123 * 124 * Return: Always returns '0'. 125 */ 126 static int amd_mdb_pcie_intx_map(struct irq_domain *domain, 127 unsigned int irq, irq_hw_number_t hwirq) 128 { 129 irq_set_chip_and_handler(irq, &amd_mdb_intx_irq_chip, 130 handle_level_irq); 131 irq_set_chip_data(irq, domain->host_data); 132 irq_set_status_flags(irq, IRQ_LEVEL); 133 134 return 0; 135 } 136 137 /* INTx IRQ domain operations. */ 138 static const struct irq_domain_ops amd_intx_domain_ops = { 139 .map = amd_mdb_pcie_intx_map, 140 }; 141 142 static irqreturn_t dw_pcie_rp_intx(int irq, void *args) 143 { 144 struct amd_mdb_pcie *pcie = args; 145 unsigned long val; 146 int i, int_status; 147 148 val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); 149 int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val); 150 151 for (i = 0; i < PCI_NUM_INTX; i++) { 152 if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i)) 153 generic_handle_domain_irq(pcie->intx_domain, i); 154 } 155 156 return IRQ_HANDLED; 157 } 158 159 #define _IC(x, s)[AMD_MDB_PCIE_INTR_ ## x] = { __stringify(x), s } 160 161 static const struct { 162 const char *sym; 163 const char *str; 164 } intr_cause[32] = { 165 _IC(CMPL_TIMEOUT, "Completion timeout"), 166 _IC(PM_PME_RCVD, "PM_PME message received"), 167 _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"), 168 _IC(MISC_CORRECTABLE, "Correctable error message"), 169 _IC(NONFATAL, "Non fatal error message"), 170 _IC(FATAL, "Fatal error message"), 171 }; 172 173 static void amd_mdb_event_irq_mask(struct irq_data *d) 174 { 175 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(d); 176 struct dw_pcie *pci = &pcie->pci; 177 struct dw_pcie_rp *port = &pci->pp; 178 unsigned long flags; 179 u32 val; 180 181 raw_spin_lock_irqsave(&port->lock, flags); 182 val = BIT(d->hwirq); 183 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); 184 raw_spin_unlock_irqrestore(&port->lock, flags); 185 } 186 187 static void amd_mdb_event_irq_unmask(struct irq_data *d) 188 { 189 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(d); 190 struct dw_pcie *pci = &pcie->pci; 191 struct dw_pcie_rp *port = &pci->pp; 192 unsigned long flags; 193 u32 val; 194 195 raw_spin_lock_irqsave(&port->lock, flags); 196 val = BIT(d->hwirq); 197 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); 198 raw_spin_unlock_irqrestore(&port->lock, flags); 199 } 200 201 static struct irq_chip amd_mdb_event_irq_chip = { 202 .name = "AMD MDB RC-Event", 203 .irq_mask = amd_mdb_event_irq_mask, 204 .irq_unmask = amd_mdb_event_irq_unmask, 205 }; 206 207 static int amd_mdb_pcie_event_map(struct irq_domain *domain, 208 unsigned int irq, irq_hw_number_t hwirq) 209 { 210 irq_set_chip_and_handler(irq, &amd_mdb_event_irq_chip, 211 handle_level_irq); 212 irq_set_chip_data(irq, domain->host_data); 213 irq_set_status_flags(irq, IRQ_LEVEL); 214 215 return 0; 216 } 217 218 static const struct irq_domain_ops event_domain_ops = { 219 .map = amd_mdb_pcie_event_map, 220 }; 221 222 static irqreturn_t amd_mdb_pcie_event(int irq, void *args) 223 { 224 struct amd_mdb_pcie *pcie = args; 225 unsigned long val; 226 int i; 227 228 val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); 229 val &= ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC); 230 for_each_set_bit(i, &val, 32) 231 generic_handle_domain_irq(pcie->mdb_domain, i); 232 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); 233 234 return IRQ_HANDLED; 235 } 236 237 static void amd_mdb_pcie_free_irq_domains(struct amd_mdb_pcie *pcie) 238 { 239 if (pcie->intx_domain) { 240 irq_domain_remove(pcie->intx_domain); 241 pcie->intx_domain = NULL; 242 } 243 244 if (pcie->mdb_domain) { 245 irq_domain_remove(pcie->mdb_domain); 246 pcie->mdb_domain = NULL; 247 } 248 } 249 250 static int amd_mdb_pcie_init_port(struct amd_mdb_pcie *pcie) 251 { 252 unsigned long val; 253 254 /* Disable all TLP interrupts. */ 255 writel_relaxed(AMD_MDB_PCIE_IMR_ALL_MASK, 256 pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); 257 258 /* Clear pending TLP interrupts. */ 259 val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); 260 val &= AMD_MDB_PCIE_IMR_ALL_MASK; 261 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); 262 263 /* Enable all TLP interrupts. */ 264 writel_relaxed(AMD_MDB_PCIE_IMR_ALL_MASK, 265 pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); 266 267 return 0; 268 } 269 270 /** 271 * amd_mdb_pcie_init_irq_domains - Initialize IRQ domain 272 * @pcie: PCIe port information 273 * @pdev: Platform device 274 * 275 * Return: Returns '0' on success and error value on failure. 276 */ 277 static int amd_mdb_pcie_init_irq_domains(struct amd_mdb_pcie *pcie, 278 struct platform_device *pdev) 279 { 280 struct dw_pcie *pci = &pcie->pci; 281 struct dw_pcie_rp *pp = &pci->pp; 282 struct device *dev = &pdev->dev; 283 struct device_node *node = dev->of_node; 284 struct device_node *pcie_intc_node; 285 int err; 286 287 pcie_intc_node = of_get_next_child(node, NULL); 288 if (!pcie_intc_node) { 289 dev_err(dev, "No PCIe Intc node found\n"); 290 return -ENODEV; 291 } 292 293 pcie->mdb_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), 32, 294 &event_domain_ops, pcie); 295 if (!pcie->mdb_domain) { 296 err = -ENOMEM; 297 dev_err(dev, "Failed to add MDB domain\n"); 298 goto out; 299 } 300 301 irq_domain_update_bus_token(pcie->mdb_domain, DOMAIN_BUS_NEXUS); 302 303 pcie->intx_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), 304 PCI_NUM_INTX, &amd_intx_domain_ops, pcie); 305 if (!pcie->intx_domain) { 306 err = -ENOMEM; 307 dev_err(dev, "Failed to add INTx domain\n"); 308 goto mdb_out; 309 } 310 311 of_node_put(pcie_intc_node); 312 irq_domain_update_bus_token(pcie->intx_domain, DOMAIN_BUS_WIRED); 313 314 raw_spin_lock_init(&pp->lock); 315 316 return 0; 317 mdb_out: 318 amd_mdb_pcie_free_irq_domains(pcie); 319 out: 320 of_node_put(pcie_intc_node); 321 return err; 322 } 323 324 static irqreturn_t amd_mdb_pcie_intr_handler(int irq, void *args) 325 { 326 struct amd_mdb_pcie *pcie = args; 327 struct device *dev; 328 struct irq_data *d; 329 330 dev = pcie->pci.dev; 331 332 /* 333 * In the future, error reporting will be hooked to the AER subsystem. 334 * Currently, the driver prints a warning message to the user. 335 */ 336 d = irq_domain_get_irq_data(pcie->mdb_domain, irq); 337 if (intr_cause[d->hwirq].str) 338 dev_warn(dev, "%s\n", intr_cause[d->hwirq].str); 339 else 340 dev_warn_once(dev, "Unknown IRQ %ld\n", d->hwirq); 341 342 return IRQ_HANDLED; 343 } 344 345 static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie, 346 struct platform_device *pdev) 347 { 348 struct dw_pcie *pci = &pcie->pci; 349 struct dw_pcie_rp *pp = &pci->pp; 350 struct device *dev = &pdev->dev; 351 int i, irq, err; 352 353 amd_mdb_pcie_init_port(pcie); 354 355 pp->irq = platform_get_irq(pdev, 0); 356 if (pp->irq < 0) 357 return pp->irq; 358 359 for (i = 0; i < ARRAY_SIZE(intr_cause); i++) { 360 if (!intr_cause[i].str) 361 continue; 362 363 irq = irq_create_mapping(pcie->mdb_domain, i); 364 if (!irq) { 365 dev_err(dev, "Failed to map MDB domain interrupt\n"); 366 return -ENOMEM; 367 } 368 369 err = devm_request_irq(dev, irq, amd_mdb_pcie_intr_handler, 370 IRQF_NO_THREAD, intr_cause[i].sym, pcie); 371 if (err) { 372 dev_err(dev, "Failed to request IRQ %d, err=%d\n", 373 irq, err); 374 return err; 375 } 376 } 377 378 pcie->intx_irq = irq_create_mapping(pcie->mdb_domain, 379 AMD_MDB_PCIE_INTR_INTX); 380 if (!pcie->intx_irq) { 381 dev_err(dev, "Failed to map INTx interrupt\n"); 382 return -ENXIO; 383 } 384 385 err = devm_request_irq(dev, pcie->intx_irq, dw_pcie_rp_intx, 386 IRQF_NO_THREAD, NULL, pcie); 387 if (err) { 388 dev_err(dev, "Failed to request INTx IRQ %d, err=%d\n", 389 irq, err); 390 return err; 391 } 392 393 /* Plug the main event handler. */ 394 err = devm_request_irq(dev, pp->irq, amd_mdb_pcie_event, IRQF_NO_THREAD, 395 "amd_mdb pcie_irq", pcie); 396 if (err) { 397 dev_err(dev, "Failed to request event IRQ %d, err=%d\n", 398 pp->irq, err); 399 return err; 400 } 401 402 return 0; 403 } 404 405 static int amd_mdb_add_pcie_port(struct amd_mdb_pcie *pcie, 406 struct platform_device *pdev) 407 { 408 struct dw_pcie *pci = &pcie->pci; 409 struct dw_pcie_rp *pp = &pci->pp; 410 struct device *dev = &pdev->dev; 411 int err; 412 413 pcie->slcr = devm_platform_ioremap_resource_byname(pdev, "slcr"); 414 if (IS_ERR(pcie->slcr)) 415 return PTR_ERR(pcie->slcr); 416 417 err = amd_mdb_pcie_init_irq_domains(pcie, pdev); 418 if (err) 419 return err; 420 421 err = amd_mdb_setup_irq(pcie, pdev); 422 if (err) { 423 dev_err(dev, "Failed to set up interrupts, err=%d\n", err); 424 goto out; 425 } 426 427 pp->ops = &amd_mdb_pcie_host_ops; 428 429 err = dw_pcie_host_init(pp); 430 if (err) { 431 dev_err(dev, "Failed to initialize host, err=%d\n", err); 432 goto out; 433 } 434 435 return 0; 436 437 out: 438 amd_mdb_pcie_free_irq_domains(pcie); 439 return err; 440 } 441 442 static int amd_mdb_pcie_probe(struct platform_device *pdev) 443 { 444 struct device *dev = &pdev->dev; 445 struct amd_mdb_pcie *pcie; 446 struct dw_pcie *pci; 447 448 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 449 if (!pcie) 450 return -ENOMEM; 451 452 pci = &pcie->pci; 453 pci->dev = dev; 454 455 platform_set_drvdata(pdev, pcie); 456 457 return amd_mdb_add_pcie_port(pcie, pdev); 458 } 459 460 static const struct of_device_id amd_mdb_pcie_of_match[] = { 461 { 462 .compatible = "amd,versal2-mdb-host", 463 }, 464 {}, 465 }; 466 467 static struct platform_driver amd_mdb_pcie_driver = { 468 .driver = { 469 .name = "amd-mdb-pcie", 470 .of_match_table = amd_mdb_pcie_of_match, 471 .suppress_bind_attrs = true, 472 }, 473 .probe = amd_mdb_pcie_probe, 474 }; 475 476 builtin_platform_driver(amd_mdb_pcie_driver); 477