[PATCH 1/3] PCI: designware: add legacy PCI interrupt mapping
Jingoo Han
jg1.han at samsung.com
Fri Feb 28 02:01:46 EST 2014
On Friday, February 28, 2014 1:25 PM, Tim Harvey wrote:
> On Thu, Feb 27, 2014 at 6:00 PM, Jingoo Han <jg1.han at samsung.com> wrote:
> > On Friday, February 28, 2014 10:20 AM, Tim Harvey wrote:
> >>
> >> The IMX6 maps INTA/B/C/D to ARM GIC IRQ 155/154/153/152 respectively.
> >> This allows a PCIe-to-PCI bridge to function properly.
> >>
> >> The irq field of the pcie_host struct is expanded to 4 interrupts to
> >> allow for INTA/B/C/D and the IMX6 PCIe host driver will populate them
> >> all from devicetree. I'm not clear if the Exynos driver has this
> >> capability so it places the same interrupt in all 4 slots.
> >
> > (+cc Marek Vasut, Pratyush Anand, Kishon Vijay Abraham I, Mohit KUMAR DCG)
> >
> > In the case of Exynos,
> > 'INTA/B/C/D' are mapped to only one interrupt (<0 20 0>).
> > Thus, the current code works properly on Exynos platform.
> >
> > There are three interrupts for Exynos PCIe; INTx, MSI, PHY Link,
> > respectively as below.
> >
> > ./arch/arm/boot/dts/exynos5440.dtsi
> > interrupts = <0 20 0>, <0 21 0>, <0 22 0>;
> >
> > <0 20 0>: PCIe RC0 pulse interrupt,
> > INTA, INTB, INTC and INTD, etc
> > <0 21 0>: PCIe RC0 level interrupt,
> > MSI, etc
> > <0 22 0>: PCIe RC0 special interrupt,
> > PHY Link related interrupts, etc
> >
> > Of course, legacy INTx is handled as message only.
> >
> > Mohit, Kishon,
> > How about the other SoCs? INTx is mapped to single interrupt
> > such as Exynos, or separate interrupts such as i.MX6?
>
> Jingoo,
>
> Ok - so at least the I.MX6 and Exynos, which both use the designware
> IP need different IRQ mappings. It seems to me then that the map_irq
> should be moved out of drivers/pci/host/pcie-designware.c and into the
> SoC specific host controller drivers (pci-imx.c and pci-exynos.c). If
> that becomes the consensus I can submit a patch that does that.
(+CC Arnd Bergmann)
If you want to split dw_pcie_map_irq(), the following would be better.
./drivers/pci/host/pcie-designware.c
static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
if (pp->ops->writel_rc)
return pp->ops->map_irq(pp, pin);
else
return pp->irq;
}
./drivers/pci/host/pci-imx6.c
static int imx6_pcie_map_irq(struct pcie_port *pp, u8 pin)
{
.....
}
Also, please add additional 'irq[4]' variable to 'struct imx6_pcie',
instead of 'struct pcie_port'. Other SoCs does not use four separate
INTx, as far as I know.
Best regards,
Jingoo Han
>
> Thanks,
>
> Tim
>
> >
> > Best regards,
> > Jingoo Han
> >
> >>
> >> Signed-off-by: Tim Harvey <tharvey at gateworks.com>
> >> Cc: Bjorn Helgaas <bhelgaas at google.com>
> >> Cc: Richard Zhu <r65037 at freescale.com>
> >> Cc: Shawn Guo <shawn.guo at linaro.org>
> >> Cc: Lucas Stach <l.stach at pengutronix.de>
> >> Cc: Sean Cross <xobs at kosagi.com>
> >> Cc: Jingoo Han <jg1.han at samsung.com>
> >> ---
> >> arch/arm/boot/dts/imx6qdl.dtsi | 2 +-
> >> drivers/pci/host/pci-exynos.c | 7 +++++--
> >> drivers/pci/host/pci-imx6.c | 11 +++++++----
> >> drivers/pci/host/pcie-designware.c | 8 +++++++-
> >> drivers/pci/host/pcie-designware.h | 2 +-
> >> 5 files changed, 21 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> >> index eed6897..fad8d90 100644
> >> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> >> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> >> @@ -126,7 +126,7 @@
> >> 0x81000000 0 0 0x01f80000 0 0x00010000 /* downstream I/O */
> >> 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable
> >> memory */
> >> num-lanes = <1>;
> >> - interrupts = <0 123 0x04>;
> >> + interrupts = <0 123 0x04>, <0 122 0x04>, <0 121 0x04>, <0 120 0x04>;
> >> clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
> >> clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
> >> status = "disabled";
> >> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
> >> index 3de6bfb..d85dcb0 100644
> >> --- a/drivers/pci/host/pci-exynos.c
> >> +++ b/drivers/pci/host/pci-exynos.c
> >> @@ -515,11 +515,14 @@ static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
> >> {
> >> int ret;
> >>
> >> - pp->irq = platform_get_irq(pdev, 1);
> >> - if (!pp->irq) {
> >> + pp->irq[0] = platform_get_irq(pdev, 1);
> >> + if (!pp->irq[0]) {
> >> dev_err(&pdev->dev, "failed to get irq\n");
> >> return -ENODEV;
> >> }
> >> + pp->irq[1] = pp->irq[0];
> >> + pp->irq[2] = pp->irq[0];
> >> + pp->irq[3] = pp->irq[0];
> >> ret = devm_request_irq(&pdev->dev, pp->irq, exynos_pcie_irq_handler,
> >> IRQF_SHARED, "exynos-pcie", pp);
> >> if (ret) {
> >> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> >> index e8663a8..aaa05c8 100644
> >> --- a/drivers/pci/host/pci-imx6.c
> >> +++ b/drivers/pci/host/pci-imx6.c
> >> @@ -470,11 +470,14 @@ static int imx6_add_pcie_port(struct pcie_port *pp,
> >> struct platform_device *pdev)
> >> {
> >> int ret;
> >> + int i;
> >>
> >> - pp->irq = platform_get_irq(pdev, 0);
> >> - if (!pp->irq) {
> >> - dev_err(&pdev->dev, "failed to get irq\n");
> >> - return -ENODEV;
> >> + for (i = 0; i < 4; i++) {
> >> + pp->irq[i] = platform_get_irq(pdev, i);
> >> + if (!pp->irq[i]) {
> >> + dev_err(&pdev->dev, "failed to get irq%d\n", i);
> >> + return -ENODEV;
> >> + }
> >> }
> >>
> >> pp->root_bus_nr = -1;
> >> diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
> >> index 17ce88f..5808177 100644
> >> --- a/drivers/pci/host/pcie-designware.c
> >> +++ b/drivers/pci/host/pcie-designware.c
> >> @@ -738,8 +738,14 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> >> static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> >> {
> >> struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> >> + int irq = -1;
> >>
> >> - return pp->irq;
> >> + if (pin > 0 && pin < 5)
> >> + irq = pp->irq[pin - 1];
> >> + dev_info(&dev->dev, "map_irq: %04x:%04x slot%d pin%d irq%d\n",
> >> + dev->vendor, dev->device, slot, pin, irq);
> >> +
> >> + return irq;
> >> }
> >>
> >> static void dw_pcie_add_bus(struct pci_bus *bus)
> >> diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
> >> index 3063b35..5c596c0 100644
> >> --- a/drivers/pci/host/pcie-designware.h
> >> +++ b/drivers/pci/host/pcie-designware.h
> >> @@ -46,7 +46,7 @@ struct pcie_port {
> >> struct resource io;
> >> struct resource mem;
> >> struct pcie_port_info config;
> >> - int irq;
> >> + int irq[4];
> >> u32 lanes;
> >> struct pcie_host_ops *ops;
> >> int msi_irq;
> >> --
> >> 1.8.3.2
> >
More information about the linux-arm-kernel
mailing list