139bd5f82SMinda Chen // SPDX-License-Identifier: GPL-2.0 239bd5f82SMinda Chen /* 339bd5f82SMinda Chen * PLDA PCIe XpressRich host controller driver 439bd5f82SMinda Chen * 539bd5f82SMinda Chen * Copyright (C) 2023 Microchip Co. Ltd 639bd5f82SMinda Chen * 739bd5f82SMinda Chen * Author: Daire McNamara <daire.mcnamara@microchip.com> 839bd5f82SMinda Chen */ 939bd5f82SMinda Chen 104602c370SMinda Chen #include <linux/irqchip/chained_irq.h> 114602c370SMinda Chen #include <linux/irqdomain.h> 124602c370SMinda Chen #include <linux/msi.h> 134602c370SMinda Chen #include <linux/pci_regs.h> 1439bd5f82SMinda Chen #include <linux/pci-ecam.h> 1539bd5f82SMinda Chen 1639bd5f82SMinda Chen #include "pcie-plda.h" 1739bd5f82SMinda Chen 184602c370SMinda Chen static void plda_handle_msi(struct irq_desc *desc) 194602c370SMinda Chen { 204602c370SMinda Chen struct plda_pcie_rp *port = irq_desc_get_handler_data(desc); 214602c370SMinda Chen struct irq_chip *chip = irq_desc_get_chip(desc); 224602c370SMinda Chen struct device *dev = port->dev; 234602c370SMinda Chen struct plda_msi *msi = &port->msi; 244602c370SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 254602c370SMinda Chen unsigned long status; 264602c370SMinda Chen u32 bit; 274602c370SMinda Chen int ret; 284602c370SMinda Chen 294602c370SMinda Chen chained_irq_enter(chip, desc); 304602c370SMinda Chen 314602c370SMinda Chen status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL); 324602c370SMinda Chen if (status & PM_MSI_INT_MSI_MASK) { 334602c370SMinda Chen writel_relaxed(status & PM_MSI_INT_MSI_MASK, 344602c370SMinda Chen bridge_base_addr + ISTATUS_LOCAL); 354602c370SMinda Chen status = readl_relaxed(bridge_base_addr + ISTATUS_MSI); 364602c370SMinda Chen for_each_set_bit(bit, &status, msi->num_vectors) { 374602c370SMinda Chen ret = generic_handle_domain_irq(msi->dev_domain, bit); 384602c370SMinda Chen if (ret) 394602c370SMinda Chen dev_err_ratelimited(dev, "bad MSI IRQ %d\n", 404602c370SMinda Chen bit); 414602c370SMinda Chen } 424602c370SMinda Chen } 434602c370SMinda Chen 444602c370SMinda Chen chained_irq_exit(chip, desc); 454602c370SMinda Chen } 464602c370SMinda Chen 474602c370SMinda Chen static void plda_msi_bottom_irq_ack(struct irq_data *data) 484602c370SMinda Chen { 494602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 504602c370SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 514602c370SMinda Chen u32 bitpos = data->hwirq; 524602c370SMinda Chen 534602c370SMinda Chen writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI); 544602c370SMinda Chen } 554602c370SMinda Chen 564602c370SMinda Chen static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 574602c370SMinda Chen { 584602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 594602c370SMinda Chen phys_addr_t addr = port->msi.vector_phy; 604602c370SMinda Chen 614602c370SMinda Chen msg->address_lo = lower_32_bits(addr); 624602c370SMinda Chen msg->address_hi = upper_32_bits(addr); 634602c370SMinda Chen msg->data = data->hwirq; 644602c370SMinda Chen 654602c370SMinda Chen dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n", 664602c370SMinda Chen (int)data->hwirq, msg->address_hi, msg->address_lo); 674602c370SMinda Chen } 684602c370SMinda Chen 694602c370SMinda Chen static int plda_msi_set_affinity(struct irq_data *irq_data, 704602c370SMinda Chen const struct cpumask *mask, bool force) 714602c370SMinda Chen { 724602c370SMinda Chen return -EINVAL; 734602c370SMinda Chen } 744602c370SMinda Chen 754602c370SMinda Chen static struct irq_chip plda_msi_bottom_irq_chip = { 764602c370SMinda Chen .name = "PLDA MSI", 774602c370SMinda Chen .irq_ack = plda_msi_bottom_irq_ack, 784602c370SMinda Chen .irq_compose_msi_msg = plda_compose_msi_msg, 794602c370SMinda Chen .irq_set_affinity = plda_msi_set_affinity, 804602c370SMinda Chen }; 814602c370SMinda Chen 824602c370SMinda Chen static int plda_irq_msi_domain_alloc(struct irq_domain *domain, 834602c370SMinda Chen unsigned int virq, 844602c370SMinda Chen unsigned int nr_irqs, 854602c370SMinda Chen void *args) 864602c370SMinda Chen { 874602c370SMinda Chen struct plda_pcie_rp *port = domain->host_data; 884602c370SMinda Chen struct plda_msi *msi = &port->msi; 894602c370SMinda Chen unsigned long bit; 904602c370SMinda Chen 914602c370SMinda Chen mutex_lock(&msi->lock); 924602c370SMinda Chen bit = find_first_zero_bit(msi->used, msi->num_vectors); 934602c370SMinda Chen if (bit >= msi->num_vectors) { 944602c370SMinda Chen mutex_unlock(&msi->lock); 954602c370SMinda Chen return -ENOSPC; 964602c370SMinda Chen } 974602c370SMinda Chen 984602c370SMinda Chen set_bit(bit, msi->used); 994602c370SMinda Chen 1004602c370SMinda Chen irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip, 1014602c370SMinda Chen domain->host_data, handle_edge_irq, NULL, NULL); 1024602c370SMinda Chen 1034602c370SMinda Chen mutex_unlock(&msi->lock); 1044602c370SMinda Chen 1054602c370SMinda Chen return 0; 1064602c370SMinda Chen } 1074602c370SMinda Chen 1084602c370SMinda Chen static void plda_irq_msi_domain_free(struct irq_domain *domain, 1094602c370SMinda Chen unsigned int virq, 1104602c370SMinda Chen unsigned int nr_irqs) 1114602c370SMinda Chen { 1124602c370SMinda Chen struct irq_data *d = irq_domain_get_irq_data(domain, virq); 1134602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d); 1144602c370SMinda Chen struct plda_msi *msi = &port->msi; 1154602c370SMinda Chen 1164602c370SMinda Chen mutex_lock(&msi->lock); 1174602c370SMinda Chen 1184602c370SMinda Chen if (test_bit(d->hwirq, msi->used)) 1194602c370SMinda Chen __clear_bit(d->hwirq, msi->used); 1204602c370SMinda Chen else 1214602c370SMinda Chen dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq); 1224602c370SMinda Chen 1234602c370SMinda Chen mutex_unlock(&msi->lock); 1244602c370SMinda Chen } 1254602c370SMinda Chen 1264602c370SMinda Chen static const struct irq_domain_ops msi_domain_ops = { 1274602c370SMinda Chen .alloc = plda_irq_msi_domain_alloc, 1284602c370SMinda Chen .free = plda_irq_msi_domain_free, 1294602c370SMinda Chen }; 1304602c370SMinda Chen 1314602c370SMinda Chen static struct irq_chip plda_msi_irq_chip = { 1324602c370SMinda Chen .name = "PLDA PCIe MSI", 1334602c370SMinda Chen .irq_ack = irq_chip_ack_parent, 1344602c370SMinda Chen .irq_mask = pci_msi_mask_irq, 1354602c370SMinda Chen .irq_unmask = pci_msi_unmask_irq, 1364602c370SMinda Chen }; 1374602c370SMinda Chen 1384602c370SMinda Chen static struct msi_domain_info plda_msi_domain_info = { 1394602c370SMinda Chen .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 1404602c370SMinda Chen MSI_FLAG_PCI_MSIX), 1414602c370SMinda Chen .chip = &plda_msi_irq_chip, 1424602c370SMinda Chen }; 1434602c370SMinda Chen 1444602c370SMinda Chen static int plda_allocate_msi_domains(struct plda_pcie_rp *port) 1454602c370SMinda Chen { 1464602c370SMinda Chen struct device *dev = port->dev; 1474602c370SMinda Chen struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node); 1484602c370SMinda Chen struct plda_msi *msi = &port->msi; 1494602c370SMinda Chen 1504602c370SMinda Chen mutex_init(&port->msi.lock); 1514602c370SMinda Chen 1524602c370SMinda Chen msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors, 1534602c370SMinda Chen &msi_domain_ops, port); 1544602c370SMinda Chen if (!msi->dev_domain) { 1554602c370SMinda Chen dev_err(dev, "failed to create IRQ domain\n"); 1564602c370SMinda Chen return -ENOMEM; 1574602c370SMinda Chen } 1584602c370SMinda Chen 1594602c370SMinda Chen msi->msi_domain = pci_msi_create_irq_domain(fwnode, 1604602c370SMinda Chen &plda_msi_domain_info, 1614602c370SMinda Chen msi->dev_domain); 1624602c370SMinda Chen if (!msi->msi_domain) { 1634602c370SMinda Chen dev_err(dev, "failed to create MSI domain\n"); 1644602c370SMinda Chen irq_domain_remove(msi->dev_domain); 1654602c370SMinda Chen return -ENOMEM; 1664602c370SMinda Chen } 1674602c370SMinda Chen 1684602c370SMinda Chen return 0; 1694602c370SMinda Chen } 1704602c370SMinda Chen 1714602c370SMinda Chen static void plda_handle_intx(struct irq_desc *desc) 1724602c370SMinda Chen { 1734602c370SMinda Chen struct plda_pcie_rp *port = irq_desc_get_handler_data(desc); 1744602c370SMinda Chen struct irq_chip *chip = irq_desc_get_chip(desc); 1754602c370SMinda Chen struct device *dev = port->dev; 1764602c370SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 1774602c370SMinda Chen unsigned long status; 1784602c370SMinda Chen u32 bit; 1794602c370SMinda Chen int ret; 1804602c370SMinda Chen 1814602c370SMinda Chen chained_irq_enter(chip, desc); 1824602c370SMinda Chen 1834602c370SMinda Chen status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL); 1844602c370SMinda Chen if (status & PM_MSI_INT_INTX_MASK) { 1854602c370SMinda Chen status &= PM_MSI_INT_INTX_MASK; 1864602c370SMinda Chen status >>= PM_MSI_INT_INTX_SHIFT; 1874602c370SMinda Chen for_each_set_bit(bit, &status, PCI_NUM_INTX) { 1884602c370SMinda Chen ret = generic_handle_domain_irq(port->intx_domain, bit); 1894602c370SMinda Chen if (ret) 1904602c370SMinda Chen dev_err_ratelimited(dev, "bad INTx IRQ %d\n", 1914602c370SMinda Chen bit); 1924602c370SMinda Chen } 1934602c370SMinda Chen } 1944602c370SMinda Chen 1954602c370SMinda Chen chained_irq_exit(chip, desc); 1964602c370SMinda Chen } 1974602c370SMinda Chen 1984602c370SMinda Chen static void plda_ack_intx_irq(struct irq_data *data) 1994602c370SMinda Chen { 2004602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 2014602c370SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 2024602c370SMinda Chen u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); 2034602c370SMinda Chen 2044602c370SMinda Chen writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL); 2054602c370SMinda Chen } 2064602c370SMinda Chen 2074602c370SMinda Chen static void plda_mask_intx_irq(struct irq_data *data) 2084602c370SMinda Chen { 2094602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 2104602c370SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 2114602c370SMinda Chen unsigned long flags; 2124602c370SMinda Chen u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); 2134602c370SMinda Chen u32 val; 2144602c370SMinda Chen 2154602c370SMinda Chen raw_spin_lock_irqsave(&port->lock, flags); 2164602c370SMinda Chen val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); 2174602c370SMinda Chen val &= ~mask; 2184602c370SMinda Chen writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); 2194602c370SMinda Chen raw_spin_unlock_irqrestore(&port->lock, flags); 2204602c370SMinda Chen } 2214602c370SMinda Chen 2224602c370SMinda Chen static void plda_unmask_intx_irq(struct irq_data *data) 2234602c370SMinda Chen { 2244602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 2254602c370SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 2264602c370SMinda Chen unsigned long flags; 2274602c370SMinda Chen u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT); 2284602c370SMinda Chen u32 val; 2294602c370SMinda Chen 2304602c370SMinda Chen raw_spin_lock_irqsave(&port->lock, flags); 2314602c370SMinda Chen val = readl_relaxed(bridge_base_addr + IMASK_LOCAL); 2324602c370SMinda Chen val |= mask; 2334602c370SMinda Chen writel_relaxed(val, bridge_base_addr + IMASK_LOCAL); 2344602c370SMinda Chen raw_spin_unlock_irqrestore(&port->lock, flags); 2354602c370SMinda Chen } 2364602c370SMinda Chen 2374602c370SMinda Chen static struct irq_chip plda_intx_irq_chip = { 2384602c370SMinda Chen .name = "PLDA PCIe INTx", 2394602c370SMinda Chen .irq_ack = plda_ack_intx_irq, 2404602c370SMinda Chen .irq_mask = plda_mask_intx_irq, 2414602c370SMinda Chen .irq_unmask = plda_unmask_intx_irq, 2424602c370SMinda Chen }; 2434602c370SMinda Chen 2444602c370SMinda Chen static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq, 2454602c370SMinda Chen irq_hw_number_t hwirq) 2464602c370SMinda Chen { 2474602c370SMinda Chen irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq); 2484602c370SMinda Chen irq_set_chip_data(irq, domain->host_data); 2494602c370SMinda Chen 2504602c370SMinda Chen return 0; 2514602c370SMinda Chen } 2524602c370SMinda Chen 2534602c370SMinda Chen static const struct irq_domain_ops intx_domain_ops = { 2544602c370SMinda Chen .map = plda_pcie_intx_map, 2554602c370SMinda Chen }; 2564602c370SMinda Chen 2574602c370SMinda Chen static u32 plda_get_events(struct plda_pcie_rp *port) 2584602c370SMinda Chen { 2594602c370SMinda Chen u32 events, val, origin; 2604602c370SMinda Chen 2614602c370SMinda Chen origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL); 2624602c370SMinda Chen 2634602c370SMinda Chen /* MSI event and sys events */ 2644602c370SMinda Chen val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT; 2654602c370SMinda Chen events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1); 2664602c370SMinda Chen 2674602c370SMinda Chen /* INTx events */ 2684602c370SMinda Chen if (origin & PM_MSI_INT_INTX_MASK) 2694602c370SMinda Chen events |= BIT(PM_MSI_INT_INTX_SHIFT); 2704602c370SMinda Chen 2714602c370SMinda Chen /* remains are same with register */ 2724602c370SMinda Chen events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0); 2734602c370SMinda Chen 2744602c370SMinda Chen return events; 2754602c370SMinda Chen } 2764602c370SMinda Chen 2774602c370SMinda Chen static irqreturn_t plda_event_handler(int irq, void *dev_id) 2784602c370SMinda Chen { 2794602c370SMinda Chen return IRQ_HANDLED; 2804602c370SMinda Chen } 2814602c370SMinda Chen 2824602c370SMinda Chen static void plda_handle_event(struct irq_desc *desc) 2834602c370SMinda Chen { 2844602c370SMinda Chen struct plda_pcie_rp *port = irq_desc_get_handler_data(desc); 2854602c370SMinda Chen unsigned long events; 2864602c370SMinda Chen u32 bit; 2874602c370SMinda Chen struct irq_chip *chip = irq_desc_get_chip(desc); 2884602c370SMinda Chen 2894602c370SMinda Chen chained_irq_enter(chip, desc); 2904602c370SMinda Chen 2914602c370SMinda Chen events = port->event_ops->get_events(port); 2924602c370SMinda Chen 293*a576fff3SMinda Chen events &= port->events_bitmap; 2944602c370SMinda Chen for_each_set_bit(bit, &events, port->num_events) 2954602c370SMinda Chen generic_handle_domain_irq(port->event_domain, bit); 2964602c370SMinda Chen 2974602c370SMinda Chen chained_irq_exit(chip, desc); 2984602c370SMinda Chen } 2994602c370SMinda Chen 3004602c370SMinda Chen static u32 plda_hwirq_to_mask(int hwirq) 3014602c370SMinda Chen { 3024602c370SMinda Chen u32 mask; 3034602c370SMinda Chen 3044602c370SMinda Chen /* hwirq 23 - 0 are the same with register */ 3054602c370SMinda Chen if (hwirq < EVENT_PM_MSI_INT_INTX) 3064602c370SMinda Chen mask = BIT(hwirq); 3074602c370SMinda Chen else if (hwirq == EVENT_PM_MSI_INT_INTX) 3084602c370SMinda Chen mask = PM_MSI_INT_INTX_MASK; 3094602c370SMinda Chen else 3104602c370SMinda Chen mask = BIT(hwirq + PCI_NUM_INTX - 1); 3114602c370SMinda Chen 3124602c370SMinda Chen return mask; 3134602c370SMinda Chen } 3144602c370SMinda Chen 3154602c370SMinda Chen static void plda_ack_event_irq(struct irq_data *data) 3164602c370SMinda Chen { 3174602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 3184602c370SMinda Chen 3194602c370SMinda Chen writel_relaxed(plda_hwirq_to_mask(data->hwirq), 3204602c370SMinda Chen port->bridge_addr + ISTATUS_LOCAL); 3214602c370SMinda Chen } 3224602c370SMinda Chen 3234602c370SMinda Chen static void plda_mask_event_irq(struct irq_data *data) 3244602c370SMinda Chen { 3254602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 3264602c370SMinda Chen u32 mask, val; 3274602c370SMinda Chen 3284602c370SMinda Chen mask = plda_hwirq_to_mask(data->hwirq); 3294602c370SMinda Chen 3304602c370SMinda Chen raw_spin_lock(&port->lock); 3314602c370SMinda Chen val = readl_relaxed(port->bridge_addr + IMASK_LOCAL); 3324602c370SMinda Chen val &= ~mask; 3334602c370SMinda Chen writel_relaxed(val, port->bridge_addr + IMASK_LOCAL); 3344602c370SMinda Chen raw_spin_unlock(&port->lock); 3354602c370SMinda Chen } 3364602c370SMinda Chen 3374602c370SMinda Chen static void plda_unmask_event_irq(struct irq_data *data) 3384602c370SMinda Chen { 3394602c370SMinda Chen struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data); 3404602c370SMinda Chen u32 mask, val; 3414602c370SMinda Chen 3424602c370SMinda Chen mask = plda_hwirq_to_mask(data->hwirq); 3434602c370SMinda Chen 3444602c370SMinda Chen raw_spin_lock(&port->lock); 3454602c370SMinda Chen val = readl_relaxed(port->bridge_addr + IMASK_LOCAL); 3464602c370SMinda Chen val |= mask; 3474602c370SMinda Chen writel_relaxed(val, port->bridge_addr + IMASK_LOCAL); 3484602c370SMinda Chen raw_spin_unlock(&port->lock); 3494602c370SMinda Chen } 3504602c370SMinda Chen 3514602c370SMinda Chen static struct irq_chip plda_event_irq_chip = { 3524602c370SMinda Chen .name = "PLDA PCIe EVENT", 3534602c370SMinda Chen .irq_ack = plda_ack_event_irq, 3544602c370SMinda Chen .irq_mask = plda_mask_event_irq, 3554602c370SMinda Chen .irq_unmask = plda_unmask_event_irq, 3564602c370SMinda Chen }; 3574602c370SMinda Chen 3584602c370SMinda Chen static const struct plda_event_ops plda_event_ops = { 3594602c370SMinda Chen .get_events = plda_get_events, 3604602c370SMinda Chen }; 3614602c370SMinda Chen 3624602c370SMinda Chen static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq, 3634602c370SMinda Chen irq_hw_number_t hwirq) 3644602c370SMinda Chen { 3654602c370SMinda Chen struct plda_pcie_rp *port = (void *)domain->host_data; 3664602c370SMinda Chen 3674602c370SMinda Chen irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq); 3684602c370SMinda Chen irq_set_chip_data(irq, domain->host_data); 3694602c370SMinda Chen 3704602c370SMinda Chen return 0; 3714602c370SMinda Chen } 3724602c370SMinda Chen 3734602c370SMinda Chen static const struct irq_domain_ops plda_event_domain_ops = { 3744602c370SMinda Chen .map = plda_pcie_event_map, 3754602c370SMinda Chen }; 3764602c370SMinda Chen 3774602c370SMinda Chen static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port) 3784602c370SMinda Chen { 3794602c370SMinda Chen struct device *dev = port->dev; 3804602c370SMinda Chen struct device_node *node = dev->of_node; 3814602c370SMinda Chen struct device_node *pcie_intc_node; 3824602c370SMinda Chen 3834602c370SMinda Chen /* Setup INTx */ 3844602c370SMinda Chen pcie_intc_node = of_get_next_child(node, NULL); 3854602c370SMinda Chen if (!pcie_intc_node) { 3864602c370SMinda Chen dev_err(dev, "failed to find PCIe Intc node\n"); 3874602c370SMinda Chen return -EINVAL; 3884602c370SMinda Chen } 3894602c370SMinda Chen 3904602c370SMinda Chen port->event_domain = irq_domain_add_linear(pcie_intc_node, 3914602c370SMinda Chen port->num_events, 3924602c370SMinda Chen &plda_event_domain_ops, 3934602c370SMinda Chen port); 3944602c370SMinda Chen if (!port->event_domain) { 3954602c370SMinda Chen dev_err(dev, "failed to get event domain\n"); 3964602c370SMinda Chen of_node_put(pcie_intc_node); 3974602c370SMinda Chen return -ENOMEM; 3984602c370SMinda Chen } 3994602c370SMinda Chen 4004602c370SMinda Chen irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS); 4014602c370SMinda Chen 4024602c370SMinda Chen port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, 4034602c370SMinda Chen &intx_domain_ops, port); 4044602c370SMinda Chen if (!port->intx_domain) { 4054602c370SMinda Chen dev_err(dev, "failed to get an INTx IRQ domain\n"); 4064602c370SMinda Chen of_node_put(pcie_intc_node); 4074602c370SMinda Chen return -ENOMEM; 4084602c370SMinda Chen } 4094602c370SMinda Chen 4104602c370SMinda Chen irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED); 4114602c370SMinda Chen 4124602c370SMinda Chen of_node_put(pcie_intc_node); 4134602c370SMinda Chen raw_spin_lock_init(&port->lock); 4144602c370SMinda Chen 4154602c370SMinda Chen return plda_allocate_msi_domains(port); 4164602c370SMinda Chen } 4174602c370SMinda Chen 4184602c370SMinda Chen int plda_init_interrupts(struct platform_device *pdev, 4194602c370SMinda Chen struct plda_pcie_rp *port, 4204602c370SMinda Chen const struct plda_event *event) 4214602c370SMinda Chen { 4224602c370SMinda Chen struct device *dev = &pdev->dev; 4234602c370SMinda Chen int irq; 424*a576fff3SMinda Chen int intx_irq, msi_irq, event_irq; 4254602c370SMinda Chen int ret; 426*a576fff3SMinda Chen u32 i; 4274602c370SMinda Chen 4284602c370SMinda Chen if (!port->event_ops) 4294602c370SMinda Chen port->event_ops = &plda_event_ops; 4304602c370SMinda Chen 4314602c370SMinda Chen if (!port->event_irq_chip) 4324602c370SMinda Chen port->event_irq_chip = &plda_event_irq_chip; 4334602c370SMinda Chen 4344602c370SMinda Chen ret = plda_pcie_init_irq_domains(port); 4354602c370SMinda Chen if (ret) { 4364602c370SMinda Chen dev_err(dev, "failed creating IRQ domains\n"); 4374602c370SMinda Chen return ret; 4384602c370SMinda Chen } 4394602c370SMinda Chen 4404602c370SMinda Chen irq = platform_get_irq(pdev, 0); 4414602c370SMinda Chen if (irq < 0) 4424602c370SMinda Chen return -ENODEV; 4434602c370SMinda Chen 444*a576fff3SMinda Chen for_each_set_bit(i, &port->events_bitmap, port->num_events) { 4454602c370SMinda Chen event_irq = irq_create_mapping(port->event_domain, i); 4464602c370SMinda Chen if (!event_irq) { 4474602c370SMinda Chen dev_err(dev, "failed to map hwirq %d\n", i); 4484602c370SMinda Chen return -ENXIO; 4494602c370SMinda Chen } 4504602c370SMinda Chen 4514602c370SMinda Chen if (event->request_event_irq) 4524602c370SMinda Chen ret = event->request_event_irq(port, event_irq, i); 4534602c370SMinda Chen else 4544602c370SMinda Chen ret = devm_request_irq(dev, event_irq, 4554602c370SMinda Chen plda_event_handler, 4564602c370SMinda Chen 0, NULL, port); 4574602c370SMinda Chen 4584602c370SMinda Chen if (ret) { 4594602c370SMinda Chen dev_err(dev, "failed to request IRQ %d\n", event_irq); 4604602c370SMinda Chen return ret; 4614602c370SMinda Chen } 4624602c370SMinda Chen } 4634602c370SMinda Chen 4644602c370SMinda Chen intx_irq = irq_create_mapping(port->event_domain, 4654602c370SMinda Chen event->intx_event); 4664602c370SMinda Chen if (!intx_irq) { 4674602c370SMinda Chen dev_err(dev, "failed to map INTx interrupt\n"); 4684602c370SMinda Chen return -ENXIO; 4694602c370SMinda Chen } 4704602c370SMinda Chen 4714602c370SMinda Chen /* Plug the INTx chained handler */ 4724602c370SMinda Chen irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port); 4734602c370SMinda Chen 4744602c370SMinda Chen msi_irq = irq_create_mapping(port->event_domain, 4754602c370SMinda Chen event->msi_event); 4764602c370SMinda Chen if (!msi_irq) 4774602c370SMinda Chen return -ENXIO; 4784602c370SMinda Chen 4794602c370SMinda Chen /* Plug the MSI chained handler */ 4804602c370SMinda Chen irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port); 4814602c370SMinda Chen 4824602c370SMinda Chen /* Plug the main event chained handler */ 4834602c370SMinda Chen irq_set_chained_handler_and_data(irq, plda_handle_event, port); 4844602c370SMinda Chen 4854602c370SMinda Chen return 0; 4864602c370SMinda Chen } 4874602c370SMinda Chen EXPORT_SYMBOL_GPL(plda_init_interrupts); 4884602c370SMinda Chen 48939bd5f82SMinda Chen void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index, 49039bd5f82SMinda Chen phys_addr_t axi_addr, phys_addr_t pci_addr, 49139bd5f82SMinda Chen size_t size) 49239bd5f82SMinda Chen { 49339bd5f82SMinda Chen u32 atr_sz = ilog2(size) - 1; 49439bd5f82SMinda Chen u32 val; 49539bd5f82SMinda Chen 49639bd5f82SMinda Chen if (index == 0) 49739bd5f82SMinda Chen val = PCIE_CONFIG_INTERFACE; 49839bd5f82SMinda Chen else 49939bd5f82SMinda Chen val = PCIE_TX_RX_INTERFACE; 50039bd5f82SMinda Chen 50139bd5f82SMinda Chen writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + 50239bd5f82SMinda Chen ATR0_AXI4_SLV0_TRSL_PARAM); 50339bd5f82SMinda Chen 50439bd5f82SMinda Chen val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) | 50539bd5f82SMinda Chen ATR_IMPL_ENABLE; 50639bd5f82SMinda Chen writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + 50739bd5f82SMinda Chen ATR0_AXI4_SLV0_SRCADDR_PARAM); 50839bd5f82SMinda Chen 50939bd5f82SMinda Chen val = upper_32_bits(axi_addr); 51039bd5f82SMinda Chen writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + 51139bd5f82SMinda Chen ATR0_AXI4_SLV0_SRC_ADDR); 51239bd5f82SMinda Chen 51339bd5f82SMinda Chen val = lower_32_bits(pci_addr); 51439bd5f82SMinda Chen writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + 51539bd5f82SMinda Chen ATR0_AXI4_SLV0_TRSL_ADDR_LSB); 51639bd5f82SMinda Chen 51739bd5f82SMinda Chen val = upper_32_bits(pci_addr); 51839bd5f82SMinda Chen writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) + 51939bd5f82SMinda Chen ATR0_AXI4_SLV0_TRSL_ADDR_UDW); 52039bd5f82SMinda Chen 52139bd5f82SMinda Chen val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); 52239bd5f82SMinda Chen val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT); 52339bd5f82SMinda Chen writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM); 52439bd5f82SMinda Chen writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR); 52539bd5f82SMinda Chen } 52639bd5f82SMinda Chen EXPORT_SYMBOL_GPL(plda_pcie_setup_window); 52739bd5f82SMinda Chen 52839bd5f82SMinda Chen int plda_pcie_setup_iomems(struct platform_device *pdev, 52939bd5f82SMinda Chen struct plda_pcie_rp *port) 53039bd5f82SMinda Chen { 53139bd5f82SMinda Chen void __iomem *bridge_base_addr = port->bridge_addr; 53239bd5f82SMinda Chen struct pci_host_bridge *bridge = platform_get_drvdata(pdev); 53339bd5f82SMinda Chen struct resource_entry *entry; 53439bd5f82SMinda Chen u64 pci_addr; 53539bd5f82SMinda Chen u32 index = 1; 53639bd5f82SMinda Chen 53739bd5f82SMinda Chen resource_list_for_each_entry(entry, &bridge->windows) { 53839bd5f82SMinda Chen if (resource_type(entry->res) == IORESOURCE_MEM) { 53939bd5f82SMinda Chen pci_addr = entry->res->start - entry->offset; 54039bd5f82SMinda Chen plda_pcie_setup_window(bridge_base_addr, index, 54139bd5f82SMinda Chen entry->res->start, pci_addr, 54239bd5f82SMinda Chen resource_size(entry->res)); 54339bd5f82SMinda Chen index++; 54439bd5f82SMinda Chen } 54539bd5f82SMinda Chen } 54639bd5f82SMinda Chen 54739bd5f82SMinda Chen return 0; 54839bd5f82SMinda Chen } 54939bd5f82SMinda Chen EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems); 550