From dbdd8906ac776e9b8d51284d4dc0ce24920a2231 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 12 Sep 2014 06:53:00 +0000 Subject: [PATCH] atheros: ar2315-pci: rework interrupt handling Add PCI IRQ controller to facilitate interrupt handling, move interrupts initialization to the IRQ controller initialization from pcibios_plat_dev_init() callback. Also remove odd PCI dev configuration manipulation from pcibios_plat_dev_init() callback. Signed-off-by: Sergey Ryazanov SVN-Revision: 42501 --- .../atheros/patches-3.14/100-board.patch | 50 +++++--- .../atheros/patches-3.14/105-ar2315_pci.patch | 119 +++++++++++------- 2 files changed, 103 insertions(+), 66 deletions(-) diff --git a/target/linux/atheros/patches-3.14/100-board.patch b/target/linux/atheros/patches-3.14/100-board.patch index 7b1adbd711..c87734b69d 100644 --- a/target/linux/atheros/patches-3.14/100-board.patch +++ b/target/linux/atheros/patches-3.14/100-board.patch @@ -674,7 +674,7 @@ +#endif /* __ASM_MACH_AR231X_WAR_H */ --- /dev/null +++ b/arch/mips/include/asm/mach-ar231x/ar2315_regs.h -@@ -0,0 +1,614 @@ +@@ -0,0 +1,624 @@ +/* + * Register definitions for AR2315+ + * @@ -716,6 +716,16 @@ +#define AR2315_MISC_IRQ_COUNT 10 + +/* ++ * PCI interrupts, which share IP5 ++ * Keep ordered according to AR2315_PCI_INT_XXX bits ++ */ ++#define AR2315_PCI_IRQ_BASE 0x50 ++#define AR2315_PCI_IRQ_EXT (AR2315_PCI_IRQ_BASE+0) ++#define AR2315_PCI_IRQ_ABORT (AR2315_PCI_IRQ_BASE+1) ++#define AR2315_PCI_IRQ_COUNT 2 ++#define AR2315_PCI_IRQ_SHIFT 25 /* in AR2315_PCI_INT_STATUS */ ++ ++/* + * Address map + */ +#define AR2315_SPI_READ 0x08000000 /* SPI FLASH */ @@ -1138,25 +1148,25 @@ + +#define AR2315_PCI_OUT_PTR (AR2315_PCI + 0x0408) + -+#define AR2315_PCI_INT_STATUS (AR2315_PCI + 0x0500) /* write one to clr */ -+#define AR2315_PCI_TXINT 0x00000001 /* Desc In Completed */ -+#define AR2315_PCI_TXOK 0x00000002 /* Desc In OK */ -+#define AR2315_PCI_TXERR 0x00000004 /* Desc In ERR */ -+#define AR2315_PCI_TXEOL 0x00000008 /* Desc In End-of-List */ -+#define AR2315_PCI_RXINT 0x00000010 /* Desc Out Completed */ -+#define AR2315_PCI_RXOK 0x00000020 /* Desc Out OK */ -+#define AR2315_PCI_RXERR 0x00000040 /* Desc Out ERR */ -+#define AR2315_PCI_RXEOL 0x00000080 /* Desc Out EOL */ -+#define AR2315_PCI_TXOOD 0x00000200 /* Desc In Out-of-Desc */ -+#define AR2315_PCI_MASK 0x0000FFFF /* Desc Mask */ -+#define AR2315_PCI_EXT_INT 0x02000000 -+#define AR2315_PCI_ABORT_INT 0x04000000 -+ -+#define AR2315_PCI_INT_MASK (AR2315_PCI + 0x0504) /* same as INT_STATUS */ -+ -+#define AR2315_PCI_INTEN_REG (AR2315_PCI + 0x0508) -+#define AR2315_PCI_INT_DISABLE 0x00 /* disable pci interrupts */ -+#define AR2315_PCI_INT_ENABLE 0x01 /* enable pci interrupts */ ++#define AR2315_PCI_ISR (AR2315_PCI + 0x0500) /* write one to clr */ ++#define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */ ++#define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */ ++#define AR2315_PCI_INT_TXERR 0x00000004 /* Desc In ERR */ ++#define AR2315_PCI_INT_TXEOL 0x00000008 /* Desc In End-of-List */ ++#define AR2315_PCI_INT_RX 0x00000010 /* Desc Out Completed */ ++#define AR2315_PCI_INT_RXOK 0x00000020 /* Desc Out OK */ ++#define AR2315_PCI_INT_RXERR 0x00000040 /* Desc Out ERR */ ++#define AR2315_PCI_INT_RXEOL 0x00000080 /* Desc Out EOL */ ++#define AR2315_PCI_INT_TXOOD 0x00000200 /* Desc In Out-of-Desc */ ++#define AR2315_PCI_INT_DESCMASK 0x0000FFFF /* Desc Mask */ ++#define AR2315_PCI_INT_EXT 0x02000000 /* Extern PCI INTA */ ++#define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */ ++ ++#define AR2315_PCI_IMR (AR2315_PCI + 0x0504) /* mask _PCI_ISR bits */ ++ ++#define AR2315_PCI_IER (AR2315_PCI + 0x0508) /* global PCI int en */ ++#define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */ ++#define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */ + +#define AR2315_PCI_HOST_IN_EN (AR2315_PCI + 0x0800) +#define AR2315_PCI_HOST_IN_DIS (AR2315_PCI + 0x0804) 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); -- 2.30.2