From: Felix Fietkau Date: Fri, 13 Mar 2015 03:01:31 +0000 (+0000) Subject: atheros: v3.18: switch to IRQ domain X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=eb370470d8928c910ce75a23bc67b22d8a4e2883;p=openwrt%2Fstaging%2Fneocturne.git atheros: v3.18: switch to IRQ domain Rework MISC and PCI IRQ controllers code to use IRQ domains and bitops. Signed-off-by: Sergey Ryazanov SVN-Revision: 44727 --- diff --git a/target/linux/atheros/config-3.18 b/target/linux/atheros/config-3.18 index 77d1498230..a275a6f703 100644 --- a/target/linux/atheros/config-3.18 +++ b/target/linux/atheros/config-3.18 @@ -87,6 +87,7 @@ CONFIG_IMAGE_CMDLINE_HACK=y CONFIG_INITRAMFS_SOURCE="" CONFIG_IP17XX_PHY=y CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_WORK=y CONFIG_LEDS_GPIO=y diff --git a/target/linux/atheros/patches-3.18/100-board.patch b/target/linux/atheros/patches-3.18/100-board.patch index 9e4434c38b..7dd0b7aa36 100644 --- a/target/linux/atheros/patches-3.18/100-board.patch +++ b/target/linux/atheros/patches-3.18/100-board.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -96,6 +96,19 @@ config AR7 +@@ -96,6 +96,20 @@ config AR7 Support for the Texas Instruments AR7 System-on-a-Chip family: TNETD7100, 7200 and 7300. @@ -10,6 +10,7 @@ + select CSRC_R4K + select DMA_NONCOHERENT + select IRQ_CPU ++ select IRQ_DOMAIN + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_32BIT_KERNEL @@ -20,7 +21,7 @@ config ATH79 bool "Atheros AR71XX/AR724X/AR913X based boards" select ARCH_REQUIRE_GPIOLIB -@@ -834,6 +847,7 @@ config MIPS_PARAVIRT +@@ -834,6 +848,7 @@ config MIPS_PARAVIRT endchoice @@ -668,15 +669,15 @@ +/* + * Miscellaneous interrupts, which share IP2. + */ -+#define AR2315_MISC_IRQ_UART0 (AR231X_MISC_IRQ_BASE+0) -+#define AR2315_MISC_IRQ_I2C_RSVD (AR231X_MISC_IRQ_BASE+1) -+#define AR2315_MISC_IRQ_SPI (AR231X_MISC_IRQ_BASE+2) -+#define AR2315_MISC_IRQ_AHB (AR231X_MISC_IRQ_BASE+3) -+#define AR2315_MISC_IRQ_APB (AR231X_MISC_IRQ_BASE+4) -+#define AR2315_MISC_IRQ_TIMER (AR231X_MISC_IRQ_BASE+5) -+#define AR2315_MISC_IRQ_GPIO (AR231X_MISC_IRQ_BASE+6) -+#define AR2315_MISC_IRQ_WATCHDOG (AR231X_MISC_IRQ_BASE+7) -+#define AR2315_MISC_IRQ_IR_RSVD (AR231X_MISC_IRQ_BASE+8) ++#define AR2315_MISC_IRQ_UART0 0 ++#define AR2315_MISC_IRQ_I2C_RSVD 1 ++#define AR2315_MISC_IRQ_SPI 2 ++#define AR2315_MISC_IRQ_AHB 3 ++#define AR2315_MISC_IRQ_APB 4 ++#define AR2315_MISC_IRQ_TIMER 5 ++#define AR2315_MISC_IRQ_GPIO 6 ++#define AR2315_MISC_IRQ_WATCHDOG 7 ++#define AR2315_MISC_IRQ_IR_RSVD 8 +#define AR2315_MISC_IRQ_COUNT 9 + +/* @@ -1149,15 +1150,15 @@ +/* + * Miscellaneous interrupts, which share IP6. + */ -+#define AR5312_MISC_IRQ_TIMER (AR231X_MISC_IRQ_BASE+0) -+#define AR5312_MISC_IRQ_AHB_PROC (AR231X_MISC_IRQ_BASE+1) -+#define AR5312_MISC_IRQ_AHB_DMA (AR231X_MISC_IRQ_BASE+2) -+#define AR5312_MISC_IRQ_GPIO (AR231X_MISC_IRQ_BASE+3) -+#define AR5312_MISC_IRQ_UART0 (AR231X_MISC_IRQ_BASE+4) -+#define AR5312_MISC_IRQ_UART0_DMA (AR231X_MISC_IRQ_BASE+5) -+#define AR5312_MISC_IRQ_WATCHDOG (AR231X_MISC_IRQ_BASE+6) -+#define AR5312_MISC_IRQ_LOCAL (AR231X_MISC_IRQ_BASE+7) -+#define AR5312_MISC_IRQ_SPI (AR231X_MISC_IRQ_BASE+8) ++#define AR5312_MISC_IRQ_TIMER 0 ++#define AR5312_MISC_IRQ_AHB_PROC 1 ++#define AR5312_MISC_IRQ_AHB_DMA 2 ++#define AR5312_MISC_IRQ_GPIO 3 ++#define AR5312_MISC_IRQ_UART0 4 ++#define AR5312_MISC_IRQ_UART0_DMA 5 ++#define AR5312_MISC_IRQ_WATCHDOG 6 ++#define AR5312_MISC_IRQ_LOCAL 7 ++#define AR5312_MISC_IRQ_SPI 8 +#define AR5312_MISC_IRQ_COUNT 9 + +/* @@ -1353,7 +1354,7 @@ +#endif /* __ASM_MACH_ATH25_AR5312_REGS_H */ --- /dev/null +++ b/arch/mips/ath25/ar5312.c -@@ -0,0 +1,474 @@ +@@ -0,0 +1,492 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive @@ -1378,6 +1379,8 @@ +#include +#include +#include ++#include ++#include +#include +#include +#include @@ -1394,6 +1397,7 @@ +#include "ar5312_regs.h" + +static void __iomem *ar5312_rst_base; ++static struct irq_domain *ar5312_misc_irq_domain; + +static inline u32 ar5312_rst_reg_read(u32 reg) +{ @@ -1435,40 +1439,36 @@ + +static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc) +{ -+ unsigned int ar231x_misc_intrs = ar5312_rst_reg_read(AR5312_ISR) & -+ ar5312_rst_reg_read(AR5312_IMR); -+ -+ if (ar231x_misc_intrs & AR5312_ISR_TIMER) { -+ generic_handle_irq(AR5312_MISC_IRQ_TIMER); -+ (void)ar5312_rst_reg_read(AR5312_TIMER); -+ } else if (ar231x_misc_intrs & AR5312_ISR_AHBPROC) -+ generic_handle_irq(AR5312_MISC_IRQ_AHB_PROC); -+ else if ((ar231x_misc_intrs & AR5312_ISR_UART0)) -+ generic_handle_irq(AR5312_MISC_IRQ_UART0); -+ else if (ar231x_misc_intrs & AR5312_ISR_WD) -+ generic_handle_irq(AR5312_MISC_IRQ_WATCHDOG); -+ else ++ u32 pending = ar5312_rst_reg_read(AR5312_ISR) & ++ ar5312_rst_reg_read(AR5312_IMR); ++ unsigned nr, misc_irq = 0; ++ ++ if (pending) { ++ struct irq_domain *domain = irq_get_handler_data(irq); ++ ++ nr = __ffs(pending); ++ misc_irq = irq_find_mapping(domain, nr); ++ } ++ ++ if (misc_irq) { ++ generic_handle_irq(misc_irq); ++ if (nr == AR5312_MISC_IRQ_TIMER) ++ ar5312_rst_reg_read(AR5312_TIMER); ++ } else { + spurious_interrupt(); ++ } +} + +/* Enable the specified AR5312_MISC_IRQ interrupt */ +static void ar5312_misc_irq_unmask(struct irq_data *d) +{ -+ unsigned int imr; -+ -+ imr = ar5312_rst_reg_read(AR5312_IMR); -+ imr |= 1 << (d->irq - AR231X_MISC_IRQ_BASE); -+ ar5312_rst_reg_write(AR5312_IMR, imr); ++ ar5312_rst_reg_mask(AR5312_IMR, 0, BIT(d->hwirq)); +} + +/* Disable the specified AR5312_MISC_IRQ interrupt */ +static void ar5312_misc_irq_mask(struct irq_data *d) +{ -+ unsigned int imr; -+ -+ imr = ar5312_rst_reg_read(AR5312_IMR); -+ imr &= ~(1 << (d->irq - AR231X_MISC_IRQ_BASE)); -+ ar5312_rst_reg_write(AR5312_IMR, imr); ++ ar5312_rst_reg_mask(AR5312_IMR, BIT(d->hwirq), 0); + ar5312_rst_reg_read(AR5312_IMR); /* flush write buffer */ +} + @@ -1478,9 +1478,20 @@ + .irq_mask = ar5312_misc_irq_mask, +}; + ++static int ar5312_misc_irq_map(struct irq_domain *d, unsigned irq, ++ irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip, handle_level_irq); ++ return 0; ++} ++ ++static struct irq_domain_ops ar5312_misc_irq_domain_ops = { ++ .map = ar5312_misc_irq_map, ++}; ++ +static void ar5312_irq_dispatch(void) +{ -+ int pending = read_c0_status() & read_c0_cause(); ++ u32 pending = read_c0_status() & read_c0_cause(); + + if (pending & CAUSEF_IP2) + do_IRQ(AR5312_IRQ_WLAN0); @@ -1500,17 +1511,23 @@ + +void __init ar5312_arch_init_irq(void) +{ -+ int i; ++ struct irq_domain *domain; ++ unsigned irq; + + ath25_irq_dispatch = ar5312_irq_dispatch; -+ for (i = 0; i < AR5312_MISC_IRQ_COUNT; i++) { -+ int irq = AR231X_MISC_IRQ_BASE + i; + -+ irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip, -+ handle_level_irq); -+ } -+ setup_irq(AR5312_MISC_IRQ_AHB_PROC, &ar5312_ahb_err_interrupt); ++ domain = irq_domain_add_linear(NULL, AR5312_MISC_IRQ_COUNT, ++ &ar5312_misc_irq_domain_ops, NULL); ++ if (!domain) ++ panic("Failed to add IRQ domain"); ++ ++ irq = irq_create_mapping(domain, AR5312_MISC_IRQ_AHB_PROC); ++ setup_irq(irq, &ar5312_ahb_err_interrupt); ++ + irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler); ++ irq_set_handler_data(AR5312_IRQ_MISC, domain); ++ ++ ar5312_misc_irq_domain = domain; +} + +static void ar5312_device_reset_set(u32 mask) @@ -1825,12 +1842,14 @@ + +void __init ar5312_arch_init(void) +{ -+ ath25_serial_setup(AR5312_UART0_BASE, AR5312_MISC_IRQ_UART0, -+ ar5312_sys_frequency()); ++ unsigned irq = irq_create_mapping(ar5312_misc_irq_domain, ++ AR5312_MISC_IRQ_UART0); ++ ++ ath25_serial_setup(AR5312_UART0_BASE, irq, ar5312_sys_frequency()); +} --- /dev/null +++ b/arch/mips/ath25/ar2315.c -@@ -0,0 +1,418 @@ +@@ -0,0 +1,438 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive @@ -1854,6 +1873,8 @@ +#include +#include +#include ++#include ++#include +#include +#include +#include @@ -1871,6 +1892,7 @@ +#include "ar2315_regs.h" + +static void __iomem *ar2315_rst_base; ++static struct irq_domain *ar2315_misc_irq_domain; + +static inline u32 ar2315_rst_reg_read(u32 reg) +{ @@ -1909,43 +1931,36 @@ + +static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc) +{ -+ unsigned int misc_intr = ar2315_rst_reg_read(AR2315_ISR) & -+ ar2315_rst_reg_read(AR2315_IMR); -+ -+ if (misc_intr & AR2315_ISR_SPI) -+ generic_handle_irq(AR2315_MISC_IRQ_SPI); -+ else if (misc_intr & AR2315_ISR_TIMER) -+ generic_handle_irq(AR2315_MISC_IRQ_TIMER); -+ else if (misc_intr & AR2315_ISR_AHB) -+ generic_handle_irq(AR2315_MISC_IRQ_AHB); -+ else if (misc_intr & AR2315_ISR_GPIO) { -+ ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO); -+ generic_handle_irq(AR2315_MISC_IRQ_GPIO); -+ } else if (misc_intr & AR2315_ISR_UART0) -+ generic_handle_irq(AR2315_MISC_IRQ_UART0); -+ else if (misc_intr & AR2315_ISR_WD) { -+ ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD); -+ generic_handle_irq(AR2315_MISC_IRQ_WATCHDOG); -+ } else ++ u32 pending = ar2315_rst_reg_read(AR2315_ISR) & ++ ar2315_rst_reg_read(AR2315_IMR); ++ unsigned nr, misc_irq = 0; ++ ++ if (pending) { ++ struct irq_domain *domain = irq_get_handler_data(irq); ++ ++ nr = __ffs(pending); ++ misc_irq = irq_find_mapping(domain, nr); ++ } ++ ++ if (misc_irq) { ++ if (nr == AR2315_MISC_IRQ_GPIO) ++ ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO); ++ else if (nr == AR2315_MISC_IRQ_WATCHDOG) ++ ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD); ++ generic_handle_irq(misc_irq); ++ } else { + spurious_interrupt(); ++ } +} + +static void ar2315_misc_irq_unmask(struct irq_data *d) +{ -+ unsigned int imr; -+ -+ imr = ar2315_rst_reg_read(AR2315_IMR); -+ imr |= 1 << (d->irq - AR231X_MISC_IRQ_BASE); -+ ar2315_rst_reg_write(AR2315_IMR, imr); ++ ar2315_rst_reg_mask(AR2315_IMR, 0, BIT(d->hwirq)); +} + +static void ar2315_misc_irq_mask(struct irq_data *d) +{ -+ unsigned int imr; -+ -+ imr = ar2315_rst_reg_read(AR2315_IMR); -+ imr &= ~(1 << (d->irq - AR231X_MISC_IRQ_BASE)); -+ ar2315_rst_reg_write(AR2315_IMR, imr); ++ ar2315_rst_reg_mask(AR2315_IMR, BIT(d->hwirq), 0); +} + +static struct irq_chip ar2315_misc_irq_chip = { @@ -1954,6 +1969,17 @@ + .irq_mask = ar2315_misc_irq_mask, +}; + ++static int ar2315_misc_irq_map(struct irq_domain *d, unsigned irq, ++ irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip, handle_level_irq); ++ return 0; ++} ++ ++static struct irq_domain_ops ar2315_misc_irq_domain_ops = { ++ .map = ar2315_misc_irq_map, ++}; ++ +/* + * Called when an interrupt is received, this function + * determines exactly which interrupt it was, and it @@ -1964,7 +1990,7 @@ + */ +static void ar2315_irq_dispatch(void) +{ -+ int pending = read_c0_status() & read_c0_cause(); ++ u32 pending = read_c0_status() & read_c0_cause(); + + if (pending & CAUSEF_IP3) + do_IRQ(AR2315_IRQ_WLAN0); @@ -1980,17 +2006,23 @@ + +void __init ar2315_arch_init_irq(void) +{ -+ int i; ++ struct irq_domain *domain; ++ unsigned irq; + + ath25_irq_dispatch = ar2315_irq_dispatch; -+ for (i = 0; i < AR2315_MISC_IRQ_COUNT; i++) { -+ int irq = AR231X_MISC_IRQ_BASE + i; + -+ irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip, -+ handle_level_irq); -+ } -+ setup_irq(AR2315_MISC_IRQ_AHB, &ar2315_ahb_err_interrupt); ++ domain = irq_domain_add_linear(NULL, AR2315_MISC_IRQ_COUNT, ++ &ar2315_misc_irq_domain_ops, NULL); ++ if (!domain) ++ panic("Failed to add IRQ domain"); ++ ++ irq = irq_create_mapping(domain, AR2315_MISC_IRQ_AHB); ++ setup_irq(irq, &ar2315_ahb_err_interrupt); ++ + irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler); ++ irq_set_handler_data(AR2315_IRQ_MISC, domain); ++ ++ ar2315_misc_irq_domain = domain; +} + +static void ar2315_device_reset_set(u32 mask) @@ -2046,8 +2078,6 @@ + }, + { + .flags = IORESOURCE_IRQ, -+ .start = AR2315_MISC_IRQ_WATCHDOG, -+ .end = AR2315_MISC_IRQ_WATCHDOG, + } +}; + @@ -2109,11 +2139,18 @@ + ar2315_eth_data.macaddr = ath25_board.config->enet0_mac; + + ar2315_init_gpio_leds(); ++ ++ ar2315_wdt_res[1].start = irq_create_mapping(ar2315_misc_irq_domain, ++ AR2315_MISC_IRQ_WATCHDOG); ++ ar2315_wdt_res[1].end = ar2315_wdt_res[1].start; + platform_device_register(&ar2315_wdt); ++ + platform_device_register(&ar2315_spiflash); ++ + ath25_add_ethernet(0, AR2315_ENET0_BASE, "eth0_mii", + AR2315_ENET0_MII_BASE, AR2315_IRQ_ENET0, + &ar2315_eth_data); ++ + ath25_add_wmac(0, AR2315_WLAN0_BASE, AR2315_IRQ_WLAN0); +} + @@ -2246,8 +2283,10 @@ + +void __init ar2315_arch_init(void) +{ -+ ath25_serial_setup(AR2315_UART0_BASE, AR2315_MISC_IRQ_UART0, -+ ar2315_apb_frequency()); ++ unsigned irq = irq_create_mapping(ar2315_misc_irq_domain, ++ AR2315_MISC_IRQ_UART0); ++ ++ ath25_serial_setup(AR2315_UART0_BASE, irq, ar2315_apb_frequency()); +} --- /dev/null +++ b/arch/mips/ath25/ar2315.h @@ -2329,11 +2368,10 @@ +#endif --- /dev/null +++ b/arch/mips/ath25/devices.h -@@ -0,0 +1,46 @@ +@@ -0,0 +1,45 @@ +#ifndef __ATH25_DEVICES_H +#define __ATH25_DEVICES_H + -+#define AR231X_MISC_IRQ_BASE 0x20 +#define AR231X_GPIO_IRQ_BASE 0x30 + +#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S) diff --git a/target/linux/atheros/patches-3.18/101-early-printk-support.patch b/target/linux/atheros/patches-3.18/101-early-printk-support.patch index 766c903552..713dda5d7f 100644 --- a/target/linux/atheros/patches-3.18/101-early-printk-support.patch +++ b/target/linux/atheros/patches-3.18/101-early-printk-support.patch @@ -60,7 +60,7 @@ obj-$(CONFIG_SOC_AR2315) += ar2315.o --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -106,6 +106,7 @@ config ATH25 +@@ -107,6 +107,7 @@ config ATH25 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_32BIT_KERNEL select ARCH_REQUIRE_GPIOLIB diff --git a/target/linux/atheros/patches-3.18/102-ar5312_gpio.patch b/target/linux/atheros/patches-3.18/102-ar5312_gpio.patch index 9283616b01..56ac81ee40 100644 --- a/target/linux/atheros/patches-3.18/102-ar5312_gpio.patch +++ b/target/linux/atheros/patches-3.18/102-ar5312_gpio.patch @@ -10,7 +10,7 @@ config SOC_AR2315 --- a/arch/mips/ath25/ar5312.c +++ b/arch/mips/ath25/ar5312.c -@@ -205,6 +205,22 @@ static struct platform_device ar5312_phy +@@ -221,6 +221,22 @@ static struct platform_device ar5312_phy .num_resources = 1, }; @@ -33,7 +33,7 @@ #ifdef CONFIG_LEDS_GPIO static struct gpio_led ar5312_leds[] = { { .name = "wlan", .gpio = 0, .active_low = 1, }, -@@ -290,6 +306,8 @@ void __init ar5312_init_devices(void) +@@ -306,6 +322,8 @@ void __init ar5312_init_devices(void) platform_device_register(&ar5312_physmap_flash); diff --git a/target/linux/atheros/patches-3.18/103-ar2315_gpio.patch b/target/linux/atheros/patches-3.18/103-ar2315_gpio.patch index 32022e6aeb..4b8117151d 100644 --- a/target/linux/atheros/patches-3.18/103-ar2315_gpio.patch +++ b/target/linux/atheros/patches-3.18/103-ar2315_gpio.patch @@ -8,7 +8,7 @@ default y --- a/arch/mips/ath25/ar2315.c +++ b/arch/mips/ath25/ar2315.c -@@ -225,6 +225,34 @@ static struct platform_device ar2315_wdt +@@ -236,6 +236,32 @@ static struct platform_device ar2315_wdt .num_resources = ARRAY_SIZE(ar2315_wdt_res) }; @@ -22,8 +22,6 @@ + { + .name = "ar2315-gpio", + .flags = IORESOURCE_IRQ, -+ .start = AR2315_MISC_IRQ_GPIO, -+ .end = AR2315_MISC_IRQ_GPIO, + }, + { + .name = "ar2315-gpio-irq-base", @@ -43,14 +41,18 @@ #ifdef CONFIG_LEDS_GPIO static struct gpio_led ar2315_leds[6]; static struct gpio_led_platform_data ar2315_led_data = { -@@ -275,6 +303,7 @@ void __init ar2315_init_devices(void) +@@ -286,6 +312,11 @@ void __init ar2315_init_devices(void) ath25_find_config(AR2315_SPI_READ_BASE, AR2315_SPI_READ_SIZE); ar2315_eth_data.macaddr = ath25_board.config->enet0_mac; ++ ar2315_gpio_res[1].start = irq_create_mapping(ar2315_misc_irq_domain, ++ AR2315_MISC_IRQ_GPIO); ++ ar2315_gpio_res[1].end = ar2315_gpio_res[1].start; + platform_device_register(&ar2315_gpio); ++ ar2315_init_gpio_leds(); - platform_device_register(&ar2315_wdt); - platform_device_register(&ar2315_spiflash); + + ar2315_wdt_res[1].start = irq_create_mapping(ar2315_misc_irq_domain, --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -112,6 +112,13 @@ config GPIO_MAX730X diff --git a/target/linux/atheros/patches-3.18/105-ar2315_pci.patch b/target/linux/atheros/patches-3.18/105-ar2315_pci.patch index 0814c711e5..4de4f3ab8b 100644 --- a/target/linux/atheros/patches-3.18/105-ar2315_pci.patch +++ b/target/linux/atheros/patches-3.18/105-ar2315_pci.patch @@ -10,7 +10,7 @@ obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o --- /dev/null +++ b/arch/mips/pci/pci-ar2315.c -@@ -0,0 +1,494 @@ +@@ -0,0 +1,511 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License @@ -47,7 +47,7 @@ + * We know (and support) only one board that uses the PCI interface - + * Fonera 2.0g (FON2202). It has a USB EHCI controller connected to the + * AR2315 PCI bus. IDSEL pin of USB controller is connected to AD[13] line -+ * and IDSEL pin of AR125 is connected to AD[16] line. ++ * and IDSEL pin of AR2315 is connected to AD[16] line. + */ + +#include @@ -57,7 +57,9 @@ +#include +#include +#include ++#include +#include ++#include +#include +#include + @@ -150,11 +152,9 @@ + * 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 */ ++#define AR2315_PCI_IRQ_EXT 25 ++#define AR2315_PCI_IRQ_ABORT 26 ++#define AR2315_PCI_IRQ_COUNT 27 + +/* Arbitrary size of memory region to access the configuration space */ +#define AR2315_PCI_CFG_SIZE 0x00100000 @@ -173,6 +173,8 @@ + void __iomem *cfg_mem; + void __iomem *mmr_mem; + unsigned irq; ++ unsigned irq_ext; ++ struct irq_domain *domain; + struct pci_controller pci_ctrl; + struct resource mem_res; + struct resource io_res; @@ -334,11 +336,13 @@ + struct ar2315_pci_ctrl *apc = irq_get_handler_data(irq); + u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) & + ar2315_pci_reg_read(apc, AR2315_PCI_IMR); ++ unsigned pci_irq = 0; + -+ 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); ++ if (pending) ++ pci_irq = irq_find_mapping(apc->domain, __ffs(pending)); ++ ++ if (pci_irq) ++ generic_handle_irq(pci_irq); + else + spurious_interrupt(); +} @@ -346,15 +350,14 @@ +static void ar2315_pci_irq_mask(struct irq_data *d) +{ + struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); -+ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT); + -+ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, m, 0); ++ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, BIT(d->hwirq), 0); +} + +static void ar2315_pci_irq_mask_ack(struct irq_data *d) +{ + struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); -+ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT); ++ u32 m = BIT(d->hwirq); + + ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, m, 0); + ar2315_pci_reg_write(apc, AR2315_PCI_ISR, m); @@ -363,9 +366,8 @@ +static void ar2315_pci_irq_unmask(struct irq_data *d) +{ + struct ar2315_pci_ctrl *apc = irq_data_get_irq_chip_data(d); -+ u32 m = 1 << (d->irq - AR2315_PCI_IRQ_BASE + AR2315_PCI_IRQ_SHIFT); + -+ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, 0, m); ++ ar2315_pci_reg_mask(apc, AR2315_PCI_IMR, 0, BIT(d->hwirq)); +} + +static struct irq_chip ar2315_pci_irq_chip = { @@ -375,21 +377,25 @@ + .irq_unmask = ar2315_pci_irq_unmask, +}; + -+static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc) ++static int ar2315_pci_irq_map(struct irq_domain *d, unsigned irq, ++ irq_hw_number_t hw) +{ -+ int i; ++ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip, handle_level_irq); ++ irq_set_chip_data(irq, d->host_data); ++ return 0; ++} + ++static struct irq_domain_ops ar2315_pci_irq_domain_ops = { ++ .map = ar2315_pci_irq_map, ++}; ++ ++static void ar2315_pci_irq_init(struct ar2315_pci_ctrl *apc) ++{ + ar2315_pci_reg_mask(apc, AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0); + ar2315_pci_reg_mask(apc, 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_chip_data(irq, apc); -+ } ++ apc->irq_ext = irq_create_mapping(apc->domain, AR2315_PCI_IRQ_EXT); + + irq_set_chained_handler(apc->irq, ar2315_pci_irq_handler); + irq_set_handler_data(apc->irq, apc); @@ -465,6 +471,13 @@ + if (err) + return err; + ++ apc->domain = irq_domain_add_linear(NULL, AR2315_PCI_IRQ_COUNT, ++ &ar2315_pci_irq_domain_ops, apc); ++ if (!apc->domain) { ++ dev_err(dev, "failed to add IRQ domain\n"); ++ return -ENOMEM; ++ } ++ + ar2315_pci_irq_init(apc); + + /* PCI controller does not support I/O ports */ @@ -479,6 +492,8 @@ + + register_pci_controller(&apc->pci_ctrl); + ++ dev_info(dev, "register PCI controller\n"); ++ + return 0; +} + @@ -498,7 +513,9 @@ + +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ -+ return AR2315_PCI_IRQ_EXT; ++ struct ar2315_pci_ctrl *apc = ar2315_pci_bus_to_apc(dev->bus); ++ ++ return slot ? 0 : apc->irq_ext; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) @@ -520,7 +537,7 @@ + default y --- a/arch/mips/ath25/ar2315.c +++ b/arch/mips/ath25/ar2315.c -@@ -137,6 +137,10 @@ static void ar2315_irq_dispatch(void) +@@ -144,6 +144,10 @@ static void ar2315_irq_dispatch(void) do_IRQ(AR2315_IRQ_WLAN0); else if (pending & CAUSEF_IP4) do_IRQ(AR2315_IRQ_ENET0); @@ -531,7 +548,7 @@ else if (pending & CAUSEF_IP2) do_IRQ(AR2315_IRQ_MISC); else if (pending & CAUSEF_IP7) -@@ -440,8 +444,60 @@ void __init ar2315_plat_mem_setup(void) +@@ -460,10 +464,62 @@ void __init ar2315_plat_mem_setup(void) _machine_restart = ar2315_restart; } @@ -560,8 +577,10 @@ + void __init ar2315_arch_init(void) { - ath25_serial_setup(AR2315_UART0_BASE, AR2315_MISC_IRQ_UART0, - ar2315_apb_frequency()); + unsigned irq = irq_create_mapping(ar2315_misc_irq_domain, + AR2315_MISC_IRQ_UART0); + + ath25_serial_setup(AR2315_UART0_BASE, irq, ar2315_apb_frequency()); + +#ifdef CONFIG_PCI_AR2315 + if (ath25_soc == ATH25_SOC_AR2315) {