Lines Matching +full:versal +full:- +full:cpm +full:- +full:host +full:- +full:1
1 // SPDX-License-Identifier: GPL-2.0+
3 * PCIe host controller driver for Xilinx Versal CPM DMA Bridge
5 * (C) Copyright 2019 - 2020, Xilinx, Inc.
22 #include <linux/pci-ecam.h>
36 #define XILINX_CPM_PCIE_MISC_IR_LOCAL BIT(1)
102 * struct xilinx_cpm_pcie_port - PCIe port information
104 * @cpm_base: CPM System Level Control and Status Register(SLCR) Base
107 * @cpm_domain: CPM IRQ domain pointer
127 return readl_relaxed(port->reg_base + reg); in pcie_read()
133 writel_relaxed(val, port->reg_base + reg); in pcie_write()
147 dev_dbg(port->dev, "Requester ID %lu\n", in cpm_pcie_clear_err_interrupts()
161 mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT); in xilinx_cpm_mask_leg_irq()
162 raw_spin_lock_irqsave(&port->lock, flags); in xilinx_cpm_mask_leg_irq()
165 raw_spin_unlock_irqrestore(&port->lock, flags); in xilinx_cpm_mask_leg_irq()
175 mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT); in xilinx_cpm_unmask_leg_irq()
176 raw_spin_lock_irqsave(&port->lock, flags); in xilinx_cpm_unmask_leg_irq()
179 raw_spin_unlock_irqrestore(&port->lock, flags); in xilinx_cpm_unmask_leg_irq()
189 * xilinx_cpm_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
201 irq_set_chip_data(irq, domain->host_data); in xilinx_cpm_pcie_intx_map()
225 generic_handle_irq(irq_find_mapping(port->intx_domain, i)); in xilinx_cpm_pcie_intx_flow()
235 raw_spin_lock(&port->lock); in xilinx_cpm_mask_event_irq()
237 val &= ~BIT(d->hwirq); in xilinx_cpm_mask_event_irq()
239 raw_spin_unlock(&port->lock); in xilinx_cpm_mask_event_irq()
247 raw_spin_lock(&port->lock); in xilinx_cpm_unmask_event_irq()
249 val |= BIT(d->hwirq); in xilinx_cpm_unmask_event_irq()
251 raw_spin_unlock(&port->lock); in xilinx_cpm_unmask_event_irq()
255 .name = "RC-Event",
265 irq_set_chip_data(irq, domain->host_data); in xilinx_cpm_pcie_event_map()
285 generic_handle_irq(irq_find_mapping(port->cpm_domain, i)); in xilinx_cpm_pcie_event_flow()
290 * CPM SLCR block. in xilinx_cpm_pcie_event_flow()
292 val = readl_relaxed(port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS); in xilinx_cpm_pcie_event_flow()
295 port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS); in xilinx_cpm_pcie_event_flow()
331 struct device *dev = port->dev; in xilinx_cpm_pcie_intr_handler()
334 d = irq_domain_get_irq_data(port->cpm_domain, irq); in xilinx_cpm_pcie_intr_handler()
336 switch (d->hwirq) { in xilinx_cpm_pcie_intr_handler()
344 if (intr_cause[d->hwirq].str) in xilinx_cpm_pcie_intr_handler()
345 dev_warn(dev, "%s\n", intr_cause[d->hwirq].str); in xilinx_cpm_pcie_intr_handler()
347 dev_warn(dev, "Unknown IRQ %ld\n", d->hwirq); in xilinx_cpm_pcie_intr_handler()
355 if (port->intx_domain) { in xilinx_cpm_free_irq_domains()
356 irq_domain_remove(port->intx_domain); in xilinx_cpm_free_irq_domains()
357 port->intx_domain = NULL; in xilinx_cpm_free_irq_domains()
360 if (port->cpm_domain) { in xilinx_cpm_free_irq_domains()
361 irq_domain_remove(port->cpm_domain); in xilinx_cpm_free_irq_domains()
362 port->cpm_domain = NULL; in xilinx_cpm_free_irq_domains()
367 * xilinx_cpm_pcie_init_irq_domain - Initialize IRQ domain
374 struct device *dev = port->dev; in xilinx_cpm_pcie_init_irq_domain()
375 struct device_node *node = dev->of_node; in xilinx_cpm_pcie_init_irq_domain()
382 return -EINVAL; in xilinx_cpm_pcie_init_irq_domain()
385 port->cpm_domain = irq_domain_add_linear(pcie_intc_node, 32, in xilinx_cpm_pcie_init_irq_domain()
388 if (!port->cpm_domain) in xilinx_cpm_pcie_init_irq_domain()
391 irq_domain_update_bus_token(port->cpm_domain, DOMAIN_BUS_NEXUS); in xilinx_cpm_pcie_init_irq_domain()
393 port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, in xilinx_cpm_pcie_init_irq_domain()
396 if (!port->intx_domain) in xilinx_cpm_pcie_init_irq_domain()
399 irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED); in xilinx_cpm_pcie_init_irq_domain()
402 raw_spin_lock_init(&port->lock); in xilinx_cpm_pcie_init_irq_domain()
409 return -ENOMEM; in xilinx_cpm_pcie_init_irq_domain()
414 struct device *dev = port->dev; in xilinx_cpm_setup_irq()
418 port->irq = platform_get_irq(pdev, 0); in xilinx_cpm_setup_irq()
419 if (port->irq < 0) in xilinx_cpm_setup_irq()
420 return port->irq; in xilinx_cpm_setup_irq()
428 irq = irq_create_mapping(port->cpm_domain, i); in xilinx_cpm_setup_irq()
431 return -ENXIO; in xilinx_cpm_setup_irq()
442 port->intx_irq = irq_create_mapping(port->cpm_domain, in xilinx_cpm_setup_irq()
444 if (!port->intx_irq) { in xilinx_cpm_setup_irq()
446 return -ENXIO; in xilinx_cpm_setup_irq()
450 irq_set_chained_handler_and_data(port->intx_irq, in xilinx_cpm_setup_irq()
454 irq_set_chained_handler_and_data(port->irq, in xilinx_cpm_setup_irq()
461 * xilinx_cpm_pcie_init_port - Initialize hardware
467 dev_info(port->dev, "PCIe Link is UP\n"); in xilinx_cpm_pcie_init_port()
469 dev_info(port->dev, "PCIe Link is DOWN\n"); in xilinx_cpm_pcie_init_port()
482 * CPM SLCR block. in xilinx_cpm_pcie_init_port()
485 port->cpm_base + XILINX_CPM_PCIE_MISC_IR_ENABLE); in xilinx_cpm_pcie_init_port()
493 * xilinx_cpm_pcie_parse_dt - Parse Device tree
502 struct device *dev = port->dev; in xilinx_cpm_pcie_parse_dt()
506 port->cpm_base = devm_platform_ioremap_resource_byname(pdev, in xilinx_cpm_pcie_parse_dt()
508 if (IS_ERR(port->cpm_base)) in xilinx_cpm_pcie_parse_dt()
509 return PTR_ERR(port->cpm_base); in xilinx_cpm_pcie_parse_dt()
513 return -ENXIO; in xilinx_cpm_pcie_parse_dt()
515 port->cfg = pci_ecam_create(dev, res, bus_range, in xilinx_cpm_pcie_parse_dt()
517 if (IS_ERR(port->cfg)) in xilinx_cpm_pcie_parse_dt()
518 return PTR_ERR(port->cfg); in xilinx_cpm_pcie_parse_dt()
520 port->reg_base = port->cfg->win; in xilinx_cpm_pcie_parse_dt()
527 irq_set_chained_handler_and_data(port->intx_irq, NULL, NULL); in xilinx_cpm_free_interrupts()
528 irq_set_chained_handler_and_data(port->irq, NULL, NULL); in xilinx_cpm_free_interrupts()
532 * xilinx_cpm_pcie_probe - Probe function
540 struct device *dev = &pdev->dev; in xilinx_cpm_pcie_probe()
547 return -ENODEV; in xilinx_cpm_pcie_probe()
551 port->dev = dev; in xilinx_cpm_pcie_probe()
557 bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); in xilinx_cpm_pcie_probe()
559 return -ENODEV; in xilinx_cpm_pcie_probe()
561 err = xilinx_cpm_pcie_parse_dt(port, bus->res); in xilinx_cpm_pcie_probe()
575 bridge->sysdata = port->cfg; in xilinx_cpm_pcie_probe()
576 bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops; in xilinx_cpm_pcie_probe()
587 pci_ecam_free(port->cfg); in xilinx_cpm_pcie_probe()
594 { .compatible = "xlnx,versal-cpm-host-1.00", },
600 .name = "xilinx-cpm-pcie",