lkml.org 
[lkml]   [2020]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 117/477] staging: mt7621-pci: fix PCIe interrupt mapping
    Date
    From: Sergio Paracuellos <sergio.paracuellos@gmail.com>

    [ Upstream commit fab6710e4c51f4eb622f95a08322ab5fdbe3f295 ]

    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>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/staging/mt7621-dts/mt7621.dtsi | 9 +++----
    drivers/staging/mt7621-pci/pci-mt7621.c | 36 +++++++++++++++++++++++--
    2 files changed, 38 insertions(+), 7 deletions(-)

    diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
    index 9e5cf68731bb0..82aa93634eda3 100644
    --- a/drivers/staging/mt7621-dts/mt7621.dtsi
    +++ b/drivers/staging/mt7621-dts/mt7621.dtsi
    @@ -523,11 +523,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";

    diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c
    index b9d460a9c0419..36207243a71b0 100644
    --- 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(struct mt7621_pcie *pcie)
    }
    }

    +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 mt7621_pcie *pcie,
    {
    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 mt7621_pcie *pcie,
    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_bridges(struct mt7621_pcie *pcie)
    {
    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_bridges(struct mt7621_pcie *pcie)
    (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(struct pci_host_bridge *host,
    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;

    --
    2.25.1


    \
     
     \ /
      Last update: 2020-06-23 23:42    [W:2.161 / U:0.184 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site