Lines Matching +full:pcie +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe host controller driver for AMD MDB PCIe Bridge
5 * Copyright (C) 2024-2025, Advanced Micro Devices, Inc.
22 #include "pcie-designware.h"
24 #define AMD_MDB_TLP_IR_STATUS_MISC 0x4C0
25 #define AMD_MDB_TLP_IR_MASK_MISC 0x4C4
26 #define AMD_MDB_TLP_IR_ENABLE_MISC 0x4C8
27 #define AMD_MDB_TLP_IR_DISABLE_MISC 0x4CC
55 * struct amd_mdb_pcie - PCIe port information
56 * @pci: DesignWare PCIe controller structure
77 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(data); in amd_mdb_intx_irq_mask() local
78 struct dw_pcie *pci = &pcie->pci; in amd_mdb_intx_irq_mask()
79 struct dw_pcie_rp *port = &pci->pp; in amd_mdb_intx_irq_mask()
83 raw_spin_lock_irqsave(&port->lock, flags); in amd_mdb_intx_irq_mask()
85 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq)); in amd_mdb_intx_irq_mask()
89 * interrupt, writing '0' has no effect. in amd_mdb_intx_irq_mask()
91 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); in amd_mdb_intx_irq_mask()
92 raw_spin_unlock_irqrestore(&port->lock, flags); in amd_mdb_intx_irq_mask()
97 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(data); in amd_mdb_intx_irq_unmask() local
98 struct dw_pcie *pci = &pcie->pci; in amd_mdb_intx_irq_unmask()
99 struct dw_pcie_rp *port = &pci->pp; in amd_mdb_intx_irq_unmask()
103 raw_spin_lock_irqsave(&port->lock, flags); in amd_mdb_intx_irq_unmask()
105 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq)); in amd_mdb_intx_irq_unmask()
109 * interrupt, writing '0' has no effect. in amd_mdb_intx_irq_unmask()
111 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); in amd_mdb_intx_irq_unmask()
112 raw_spin_unlock_irqrestore(&port->lock, flags); in amd_mdb_intx_irq_unmask()
122 * amd_mdb_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
127 * Return: Always returns '0'.
134 irq_set_chip_data(irq, domain->host_data); in amd_mdb_pcie_intx_map()
137 return 0; in amd_mdb_pcie_intx_map()
147 struct amd_mdb_pcie *pcie = args; in dw_pcie_rp_intx() local
151 val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); in dw_pcie_rp_intx()
154 for (i = 0; i < PCI_NUM_INTX; i++) { in dw_pcie_rp_intx()
156 generic_handle_domain_irq(pcie->intx_domain, i); in dw_pcie_rp_intx()
178 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(d); in amd_mdb_event_irq_mask() local
179 struct dw_pcie *pci = &pcie->pci; in amd_mdb_event_irq_mask()
180 struct dw_pcie_rp *port = &pci->pp; in amd_mdb_event_irq_mask()
184 raw_spin_lock_irqsave(&port->lock, flags); in amd_mdb_event_irq_mask()
185 val = BIT(d->hwirq); in amd_mdb_event_irq_mask()
186 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); in amd_mdb_event_irq_mask()
187 raw_spin_unlock_irqrestore(&port->lock, flags); in amd_mdb_event_irq_mask()
192 struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(d); in amd_mdb_event_irq_unmask() local
193 struct dw_pcie *pci = &pcie->pci; in amd_mdb_event_irq_unmask()
194 struct dw_pcie_rp *port = &pci->pp; in amd_mdb_event_irq_unmask()
198 raw_spin_lock_irqsave(&port->lock, flags); in amd_mdb_event_irq_unmask()
199 val = BIT(d->hwirq); in amd_mdb_event_irq_unmask()
200 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); in amd_mdb_event_irq_unmask()
201 raw_spin_unlock_irqrestore(&port->lock, flags); in amd_mdb_event_irq_unmask()
205 .name = "AMD MDB RC-Event",
215 irq_set_chip_data(irq, domain->host_data); in amd_mdb_pcie_event_map()
218 return 0; in amd_mdb_pcie_event_map()
227 struct amd_mdb_pcie *pcie = args; in amd_mdb_pcie_event() local
231 val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); in amd_mdb_pcie_event()
232 val &= ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC); in amd_mdb_pcie_event()
234 generic_handle_domain_irq(pcie->mdb_domain, i); in amd_mdb_pcie_event()
235 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); in amd_mdb_pcie_event()
240 static void amd_mdb_pcie_free_irq_domains(struct amd_mdb_pcie *pcie) in amd_mdb_pcie_free_irq_domains() argument
242 if (pcie->intx_domain) { in amd_mdb_pcie_free_irq_domains()
243 irq_domain_remove(pcie->intx_domain); in amd_mdb_pcie_free_irq_domains()
244 pcie->intx_domain = NULL; in amd_mdb_pcie_free_irq_domains()
247 if (pcie->mdb_domain) { in amd_mdb_pcie_free_irq_domains()
248 irq_domain_remove(pcie->mdb_domain); in amd_mdb_pcie_free_irq_domains()
249 pcie->mdb_domain = NULL; in amd_mdb_pcie_free_irq_domains()
253 static int amd_mdb_pcie_init_port(struct amd_mdb_pcie *pcie) in amd_mdb_pcie_init_port() argument
259 pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); in amd_mdb_pcie_init_port()
262 val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); in amd_mdb_pcie_init_port()
264 writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); in amd_mdb_pcie_init_port()
268 pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); in amd_mdb_pcie_init_port()
270 return 0; in amd_mdb_pcie_init_port()
274 * amd_mdb_pcie_init_irq_domains - Initialize IRQ domain
275 * @pcie: PCIe port information
278 * Return: Returns '0' on success and error value on failure.
280 static int amd_mdb_pcie_init_irq_domains(struct amd_mdb_pcie *pcie, in amd_mdb_pcie_init_irq_domains() argument
283 struct dw_pcie *pci = &pcie->pci; in amd_mdb_pcie_init_irq_domains()
284 struct dw_pcie_rp *pp = &pci->pp; in amd_mdb_pcie_init_irq_domains()
285 struct device *dev = &pdev->dev; in amd_mdb_pcie_init_irq_domains()
286 struct device_node *node = dev->of_node; in amd_mdb_pcie_init_irq_domains()
290 pcie_intc_node = of_get_child_by_name(node, "interrupt-controller"); in amd_mdb_pcie_init_irq_domains()
292 dev_err(dev, "No PCIe Intc node found\n"); in amd_mdb_pcie_init_irq_domains()
293 return -ENODEV; in amd_mdb_pcie_init_irq_domains()
296 pcie->mdb_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), 32, in amd_mdb_pcie_init_irq_domains()
297 &event_domain_ops, pcie); in amd_mdb_pcie_init_irq_domains()
298 if (!pcie->mdb_domain) { in amd_mdb_pcie_init_irq_domains()
299 err = -ENOMEM; in amd_mdb_pcie_init_irq_domains()
304 irq_domain_update_bus_token(pcie->mdb_domain, DOMAIN_BUS_NEXUS); in amd_mdb_pcie_init_irq_domains()
306 pcie->intx_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), in amd_mdb_pcie_init_irq_domains()
307 PCI_NUM_INTX, &amd_intx_domain_ops, pcie); in amd_mdb_pcie_init_irq_domains()
308 if (!pcie->intx_domain) { in amd_mdb_pcie_init_irq_domains()
309 err = -ENOMEM; in amd_mdb_pcie_init_irq_domains()
315 irq_domain_update_bus_token(pcie->intx_domain, DOMAIN_BUS_WIRED); in amd_mdb_pcie_init_irq_domains()
317 raw_spin_lock_init(&pp->lock); in amd_mdb_pcie_init_irq_domains()
319 return 0; in amd_mdb_pcie_init_irq_domains()
321 amd_mdb_pcie_free_irq_domains(pcie); in amd_mdb_pcie_init_irq_domains()
329 struct amd_mdb_pcie *pcie = args; in amd_mdb_pcie_intr_handler() local
333 dev = pcie->pci.dev; in amd_mdb_pcie_intr_handler()
339 d = irq_domain_get_irq_data(pcie->mdb_domain, irq); in amd_mdb_pcie_intr_handler()
340 if (intr_cause[d->hwirq].str) in amd_mdb_pcie_intr_handler()
341 dev_warn(dev, "%s\n", intr_cause[d->hwirq].str); in amd_mdb_pcie_intr_handler()
343 dev_warn_once(dev, "Unknown IRQ %ld\n", d->hwirq); in amd_mdb_pcie_intr_handler()
348 static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie, in amd_mdb_setup_irq() argument
351 struct dw_pcie *pci = &pcie->pci; in amd_mdb_setup_irq()
352 struct dw_pcie_rp *pp = &pci->pp; in amd_mdb_setup_irq()
353 struct device *dev = &pdev->dev; in amd_mdb_setup_irq()
356 amd_mdb_pcie_init_port(pcie); in amd_mdb_setup_irq()
358 pp->irq = platform_get_irq(pdev, 0); in amd_mdb_setup_irq()
359 if (pp->irq < 0) in amd_mdb_setup_irq()
360 return pp->irq; in amd_mdb_setup_irq()
362 for (i = 0; i < ARRAY_SIZE(intr_cause); i++) { in amd_mdb_setup_irq()
366 irq = irq_create_mapping(pcie->mdb_domain, i); in amd_mdb_setup_irq()
369 return -ENOMEM; in amd_mdb_setup_irq()
373 IRQF_NO_THREAD, intr_cause[i].sym, pcie); in amd_mdb_setup_irq()
381 pcie->intx_irq = irq_create_mapping(pcie->mdb_domain, in amd_mdb_setup_irq()
383 if (!pcie->intx_irq) { in amd_mdb_setup_irq()
385 return -ENXIO; in amd_mdb_setup_irq()
388 err = devm_request_irq(dev, pcie->intx_irq, dw_pcie_rp_intx, in amd_mdb_setup_irq()
389 IRQF_NO_THREAD, NULL, pcie); in amd_mdb_setup_irq()
397 err = devm_request_irq(dev, pp->irq, amd_mdb_pcie_event, IRQF_NO_THREAD, in amd_mdb_setup_irq()
398 "amd_mdb pcie_irq", pcie); in amd_mdb_setup_irq()
401 pp->irq, err); in amd_mdb_setup_irq()
405 return 0; in amd_mdb_setup_irq()
408 static int amd_mdb_parse_pcie_port(struct amd_mdb_pcie *pcie) in amd_mdb_parse_pcie_port() argument
410 struct device *dev = pcie->pci.dev; in amd_mdb_parse_pcie_port()
418 for_each_child_of_node_with_prefix(dev->of_node, pcie_port_node, "pcie") { in amd_mdb_parse_pcie_port()
419 pcie->perst_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(pcie_port_node), in amd_mdb_parse_pcie_port()
421 if (IS_ERR(pcie->perst_gpio)) in amd_mdb_parse_pcie_port()
422 return dev_err_probe(dev, PTR_ERR(pcie->perst_gpio), in amd_mdb_parse_pcie_port()
424 return 0; in amd_mdb_parse_pcie_port()
427 return -ENODEV; in amd_mdb_parse_pcie_port()
430 static int amd_mdb_add_pcie_port(struct amd_mdb_pcie *pcie, in amd_mdb_add_pcie_port() argument
433 struct dw_pcie *pci = &pcie->pci; in amd_mdb_add_pcie_port()
434 struct dw_pcie_rp *pp = &pci->pp; in amd_mdb_add_pcie_port()
435 struct device *dev = &pdev->dev; in amd_mdb_add_pcie_port()
438 pcie->slcr = devm_platform_ioremap_resource_byname(pdev, "slcr"); in amd_mdb_add_pcie_port()
439 if (IS_ERR(pcie->slcr)) in amd_mdb_add_pcie_port()
440 return PTR_ERR(pcie->slcr); in amd_mdb_add_pcie_port()
442 err = amd_mdb_pcie_init_irq_domains(pcie, pdev); in amd_mdb_add_pcie_port()
446 err = amd_mdb_setup_irq(pcie, pdev); in amd_mdb_add_pcie_port()
452 pp->ops = &amd_mdb_pcie_host_ops; in amd_mdb_add_pcie_port()
454 if (pcie->perst_gpio) { in amd_mdb_add_pcie_port()
456 gpiod_set_value_cansleep(pcie->perst_gpio, 0); in amd_mdb_add_pcie_port()
466 return 0; in amd_mdb_add_pcie_port()
469 amd_mdb_pcie_free_irq_domains(pcie); in amd_mdb_add_pcie_port()
475 struct device *dev = &pdev->dev; in amd_mdb_pcie_probe()
476 struct amd_mdb_pcie *pcie; in amd_mdb_pcie_probe() local
480 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); in amd_mdb_pcie_probe()
481 if (!pcie) in amd_mdb_pcie_probe()
482 return -ENOMEM; in amd_mdb_pcie_probe()
484 pci = &pcie->pci; in amd_mdb_pcie_probe()
485 pci->dev = dev; in amd_mdb_pcie_probe()
487 platform_set_drvdata(pdev, pcie); in amd_mdb_pcie_probe()
489 ret = amd_mdb_parse_pcie_port(pcie); in amd_mdb_pcie_probe()
491 * If amd_mdb_parse_pcie_port returns -ENODEV, it indicates that the in amd_mdb_pcie_probe()
492 * PCIe Bridge node was not found in the device tree. This is not in amd_mdb_pcie_probe()
494 * reset GPIO is acquired directly from the PCIe Host Bridge node. in amd_mdb_pcie_probe()
497 if (ret != -ENODEV) in amd_mdb_pcie_probe()
500 pcie->perst_gpio = devm_gpiod_get_optional(dev, "reset", in amd_mdb_pcie_probe()
502 if (IS_ERR(pcie->perst_gpio)) in amd_mdb_pcie_probe()
503 return dev_err_probe(dev, PTR_ERR(pcie->perst_gpio), in amd_mdb_pcie_probe()
507 return amd_mdb_add_pcie_port(pcie, pdev); in amd_mdb_pcie_probe()
512 .compatible = "amd,versal2-mdb-host",
519 .name = "amd-mdb-pcie",