diff options
Diffstat (limited to 'target/linux/ramips/patches-5.10/0121-staging-mt7621-pci-fix-PCIe-interrupt-mapping.patch')
-rw-r--r-- | target/linux/ramips/patches-5.10/0121-staging-mt7621-pci-fix-PCIe-interrupt-mapping.patch | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/target/linux/ramips/patches-5.10/0121-staging-mt7621-pci-fix-PCIe-interrupt-mapping.patch b/target/linux/ramips/patches-5.10/0121-staging-mt7621-pci-fix-PCIe-interrupt-mapping.patch new file mode 100644 index 0000000000..68de6df2db --- /dev/null +++ b/target/linux/ramips/patches-5.10/0121-staging-mt7621-pci-fix-PCIe-interrupt-mapping.patch @@ -0,0 +1,157 @@ +From fab6710e4c51f4eb622f95a08322ab5fdbe3f295 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos <sergio.paracuellos@gmail.com> +Date: Mon, 13 Apr 2020 07:59:42 +0200 +Subject: [PATCH] staging: mt7621-pci: fix PCIe interrupt mapping + +MT7621 has three assigned interrupts for the pcie. This +interrupts should properly being mapped taking into account +which devices are finally connected in which bus according +to link status. So the irq mappings should be as follows +according to link status (three bits indicating which devices +are link up): + +* For PCIe Bus 1 slot 0: + - status = 0x2 || status = 0x6 => IRQ = pcie1_irq (24). + - status = 0x4 => IRQ = pcie2_irq (25). + - default => IRQ = pcie0_irq (23). +* For PCIe Bus 2 slot 0: + - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). + - default => IRQ = pcie1_irq (24). +* For PCIe Bus 2 slot 1: + - status = 0x5 || status = 0x6 => IRQ = pcie2_irq (25). + - default => IRQ = pcie1_irq (24). +* For PCIe Bus 3 any slot: + - default => IRQ = pcie2_irq (25). + +Because of this, the function 'of_irq_parse_and_map_pci' cannot +be used and we need to change device tree information from using +the 'interrupt-map' and 'interrupt-map-mask' properties into an +'interrupts' property to be able to get irq information from the +ports using the 'platform_get_irq' and storing an 'irq-map' into +the pcie driver data node to properly map correct irq using a +new 'mt7621_map_irq' function where this map will be read and the +correct irq returned. + +Fixes: 46d093124df4 ("staging: mt7621-pci: improve interrupt mapping") +Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com> +Link: https://lore.kernel.org/r/20200413055942.2714-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/staging/mt7621-dts/mt7621.dtsi | 9 +++---- + drivers/staging/mt7621-pci/pci-mt7621.c | 36 +++++++++++++++++++++++-- + 2 files changed, 38 insertions(+), 7 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -97,6 +97,7 @@ + * @pcie_rst: pointer to port reset control + * @gpio_rst: gpio reset + * @slot: port slot ++ * @irq: GIC irq + * @enabled: indicates if port is enabled + */ + struct mt7621_pcie_port { +@@ -107,6 +108,7 @@ struct mt7621_pcie_port { + struct reset_control *pcie_rst; + struct gpio_desc *gpio_rst; + u32 slot; ++ int irq; + bool enabled; + }; + +@@ -120,6 +122,7 @@ struct mt7621_pcie_port { + * @dev: Pointer to PCIe device + * @io_map_base: virtual memory base address for io + * @ports: pointer to PCIe port information ++ * @irq_map: irq mapping info according pcie link status + * @resets_inverted: depends on chip revision + * reset lines are inverted. + */ +@@ -135,6 +138,7 @@ struct mt7621_pcie { + } offset; + unsigned long io_map_base; + struct list_head ports; ++ int irq_map[PCIE_P2P_MAX]; + bool resets_inverted; + }; + +@@ -279,6 +283,16 @@ static void setup_cm_memory_region(struc + } + } + ++static int mt7621_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) ++{ ++ struct mt7621_pcie *pcie = pdev->bus->sysdata; ++ struct device *dev = pcie->dev; ++ int irq = pcie->irq_map[slot]; ++ ++ dev_info(dev, "bus=%d slot=%d irq=%d\n", pdev->bus->number, slot, irq); ++ return irq; ++} ++ + static int mt7621_pci_parse_request_of_pci_ranges(struct mt7621_pcie *pcie) + { + struct device *dev = pcie->dev; +@@ -330,6 +344,7 @@ static int mt7621_pcie_parse_port(struct + { + struct mt7621_pcie_port *port; + struct device *dev = pcie->dev; ++ struct platform_device *pdev = to_platform_device(dev); + struct device_node *pnode = dev->of_node; + struct resource regs; + char name[10]; +@@ -371,6 +386,12 @@ static int mt7621_pcie_parse_port(struct + port->slot = slot; + port->pcie = pcie; + ++ port->irq = platform_get_irq(pdev, slot); ++ if (port->irq < 0) { ++ dev_err(dev, "Failed to get IRQ for PCIe%d\n", slot); ++ return -ENXIO; ++ } ++ + INIT_LIST_HEAD(&port->list); + list_add_tail(&port->list, &pcie->ports); + +@@ -585,13 +606,15 @@ static int mt7621_pcie_init_virtual_brid + { + u32 pcie_link_status = 0; + u32 n; +- int i; ++ int i = 0; + u32 p2p_br_devnum[PCIE_P2P_MAX]; ++ int irqs[PCIE_P2P_MAX]; + struct mt7621_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) { + u32 slot = port->slot; + ++ irqs[i++] = port->irq; + if (port->enabled) + pcie_link_status |= BIT(slot); + } +@@ -614,6 +637,15 @@ static int mt7621_pcie_init_virtual_brid + (p2p_br_devnum[1] << PCIE_P2P_BR_DEVNUM1_SHIFT) | + (p2p_br_devnum[2] << PCIE_P2P_BR_DEVNUM2_SHIFT)); + ++ /* Assign IRQs */ ++ n = 0; ++ for (i = 0; i < PCIE_P2P_MAX; i++) ++ if (pcie_link_status & BIT(i)) ++ pcie->irq_map[n++] = irqs[i]; ++ ++ for (i = n; i < PCIE_P2P_MAX; i++) ++ pcie->irq_map[i] = -1; ++ + return 0; + } + +@@ -638,7 +670,7 @@ static int mt7621_pcie_register_host(str + host->busnr = pcie->busn.start; + host->dev.parent = pcie->dev; + host->ops = &mt7621_pci_ops; +- host->map_irq = of_irq_parse_and_map_pci; ++ host->map_irq = mt7621_map_irq; + host->swizzle_irq = pci_common_swizzle; + host->sysdata = pcie; + |