ramips: mt7621: backport more pcie driver fixes
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
This commit is contained in:
parent
13a185bf8a
commit
51c6b14092
@ -568,11 +568,10 @@
|
||||
0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */
|
||||
>;
|
||||
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0xF0000 0 0 1>;
|
||||
interrupt-map = <0x10000 0 0 1 &gic GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x20000 0 0 1 &gic GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0x30000 0 0 1 &gic GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH
|
||||
GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH
|
||||
GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
|
@ -0,0 +1,65 @@
|
||||
From 5fcded5e857cf66c9592e4be28c4dab4520c9177 Mon Sep 17 00:00:00 2001
|
||||
From: Sergio Paracuellos <sergio.paracuellos@gmail.com>
|
||||
Date: Thu, 9 Apr 2020 13:16:52 +0200
|
||||
Subject: [PATCH] staging: mt7621-pci: properly power off dual-ported pcie phy
|
||||
|
||||
Pcie phy for pcie0 and pcie1 is shared using a dual ported
|
||||
one. Current code was assuming that if nothing is connected
|
||||
in pcie0 it won't be also nothing connected in pcie1. This
|
||||
assumtion is wrong for some devices such us 'Mikrotik rbm33g'
|
||||
and 'ZyXEL LTE3301-PLUS' where only connecting a card to the
|
||||
second bus on the phy is possible. For such devices kernel
|
||||
hangs in the same point because of the wrong poweroff of the
|
||||
phy getting the following trace:
|
||||
|
||||
mt7621-pci-phy 1e149000.pcie-phy: PHY for 0xbe149000 (dual port = 1)
|
||||
mt7621-pci-phy 1e14a000.pcie-phy: PHY for 0xbe14a000 (dual port = 0)
|
||||
mt7621-pci-phy 1e149000.pcie-phy: Xtal is 40MHz
|
||||
mt7621-pci-phy 1e14a000.pcie-phy: Xtal is 40MHz
|
||||
mt7621-pci 1e140000.pcie: pcie0 no card, disable it (RST & CLK)
|
||||
[hangs]
|
||||
|
||||
The wrong assumption is located in the 'mt7621_pcie_init_ports'
|
||||
function where we are just making a power off of the phy for
|
||||
slots 0 and 2 if nothing is connected in them. Hence, only
|
||||
poweroff the phy if nothing is connected in both slot 0 and
|
||||
slot 1 avoiding the kernel to hang.
|
||||
|
||||
Fixes: 5737cfe87a9c ("staging: mt7621-pci: avoid to poweroff the phy for slot one")
|
||||
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20200409111652.30964-1-sergio.paracuellos@gmail.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/mt7621-pci/pci-mt7621.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/staging/mt7621-pci/pci-mt7621.c
|
||||
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
|
||||
@@ -502,17 +502,25 @@ static void mt7621_pcie_init_ports(struc
|
||||
|
||||
mt7621_pcie_reset_ep_deassert(pcie);
|
||||
|
||||
+ tmp = NULL;
|
||||
list_for_each_entry(port, &pcie->ports, list) {
|
||||
u32 slot = port->slot;
|
||||
|
||||
if (!mt7621_pcie_port_is_linkup(port)) {
|
||||
dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n",
|
||||
slot);
|
||||
- if (slot != 1)
|
||||
- phy_power_off(port->phy);
|
||||
mt7621_control_assert(port);
|
||||
mt7621_pcie_port_clk_disable(port);
|
||||
port->enabled = false;
|
||||
+
|
||||
+ if (slot == 0) {
|
||||
+ tmp = port;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (slot == 1 && tmp && !tmp->enabled)
|
||||
+ phy_power_off(tmp->phy);
|
||||
+
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user