diff options
Diffstat (limited to 'target/linux/atheros/patches-3.14/105-ar2315_pci.patch')
-rw-r--r-- | target/linux/atheros/patches-3.14/105-ar2315_pci.patch | 119 |
1 files changed, 73 insertions, 46 deletions
diff --git a/target/linux/atheros/patches-3.14/105-ar2315_pci.patch b/target/linux/atheros/patches-3.14/105-ar2315_pci.patch index 45f9cdffc0..8009da0684 100644 --- a/target/linux/atheros/patches-3.14/105-ar2315_pci.patch +++ b/target/linux/atheros/patches-3.14/105-ar2315_pci.patch @@ -7,7 +7,7 @@ +obj-$(CONFIG_ATHEROS_AR2315_PCI) += pci.o --- /dev/null +++ b/arch/mips/ar231x/pci.c -@@ -0,0 +1,280 @@ +@@ -0,0 +1,336 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License @@ -174,23 +174,11 @@ + +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ -+ return AR2315_IRQ_LCBUS_PCI; ++ return AR2315_PCI_IRQ_EXT; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ -+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 5); -+ pci_write_config_word(dev, 0x40, 0); -+ -+ /* Clear any pending Abort or external Interrupts -+ * and enable interrupt processing */ -+ ar231x_mask_reg(AR2315_PCI_INTEN_REG, AR2315_PCI_INT_ENABLE, 0); -+ ar231x_write_reg(AR2315_PCI_INT_STATUS, (AR2315_PCI_ABORT_INT | -+ AR2315_PCI_EXT_INT)); -+ ar231x_write_reg(AR2315_PCI_INT_MASK, (AR2315_PCI_ABORT_INT | -+ AR2315_PCI_EXT_INT)); -+ ar231x_mask_reg(AR2315_PCI_INTEN_REG, 0, AR2315_PCI_INT_ENABLE); -+ + return 0; +} + @@ -218,6 +206,72 @@ + return 0; +} + ++static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc) ++{ ++ u32 pending = ar231x_read_reg(AR2315_PCI_ISR) & ++ ar231x_read_reg(AR2315_PCI_IMR); ++ ++ if (pending & AR2315_PCI_INT_EXT) ++ generic_handle_irq(AR2315_PCI_IRQ_EXT); ++ else if (pending & AR2315_PCI_INT_ABORT) ++ generic_handle_irq(AR2315_PCI_IRQ_ABORT); ++ else ++ spurious_interrupt(); ++} ++ ++static void ar2315_pci_irq_mask(struct irq_data *d) ++{ ++ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT); ++ ++ ar231x_mask_reg(AR2315_PCI_IMR, m, 0); ++} ++ ++static void ar2315_pci_irq_mask_ack(struct irq_data *d) ++{ ++ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT); ++ ++ ar231x_mask_reg(AR2315_PCI_IMR, m, 0); ++ ar231x_write_reg(AR2315_PCI_ISR, m); ++} ++ ++static void ar2315_pci_irq_unmask(struct irq_data *d) ++{ ++ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT); ++ ++ ar231x_mask_reg(AR2315_PCI_IMR, 0, m); ++} ++ ++static struct irq_chip ar2315_pci_irq_chip = { ++ .name = "AR2315-PCI", ++ .irq_mask = ar2315_pci_irq_mask, ++ .irq_mask_ack = ar2315_pci_irq_mask_ack, ++ .irq_unmask = ar2315_pci_irq_unmask, ++}; ++ ++static void ar2315_pci_irq_init(void) ++{ ++ int i; ++ ++ ar231x_mask_reg(AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0); ++ ar231x_mask_reg(AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT | ++ AR2315_PCI_INT_EXT), 0); ++ ++ for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) { ++ int irq = AR2315_PCI_IRQ_BASE + i; ++ ++ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip, ++ handle_level_irq); ++ } ++ ++ irq_set_chained_handler(AR2315_IRQ_LCBUS_PCI, ar2315_pci_irq_handler); ++ ++ /* Clear any pending Abort or external Interrupts ++ * and enable interrupt processing */ ++ ar231x_write_reg(AR2315_PCI_ISR, (AR2315_PCI_INT_ABORT | ++ AR2315_PCI_INT_EXT)); ++ ar231x_mask_reg(AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE); ++} ++ +static int __init +ar2315_pci_init(void) +{ @@ -235,9 +289,9 @@ + AR2315_MEM_SIZE, AR2315_IO_SIZE); + set_io_port_base(ar2315_pci_controller.io_map_base); /* PCI I/O space*/ + ++ /* Reset PCI DMA logic */ + reg = ar231x_mask_reg(AR2315_RESET, 0, AR2315_RESET_PCIDMA); + msleep(20); -+ + reg &= ~AR2315_RESET_PCIDMA; + ar231x_write_reg(AR2315_RESET, reg); + msleep(20); @@ -278,6 +332,8 @@ + if (res) + goto error; + ++ ar2315_pci_irq_init(); ++ + register_pci_controller(&ar2315_pci_controller); + + return 0; @@ -303,42 +359,13 @@ + default y --- a/arch/mips/ar231x/ar2315.c +++ b/arch/mips/ar231x/ar2315.c -@@ -87,6 +87,28 @@ static void ar2315_misc_irq_handler(unsi - do_IRQ(AR2315_MISC_IRQ_NONE); - } - -+#ifdef CONFIG_ATHEROS_AR2315_PCI -+static inline void pci_abort_irq(void) -+{ -+ ar231x_write_reg(AR2315_PCI_INT_STATUS, AR2315_PCI_ABORT_INT); -+} -+ -+static inline void pci_ack_irq(void) -+{ -+ ar231x_write_reg(AR2315_PCI_INT_STATUS, AR2315_PCI_EXT_INT); -+} -+ -+static void ar2315_pci_irq(int irq) -+{ -+ if (ar231x_read_reg(AR2315_PCI_INT_STATUS) == AR2315_PCI_ABORT_INT) -+ pci_abort_irq(); -+ else { -+ do_IRQ(irq); -+ pci_ack_irq(); -+ } -+} -+#endif /* CONFIG_ATHEROS_AR2315_PCI */ -+ - /* - * Called when an interrupt is received, this function - * determines exactly which interrupt it was, and it -@@ -104,6 +126,10 @@ ar2315_irq_dispatch(void) +@@ -104,6 +104,10 @@ ar2315_irq_dispatch(void) do_IRQ(AR2315_IRQ_WLAN0_INTRS); else if (pending & CAUSEF_IP4) do_IRQ(AR2315_IRQ_ENET0_INTRS); +#ifdef CONFIG_ATHEROS_AR2315_PCI + else if (pending & CAUSEF_IP5) -+ ar2315_pci_irq(AR2315_IRQ_LCBUS_PCI); ++ do_IRQ(AR2315_IRQ_LCBUS_PCI); +#endif else if (pending & CAUSEF_IP2) do_IRQ(AR2315_IRQ_MISC_INTRS); |