diff options
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r-- | arch/mips/ath79/Kconfig | 20 | ||||
-rw-r--r-- | arch/mips/ath79/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/ath79/clock.c | 80 | ||||
-rw-r--r-- | arch/mips/ath79/common.c | 4 | ||||
-rw-r--r-- | arch/mips/ath79/dev-common.c | 24 | ||||
-rw-r--r-- | arch/mips/ath79/dev-usb.c | 126 | ||||
-rw-r--r-- | arch/mips/ath79/dev-wmac.c | 30 | ||||
-rw-r--r-- | arch/mips/ath79/early_printk.c | 2 | ||||
-rw-r--r-- | arch/mips/ath79/gpio.c | 52 | ||||
-rw-r--r-- | arch/mips/ath79/irq.c | 187 | ||||
-rw-r--r-- | arch/mips/ath79/mach-ap121.c | 2 | ||||
-rw-r--r-- | arch/mips/ath79/mach-ap136.c | 156 | ||||
-rw-r--r-- | arch/mips/ath79/mach-ap81.c | 2 | ||||
-rw-r--r-- | arch/mips/ath79/mach-db120.c | 2 | ||||
-rw-r--r-- | arch/mips/ath79/mach-pb44.c | 6 | ||||
-rw-r--r-- | arch/mips/ath79/machtypes.h | 1 | ||||
-rw-r--r-- | arch/mips/ath79/pci.c | 165 | ||||
-rw-r--r-- | arch/mips/ath79/pci.h | 1 | ||||
-rw-r--r-- | arch/mips/ath79/setup.c | 18 |
19 files changed, 698 insertions, 181 deletions
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index f44feee2d67f..3995e31a73e2 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -14,6 +14,18 @@ config ATH79_MACH_AP121 Say 'Y' here if you want your kernel to support the Atheros AP121 reference board. +config ATH79_MACH_AP136 + bool "Atheros AP136 reference board" + select SOC_QCA955X + select ATH79_DEV_GPIO_BUTTONS + select ATH79_DEV_LEDS_GPIO + select ATH79_DEV_SPI + select ATH79_DEV_USB + select ATH79_DEV_WMAC + help + Say 'Y' here if you want your kernel to support the + Atheros AP136 reference board. + config ATH79_MACH_AP81 bool "Atheros AP81 reference board" select SOC_AR913X @@ -88,6 +100,12 @@ config SOC_AR934X select PCI_AR724X if PCI def_bool n +config SOC_QCA955X + select USB_ARCH_HAS_EHCI + select HW_HAS_PCI + select PCI_AR724X if PCI + def_bool n + config PCI_AR724X def_bool n @@ -104,7 +122,7 @@ config ATH79_DEV_USB def_bool n config ATH79_DEV_WMAC - depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X) + depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X) def_bool n endif diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile index 2b54d98263f3..5c9ff692ff3c 100644 --- a/arch/mips/ath79/Makefile +++ b/arch/mips/ath79/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_ATH79_DEV_WMAC) += dev-wmac.o # Machines # obj-$(CONFIG_ATH79_MACH_AP121) += mach-ap121.o +obj-$(CONFIG_ATH79_MACH_AP136) += mach-ap136.o obj-$(CONFIG_ATH79_MACH_AP81) += mach-ap81.o obj-$(CONFIG_ATH79_MACH_DB120) += mach-db120.o obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 579f452c0b45..765ef30e3e1c 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -198,7 +198,7 @@ static void __init ar934x_clocks_init(void) dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); - if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) + if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) ath79_ref_clk.rate = 40 * 1000 * 1000; else ath79_ref_clk.rate = 25 * 1000 * 1000; @@ -295,6 +295,82 @@ static void __init ar934x_clocks_init(void) iounmap(dpll_base); } +static void __init qca955x_clocks_init(void) +{ + u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; + u32 cpu_pll, ddr_pll; + u32 bootstrap; + + bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); + if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) + ath79_ref_clk.rate = 40 * 1000 * 1000; + else + ath79_ref_clk.rate = 25 * 1000 * 1000; + + pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); + out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; + nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & + QCA955X_PLL_CPU_CONFIG_NINT_MASK; + frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & + QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; + + cpu_pll = nint * ath79_ref_clk.rate / ref_div; + cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); + cpu_pll /= (1 << out_div); + + pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); + out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; + nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & + QCA955X_PLL_DDR_CONFIG_NINT_MASK; + frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & + QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; + + ddr_pll = nint * ath79_ref_clk.rate / ref_div; + ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); + ddr_pll /= (1 << out_div); + + clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); + + postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & + QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + + if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) + ath79_cpu_clk.rate = ath79_ref_clk.rate; + else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) + ath79_cpu_clk.rate = ddr_pll / (postdiv + 1); + else + ath79_cpu_clk.rate = cpu_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & + QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + + if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) + ath79_ddr_clk.rate = ath79_ref_clk.rate; + else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) + ath79_ddr_clk.rate = cpu_pll / (postdiv + 1); + else + ath79_ddr_clk.rate = ddr_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & + QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + + if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + ath79_ahb_clk.rate = ath79_ref_clk.rate; + else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) + ath79_ahb_clk.rate = ddr_pll / (postdiv + 1); + else + ath79_ahb_clk.rate = cpu_pll / (postdiv + 1); + + ath79_wdt_clk.rate = ath79_ref_clk.rate; + ath79_uart_clk.rate = ath79_ref_clk.rate; +} + void __init ath79_clocks_init(void) { if (soc_is_ar71xx()) @@ -307,6 +383,8 @@ void __init ath79_clocks_init(void) ar933x_clocks_init(); else if (soc_is_ar934x()) ar934x_clocks_init(); + else if (soc_is_qca955x()) + qca955x_clocks_init(); else BUG(); diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index 5a4adfc9d79d..eb3966cd8cfc 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -72,6 +72,8 @@ void ath79_device_reset_set(u32 mask) reg = AR933X_RESET_REG_RESET_MODULE; else if (soc_is_ar934x()) reg = AR934X_RESET_REG_RESET_MODULE; + else if (soc_is_qca955x()) + reg = QCA955X_RESET_REG_RESET_MODULE; else BUG(); @@ -98,6 +100,8 @@ void ath79_device_reset_clear(u32 mask) reg = AR933X_RESET_REG_RESET_MODULE; else if (soc_is_ar934x()) reg = AR934X_RESET_REG_RESET_MODULE; + else if (soc_is_qca955x()) + reg = QCA955X_RESET_REG_RESET_MODULE; else BUG(); diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c index 45efc63b08b6..a3a2741d0688 100644 --- a/arch/mips/ath79/dev-common.c +++ b/arch/mips/ath79/dev-common.c @@ -36,7 +36,7 @@ static struct resource ath79_uart_resources[] = { static struct plat_serial8250_port ath79_uart_data[] = { { .mapbase = AR71XX_UART_BASE, - .irq = ATH79_MISC_IRQ_UART, + .irq = ATH79_MISC_IRQ(3), .flags = AR71XX_UART_FLAGS, .iotype = UPIO_MEM32, .regshift = 2, @@ -62,8 +62,8 @@ static struct resource ar933x_uart_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = ATH79_MISC_IRQ_UART, - .end = ATH79_MISC_IRQ_UART, + .start = ATH79_MISC_IRQ(3), + .end = ATH79_MISC_IRQ(3), .flags = IORESOURCE_IRQ, }, }; @@ -90,7 +90,8 @@ void __init ath79_register_uart(void) if (soc_is_ar71xx() || soc_is_ar724x() || soc_is_ar913x() || - soc_is_ar934x()) { + soc_is_ar934x() || + soc_is_qca955x()) { ath79_uart_data[0].uartclk = clk_get_rate(clk); platform_device_register(&ath79_uart_device); } else if (soc_is_ar933x()) { @@ -101,12 +102,15 @@ void __init ath79_register_uart(void) } } -static struct platform_device ath79_wdt_device = { - .name = "ath79-wdt", - .id = -1, -}; - void __init ath79_register_wdt(void) { - platform_device_register(&ath79_wdt_device); + struct resource res; + + memset(&res, 0, sizeof(res)); + + res.flags = IORESOURCE_MEM; + res.start = AR71XX_RESET_BASE + AR71XX_RESET_REG_WDOG_CTRL; + res.end = res.start + 0x8 - 1; + + platform_device_register_simple("ath79-wdt", -1, &res, 1); } diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c index bd2bc108e1b5..8227265bcc2d 100644 --- a/arch/mips/ath79/dev-usb.c +++ b/arch/mips/ath79/dev-usb.c @@ -25,29 +25,11 @@ #include "common.h" #include "dev-usb.h" -static struct resource ath79_ohci_resources[2]; - -static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32); +static u64 ath79_usb_dmamask = DMA_BIT_MASK(32); static struct usb_ohci_pdata ath79_ohci_pdata = { }; -static struct platform_device ath79_ohci_device = { - .name = "ohci-platform", - .id = -1, - .resource = ath79_ohci_resources, - .num_resources = ARRAY_SIZE(ath79_ohci_resources), - .dev = { - .dma_mask = &ath79_ohci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &ath79_ohci_pdata, - }, -}; - -static struct resource ath79_ehci_resources[2]; - -static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32); - static struct usb_ehci_pdata ath79_ehci_pdata_v1 = { .has_synopsys_hc_bug = 1, }; @@ -57,22 +39,16 @@ static struct usb_ehci_pdata ath79_ehci_pdata_v2 = { .has_tt = 1, }; -static struct platform_device ath79_ehci_device = { - .name = "ehci-platform", - .id = -1, - .resource = ath79_ehci_resources, - .num_resources = ARRAY_SIZE(ath79_ehci_resources), - .dev = { - .dma_mask = &ath79_ehci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -static void __init ath79_usb_init_resource(struct resource res[2], - unsigned long base, - unsigned long size, - int irq) +static void __init ath79_usb_register(const char *name, int id, + unsigned long base, unsigned long size, + int irq, const void *data, + size_t data_size) { + struct resource res[2]; + struct platform_device *pdev; + + memset(res, 0, sizeof(res)); + res[0].flags = IORESOURCE_MEM; res[0].start = base; res[0].end = base + size - 1; @@ -80,6 +56,19 @@ static void __init ath79_usb_init_resource(struct resource res[2], res[1].flags = IORESOURCE_IRQ; res[1].start = irq; res[1].end = irq; + + pdev = platform_device_register_resndata(NULL, name, id, + res, ARRAY_SIZE(res), + data, data_size); + + if (IS_ERR(pdev)) { + pr_err("ath79: unable to register USB at %08lx, err=%d\n", + base, (int) PTR_ERR(pdev)); + return; + } + + pdev->dev.dma_mask = &ath79_usb_dmamask; + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); } #define AR71XX_USB_RESET_MASK (AR71XX_RESET_USB_HOST | \ @@ -106,14 +95,15 @@ static void __init ath79_usb_setup(void) mdelay(900); - ath79_usb_init_resource(ath79_ohci_resources, AR71XX_OHCI_BASE, - AR71XX_OHCI_SIZE, ATH79_MISC_IRQ_OHCI); - platform_device_register(&ath79_ohci_device); + ath79_usb_register("ohci-platform", -1, + AR71XX_OHCI_BASE, AR71XX_OHCI_SIZE, + ATH79_MISC_IRQ(6), + &ath79_ohci_pdata, sizeof(ath79_ohci_pdata)); - ath79_usb_init_resource(ath79_ehci_resources, AR71XX_EHCI_BASE, - AR71XX_EHCI_SIZE, ATH79_CPU_IRQ_USB); - ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v1; - platform_device_register(&ath79_ehci_device); + ath79_usb_register("ehci-platform", -1, + AR71XX_EHCI_BASE, AR71XX_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ehci_pdata_v1, sizeof(ath79_ehci_pdata_v1)); } static void __init ar7240_usb_setup(void) @@ -135,9 +125,10 @@ static void __init ar7240_usb_setup(void) iounmap(usb_ctrl_base); - ath79_usb_init_resource(ath79_ohci_resources, AR7240_OHCI_BASE, - AR7240_OHCI_SIZE, ATH79_CPU_IRQ_USB); - platform_device_register(&ath79_ohci_device); + ath79_usb_register("ohci-platform", -1, + AR7240_OHCI_BASE, AR7240_OHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ohci_pdata, sizeof(ath79_ohci_pdata)); } static void __init ar724x_usb_setup(void) @@ -151,10 +142,10 @@ static void __init ar724x_usb_setup(void) ath79_device_reset_clear(AR724X_RESET_USB_PHY); mdelay(10); - ath79_usb_init_resource(ath79_ehci_resources, AR724X_EHCI_BASE, - AR724X_EHCI_SIZE, ATH79_CPU_IRQ_USB); - ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; - platform_device_register(&ath79_ehci_device); + ath79_usb_register("ehci-platform", -1, + AR724X_EHCI_BASE, AR724X_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } static void __init ar913x_usb_setup(void) @@ -168,10 +159,10 @@ static void __init ar913x_usb_setup(void) ath79_device_reset_clear(AR913X_RESET_USB_PHY); mdelay(10); - ath79_usb_init_resource(ath79_ehci_resources, AR913X_EHCI_BASE, - AR913X_EHCI_SIZE, ATH79_CPU_IRQ_USB); - ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; - platform_device_register(&ath79_ehci_device); + ath79_usb_register("ehci-platform", -1, + AR913X_EHCI_BASE, AR913X_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } static void __init ar933x_usb_setup(void) @@ -185,10 +176,10 @@ static void __init ar933x_usb_setup(void) ath79_device_reset_clear(AR933X_RESET_USB_PHY); mdelay(10); - ath79_usb_init_resource(ath79_ehci_resources, AR933X_EHCI_BASE, - AR933X_EHCI_SIZE, ATH79_CPU_IRQ_USB); - ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; - platform_device_register(&ath79_ehci_device); + ath79_usb_register("ehci-platform", -1, + AR933X_EHCI_BASE, AR933X_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } static void __init ar934x_usb_setup(void) @@ -211,10 +202,23 @@ static void __init ar934x_usb_setup(void) ath79_device_reset_clear(AR934X_RESET_USB_HOST); udelay(1000); - ath79_usb_init_resource(ath79_ehci_resources, AR934X_EHCI_BASE, - AR934X_EHCI_SIZE, ATH79_CPU_IRQ_USB); - ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; - platform_device_register(&ath79_ehci_device); + ath79_usb_register("ehci-platform", -1, + AR934X_EHCI_BASE, AR934X_EHCI_SIZE, + ATH79_CPU_IRQ(3), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); +} + +static void __init qca955x_usb_setup(void) +{ + ath79_usb_register("ehci-platform", 0, + QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE, + ATH79_IP3_IRQ(0), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); + + ath79_usb_register("ehci-platform", 1, + QCA955X_EHCI1_BASE, QCA955X_EHCI_SIZE, + ATH79_IP3_IRQ(1), + &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); } void __init ath79_register_usb(void) @@ -231,6 +235,8 @@ void __init ath79_register_usb(void) ar933x_usb_setup(); else if (soc_is_ar934x()) ar934x_usb_setup(); + else if (soc_is_qca955x()) + qca955x_usb_setup(); else BUG(); } diff --git a/arch/mips/ath79/dev-wmac.c b/arch/mips/ath79/dev-wmac.c index d6d893c16ad4..da190b1b87ce 100644 --- a/arch/mips/ath79/dev-wmac.c +++ b/arch/mips/ath79/dev-wmac.c @@ -55,8 +55,8 @@ static void __init ar913x_wmac_setup(void) ath79_wmac_resources[0].start = AR913X_WMAC_BASE; ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1; - ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2; - ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2; + ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2); + ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2); } @@ -83,8 +83,8 @@ static void __init ar933x_wmac_setup(void) ath79_wmac_resources[0].start = AR933X_WMAC_BASE; ath79_wmac_resources[0].end = AR933X_WMAC_BASE + AR933X_WMAC_SIZE - 1; - ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2; - ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2; + ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2); + ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2); t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); if (t & AR933X_BOOTSTRAP_REF_CLK_40) @@ -107,7 +107,7 @@ static void ar934x_wmac_setup(void) ath79_wmac_resources[0].start = AR934X_WMAC_BASE; ath79_wmac_resources[0].end = AR934X_WMAC_BASE + AR934X_WMAC_SIZE - 1; ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); - ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); + ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1); t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); if (t & AR934X_BOOTSTRAP_REF_CLK_40) @@ -116,6 +116,24 @@ static void ar934x_wmac_setup(void) ath79_wmac_data.is_clk_25mhz = true; } +static void qca955x_wmac_setup(void) +{ + u32 t; + + ath79_wmac_device.name = "qca955x_wmac"; + + ath79_wmac_resources[0].start = QCA955X_WMAC_BASE; + ath79_wmac_resources[0].end = QCA955X_WMAC_BASE + QCA955X_WMAC_SIZE - 1; + ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); + ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1); + + t = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); + if (t & QCA955X_BOOTSTRAP_REF_CLK_40) + ath79_wmac_data.is_clk_25mhz = false; + else + ath79_wmac_data.is_clk_25mhz = true; +} + void __init ath79_register_wmac(u8 *cal_data) { if (soc_is_ar913x()) @@ -124,6 +142,8 @@ void __init ath79_register_wmac(u8 *cal_data) ar933x_wmac_setup(); else if (soc_is_ar934x()) ar934x_wmac_setup(); + else if (soc_is_qca955x()) + qca955x_wmac_setup(); else BUG(); diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c index dc938cb2ba58..b955fafc58ba 100644 --- a/arch/mips/ath79/early_printk.c +++ b/arch/mips/ath79/early_printk.c @@ -74,6 +74,8 @@ static void prom_putchar_init(void) case REV_ID_MAJOR_AR9341: case REV_ID_MAJOR_AR9342: case REV_ID_MAJOR_AR9344: + case REV_ID_MAJOR_QCA9556: + case REV_ID_MAJOR_QCA9558: _prom_putchar = prom_putchar_ar71xx; break; diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c index 48fe762d2526..8d025b028bb1 100644 --- a/arch/mips/ath79/gpio.c +++ b/arch/mips/ath79/gpio.c @@ -137,49 +137,45 @@ static struct gpio_chip ath79_gpio_chip = { .base = 0, }; -void ath79_gpio_function_enable(u32 mask) +static void __iomem *ath79_gpio_get_function_reg(void) { - void __iomem *base = ath79_gpio_base; - unsigned long flags; + u32 reg = 0; - spin_lock_irqsave(&ath79_gpio_lock, flags); - - __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask, - base + AR71XX_GPIO_REG_FUNC); - /* flush write */ - __raw_readl(base + AR71XX_GPIO_REG_FUNC); + if (soc_is_ar71xx() || + soc_is_ar724x() || + soc_is_ar913x() || + soc_is_ar933x()) + reg = AR71XX_GPIO_REG_FUNC; + else if (soc_is_ar934x()) + reg = AR934X_GPIO_REG_FUNC; + else + BUG(); - spin_unlock_irqrestore(&ath79_gpio_lock, flags); + return ath79_gpio_base + reg; } -void ath79_gpio_function_disable(u32 mask) +void ath79_gpio_function_setup(u32 set, u32 clear) { - void __iomem *base = ath79_gpio_base; + void __iomem *reg = ath79_gpio_get_function_reg(); unsigned long flags; spin_lock_irqsave(&ath79_gpio_lock, flags); - __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask, - base + AR71XX_GPIO_REG_FUNC); + __raw_writel((__raw_readl(reg) & ~clear) | set, reg); /* flush write */ - __raw_readl(base + AR71XX_GPIO_REG_FUNC); + __raw_readl(reg); spin_unlock_irqrestore(&ath79_gpio_lock, flags); } -void ath79_gpio_function_setup(u32 set, u32 clear) +void ath79_gpio_function_enable(u32 mask) { - void __iomem *base = ath79_gpio_base; - unsigned long flags; - - spin_lock_irqsave(&ath79_gpio_lock, flags); - - __raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set, - base + AR71XX_GPIO_REG_FUNC); - /* flush write */ - __raw_readl(base + AR71XX_GPIO_REG_FUNC); + ath79_gpio_function_setup(mask, 0); +} - spin_unlock_irqrestore(&ath79_gpio_lock, flags); +void ath79_gpio_function_disable(u32 mask) +{ + ath79_gpio_function_setup(0, mask); } void __init ath79_gpio_init(void) @@ -198,12 +194,14 @@ void __init ath79_gpio_init(void) ath79_gpio_count = AR933X_GPIO_COUNT; else if (soc_is_ar934x()) ath79_gpio_count = AR934X_GPIO_COUNT; + else if (soc_is_qca955x()) + ath79_gpio_count = QCA955X_GPIO_COUNT; else BUG(); ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); ath79_gpio_chip.ngpio = ath79_gpio_count; - if (soc_is_ar934x()) { + if (soc_is_ar934x() || soc_is_qca955x()) { ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; } diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 90d09fc15398..9c0e1761773f 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -35,44 +35,17 @@ static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) & __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); - if (pending & MISC_INT_UART) - generic_handle_irq(ATH79_MISC_IRQ_UART); - - else if (pending & MISC_INT_DMA) - generic_handle_irq(ATH79_MISC_IRQ_DMA); - - else if (pending & MISC_INT_PERFC) - generic_handle_irq(ATH79_MISC_IRQ_PERFC); - - else if (pending & MISC_INT_TIMER) - generic_handle_irq(ATH79_MISC_IRQ_TIMER); - - else if (pending & MISC_INT_TIMER2) - generic_handle_irq(ATH79_MISC_IRQ_TIMER2); - - else if (pending & MISC_INT_TIMER3) - generic_handle_irq(ATH79_MISC_IRQ_TIMER3); - - else if (pending & MISC_INT_TIMER4) - generic_handle_irq(ATH79_MISC_IRQ_TIMER4); - - else if (pending & MISC_INT_OHCI) - generic_handle_irq(ATH79_MISC_IRQ_OHCI); - - else if (pending & MISC_INT_ERROR) - generic_handle_irq(ATH79_MISC_IRQ_ERROR); - - else if (pending & MISC_INT_GPIO) - generic_handle_irq(ATH79_MISC_IRQ_GPIO); - - else if (pending & MISC_INT_WDOG) - generic_handle_irq(ATH79_MISC_IRQ_WDOG); + if (!pending) { + spurious_interrupt(); + return; + } - else if (pending & MISC_INT_ETHSW) - generic_handle_irq(ATH79_MISC_IRQ_ETHSW); + while (pending) { + int bit = __ffs(pending); - else - spurious_interrupt(); + generic_handle_irq(ATH79_MISC_IRQ(bit)); + pending &= ~BIT(bit); + } } static void ar71xx_misc_irq_unmask(struct irq_data *d) @@ -130,7 +103,10 @@ static void __init ath79_misc_irq_init(void) if (soc_is_ar71xx() || soc_is_ar913x()) ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; - else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x()) + else if (soc_is_ar724x() || + soc_is_ar933x() || + soc_is_ar934x() || + soc_is_qca955x()) ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; else BUG(); @@ -141,7 +117,7 @@ static void __init ath79_misc_irq_init(void) handle_level_irq); } - irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); + irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler); } static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) @@ -174,7 +150,89 @@ static void ar934x_ip2_irq_init(void) irq_set_chip_and_handler(i, &dummy_irq_chip, handle_level_irq); - irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch); + irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch); +} + +static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) +{ + u32 status; + + disable_irq_nosync(irq); + + status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); + status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL; + + if (status == 0) { + spurious_interrupt(); + goto enable; + } + + if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) { + /* TODO: flush DDR? */ + generic_handle_irq(ATH79_IP2_IRQ(0)); + } + + if (status & QCA955X_EXT_INT_WMAC_ALL) { + /* TODO: flush DDR? */ + generic_handle_irq(ATH79_IP2_IRQ(1)); + } + +enable: + enable_irq(irq); +} + +static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc) +{ + u32 status; + + disable_irq_nosync(irq); + + status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); + status &= QCA955X_EXT_INT_PCIE_RC2_ALL | + QCA955X_EXT_INT_USB1 | + QCA955X_EXT_INT_USB2; + + if (status == 0) { + spurious_interrupt(); + goto enable; + } + + if (status & QCA955X_EXT_INT_USB1) { + /* TODO: flush DDR? */ + generic_handle_irq(ATH79_IP3_IRQ(0)); + } + + if (status & QCA955X_EXT_INT_USB2) { + /* TODO: flush DDR? */ + generic_handle_irq(ATH79_IP3_IRQ(1)); + } + + if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) { + /* TODO: flush DDR? */ + generic_handle_irq(ATH79_IP3_IRQ(2)); + } + +enable: + enable_irq(irq); +} + +static void qca955x_irq_init(void) +{ + int i; + + for (i = ATH79_IP2_IRQ_BASE; + i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) + irq_set_chip_and_handler(i, &dummy_irq_chip, + handle_level_irq); + + irq_set_chained_handler(ATH79_CPU_IRQ(2), qca955x_ip2_irq_dispatch); + + for (i = ATH79_IP3_IRQ_BASE; + i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++) + irq_set_chip_and_handler(i, &dummy_irq_chip, + handle_level_irq); + + irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); } asmlinkage void plat_irq_dispatch(void) @@ -184,22 +242,22 @@ asmlinkage void plat_irq_dispatch(void) pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP7) - do_IRQ(ATH79_CPU_IRQ_TIMER); + do_IRQ(ATH79_CPU_IRQ(7)); else if (pending & STATUSF_IP2) ath79_ip2_handler(); else if (pending & STATUSF_IP4) - do_IRQ(ATH79_CPU_IRQ_GE0); + do_IRQ(ATH79_CPU_IRQ(4)); else if (pending & STATUSF_IP5) - do_IRQ(ATH79_CPU_IRQ_GE1); + do_IRQ(ATH79_CPU_IRQ(5)); else if (pending & STATUSF_IP3) ath79_ip3_handler(); else if (pending & STATUSF_IP6) - do_IRQ(ATH79_CPU_IRQ_MISC); + do_IRQ(ATH79_CPU_IRQ(6)); else spurious_interrupt(); @@ -212,63 +270,69 @@ asmlinkage void plat_irq_dispatch(void) * Issue a flush in the handlers to ensure that the driver sees * the update. */ + +static void ath79_default_ip2_handler(void) +{ + do_IRQ(ATH79_CPU_IRQ(2)); +} + +static void ath79_default_ip3_handler(void) +{ + do_IRQ(ATH79_CPU_IRQ(3)); +} + static void ar71xx_ip2_handler(void) { ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); - do_IRQ(ATH79_CPU_IRQ_IP2); + do_IRQ(ATH79_CPU_IRQ(2)); } static void ar724x_ip2_handler(void) { ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); - do_IRQ(ATH79_CPU_IRQ_IP2); + do_IRQ(ATH79_CPU_IRQ(2)); } static void ar913x_ip2_handler(void) { ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); - do_IRQ(ATH79_CPU_IRQ_IP2); + do_IRQ(ATH79_CPU_IRQ(2)); } static void ar933x_ip2_handler(void) { ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); - do_IRQ(ATH79_CPU_IRQ_IP2); -} - -static void ar934x_ip2_handler(void) -{ - do_IRQ(ATH79_CPU_IRQ_IP2); + do_IRQ(ATH79_CPU_IRQ(2)); } static void ar71xx_ip3_handler(void) { ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ_USB); + do_IRQ(ATH79_CPU_IRQ(3)); } static void ar724x_ip3_handler(void) { ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ_USB); + do_IRQ(ATH79_CPU_IRQ(3)); } static void ar913x_ip3_handler(void) { ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ_USB); + do_IRQ(ATH79_CPU_IRQ(3)); } static void ar933x_ip3_handler(void) { ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ_USB); + do_IRQ(ATH79_CPU_IRQ(3)); } static void ar934x_ip3_handler(void) { ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); - do_IRQ(ATH79_CPU_IRQ_USB); + do_IRQ(ATH79_CPU_IRQ(3)); } void __init arch_init_irq(void) @@ -286,16 +350,21 @@ void __init arch_init_irq(void) ath79_ip2_handler = ar933x_ip2_handler; ath79_ip3_handler = ar933x_ip3_handler; } else if (soc_is_ar934x()) { - ath79_ip2_handler = ar934x_ip2_handler; + ath79_ip2_handler = ath79_default_ip2_handler; ath79_ip3_handler = ar934x_ip3_handler; + } else if (soc_is_qca955x()) { + ath79_ip2_handler = ath79_default_ip2_handler; + ath79_ip3_handler = ath79_default_ip3_handler; } else { BUG(); } - cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; + cp0_perfcount_irq = ATH79_MISC_IRQ(5); mips_cpu_irq_init(); ath79_misc_irq_init(); if (soc_is_ar934x()) ar934x_ip2_irq_init(); + else if (soc_is_qca955x()) + qca955x_irq_init(); } diff --git a/arch/mips/ath79/mach-ap121.c b/arch/mips/ath79/mach-ap121.c index 4c20200d7c72..1bf73f2a069d 100644 --- a/arch/mips/ath79/mach-ap121.c +++ b/arch/mips/ath79/mach-ap121.c @@ -69,7 +69,7 @@ static struct spi_board_info ap121_spi_info[] = { static struct ath79_spi_platform_data ap121_spi_data = { .bus_num = 0, - .num_chipselect = 1, + .num_chipselect = 1, }; static void __init ap121_setup(void) diff --git a/arch/mips/ath79/mach-ap136.c b/arch/mips/ath79/mach-ap136.c new file mode 100644 index 000000000000..479dd4b1d0d2 --- /dev/null +++ b/arch/mips/ath79/mach-ap136.c @@ -0,0 +1,156 @@ +/* + * Qualcomm Atheros AP136 reference board support + * + * Copyright (c) 2012 Qualcomm Atheros + * Copyright (c) 2012-2013 Gabor Juhos <juhosg@openwrt.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include <linux/pci.h> +#include <linux/ath9k_platform.h> + +#include "machtypes.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-spi.h" +#include "dev-usb.h" +#include "dev-wmac.h" +#include "pci.h" + +#define AP136_GPIO_LED_STATUS_RED 14 +#define AP136_GPIO_LED_STATUS_GREEN 19 +#define AP136_GPIO_LED_USB 4 +#define AP136_GPIO_LED_WLAN_2G 13 +#define AP136_GPIO_LED_WLAN_5G 12 +#define AP136_GPIO_LED_WPS_RED 15 +#define AP136_GPIO_LED_WPS_GREEN 20 + +#define AP136_GPIO_BTN_WPS 16 +#define AP136_GPIO_BTN_RFKILL 21 + +#define AP136_KEYS_POLL_INTERVAL 20 /* msecs */ +#define AP136_KEYS_DEBOUNCE_INTERVAL (3 * AP136_KEYS_POLL_INTERVAL) + +#define AP136_WMAC_CALDATA_OFFSET 0x1000 +#define AP136_PCIE_CALDATA_OFFSET 0x5000 + +static struct gpio_led ap136_leds_gpio[] __initdata = { + { + .name = "qca:green:status", + .gpio = AP136_GPIO_LED_STATUS_GREEN, + .active_low = 1, + }, + { + .name = "qca:red:status", + .gpio = AP136_GPIO_LED_STATUS_RED, + .active_low = 1, + }, + { + .name = "qca:green:wps", + .gpio = AP136_GPIO_LED_WPS_GREEN, + .active_low = 1, + }, + { + .name = "qca:red:wps", + .gpio = AP136_GPIO_LED_WPS_RED, + .active_low = 1, + }, + { + .name = "qca:red:wlan-2g", + .gpio = AP136_GPIO_LED_WLAN_2G, + .active_low = 1, + }, + { + .name = "qca:red:usb", + .gpio = AP136_GPIO_LED_USB, + .active_low = 1, + } +}; + +static struct gpio_keys_button ap136_gpio_keys[] __initdata = { + { + .desc = "WPS button", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL, + .gpio = AP136_GPIO_BTN_WPS, + .active_low = 1, + }, + { + .desc = "RFKILL button", + .type = EV_KEY, + .code = KEY_RFKILL, + .debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL, + .gpio = AP136_GPIO_BTN_RFKILL, + .active_low = 1, + }, +}; + +static struct spi_board_info ap136_spi_info[] = { + { + .bus_num = 0, + .chip_select = 0, + .max_speed_hz = 25000000, + .modalias = "mx25l6405d", + } +}; + +static struct ath79_spi_platform_data ap136_spi_data = { + .bus_num = 0, + .num_chipselect = 1, +}; + +#ifdef CONFIG_PCI +static struct ath9k_platform_data ap136_ath9k_data; + +static int ap136_pci_plat_dev_init(struct pci_dev *dev) +{ + if (dev->bus->number == 1 && (PCI_SLOT(dev->devfn)) == 0) + dev->dev.platform_data = &ap136_ath9k_data; + + return 0; +} + +static void __init ap136_pci_init(u8 *eeprom) +{ + memcpy(ap136_ath9k_data.eeprom_data, eeprom, + sizeof(ap136_ath9k_data.eeprom_data)); + + ath79_pci_set_plat_dev_init(ap136_pci_plat_dev_init); + ath79_register_pci(); +} +#else +static inline void ap136_pci_init(void) {} +#endif /* CONFIG_PCI */ + +static void __init ap136_setup(void) +{ + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(ap136_leds_gpio), + ap136_leds_gpio); + ath79_register_gpio_keys_polled(-1, AP136_KEYS_POLL_INTERVAL, + ARRAY_SIZE(ap136_gpio_keys), + ap136_gpio_keys); + ath79_register_spi(&ap136_spi_data, ap136_spi_info, + ARRAY_SIZE(ap136_spi_info)); + ath79_register_usb(); + ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET); + ap136_pci_init(art + AP136_PCIE_CALDATA_OFFSET); +} + +MIPS_MACHINE(ATH79_MACH_AP136_010, "AP136-010", + "Atheros AP136-010 reference board", + ap136_setup); diff --git a/arch/mips/ath79/mach-ap81.c b/arch/mips/ath79/mach-ap81.c index abe19836331c..1c78d497f930 100644 --- a/arch/mips/ath79/mach-ap81.c +++ b/arch/mips/ath79/mach-ap81.c @@ -78,7 +78,7 @@ static struct spi_board_info ap81_spi_info[] = { static struct ath79_spi_platform_data ap81_spi_data = { .bus_num = 0, - .num_chipselect = 1, + .num_chipselect = 1, }; static void __init ap81_setup(void) diff --git a/arch/mips/ath79/mach-db120.c b/arch/mips/ath79/mach-db120.c index 42f540a724f4..4d661a1d2dae 100644 --- a/arch/mips/ath79/mach-db120.c +++ b/arch/mips/ath79/mach-db120.c @@ -87,7 +87,7 @@ static struct spi_board_info db120_spi_info[] = { static struct ath79_spi_platform_data db120_spi_data = { .bus_num = 0, - .num_chipselect = 1, + .num_chipselect = 1, }; #ifdef CONFIG_PCI diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c index c5f0ea5e00c3..67b980d94fb7 100644 --- a/arch/mips/ath79/mach-pb44.c +++ b/arch/mips/ath79/mach-pb44.c @@ -34,8 +34,8 @@ #define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL) static struct i2c_gpio_platform_data pb44_i2c_gpio_data = { - .sda_pin = PB44_GPIO_I2C_SDA, - .scl_pin = PB44_GPIO_I2C_SCL, + .sda_pin = PB44_GPIO_I2C_SDA, + .scl_pin = PB44_GPIO_I2C_SCL, }; static struct platform_device pb44_i2c_gpio_device = { @@ -53,7 +53,7 @@ static struct pcf857x_platform_data pb44_pcf857x_data = { static struct i2c_board_info pb44_i2c_board_info[] __initdata = { { I2C_BOARD_INFO("pcf8575", 0x20), - .platform_data = &pb44_pcf857x_data, + .platform_data = &pb44_pcf857x_data, }, }; diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h index af92e5c30d66..26254058c545 100644 --- a/arch/mips/ath79/machtypes.h +++ b/arch/mips/ath79/machtypes.h @@ -17,6 +17,7 @@ enum ath79_mach_type { ATH79_MACH_GENERIC = 0, ATH79_MACH_AP121, /* Atheros AP121 reference board */ + ATH79_MACH_AP136_010, /* Atheros AP136-010 reference board */ ATH79_MACH_AP81, /* Atheros AP81 reference board */ ATH79_MACH_DB120, /* Atheros DB120 reference board */ ATH79_MACH_PB44, /* Atheros PB44 reference board */ diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index ca83abd9d31e..730c0b03060d 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c @@ -14,10 +14,11 @@ #include <linux/init.h> #include <linux/pci.h> +#include <linux/resource.h> +#include <linux/platform_device.h> #include <asm/mach-ath79/ar71xx_regs.h> #include <asm/mach-ath79/ath79.h> #include <asm/mach-ath79/irq.h> -#include <asm/mach-ath79/pci.h> #include "pci.h" static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev); @@ -48,6 +49,21 @@ static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = { } }; +static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = { + { + .bus = 0, + .slot = 0, + .pin = 1, + .irq = ATH79_PCI_IRQ(0), + }, + { + .bus = 1, + .slot = 0, + .pin = 1, + .irq = ATH79_PCI_IRQ(1), + }, +}; + int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) { int irq = -1; @@ -63,6 +79,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) soc_is_ar9344()) { ath79_pci_irq_map = ar724x_pci_irq_map; ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); + } else if (soc_is_qca955x()) { + ath79_pci_irq_map = qca955x_pci_irq_map; + ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map); } else { pr_crit("pci %s: invalid irq map\n", pci_name((struct pci_dev *) dev)); @@ -74,7 +93,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) const struct ath79_pci_irq *entry; entry = &ath79_pci_irq_map[i]; - if (entry->slot == slot && entry->pin == pin) { + if (entry->bus == dev->bus->number && + entry->slot == slot && + entry->pin == pin) { irq = entry->irq; break; } @@ -110,21 +131,143 @@ void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev)) ath79_pci_plat_dev_init = func; } -int __init ath79_register_pci(void) +static struct platform_device * +ath79_register_pci_ar71xx(void) +{ + struct platform_device *pdev; + struct resource res[4]; + + memset(res, 0, sizeof(res)); + + res[0].name = "cfg_base"; + res[0].flags = IORESOURCE_MEM; + res[0].start = AR71XX_PCI_CFG_BASE; + res[0].end = AR71XX_PCI_CFG_BASE + AR71XX_PCI_CFG_SIZE - 1; + + res[1].flags = IORESOURCE_IRQ; + res[1].start = ATH79_CPU_IRQ(2); + res[1].end = ATH79_CPU_IRQ(2); + + res[2].name = "io_base"; + res[2].flags = IORESOURCE_IO; + res[2].start = 0; + res[2].end = 0; + + res[3].name = "mem_base"; + res[3].flags = IORESOURCE_MEM; + res[3].start = AR71XX_PCI_MEM_BASE; + res[3].end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1; + + pdev = platform_device_register_simple("ar71xx-pci", -1, + res, ARRAY_SIZE(res)); + return pdev; +} + +static struct platform_device * +ath79_register_pci_ar724x(int id, + unsigned long cfg_base, + unsigned long ctrl_base, + unsigned long crp_base, + unsigned long mem_base, + unsigned long mem_size, + unsigned long io_base, + int irq) { - if (soc_is_ar71xx()) - return ar71xx_pcibios_init(); + struct platform_device *pdev; + struct resource res[6]; + + memset(res, 0, sizeof(res)); + + res[0].name = "cfg_base"; + res[0].flags = IORESOURCE_MEM; + res[0].start = cfg_base; + res[0].end = cfg_base + AR724X_PCI_CFG_SIZE - 1; + + res[1].name = "ctrl_base"; + res[1].flags = IORESOURCE_MEM; + res[1].start = ctrl_base; + res[1].end = ctrl_base + AR724X_PCI_CTRL_SIZE - 1; + + res[2].flags = IORESOURCE_IRQ; + res[2].start = irq; + res[2].end = irq; + + res[3].name = "mem_base"; + res[3].flags = IORESOURCE_MEM; + res[3].start = mem_base; + res[3].end = mem_base + mem_size - 1; + + res[4].name = "io_base"; + res[4].flags = IORESOURCE_IO; + res[4].start = io_base; + res[4].end = io_base; - if (soc_is_ar724x()) - return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2); + res[5].name = "crp_base"; + res[5].flags = IORESOURCE_MEM; + res[5].start = crp_base; + res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1; - if (soc_is_ar9342() || soc_is_ar9344()) { + pdev = platform_device_register_simple("ar724x-pci", id, + res, ARRAY_SIZE(res)); + return pdev; +} + +int __init ath79_register_pci(void) +{ + struct platform_device *pdev = NULL; + + if (soc_is_ar71xx()) { + pdev = ath79_register_pci_ar71xx(); + } else if (soc_is_ar724x()) { + pdev = ath79_register_pci_ar724x(-1, + AR724X_PCI_CFG_BASE, + AR724X_PCI_CTRL_BASE, + AR724X_PCI_CRP_BASE, + AR724X_PCI_MEM_BASE, + AR724X_PCI_MEM_SIZE, + 0, + ATH79_CPU_IRQ(2)); + } else if (soc_is_ar9342() || + soc_is_ar9344()) { u32 bootstrap; bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); - if (bootstrap & AR934X_BOOTSTRAP_PCIE_RC) - return ar724x_pcibios_init(ATH79_IP2_IRQ(0)); + if ((bootstrap & AR934X_BOOTSTRAP_PCIE_RC) == 0) + return -ENODEV; + + pdev = ath79_register_pci_ar724x(-1, + AR724X_PCI_CFG_BASE, + AR724X_PCI_CTRL_BASE, + AR724X_PCI_CRP_BASE, + AR724X_PCI_MEM_BASE, + AR724X_PCI_MEM_SIZE, + 0, + ATH79_IP2_IRQ(0)); + } else if (soc_is_qca9558()) { + pdev = ath79_register_pci_ar724x(0, + QCA955X_PCI_CFG_BASE0, + QCA955X_PCI_CTRL_BASE0, + QCA955X_PCI_CRP_BASE0, + QCA955X_PCI_MEM_BASE0, + QCA955X_PCI_MEM_SIZE, + 0, + ATH79_IP2_IRQ(0)); + + pdev = ath79_register_pci_ar724x(1, + QCA955X_PCI_CFG_BASE1, + QCA955X_PCI_CTRL_BASE1, + QCA955X_PCI_CRP_BASE1, + QCA955X_PCI_MEM_BASE1, + QCA955X_PCI_MEM_SIZE, + 1, + ATH79_IP3_IRQ(2)); + } else { + /* No PCI support */ + return -ENODEV; } - return -ENODEV; + if (!pdev) + pr_err("unable to register PCI controller device\n"); + + return pdev ? 0 : -ENODEV; } diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h index 51c6625dcc6d..1d00a3803c37 100644 --- a/arch/mips/ath79/pci.h +++ b/arch/mips/ath79/pci.h @@ -14,6 +14,7 @@ #define _ATH79_PCI_H struct ath79_pci_irq { + int bus; u8 slot; u8 pin; int irq; diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 60d212ef8629..d5b3c9057018 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -164,13 +164,29 @@ static void __init ath79_detect_sys_type(void) rev = id & AR934X_REV_ID_REVISION_MASK; break; + case REV_ID_MAJOR_QCA9556: + ath79_soc = ATH79_SOC_QCA9556; + chip = "9556"; + rev = id & QCA955X_REV_ID_REVISION_MASK; + break; + + case REV_ID_MAJOR_QCA9558: + ath79_soc = ATH79_SOC_QCA9558; + chip = "9558"; + rev = id & QCA955X_REV_ID_REVISION_MASK; + break; + default: panic("ath79: unknown SoC, id:0x%08x", id); } ath79_soc_rev = rev; - sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); + if (soc_is_qca955x()) + sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s rev %u", + chip, rev); + else + sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev); pr_info("SoC: %s\n", ath79_sys_type); } |