From 3db6a541c8747f80a2a6ef255dbd7941d779ea2f Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Thu, 28 Jan 2016 14:50:59 -0500 Subject: [PATCH] Quark: Set up IRQ routing for PCIe explicitly IRQAGENT3 is initialized explicitly, but IRQAGENT0 isn't and its value is based on the value the BIOS or bootloader had set before. Fix this by explicitly initializing IRQAGENT0, and swizzle the IRQs to reduce conflicts. Update the pci_pin2irq function to accommodate for these changes. Also remove pci_irq2pin function since it is unused. Change-Id: I7b1dfc7659ab227fe66711a3af5a1f34fd4a7972 Signed-off-by: Ido Yariv Signed-off-by: Anas Nashif Signed-off-by: Ido Yariv --- arch/x86/soc/quark_x1000/soc.c | 4 ++++ arch/x86/soc/quark_x1000/soc.h | 27 ++++++++++----------------- drivers/pci/pci.c | 11 +++++------ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/arch/x86/soc/quark_x1000/soc.c b/arch/x86/soc/quark_x1000/soc.c index 22c9eb4b033..f7f05ba0c3c 100644 --- a/arch/x86/soc/quark_x1000/soc.c +++ b/arch/x86/soc/quark_x1000/soc.c @@ -63,6 +63,10 @@ static int pci_legacy_bridge_irq_config(struct device *unused) pci_legacy_bridge_configure(&info, 1, PCI_INTB, 17); pci_legacy_bridge_configure(&info, 1, PCI_INTC, 18); pci_legacy_bridge_configure(&info, 1, PCI_INTD, 19); + pci_legacy_bridge_configure(&info, 0, PCI_INTA, 17); + pci_legacy_bridge_configure(&info, 0, PCI_INTB, 18); + pci_legacy_bridge_configure(&info, 0, PCI_INTC, 19); + pci_legacy_bridge_configure(&info, 0, PCI_INTD, 16); } return 0; } diff --git a/arch/x86/soc/quark_x1000/soc.h b/arch/x86/soc/quark_x1000/soc.h index ce00c922fba..0141c4222fa 100644 --- a/arch/x86/soc/quark_x1000/soc.h +++ b/arch/x86/soc/quark_x1000/soc.h @@ -95,30 +95,23 @@ extern "C" { * INTC (pin 3) -> IRQ 18 * INTD (pin 4) -> IRQ 19 * + * In case a mini-PCIe card is used, the IRQs are swizzled: + * INTA (pin 1) -> IRQ 17 + * INTB (pin 2) -> IRQ 18 + * INTC (pin 3) -> IRQ 19 + * INTD (pin 4) -> IRQ 16 + * * @return IRQ number, -1 if the result is incorrect * */ -static inline int pci_pin2irq(int pin) +static inline int pci_pin2irq(int bus, int dev, int pin) { + if (bus < 0 || bus > 1) + return -1; if ((pin < PCI_INTA) || (pin > PCI_INTD)) return -1; - return NUM_STD_IRQS + pin - 1; -} - -/** - * - * @brief Convert IRQ to PCI interrupt pin - * - * @return pin number, -1 if the result is incorrect - * - */ - -static inline int pci_irq2pin(int irq) -{ - if ((irq < NUM_STD_IRQS) || (irq > NUM_STD_IRQS + PCI_INTD - 1)) - return -1; - return irq - NUM_STD_IRQS + 1; + return NUM_STD_IRQS + ((pin - 1 + bus) & 3); } #ifdef __cplusplus diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d9ef75dc775..5e06be6572d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -314,13 +314,16 @@ static inline int pci_dev_scan(union pci_addr_reg pci_ctrl_addr, lookup.baridx != lookup.info.bar) { continue; } else { + dev_info->bus = lookup.bus; + dev_info->dev = lookup.dev; dev_info->vendor_id = pci_dev_header.field.vendor_id; dev_info->device_id = pci_dev_header.field.device_id; dev_info->class_type = pci_dev_header.field.class; - dev_info->irq = pci_pin2irq( + dev_info->irq = pci_pin2irq(dev_info->bus, + dev_info->dev, pci_dev_header.field.interrupt_pin); dev_info->function = lookup.func; dev_info->bar = lookup.baridx; @@ -395,12 +398,8 @@ int pci_bus_scan(struct pci_dev_info *dev_info) pci_ctrl_addr.field.bus = lookup.bus; pci_ctrl_addr.field.device = lookup.dev; - if (pci_dev_scan(pci_ctrl_addr, dev_info)) { - dev_info->bus = lookup.bus; - dev_info->dev = lookup.dev; - + if (pci_dev_scan(pci_ctrl_addr, dev_info)) return 1; - } if (lookup.info.function != PCI_FUNCTION_ANY) { lookup.func = lookup.info.function;