diff options
Diffstat (limited to 'arch/mips')
114 files changed, 3822 insertions, 2260 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 6e04163..54be81c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -228,8 +228,9 @@ config LANTIQ select ARCH_REQUIRE_GPIOLIB select SWAP_IO_SPACE select BOOT_RAW - select HAVE_CLK - select MIPS_MACHINE + select HAVE_MACH_CLKDEV + select CLKDEV_LOOKUP + select USE_OF config LASAT bool "LASAT Networks platforms" diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c index a83302b..7dde016 100644 --- a/arch/mips/alchemy/devboards/db1200.c +++ b/arch/mips/alchemy/devboards/db1200.c @@ -22,6 +22,7 @@ #include <linux/gpio.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/module.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/leds.h> diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index e0fae8f..f44feee 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -26,6 +26,18 @@ config ATH79_MACH_AP81 Say 'Y' here if you want your kernel to support the Atheros AP81 reference board. +config ATH79_MACH_DB120 + bool "Atheros DB120 reference board" + select SOC_AR934X + 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 DB120 reference board. + config ATH79_MACH_PB44 bool "Atheros PB44 reference board" select SOC_AR71XX @@ -52,12 +64,14 @@ endmenu config SOC_AR71XX select USB_ARCH_HAS_EHCI select USB_ARCH_HAS_OHCI + select HW_HAS_PCI def_bool n config SOC_AR724X select USB_ARCH_HAS_EHCI select USB_ARCH_HAS_OHCI select HW_HAS_PCI + select PCI_AR724X if PCI def_bool n config SOC_AR913X @@ -68,6 +82,15 @@ config SOC_AR933X select USB_ARCH_HAS_EHCI def_bool n +config SOC_AR934X + select USB_ARCH_HAS_EHCI + select HW_HAS_PCI + select PCI_AR724X if PCI + def_bool n + +config PCI_AR724X + def_bool n + config ATH79_DEV_GPIO_BUTTONS def_bool n @@ -81,7 +104,7 @@ config ATH79_DEV_USB def_bool n config ATH79_DEV_WMAC - depends on (SOC_AR913X || SOC_AR933X) + depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X) def_bool n endif diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile index 3b911e09..2b54d98 100644 --- a/arch/mips/ath79/Makefile +++ b/arch/mips/ath79/Makefile @@ -11,6 +11,7 @@ obj-y := prom.o setup.o irq.o common.o clock.o gpio.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_PCI) += pci.o # # Devices @@ -27,5 +28,6 @@ obj-$(CONFIG_ATH79_DEV_WMAC) += dev-wmac.o # obj-$(CONFIG_ATH79_MACH_AP121) += mach-ap121.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 obj-$(CONFIG_ATH79_MACH_UBNT_XM) += mach-ubnt-xm.o diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 54d0eb4..b91ad3e 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -1,8 +1,11 @@ /* * Atheros AR71XX/AR724X/AR913X common routines * + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> * + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. @@ -163,6 +166,82 @@ static void __init ar933x_clocks_init(void) ath79_uart_clk.rate = ath79_ref_clk.rate; } +static void __init ar934x_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(AR934X_RESET_REG_BOOTSTRAP); + if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) + ath79_ref_clk.rate = 40 * 1000 * 1000; + else + ath79_ref_clk.rate = 25 * 1000 * 1000; + + pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); + out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + AR934X_PLL_CPU_CONFIG_REFDIV_MASK; + nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & + AR934X_PLL_CPU_CONFIG_NINT_MASK; + frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & + AR934X_PLL_CPU_CONFIG_NFRAC_MASK; + + cpu_pll = nint * ath79_ref_clk.rate / ref_div; + cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 6)); + cpu_pll /= (1 << out_div); + + pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); + out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + AR934X_PLL_DDR_CONFIG_REFDIV_MASK; + nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & + AR934X_PLL_DDR_CONFIG_NINT_MASK; + frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & + AR934X_PLL_DDR_CONFIG_NFRAC_MASK; + + ddr_pll = nint * ath79_ref_clk.rate / ref_div; + ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 10)); + ddr_pll /= (1 << out_div); + + clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); + + postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & + AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; + + if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) + ath79_cpu_clk.rate = ath79_ref_clk.rate; + else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) + ath79_cpu_clk.rate = cpu_pll / (postdiv + 1); + else + ath79_cpu_clk.rate = ddr_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & + AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; + + if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) + ath79_ddr_clk.rate = ath79_ref_clk.rate; + else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) + ath79_ddr_clk.rate = ddr_pll / (postdiv + 1); + else + ath79_ddr_clk.rate = cpu_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & + AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; + + if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) + ath79_ahb_clk.rate = ath79_ref_clk.rate; + else if (clk_ctrl & AR934X_PLL_CPU_DDR_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()) @@ -173,6 +252,8 @@ void __init ath79_clocks_init(void) ar913x_clocks_init(); else if (soc_is_ar933x()) ar933x_clocks_init(); + else if (soc_is_ar934x()) + ar934x_clocks_init(); else BUG(); diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index f0fda98..5a4adfc 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -1,9 +1,12 @@ /* * Atheros AR71XX/AR724X/AR913X common routines * - * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> * + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. @@ -67,6 +70,8 @@ void ath79_device_reset_set(u32 mask) reg = AR913X_RESET_REG_RESET_MODULE; else if (soc_is_ar933x()) reg = AR933X_RESET_REG_RESET_MODULE; + else if (soc_is_ar934x()) + reg = AR934X_RESET_REG_RESET_MODULE; else BUG(); @@ -91,6 +96,8 @@ void ath79_device_reset_clear(u32 mask) reg = AR913X_RESET_REG_RESET_MODULE; else if (soc_is_ar933x()) reg = AR933X_RESET_REG_RESET_MODULE; + else if (soc_is_ar934x()) + reg = AR934X_RESET_REG_RESET_MODULE; else BUG(); diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c index f4956f8..45efc63 100644 --- a/arch/mips/ath79/dev-common.c +++ b/arch/mips/ath79/dev-common.c @@ -89,7 +89,8 @@ void __init ath79_register_uart(void) if (soc_is_ar71xx() || soc_is_ar724x() || - soc_is_ar913x()) { + soc_is_ar913x() || + soc_is_ar934x()) { ath79_uart_data[0].uartclk = clk_get_rate(clk); platform_device_register(&ath79_uart_device); } else if (soc_is_ar933x()) { diff --git a/arch/mips/ath79/dev-gpio-buttons.c b/arch/mips/ath79/dev-gpio-buttons.c index 4b0168a..366b35f 100644 --- a/arch/mips/ath79/dev-gpio-buttons.c +++ b/arch/mips/ath79/dev-gpio-buttons.c @@ -25,12 +25,10 @@ void __init ath79_register_gpio_keys_polled(int id, struct gpio_keys_button *p; int err; - p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); + p = kmemdup(buttons, nbuttons * sizeof(*p), GFP_KERNEL); if (!p) return; - memcpy(p, buttons, nbuttons * sizeof(*p)); - pdev = platform_device_alloc("gpio-keys-polled", id); if (!pdev) goto err_free_buttons; diff --git a/arch/mips/ath79/dev-leds-gpio.c b/arch/mips/ath79/dev-leds-gpio.c index cdade68..dcb1deb 100644 --- a/arch/mips/ath79/dev-leds-gpio.c +++ b/arch/mips/ath79/dev-leds-gpio.c @@ -24,12 +24,10 @@ void __init ath79_register_leds_gpio(int id, struct gpio_led *p; int err; - p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); + p = kmemdup(leds, num_leds * sizeof(*p), GFP_KERNEL); if (!p) return; - memcpy(p, leds, num_leds * sizeof(*p)); - pdev = platform_device_alloc("leds-gpio", id); if (!pdev) goto err_free_leds; diff --git a/arch/mips/ath79/dev-wmac.c b/arch/mips/ath79/dev-wmac.c index 9c717bf..d6d893c 100644 --- a/arch/mips/ath79/dev-wmac.c +++ b/arch/mips/ath79/dev-wmac.c @@ -1,9 +1,12 @@ /* * Atheros AR913X/AR933X SoC built-in WMAC device support * + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> * + * Parts of this file are based on Atheros 2.6.15/2.6.31 BSP + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. @@ -26,8 +29,7 @@ static struct resource ath79_wmac_resources[] = { /* .start and .end fields are filled dynamically */ .flags = IORESOURCE_MEM, }, { - .start = ATH79_CPU_IRQ_IP2, - .end = ATH79_CPU_IRQ_IP2, + /* .start and .end fields are filled dynamically */ .flags = IORESOURCE_IRQ, }, }; @@ -53,6 +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; } @@ -79,6 +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; t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); if (t & AR933X_BOOTSTRAP_REF_CLK_40) @@ -92,12 +98,32 @@ static void __init ar933x_wmac_setup(void) ath79_wmac_data.external_reset = ar933x_wmac_reset; } +static void ar934x_wmac_setup(void) +{ + u32 t; + + ath79_wmac_device.name = "ar934x_wmac"; + + 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); + + t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); + if (t & AR934X_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()) ar913x_wmac_setup(); else if (soc_is_ar933x()) ar933x_wmac_setup(); + else if (soc_is_ar934x()) + ar934x_wmac_setup(); else BUG(); diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c index 6a51ced..dc938cb 100644 --- a/arch/mips/ath79/early_printk.c +++ b/arch/mips/ath79/early_printk.c @@ -71,6 +71,9 @@ static void prom_putchar_init(void) case REV_ID_MAJOR_AR7241: case REV_ID_MAJOR_AR7242: case REV_ID_MAJOR_AR913X: + case REV_ID_MAJOR_AR9341: + case REV_ID_MAJOR_AR9342: + case REV_ID_MAJOR_AR9344: _prom_putchar = prom_putchar_ar71xx; break; diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c index a2f8ca6..29054f2 100644 --- a/arch/mips/ath79/gpio.c +++ b/arch/mips/ath79/gpio.c @@ -1,9 +1,12 @@ /* * Atheros AR71XX/AR724X/AR913X GPIO API support * - * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> * + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. @@ -89,6 +92,42 @@ static int ath79_gpio_direction_output(struct gpio_chip *chip, return 0; } +static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + void __iomem *base = ath79_gpio_base; + unsigned long flags; + + spin_lock_irqsave(&ath79_gpio_lock, flags); + + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), + base + AR71XX_GPIO_REG_OE); + + spin_unlock_irqrestore(&ath79_gpio_lock, flags); + + return 0; +} + +static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + void __iomem *base = ath79_gpio_base; + unsigned long flags; + + spin_lock_irqsave(&ath79_gpio_lock, flags); + + if (value) + __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); + else + __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); + + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), + base + AR71XX_GPIO_REG_OE); + + spin_unlock_irqrestore(&ath79_gpio_lock, flags); + + return 0; +} + static struct gpio_chip ath79_gpio_chip = { .label = "ath79", .get = ath79_gpio_get_value, @@ -155,11 +194,17 @@ void __init ath79_gpio_init(void) ath79_gpio_count = AR913X_GPIO_COUNT; else if (soc_is_ar933x()) ath79_gpio_count = AR933X_GPIO_COUNT; + else if (soc_is_ar934x()) + ath79_gpio_count = AR934X_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()) { + ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; + ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; + } err = gpiochip_add(&ath79_gpio_chip); if (err) diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 1b073de..90d09fc 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -1,10 +1,11 @@ /* * Atheros AR71xx/AR724x/AR913x specific interrupt handling * - * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> * - * Parts of this file are based on Atheros' 2.6.15 BSP + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -23,8 +24,8 @@ #include <asm/mach-ath79/ar71xx_regs.h> #include "common.h" -static unsigned int ath79_ip2_flush_reg; -static unsigned int ath79_ip3_flush_reg; +static void (*ath79_ip2_handler)(void); +static void (*ath79_ip3_handler)(void); static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) { @@ -129,7 +130,7 @@ 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()) + else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x()) ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; else BUG(); @@ -143,6 +144,39 @@ static void __init ath79_misc_irq_init(void) irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); } +static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) +{ + u32 status; + + disable_irq_nosync(irq); + + status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); + + if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { + ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE); + generic_handle_irq(ATH79_IP2_IRQ(0)); + } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { + ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC); + generic_handle_irq(ATH79_IP2_IRQ(1)); + } else { + spurious_interrupt(); + } + + enable_irq(irq); +} + +static void ar934x_ip2_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_IP2, ar934x_ip2_irq_dispatch); +} + asmlinkage void plat_irq_dispatch(void) { unsigned long pending; @@ -152,10 +186,8 @@ asmlinkage void plat_irq_dispatch(void) if (pending & STATUSF_IP7) do_IRQ(ATH79_CPU_IRQ_TIMER); - else if (pending & STATUSF_IP2) { - ath79_ddr_wb_flush(ath79_ip2_flush_reg); - do_IRQ(ATH79_CPU_IRQ_IP2); - } + else if (pending & STATUSF_IP2) + ath79_ip2_handler(); else if (pending & STATUSF_IP4) do_IRQ(ATH79_CPU_IRQ_GE0); @@ -163,10 +195,8 @@ asmlinkage void plat_irq_dispatch(void) else if (pending & STATUSF_IP5) do_IRQ(ATH79_CPU_IRQ_GE1); - else if (pending & STATUSF_IP3) { - ath79_ddr_wb_flush(ath79_ip3_flush_reg); - do_IRQ(ATH79_CPU_IRQ_USB); - } + else if (pending & STATUSF_IP3) + ath79_ip3_handler(); else if (pending & STATUSF_IP6) do_IRQ(ATH79_CPU_IRQ_MISC); @@ -175,24 +205,97 @@ asmlinkage void plat_irq_dispatch(void) spurious_interrupt(); } +/* + * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for + * these devices typically allocate coherent DMA memory, however the + * DMA controller may still have some unsynchronized data in the FIFO. + * Issue a flush in the handlers to ensure that the driver sees + * the update. + */ +static void ar71xx_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +static void ar724x_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +static void ar913x_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +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); +} + +static void ar71xx_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar724x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar913x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar933x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar934x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + void __init arch_init_irq(void) { if (soc_is_ar71xx()) { - ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI; - ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB; + ath79_ip2_handler = ar71xx_ip2_handler; + ath79_ip3_handler = ar71xx_ip3_handler; } else if (soc_is_ar724x()) { - ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE; - ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB; + ath79_ip2_handler = ar724x_ip2_handler; + ath79_ip3_handler = ar724x_ip3_handler; } else if (soc_is_ar913x()) { - ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC; - ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB; + ath79_ip2_handler = ar913x_ip2_handler; + ath79_ip3_handler = ar913x_ip3_handler; } else if (soc_is_ar933x()) { - ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC; - ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB; - } else + ath79_ip2_handler = ar933x_ip2_handler; + ath79_ip3_handler = ar933x_ip3_handler; + } else if (soc_is_ar934x()) { + ath79_ip2_handler = ar934x_ip2_handler; + ath79_ip3_handler = ar934x_ip3_handler; + } else { BUG(); + } cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; mips_cpu_irq_init(); ath79_misc_irq_init(); + + if (soc_is_ar934x()) + ar934x_ip2_irq_init(); } diff --git a/arch/mips/ath79/mach-db120.c b/arch/mips/ath79/mach-db120.c new file mode 100644 index 0000000..1983e4d --- /dev/null +++ b/arch/mips/ath79/mach-db120.c @@ -0,0 +1,134 @@ +/* + * Atheros DB120 reference board support + * + * Copyright (c) 2011 Qualcomm Atheros + * Copyright (c) 2011 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-wmac.h" +#include "pci.h" + +#define DB120_GPIO_LED_WLAN_5G 12 +#define DB120_GPIO_LED_WLAN_2G 13 +#define DB120_GPIO_LED_STATUS 14 +#define DB120_GPIO_LED_WPS 15 + +#define DB120_GPIO_BTN_WPS 16 + +#define DB120_KEYS_POLL_INTERVAL 20 /* msecs */ +#define DB120_KEYS_DEBOUNCE_INTERVAL (3 * DB120_KEYS_POLL_INTERVAL) + +#define DB120_WMAC_CALDATA_OFFSET 0x1000 +#define DB120_PCIE_CALDATA_OFFSET 0x5000 + +static struct gpio_led db120_leds_gpio[] __initdata = { + { + .name = "db120:green:status", + .gpio = DB120_GPIO_LED_STATUS, + .active_low = 1, + }, + { + .name = "db120:green:wps", + .gpio = DB120_GPIO_LED_WPS, + .active_low = 1, + }, + { + .name = "db120:green:wlan-5g", + .gpio = DB120_GPIO_LED_WLAN_5G, + .active_low = 1, + }, + { + .name = "db120:green:wlan-2g", + .gpio = DB120_GPIO_LED_WLAN_2G, + .active_low = 1, + }, +}; + +static struct gpio_keys_button db120_gpio_keys[] __initdata = { + { + .desc = "WPS button", + .type = EV_KEY, + .code = KEY_WPS_BUTTON, + .debounce_interval = DB120_KEYS_DEBOUNCE_INTERVAL, + .gpio = DB120_GPIO_BTN_WPS, + .active_low = 1, + }, +}; + +static struct spi_board_info db120_spi_info[] = { + { + .bus_num = 0, + .chip_select = 0, + .max_speed_hz = 25000000, + .modalias = "s25sl064a", + } +}; + +static struct ath79_spi_platform_data db120_spi_data = { + .bus_num = 0, + .num_chipselect = 1, +}; + +#ifdef CONFIG_PCI +static struct ath9k_platform_data db120_ath9k_data; + +static int db120_pci_plat_dev_init(struct pci_dev *dev) +{ + switch (PCI_SLOT(dev->devfn)) { + case 0: + dev->dev.platform_data = &db120_ath9k_data; + break; + } + + return 0; +} + +static void __init db120_pci_init(u8 *eeprom) +{ + memcpy(db120_ath9k_data.eeprom_data, eeprom, + sizeof(db120_ath9k_data.eeprom_data)); + + ath79_pci_set_plat_dev_init(db120_pci_plat_dev_init); + ath79_register_pci(); +} +#else +static inline void db120_pci_init(void) {} +#endif /* CONFIG_PCI */ + +static void __init db120_setup(void) +{ + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + + ath79_register_leds_gpio(-1, ARRAY_SIZE(db120_leds_gpio), + db120_leds_gpio); + ath79_register_gpio_keys_polled(-1, DB120_KEYS_POLL_INTERVAL, + ARRAY_SIZE(db120_gpio_keys), + db120_gpio_keys); + ath79_register_spi(&db120_spi_data, db120_spi_info, + ARRAY_SIZE(db120_spi_info)); + ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET); + db120_pci_init(art + DB120_PCIE_CALDATA_OFFSET); +} + +MIPS_MACHINE(ATH79_MACH_DB120, "DB120", "Atheros DB120 reference board", + db120_setup); diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c index fe9701a..c5f0ea5 100644 --- a/arch/mips/ath79/mach-pb44.c +++ b/arch/mips/ath79/mach-pb44.c @@ -19,6 +19,7 @@ #include "dev-leds-gpio.h" #include "dev-spi.h" #include "dev-usb.h" +#include "pci.h" #define PB44_GPIO_I2C_SCL 0 #define PB44_GPIO_I2C_SDA 1 @@ -114,6 +115,7 @@ static void __init pb44_init(void) ath79_register_spi(&pb44_spi_data, pb44_spi_info, ARRAY_SIZE(pb44_spi_info)); ath79_register_usb(); + ath79_register_pci(); } MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board", diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c index 3c311a5..4a3c606 100644 --- a/arch/mips/ath79/mach-ubnt-xm.c +++ b/arch/mips/ath79/mach-ubnt-xm.c @@ -12,16 +12,15 @@ #include <linux/init.h> #include <linux/pci.h> - -#ifdef CONFIG_PCI #include <linux/ath9k_platform.h> -#include <asm/mach-ath79/pci-ath724x.h> -#endif /* CONFIG_PCI */ + +#include <asm/mach-ath79/irq.h> #include "machtypes.h" #include "dev-gpio-buttons.h" #include "dev-leds-gpio.h" #include "dev-spi.h" +#include "pci.h" #define UBNT_XM_GPIO_LED_L1 0 #define UBNT_XM_GPIO_LED_L2 1 @@ -33,7 +32,6 @@ #define UBNT_XM_KEYS_POLL_INTERVAL 20 #define UBNT_XM_KEYS_DEBOUNCE_INTERVAL (3 * UBNT_XM_KEYS_POLL_INTERVAL) -#define UBNT_XM_PCI_IRQ 48 #define UBNT_XM_EEPROM_ADDR (u8 *) KSEG1ADDR(0x1fff1000) static struct gpio_led ubnt_xm_leds_gpio[] __initdata = { @@ -84,12 +82,27 @@ static struct ath79_spi_platform_data ubnt_xm_spi_data = { #ifdef CONFIG_PCI static struct ath9k_platform_data ubnt_xm_eeprom_data; -static struct ath724x_pci_data ubnt_xm_pci_data[] = { - { - .irq = UBNT_XM_PCI_IRQ, - .pdata = &ubnt_xm_eeprom_data, - }, -}; +static int ubnt_xm_pci_plat_dev_init(struct pci_dev *dev) +{ + switch (PCI_SLOT(dev->devfn)) { + case 0: + dev->dev.platform_data = &ubnt_xm_eeprom_data; + break; + } + + return 0; +} + +static void __init ubnt_xm_pci_init(void) +{ + memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR, + sizeof(ubnt_xm_eeprom_data.eeprom_data)); + + ath79_pci_set_plat_dev_init(ubnt_xm_pci_plat_dev_init); + ath79_register_pci(); +} +#else +static inline void ubnt_xm_pci_init(void) {} #endif /* CONFIG_PCI */ static void __init ubnt_xm_init(void) @@ -104,13 +117,7 @@ static void __init ubnt_xm_init(void) ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info, ARRAY_SIZE(ubnt_xm_spi_info)); -#ifdef CONFIG_PCI - memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR, - sizeof(ubnt_xm_eeprom_data.eeprom_data)); - - ath724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data)); -#endif /* CONFIG_PCI */ - + ubnt_xm_pci_init(); } MIPS_MACHINE(ATH79_MACH_UBNT_XM, diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h index 9a1f382..af92e5c 100644 --- a/arch/mips/ath79/machtypes.h +++ b/arch/mips/ath79/machtypes.h @@ -18,6 +18,7 @@ enum ath79_mach_type { ATH79_MACH_GENERIC = 0, ATH79_MACH_AP121, /* Atheros AP121 reference board */ ATH79_MACH_AP81, /* Atheros AP81 reference board */ + ATH79_MACH_DB120, /* Atheros DB120 reference board */ ATH79_MACH_PB44, /* Atheros PB44 reference board */ ATH79_MACH_UBNT_XM, /* Ubiquiti Networks XM board rev 1.0 */ }; diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c new file mode 100644 index 0000000..ca83abd --- /dev/null +++ b/arch/mips/ath79/pci.c @@ -0,0 +1,130 @@ +/* + * Atheros AR71XX/AR724X specific PCI setup code + * + * Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/pci.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); +static const struct ath79_pci_irq *ath79_pci_irq_map __initdata; +static unsigned ath79_pci_nr_irqs __initdata; + +static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = { + { + .slot = 17, + .pin = 1, + .irq = ATH79_PCI_IRQ(0), + }, { + .slot = 18, + .pin = 1, + .irq = ATH79_PCI_IRQ(1), + }, { + .slot = 19, + .pin = 1, + .irq = ATH79_PCI_IRQ(2), + } +}; + +static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = { + { + .slot = 0, + .pin = 1, + .irq = ATH79_PCI_IRQ(0), + } +}; + +int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) +{ + int irq = -1; + int i; + + if (ath79_pci_nr_irqs == 0 || + ath79_pci_irq_map == NULL) { + if (soc_is_ar71xx()) { + ath79_pci_irq_map = ar71xx_pci_irq_map; + ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map); + } else if (soc_is_ar724x() || + soc_is_ar9342() || + soc_is_ar9344()) { + ath79_pci_irq_map = ar724x_pci_irq_map; + ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map); + } else { + pr_crit("pci %s: invalid irq map\n", + pci_name((struct pci_dev *) dev)); + return irq; + } + } + + for (i = 0; i < ath79_pci_nr_irqs; i++) { + const struct ath79_pci_irq *entry; + + entry = &ath79_pci_irq_map[i]; + if (entry->slot == slot && entry->pin == pin) { + irq = entry->irq; + break; + } + } + + if (irq < 0) + pr_crit("pci %s: no irq found for pin %u\n", + pci_name((struct pci_dev *) dev), pin); + else + pr_info("pci %s: using irq %d for pin %u\n", + pci_name((struct pci_dev *) dev), irq, pin); + + return irq; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + if (ath79_pci_plat_dev_init) + return ath79_pci_plat_dev_init(dev); + + return 0; +} + +void __init ath79_pci_set_irq_map(unsigned nr_irqs, + const struct ath79_pci_irq *map) +{ + ath79_pci_nr_irqs = nr_irqs; + ath79_pci_irq_map = map; +} + +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) +{ + if (soc_is_ar71xx()) + return ar71xx_pcibios_init(); + + if (soc_is_ar724x()) + return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2); + + 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)); + } + + return -ENODEV; +} diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h new file mode 100644 index 0000000..51c6625 --- /dev/null +++ b/arch/mips/ath79/pci.h @@ -0,0 +1,34 @@ +/* + * Atheros AR71XX/AR724X PCI support + * + * Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _ATH79_PCI_H +#define _ATH79_PCI_H + +struct ath79_pci_irq { + u8 slot; + u8 pin; + int irq; +}; + +#ifdef CONFIG_PCI +void ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map); +void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev)); +int ath79_register_pci(void); +#else +static inline void +ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map) {} +static inline void +ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {} +static inline int ath79_register_pci(void) { return 0; } +#endif + +#endif /* _ATH79_PCI_H */ diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 80a7d40..60d212e 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -1,10 +1,11 @@ /* * Atheros AR71XX/AR724X/AR913X specific setup * + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> * - * Parts of this file are based on Atheros' 2.6.15 BSP + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -116,18 +117,6 @@ static void __init ath79_detect_sys_type(void) rev = id & AR724X_REV_ID_REVISION_MASK; break; - case REV_ID_MAJOR_AR9330: - ath79_soc = ATH79_SOC_AR9330; - chip = "9330"; - rev = id & AR933X_REV_ID_REVISION_MASK; - break; - - case REV_ID_MAJOR_AR9331: - ath79_soc = ATH79_SOC_AR9331; - chip = "9331"; - rev = id & AR933X_REV_ID_REVISION_MASK; - break; - case REV_ID_MAJOR_AR913X: minor = id & AR913X_REV_ID_MINOR_MASK; rev = id >> AR913X_REV_ID_REVISION_SHIFT; @@ -145,6 +134,36 @@ static void __init ath79_detect_sys_type(void) } break; + case REV_ID_MAJOR_AR9330: + ath79_soc = ATH79_SOC_AR9330; + chip = "9330"; + rev = id & AR933X_REV_ID_REVISION_MASK; + break; + + case REV_ID_MAJOR_AR9331: + ath79_soc = ATH79_SOC_AR9331; + chip = "9331"; + rev = id & AR933X_REV_ID_REVISION_MASK; + break; + + case REV_ID_MAJOR_AR9341: + ath79_soc = ATH79_SOC_AR9341; + chip = "9341"; + rev = id & AR934X_REV_ID_REVISION_MASK; + break; + + case REV_ID_MAJOR_AR9342: + ath79_soc = ATH79_SOC_AR9342; + chip = "9342"; + rev = id & AR934X_REV_ID_REVISION_MASK; + break; + + case REV_ID_MAJOR_AR9344: + ath79_soc = ATH79_SOC_AR9344; + chip = "9344"; + rev = id & AR934X_REV_ID_REVISION_MASK; + break; + default: panic("ath79: unknown SoC, id:0x%08x", id); } diff --git a/arch/mips/bcm63xx/boards/Makefile b/arch/mips/bcm63xx/boards/Makefile index 9f64fb4..af07c1a 100644 --- a/arch/mips/bcm63xx/boards/Makefile +++ b/arch/mips/bcm63xx/boards/Makefile @@ -1,3 +1 @@ obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o - -ccflags-y := -Werror diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index d3a9f012..260dc24 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -9,6 +9,7 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/serial.h> diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 97e7ce9..4b93048 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -257,8 +257,6 @@ DEFINE_PER_CPU(int, cpu_state); extern void fixup_irqs(void); -static DEFINE_SPINLOCK(smp_reserve_lock); - static int octeon_cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -266,8 +264,6 @@ static int octeon_cpu_disable(void) if (cpu == 0) return -EBUSY; - spin_lock(&smp_reserve_lock); - set_cpu_online(cpu, false); cpu_clear(cpu, cpu_callin_map); local_irq_disable(); @@ -277,8 +273,6 @@ static int octeon_cpu_disable(void) flush_cache_all(); local_flush_tlb_all(); - spin_unlock(&smp_reserve_lock); - return 0; } diff --git a/arch/mips/fw/arc/Makefile b/arch/mips/fw/arc/Makefile index 5314b37..4f349ec 100644 --- a/arch/mips/fw/arc/Makefile +++ b/arch/mips/fw/arc/Makefile @@ -8,5 +8,3 @@ lib-y += cmdline.o env.o file.o identify.o init.o \ lib-$(CONFIG_ARC_MEMORY) += memory.o lib-$(CONFIG_ARC_CONSOLE) += arc_con.o lib-$(CONFIG_ARC_PROMLIB) += promlib.o - -ccflags-y := -Werror diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h new file mode 100644 index 0000000..2624754 --- /dev/null +++ b/arch/mips/include/asm/clkdev.h @@ -0,0 +1,25 @@ +/* + * based on arch/arm/include/asm/clkdev.h + * + * Copyright (C) 2008 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Helper for the clk API to assist looking up a struct clk. + */ +#ifndef __ASM_CLKDEV_H +#define __ASM_CLKDEV_H + +#include <linux/slab.h> + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) +{ + return kzalloc(size, GFP_KERNEL); +} + +#endif diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h index 2f0becb..1caa78a 100644 --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h @@ -1,10 +1,11 @@ /* * Atheros AR71XX/AR724X/AR913X SoC register definitions * + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> * - * Parts of this file are based on Atheros' 2.6.15 BSP + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -60,6 +61,9 @@ #define AR933X_EHCI_BASE 0x1b000000 #define AR933X_EHCI_SIZE 0x1000 +#define AR934X_WMAC_BASE (AR71XX_APB_BASE + 0x00100000) +#define AR934X_WMAC_SIZE 0x20000 + /* * DDR_CTRL block */ @@ -91,6 +95,12 @@ #define AR933X_DDR_REG_FLUSH_USB 0x84 #define AR933X_DDR_REG_FLUSH_WMAC 0x88 +#define AR934X_DDR_REG_FLUSH_GE0 0x9c +#define AR934X_DDR_REG_FLUSH_GE1 0xa0 +#define AR934X_DDR_REG_FLUSH_USB 0xa4 +#define AR934X_DDR_REG_FLUSH_PCIE 0xa8 +#define AR934X_DDR_REG_FLUSH_WMAC 0xac + /* * PLL block */ @@ -150,6 +160,41 @@ #define AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT 15 #define AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK 0x7 +#define AR934X_PLL_CPU_CONFIG_REG 0x00 +#define AR934X_PLL_DDR_CONFIG_REG 0x04 +#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG 0x08 + +#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT 0 +#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK 0x3f +#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT 6 +#define AR934X_PLL_CPU_CONFIG_NINT_MASK 0x3f +#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 +#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT 19 +#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK 0x3 + +#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT 0 +#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK 0x3ff +#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT 10 +#define AR934X_PLL_DDR_CONFIG_NINT_MASK 0x3f +#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT 16 +#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK 0x1f +#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT 23 +#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK 0x7 + +#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS BIT(2) +#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS BIT(3) +#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS BIT(4) +#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT 5 +#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK 0x1f +#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT 10 +#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK 0x1f +#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT 15 +#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK 0x1f +#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL BIT(20) +#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) +#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + /* * USB_CONFIG block */ @@ -185,6 +230,10 @@ #define AR933X_RESET_REG_RESET_MODULE 0x1c #define AR933X_RESET_REG_BOOTSTRAP 0xac +#define AR934X_RESET_REG_RESET_MODULE 0x1c +#define AR934X_RESET_REG_BOOTSTRAP 0xb0 +#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS 0xac + #define MISC_INT_ETHSW BIT(12) #define MISC_INT_TIMER4 BIT(10) #define MISC_INT_TIMER3 BIT(9) @@ -241,6 +290,40 @@ #define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) +#define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) +#define AR934X_BOOTSTRAP_SW_OPTION7 BIT(22) +#define AR934X_BOOTSTRAP_SW_OPTION6 BIT(21) +#define AR934X_BOOTSTRAP_SW_OPTION5 BIT(20) +#define AR934X_BOOTSTRAP_SW_OPTION4 BIT(19) +#define AR934X_BOOTSTRAP_SW_OPTION3 BIT(18) +#define AR934X_BOOTSTRAP_SW_OPTION2 BIT(17) +#define AR934X_BOOTSTRAP_SW_OPTION1 BIT(16) +#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7) +#define AR934X_BOOTSTRAP_PCIE_RC BIT(6) +#define AR934X_BOOTSTRAP_EJTAG_MODE BIT(5) +#define AR934X_BOOTSTRAP_REF_CLK_40 BIT(4) +#define AR934X_BOOTSTRAP_BOOT_FROM_SPI BIT(2) +#define AR934X_BOOTSTRAP_SDRAM_DISABLED BIT(1) +#define AR934X_BOOTSTRAP_DDR1 BIT(0) + +#define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) +#define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) +#define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) +#define AR934X_PCIE_WMAC_INT_WMAC_RXHP BIT(3) +#define AR934X_PCIE_WMAC_INT_PCIE_RC BIT(4) +#define AR934X_PCIE_WMAC_INT_PCIE_RC0 BIT(5) +#define AR934X_PCIE_WMAC_INT_PCIE_RC1 BIT(6) +#define AR934X_PCIE_WMAC_INT_PCIE_RC2 BIT(7) +#define AR934X_PCIE_WMAC_INT_PCIE_RC3 BIT(8) +#define AR934X_PCIE_WMAC_INT_WMAC_ALL \ + (AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \ + AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP) + +#define AR934X_PCIE_WMAC_INT_PCIE_ALL \ + (AR934X_PCIE_WMAC_INT_PCIE_RC | AR934X_PCIE_WMAC_INT_PCIE_RC0 | \ + AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \ + AR934X_PCIE_WMAC_INT_PCIE_RC3) + #define REV_ID_MAJOR_MASK 0xfff0 #define REV_ID_MAJOR_AR71XX 0x00a0 #define REV_ID_MAJOR_AR913X 0x00b0 @@ -249,6 +332,9 @@ #define REV_ID_MAJOR_AR7242 0x1100 #define REV_ID_MAJOR_AR9330 0x0110 #define REV_ID_MAJOR_AR9331 0x1110 +#define REV_ID_MAJOR_AR9341 0x0120 +#define REV_ID_MAJOR_AR9342 0x1120 +#define REV_ID_MAJOR_AR9344 0x2120 #define AR71XX_REV_ID_MINOR_MASK 0x3 #define AR71XX_REV_ID_MINOR_AR7130 0x0 @@ -267,6 +353,8 @@ #define AR724X_REV_ID_REVISION_MASK 0x3 +#define AR934X_REV_ID_REVISION_MASK 0xf + /* * SPI block */ @@ -308,5 +396,6 @@ #define AR724X_GPIO_COUNT 18 #define AR913X_GPIO_COUNT 22 #define AR933X_GPIO_COUNT 30 +#define AR934X_GPIO_COUNT 23 #endif /* __ASM_MACH_AR71XX_REGS_H */ diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h index 6d0c6c9..4f248c3 100644 --- a/arch/mips/include/asm/mach-ath79/ath79.h +++ b/arch/mips/include/asm/mach-ath79/ath79.h @@ -29,6 +29,9 @@ enum ath79_soc_type { ATH79_SOC_AR9132, ATH79_SOC_AR9330, ATH79_SOC_AR9331, + ATH79_SOC_AR9341, + ATH79_SOC_AR9342, + ATH79_SOC_AR9344, }; extern enum ath79_soc_type ath79_soc; @@ -75,6 +78,26 @@ static inline int soc_is_ar933x(void) ath79_soc == ATH79_SOC_AR9331); } +static inline int soc_is_ar9341(void) +{ + return (ath79_soc == ATH79_SOC_AR9341); +} + +static inline int soc_is_ar9342(void) +{ + return (ath79_soc == ATH79_SOC_AR9342); +} + +static inline int soc_is_ar9344(void) +{ + return (ath79_soc == ATH79_SOC_AR9344); +} + +static inline int soc_is_ar934x(void) +{ + return soc_is_ar9341() || soc_is_ar9342() || soc_is_ar9344(); +} + extern void __iomem *ath79_ddr_base; extern void __iomem *ath79_pll_base; extern void __iomem *ath79_reset_base; diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h index 519958f..0968f69 100644 --- a/arch/mips/include/asm/mach-ath79/irq.h +++ b/arch/mips/include/asm/mach-ath79/irq.h @@ -10,11 +10,19 @@ #define __ASM_MACH_ATH79_IRQ_H #define MIPS_CPU_IRQ_BASE 0 -#define NR_IRQS 40 +#define NR_IRQS 48 #define ATH79_MISC_IRQ_BASE 8 #define ATH79_MISC_IRQ_COUNT 32 +#define ATH79_PCI_IRQ_BASE (ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT) +#define ATH79_PCI_IRQ_COUNT 6 +#define ATH79_PCI_IRQ(_x) (ATH79_PCI_IRQ_BASE + (_x)) + +#define ATH79_IP2_IRQ_BASE (ATH79_PCI_IRQ_BASE + ATH79_PCI_IRQ_COUNT) +#define ATH79_IP2_IRQ_COUNT 2 +#define ATH79_IP2_IRQ(_x) (ATH79_IP2_IRQ_BASE + (_x)) + #define ATH79_CPU_IRQ_IP2 (MIPS_CPU_IRQ_BASE + 2) #define ATH79_CPU_IRQ_USB (MIPS_CPU_IRQ_BASE + 3) #define ATH79_CPU_IRQ_GE0 (MIPS_CPU_IRQ_BASE + 4) diff --git a/arch/mips/include/asm/mach-ath79/pci-ath724x.h b/arch/mips/include/asm/mach-ath79/pci-ath724x.h deleted file mode 100644 index 454885f..0000000 --- a/arch/mips/include/asm/mach-ath79/pci-ath724x.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Atheros 724x PCI support - * - * Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#ifndef __ASM_MACH_ATH79_PCI_ATH724X_H -#define __ASM_MACH_ATH79_PCI_ATH724X_H - -struct ath724x_pci_data { - int irq; - void *pdata; -}; - -void ath724x_pci_add_data(struct ath724x_pci_data *data, int size); - -#endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */ diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h new file mode 100644 index 0000000..7868f7f --- /dev/null +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -0,0 +1,28 @@ +/* + * Atheros AR71XX/AR724X PCI support + * + * Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_ATH79_PCI_H +#define __ASM_MACH_ATH79_PCI_H + +#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR71XX) +int ar71xx_pcibios_init(void); +#else +static inline int ar71xx_pcibios_init(void) { return 0; } +#endif + +#if defined(CONFIG_PCI_AR724X) +int ar724x_pcibios_init(int irq); +#else +static inline int ar724x_pcibios_init(int irq) { return 0; } +#endif + +#endif /* __ASM_MACH_ATH79_PCI_H */ diff --git a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h new file mode 100644 index 0000000..318f982 --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h @@ -0,0 +1,23 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com> + */ + +#ifndef _FALCON_IRQ__ +#define _FALCON_IRQ__ + +#define INT_NUM_IRQ0 8 +#define INT_NUM_IM0_IRL0 (INT_NUM_IRQ0 + 0) +#define INT_NUM_IM1_IRL0 (INT_NUM_IM0_IRL0 + 32) +#define INT_NUM_IM2_IRL0 (INT_NUM_IM1_IRL0 + 32) +#define INT_NUM_IM3_IRL0 (INT_NUM_IM2_IRL0 + 32) +#define INT_NUM_IM4_IRL0 (INT_NUM_IM3_IRL0 + 32) +#define INT_NUM_EXTRA_START (INT_NUM_IM4_IRL0 + 32) +#define INT_NUM_IM_OFFSET (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0) + +#define MIPS_CPU_TIMER_IRQ 7 + +#endif /* _FALCON_IRQ__ */ diff --git a/arch/mips/include/asm/mach-lantiq/falcon/irq.h b/arch/mips/include/asm/mach-lantiq/falcon/irq.h new file mode 100644 index 0000000..2caccd9 --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/falcon/irq.h @@ -0,0 +1,18 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com> + */ + +#ifndef __FALCON_IRQ_H +#define __FALCON_IRQ_H + +#include <falcon_irq.h> + +#define NR_IRQS 328 + +#include_next <irq.h> + +#endif diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h new file mode 100644 index 0000000..b385252 --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h @@ -0,0 +1,67 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2010 John Crispin <blogic@openwrt.org> + */ + +#ifndef _LTQ_FALCON_H__ +#define _LTQ_FALCON_H__ + +#ifdef CONFIG_SOC_FALCON + +#include <linux/pinctrl/pinctrl.h> +#include <lantiq.h> + +/* Chip IDs */ +#define SOC_ID_FALCON 0x01B8 + +/* SoC Types */ +#define SOC_TYPE_FALCON 0x01 + +/* + * during early_printk no ioremap possible at this early stage + * lets use KSEG1 instead + */ +#define LTQ_ASC0_BASE_ADDR 0x1E100C00 +#define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC0_BASE_ADDR) + +/* WDT */ +#define LTQ_RST_CAUSE_WDTRST 0x0002 + +/* CHIP ID */ +#define LTQ_STATUS_BASE_ADDR 0x1E802000 + +#define FALCON_CHIPID ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x0c)) +#define FALCON_CHIPTYPE ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x38)) +#define FALCON_CHIPCONF ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x40)) + +/* SYSCTL - start/stop/restart/configure/... different parts of the Soc */ +#define SYSCTL_SYS1 0 +#define SYSCTL_SYSETH 1 +#define SYSCTL_SYSGPE 2 + +/* BOOT_SEL - find what boot media we have */ +#define BS_FLASH 0x1 +#define BS_SPI 0x4 + +/* global register ranges */ +extern __iomem void *ltq_ebu_membase; +extern __iomem void *ltq_sys1_membase; +#define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y)) +#define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x)) + +#define ltq_sys1_w32(x, y) ltq_w32((x), ltq_sys1_membase + (y)) +#define ltq_sys1_r32(x) ltq_r32(ltq_sys1_membase + (x)) +#define ltq_sys1_w32_mask(clear, set, reg) \ + ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg) + +/* + * to keep the irq code generic we need to define this to 0 as falcon + * has no EIU/EBU + */ +#define LTQ_EBU_PCC_ISTAT 0 + +#endif /* CONFIG_SOC_FALCON */ +#endif /* _LTQ_XWAY_H__ */ diff --git a/arch/mips/include/asm/mach-lantiq/gpio.h b/arch/mips/include/asm/mach-lantiq/gpio.h new file mode 100644 index 0000000..f79505b --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/gpio.h @@ -0,0 +1,16 @@ +#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H +#define __ASM_MIPS_MACH_LANTIQ_GPIO_H + +static inline int gpio_to_irq(unsigned int gpio) +{ + return -1; +} + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value + +#define gpio_cansleep __gpio_cansleep + +#include <asm-generic/gpio.h> + +#endif diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h index ce2f029..5e8a6e9 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq.h @@ -9,6 +9,8 @@ #define _LANTIQ_H__ #include <linux/irq.h> +#include <linux/device.h> +#include <linux/clk.h> /* generic reg access functions */ #define ltq_r32(reg) __raw_readl(reg) @@ -21,25 +23,9 @@ /* register access macros for EBU and CGU */ #define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y)) #define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x)) -#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y)) -#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x)) - +#define ltq_ebu_w32_mask(x, y, z) \ + ltq_w32_mask(x, y, ltq_ebu_membase + (z)) extern __iomem void *ltq_ebu_membase; -extern __iomem void *ltq_cgu_membase; - -extern unsigned int ltq_get_cpu_ver(void); -extern unsigned int ltq_get_soc_type(void); - -/* clock speeds */ -#define CLOCK_60M 60000000 -#define CLOCK_83M 83333333 -#define CLOCK_111M 111111111 -#define CLOCK_133M 133333333 -#define CLOCK_167M 166666667 -#define CLOCK_200M 200000000 -#define CLOCK_266M 266666666 -#define CLOCK_333M 333333333 -#define CLOCK_400M 400000000 /* spinlock all ebu i/o */ extern spinlock_t ebu_lock; @@ -49,15 +35,21 @@ extern void ltq_disable_irq(struct irq_data *data); extern void ltq_mask_and_ack_irq(struct irq_data *data); extern void ltq_enable_irq(struct irq_data *data); +/* clock handling */ +extern int clk_activate(struct clk *clk); +extern void clk_deactivate(struct clk *clk); +extern struct clk *clk_get_cpu(void); +extern struct clk *clk_get_fpi(void); +extern struct clk *clk_get_io(void); + +/* find out what bootsource we have */ +extern unsigned char ltq_boot_select(void); /* find out what caused the last cpu reset */ extern int ltq_reset_cause(void); -#define LTQ_RST_CAUSE_WDTRST 0x20 #define IOPORT_RESOURCE_START 0x10000000 #define IOPORT_RESOURCE_END 0xffffffff #define IOMEM_RESOURCE_START 0x10000000 #define IOMEM_RESOURCE_END 0xffffffff -#define LTQ_FLASH_START 0x10000000 -#define LTQ_FLASH_MAX 0x04000000 #endif diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h index a305f1d..e23bf7c 100644 --- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h +++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h @@ -9,41 +9,8 @@ #ifndef _LANTIQ_PLATFORM_H__ #define _LANTIQ_PLATFORM_H__ -#include <linux/mtd/partitions.h> #include <linux/socket.h> -/* struct used to pass info to the pci core */ -enum { - PCI_CLOCK_INT = 0, - PCI_CLOCK_EXT -}; - -#define PCI_EXIN0 0x0001 -#define PCI_EXIN1 0x0002 -#define PCI_EXIN2 0x0004 -#define PCI_EXIN3 0x0008 -#define PCI_EXIN4 0x0010 -#define PCI_EXIN5 0x0020 -#define PCI_EXIN_MAX 6 - -#define PCI_GNT1 0x0040 -#define PCI_GNT2 0x0080 -#define PCI_GNT3 0x0100 -#define PCI_GNT4 0x0200 - -#define PCI_REQ1 0x0400 -#define PCI_REQ2 0x0800 -#define PCI_REQ3 0x1000 -#define PCI_REQ4 0x2000 -#define PCI_REQ_SHIFT 10 -#define PCI_REQ_MASK 0xf - -struct ltq_pci_data { - int clock; - int gpio; - int irq[16]; -}; - /* struct used to pass info to network drivers */ struct ltq_eth_data { struct sockaddr mac; diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h index b4465a8..aa0b3b8 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h @@ -17,50 +17,8 @@ #define INT_NUM_IM4_IRL0 (INT_NUM_IRQ0 + 128) #define INT_NUM_IM_OFFSET (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0) -#define LTQ_ASC_TIR(x) (INT_NUM_IM3_IRL0 + (x * 8)) -#define LTQ_ASC_RIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 1) -#define LTQ_ASC_EIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 2) - -#define LTQ_ASC_ASE_TIR INT_NUM_IM2_IRL0 -#define LTQ_ASC_ASE_RIR (INT_NUM_IM2_IRL0 + 2) -#define LTQ_ASC_ASE_EIR (INT_NUM_IM2_IRL0 + 3) - -#define LTQ_SSC_TIR (INT_NUM_IM0_IRL0 + 15) -#define LTQ_SSC_RIR (INT_NUM_IM0_IRL0 + 14) -#define LTQ_SSC_EIR (INT_NUM_IM0_IRL0 + 16) - -#define LTQ_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21) -#define LTQ_MEI_INT (INT_NUM_IM1_IRL0 + 23) - -#define LTQ_TIMER6_INT (INT_NUM_IM1_IRL0 + 23) -#define LTQ_USB_INT (INT_NUM_IM1_IRL0 + 22) -#define LTQ_USB_OC_INT (INT_NUM_IM4_IRL0 + 23) - -#define MIPS_CPU_TIMER_IRQ 7 - #define LTQ_DMA_CH0_INT (INT_NUM_IM2_IRL0) -#define LTQ_DMA_CH1_INT (INT_NUM_IM2_IRL0 + 1) -#define LTQ_DMA_CH2_INT (INT_NUM_IM2_IRL0 + 2) -#define LTQ_DMA_CH3_INT (INT_NUM_IM2_IRL0 + 3) -#define LTQ_DMA_CH4_INT (INT_NUM_IM2_IRL0 + 4) -#define LTQ_DMA_CH5_INT (INT_NUM_IM2_IRL0 + 5) -#define LTQ_DMA_CH6_INT (INT_NUM_IM2_IRL0 + 6) -#define LTQ_DMA_CH7_INT (INT_NUM_IM2_IRL0 + 7) -#define LTQ_DMA_CH8_INT (INT_NUM_IM2_IRL0 + 8) -#define LTQ_DMA_CH9_INT (INT_NUM_IM2_IRL0 + 9) -#define LTQ_DMA_CH10_INT (INT_NUM_IM2_IRL0 + 10) -#define LTQ_DMA_CH11_INT (INT_NUM_IM2_IRL0 + 11) -#define LTQ_DMA_CH12_INT (INT_NUM_IM2_IRL0 + 25) -#define LTQ_DMA_CH13_INT (INT_NUM_IM2_IRL0 + 26) -#define LTQ_DMA_CH14_INT (INT_NUM_IM2_IRL0 + 27) -#define LTQ_DMA_CH15_INT (INT_NUM_IM2_IRL0 + 28) -#define LTQ_DMA_CH16_INT (INT_NUM_IM2_IRL0 + 29) -#define LTQ_DMA_CH17_INT (INT_NUM_IM2_IRL0 + 30) -#define LTQ_DMA_CH18_INT (INT_NUM_IM2_IRL0 + 16) -#define LTQ_DMA_CH19_INT (INT_NUM_IM2_IRL0 + 21) - -#define LTQ_PPE_MBOX_INT (INT_NUM_IM2_IRL0 + 24) -#define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14) +#define MIPS_CPU_TIMER_IRQ 7 #endif diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h index 8a3c6be..6a2df70 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -17,38 +17,56 @@ #define SOC_ID_DANUBE1 0x129 #define SOC_ID_DANUBE2 0x12B #define SOC_ID_TWINPASS 0x12D -#define SOC_ID_AMAZON_SE 0x152 +#define SOC_ID_AMAZON_SE_1 0x152 /* 50601 */ +#define SOC_ID_AMAZON_SE_2 0x153 /* 50600 */ #define SOC_ID_ARX188 0x16C -#define SOC_ID_ARX168 0x16D +#define SOC_ID_ARX168_1 0x16D +#define SOC_ID_ARX168_2 0x16E #define SOC_ID_ARX182 0x16F - -/* SoC Types */ +#define SOC_ID_GRX188 0x170 +#define SOC_ID_GRX168 0x171 + +#define SOC_ID_VRX288 0x1C0 /* v1.1 */ +#define SOC_ID_VRX282 0x1C1 /* v1.1 */ +#define SOC_ID_VRX268 0x1C2 /* v1.1 */ +#define SOC_ID_GRX268 0x1C8 /* v1.1 */ +#define SOC_ID_GRX288 0x1C9 /* v1.1 */ +#define SOC_ID_VRX288_2 0x00B /* v1.2 */ +#define SOC_ID_VRX268_2 0x00C /* v1.2 */ +#define SOC_ID_GRX288_2 0x00D /* v1.2 */ +#define SOC_ID_GRX282_2 0x00E /* v1.2 */ + + /* SoC Types */ #define SOC_TYPE_DANUBE 0x01 #define SOC_TYPE_TWINPASS 0x02 #define SOC_TYPE_AR9 0x03 -#define SOC_TYPE_VR9 0x04 -#define SOC_TYPE_AMAZON_SE 0x05 +#define SOC_TYPE_VR9 0x04 /* v1.1 */ +#define SOC_TYPE_VR9_2 0x05 /* v1.2 */ +#define SOC_TYPE_AMAZON_SE 0x06 + +/* BOOT_SEL - find what boot media we have */ +#define BS_EXT_ROM 0x0 +#define BS_FLASH 0x1 +#define BS_MII0 0x2 +#define BS_PCI 0x3 +#define BS_UART1 0x4 +#define BS_SPI 0x5 +#define BS_NAND 0x6 +#define BS_RMII0 0x7 + +/* helpers used to access the cgu */ +#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y)) +#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x)) +extern __iomem void *ltq_cgu_membase; -/* ASC0/1 - serial port */ -#define LTQ_ASC0_BASE_ADDR 0x1E100400 +/* + * during early_printk no ioremap is possible + * lets use KSEG1 instead + */ #define LTQ_ASC1_BASE_ADDR 0x1E100C00 -#define LTQ_ASC_SIZE 0x400 - -/* RCU - reset control unit */ -#define LTQ_RCU_BASE_ADDR 0x1F203000 -#define LTQ_RCU_SIZE 0x1000 - -/* GPTU - general purpose timer unit */ -#define LTQ_GPTU_BASE_ADDR 0x18000300 -#define LTQ_GPTU_SIZE 0x100 +#define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC1_BASE_ADDR) /* EBU - external bus unit */ -#define LTQ_EBU_GPIO_START 0x14000000 -#define LTQ_EBU_GPIO_SIZE 0x1000 - -#define LTQ_EBU_BASE_ADDR 0x1E105300 -#define LTQ_EBU_SIZE 0x100 - #define LTQ_EBU_BUSCON0 0x0060 #define LTQ_EBU_PCC_CON 0x0090 #define LTQ_EBU_PCC_IEN 0x00A4 @@ -57,85 +75,17 @@ #define LTQ_EBU_ADDRSEL1 0x0024 #define EBU_WRDIS 0x80000000 -/* CGU - clock generation unit */ -#define LTQ_CGU_BASE_ADDR 0x1F103000 -#define LTQ_CGU_SIZE 0x1000 - -/* ICU - interrupt control unit */ -#define LTQ_ICU_BASE_ADDR 0x1F880200 -#define LTQ_ICU_SIZE 0x100 - -/* EIU - external interrupt unit */ -#define LTQ_EIU_BASE_ADDR 0x1F101000 -#define LTQ_EIU_SIZE 0x1000 - -/* PMU - power management unit */ -#define LTQ_PMU_BASE_ADDR 0x1F102000 -#define LTQ_PMU_SIZE 0x1000 - -#define PMU_DMA 0x0020 -#define PMU_USB 0x8041 -#define PMU_LED 0x0800 -#define PMU_GPT 0x1000 -#define PMU_PPE 0x2000 -#define PMU_FPI 0x4000 -#define PMU_SWITCH 0x10000000 - -/* ETOP - ethernet */ -#define LTQ_ETOP_BASE_ADDR 0x1E180000 -#define LTQ_ETOP_SIZE 0x40000 - -/* DMA */ -#define LTQ_DMA_BASE_ADDR 0x1E104100 -#define LTQ_DMA_SIZE 0x800 - -/* PCI */ -#define PCI_CR_BASE_ADDR 0x1E105400 -#define PCI_CR_SIZE 0x400 - /* WDT */ -#define LTQ_WDT_BASE_ADDR 0x1F8803F0 -#define LTQ_WDT_SIZE 0x10 - -/* STP - serial to parallel conversion unit */ -#define LTQ_STP_BASE_ADDR 0x1E100BB0 -#define LTQ_STP_SIZE 0x40 - -/* GPIO */ -#define LTQ_GPIO0_BASE_ADDR 0x1E100B10 -#define LTQ_GPIO1_BASE_ADDR 0x1E100B40 -#define LTQ_GPIO2_BASE_ADDR 0x1E100B70 -#define LTQ_GPIO_SIZE 0x30 - -/* SSC */ -#define LTQ_SSC_BASE_ADDR 0x1e100800 -#define LTQ_SSC_SIZE 0x100 - -/* MEI - dsl core */ -#define LTQ_MEI_BASE_ADDR 0x1E116000 - -/* DEU - data encryption unit */ -#define LTQ_DEU_BASE_ADDR 0x1E103100 +#define LTQ_RST_CAUSE_WDTRST 0x20 /* MPS - multi processor unit (voice) */ #define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000) #define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344)) /* request a non-gpio and set the PIO config */ -extern int ltq_gpio_request(unsigned int pin, unsigned int alt0, - unsigned int alt1, unsigned int dir, const char *name); +#define PMU_PPE BIT(13) extern void ltq_pmu_enable(unsigned int module); extern void ltq_pmu_disable(unsigned int module); -static inline int ltq_is_ar9(void) -{ - return (ltq_get_soc_type() == SOC_TYPE_AR9); -} - -static inline int ltq_is_vr9(void) -{ - return (ltq_get_soc_type() == SOC_TYPE_VR9); -} - #endif /* CONFIG_SOC_TYPE_XWAY */ #endif /* _LTQ_XWAY_H__ */ diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h index 46c0856..6e23ceb 100644 --- a/arch/mips/include/asm/mips-boards/generic.h +++ b/arch/mips/include/asm/mips-boards/generic.h @@ -93,8 +93,4 @@ extern void mips_pcibios_init(void); #define mips_pcibios_init() do { } while (0) #endif -#ifdef CONFIG_KGDB -extern void kgdb_config(void); -#endif - #endif /* __ASM_MIPS_BOARDS_GENERIC_H */ diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h index 7467d1d..5300080 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h @@ -2,6 +2,7 @@ #define _ASM_MODULE_H #include <linux/list.h> +#include <linux/elf.h> #include <asm/uaccess.h> struct mod_arch_specific { diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index fcd4060..90bf3b3 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -17,6 +17,7 @@ */ #include <linux/ioport.h> +#include <linux/of.h> /* * Each pci channel is a top-level PCI bus seem by CPU. A machine with @@ -26,6 +27,7 @@ struct pci_controller { struct pci_controller *next; struct pci_bus *bus; + struct device_node *of_node; struct pci_ops *pci_ops; struct resource *mem_resource; @@ -142,4 +144,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) extern char * (*pcibios_plat_setup)(char *str); +/* this function parses memory ranges from a device node */ +extern void __devinit pci_load_of_ranges(struct pci_controller *hose, + struct device_node *node); + #endif /* _ASM_PCI_H */ diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index 7a6e82e..7206d44 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h @@ -12,6 +12,9 @@ #define __ASM_PROM_H #ifdef CONFIG_OF +#include <linux/bug.h> +#include <linux/io.h> +#include <linux/types.h> #include <asm/bootinfo.h> extern int early_init_dt_scan_memory_arch(unsigned long node, @@ -21,6 +24,29 @@ extern int reserve_mem_mach(unsigned long addr, unsigned long size); extern void free_mem_mach(unsigned long addr, unsigned long size); extern void device_tree_init(void); + +static inline unsigned long pci_address_to_pio(phys_addr_t address) +{ + /* + * The ioport address can be directly used by inX() / outX() + */ + BUG_ON(address > IO_SPACE_LIMIT); + + return (unsigned long) address; +} +#define pci_address_to_pio pci_address_to_pio + +struct boot_param_header; + +extern void __dt_setup_arch(struct boot_param_header *bph); + +#define dt_setup_arch(sym) \ +({ \ + extern struct boot_param_header __dtb_##sym##_begin; \ + \ + __dt_setup_arch(&__dtb_##sym##_begin); \ +}) + #else /* CONFIG_OF */ static inline void device_tree_init(void) { } #endif /* CONFIG_OF */ diff --git a/arch/mips/include/asm/setup.h b/arch/mips/include/asm/setup.h index 6dce6d8..2560b6b 100644 --- a/arch/mips/include/asm/setup.h +++ b/arch/mips/include/asm/setup.h @@ -14,7 +14,8 @@ extern void *set_vi_handler(int n, vi_handler_t addr); extern void *set_except_vector(int n, void *addr); extern unsigned long ebase; -extern void per_cpu_trap_init(void); +extern void per_cpu_trap_init(bool); +extern void cpu_cache_init(void); #endif /* __KERNEL__ */ diff --git a/arch/mips/include/asm/termios.h b/arch/mips/include/asm/termios.h index 8f77f77..abdd87a 100644 --- a/arch/mips/include/asm/termios.h +++ b/arch/mips/include/asm/termios.h @@ -60,7 +60,7 @@ struct termio { }; #ifdef __KERNEL__ -#include <linux/module.h> +#include <asm/uaccess.h> /* * intr=^C quit=^\ erase=del kill=^U diff --git a/arch/mips/include/asm/traps.h b/arch/mips/include/asm/traps.h index ff74aec..420ca06 100644 --- a/arch/mips/include/asm/traps.h +++ b/arch/mips/include/asm/traps.h @@ -25,6 +25,7 @@ extern void (*board_nmi_handler_setup)(void); extern void (*board_ejtag_handler_setup)(void); extern void (*board_bind_eic_interrupt)(int irq, int regset); extern void (*board_ebase_setup)(void); +extern void (*board_cache_error_setup)(void); extern int register_nmi_notifier(struct notifier_block *nb); diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 504d40a..440a21d 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -11,7 +11,7 @@ #include <linux/types.h> #ifdef CONFIG_EXPORT_UASM -#include <linux/module.h> +#include <linux/export.h> #define __uasminit #define __uasminitdata #define UASM_EXPORT_SYMBOL(sym) EXPORT_SYMBOL(sym) diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index a9dff33..e44abea 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile @@ -16,5 +16,3 @@ obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o # PM support obj-$(CONFIG_PM) += pm.o - -ccflags-y := -Werror -Wall diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5099201..6ae7ce4 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -340,7 +340,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R2000"; c->isa_level = MIPS_CPU_ISA_I; c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | - MIPS_CPU_NOFPUEX; + MIPS_CPU_NOFPUEX; if (__cpu_has_fpu()) c->options |= MIPS_CPU_FPU; c->tlbsize = 64; @@ -361,7 +361,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) } c->isa_level = MIPS_CPU_ISA_I; c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | - MIPS_CPU_NOFPUEX; + MIPS_CPU_NOFPUEX; if (__cpu_has_fpu()) c->options |= MIPS_CPU_FPU; c->tlbsize = 64; @@ -387,8 +387,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->isa_level = MIPS_CPU_ISA_III; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_VCE | - MIPS_CPU_LLSC; + MIPS_CPU_WATCH | MIPS_CPU_VCE | + MIPS_CPU_LLSC; c->tlbsize = 48; break; case PRID_IMP_VR41XX: @@ -434,7 +434,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R4300"; c->isa_level = MIPS_CPU_ISA_III; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 32; break; case PRID_IMP_R4600: @@ -446,7 +446,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->tlbsize = 48; break; #if 0 - case PRID_IMP_R4650: + case PRID_IMP_R4650: /* * This processor doesn't have an MMU, so it's not * "real easy" to run Linux on it. It is left purely @@ -455,9 +455,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) */ c->cputype = CPU_R4650; __cpu_name[cpu] = "R4650"; - c->isa_level = MIPS_CPU_ISA_III; + c->isa_level = MIPS_CPU_ISA_III; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; - c->tlbsize = 48; + c->tlbsize = 48; break; #endif case PRID_IMP_TX39: @@ -488,7 +488,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R4700"; c->isa_level = MIPS_CPU_ISA_III; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 48; break; case PRID_IMP_TX49: @@ -505,7 +505,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R5000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 48; break; case PRID_IMP_R5432: @@ -513,7 +513,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R5432"; c->isa_level = MIPS_CPU_ISA_IV; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_LLSC; + MIPS_CPU_WATCH | MIPS_CPU_LLSC; c->tlbsize = 48; break; case PRID_IMP_R5500: @@ -521,7 +521,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R5500"; c->isa_level = MIPS_CPU_ISA_IV; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_LLSC; + MIPS_CPU_WATCH | MIPS_CPU_LLSC; c->tlbsize = 48; break; case PRID_IMP_NEVADA: @@ -529,7 +529,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "Nevada"; c->isa_level = MIPS_CPU_ISA_IV; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC; + MIPS_CPU_DIVEC | MIPS_CPU_LLSC; c->tlbsize = 48; break; case PRID_IMP_R6000: @@ -537,7 +537,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R6000"; c->isa_level = MIPS_CPU_ISA_II; c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 32; break; case PRID_IMP_R6000A: @@ -545,7 +545,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R6000A"; c->isa_level = MIPS_CPU_ISA_II; c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 32; break; case PRID_IMP_RM7000: @@ -553,7 +553,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "RM7000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; /* * Undocumented RM7000: Bit 29 in the info register of * the RM7000 v2.0 indicates if the TLB has 48 or 64 @@ -569,7 +569,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "RM9000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; /* * Bit 29 in the info register of the RM9000 * indicates if the TLB has 48 or 64 entries. @@ -584,8 +584,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "RM8000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; c->tlbsize = 384; /* has weird TLB: 3-way x 128 */ break; case PRID_IMP_R10000: @@ -593,9 +593,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R10000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 64; break; case PRID_IMP_R12000: @@ -603,9 +603,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R12000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 64; break; case PRID_IMP_R14000: @@ -613,9 +613,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "R14000"; c->isa_level = MIPS_CPU_ISA_IV; c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_FPU | MIPS_CPU_32FPR | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; + MIPS_CPU_LLSC; c->tlbsize = 64; break; case PRID_IMP_LOONGSON2: @@ -739,7 +739,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) if (config3 & MIPS_CONF3_VEIC) c->options |= MIPS_CPU_VEIC; if (config3 & MIPS_CONF3_MT) - c->ases |= MIPS_ASE_MIPSMT; + c->ases |= MIPS_ASE_MIPSMT; if (config3 & MIPS_CONF3_ULRI) c->options |= MIPS_CPU_ULRI; @@ -767,7 +767,7 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c) /* MIPS32 or MIPS64 compliant CPU. */ c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; c->scache.flags = MIPS_CACHE_NOT_PRESENT; diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 811084f..574b4e9 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1532,7 +1532,8 @@ init_hw_perf_events(void) irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; } else { #endif - if (cp0_perfcount_irq >= 0) + if ((cp0_perfcount_irq >= 0) && + (cp0_compare_irq != cp0_perfcount_irq)) irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; else irq = -1; diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index f8b2c59..5542817 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -41,27 +41,27 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "processor\t\t: %ld\n", n); sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", - cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : ""); + cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : ""); seq_printf(m, fmt, __cpu_name[n], - (version >> 4) & 0x0f, version & 0x0f, - (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); + (version >> 4) & 0x0f, version & 0x0f, + (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); seq_printf(m, "BogoMIPS\t\t: %u.%02u\n", - cpu_data[n].udelay_val / (500000/HZ), - (cpu_data[n].udelay_val / (5000/HZ)) % 100); + cpu_data[n].udelay_val / (500000/HZ), + (cpu_data[n].udelay_val / (5000/HZ)) % 100); seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no"); seq_printf(m, "microsecond timers\t: %s\n", - cpu_has_counter ? "yes" : "no"); + cpu_has_counter ? "yes" : "no"); seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); seq_printf(m, "extra interrupt vector\t: %s\n", - cpu_has_divec ? "yes" : "no"); + cpu_has_divec ? "yes" : "no"); seq_printf(m, "hardware watchpoint\t: %s", - cpu_has_watch ? "yes, " : "no\n"); + cpu_has_watch ? "yes, " : "no\n"); if (cpu_has_watch) { seq_printf(m, "count: %d, address/irw mask: [", - cpu_data[n].watch_reg_count); + cpu_data[n].watch_reg_count); for (i = 0; i < cpu_data[n].watch_reg_count; i++) seq_printf(m, "%s0x%04x", i ? ", " : "" , - cpu_data[n].watch_reg_masks[i]); + cpu_data[n].watch_reg_masks[i]); seq_printf(m, "]\n"); } seq_printf(m, "ASEs implemented\t:%s%s%s%s%s%s\n", @@ -73,13 +73,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpu_has_mipsmt ? " mt" : "" ); seq_printf(m, "shadow register sets\t: %d\n", - cpu_data[n].srsets); + cpu_data[n].srsets); seq_printf(m, "kscratch registers\t: %d\n", - hweight8(cpu_data[n].kscratch_mask)); + hweight8(cpu_data[n].kscratch_mask)); seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", - cpu_has_vce ? "%u" : "not available"); + cpu_has_vce ? "%u" : "not available"); seq_printf(m, fmt, 'D', vced_count); seq_printf(m, fmt, 'I', vcei_count); seq_printf(m, "\n"); diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 558b539..f11b2bb 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -95,3 +95,16 @@ void __init device_tree_init(void) /* free the space reserved for the dt blob */ free_mem_mach(base, size); } + +void __init __dt_setup_arch(struct boot_param_header *bph) +{ + if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { + pr_err("DTB has bad magic, ignoring builtin OF DTB\n"); + + return; + } + + initial_boot_params = bph; + + early_init_devtree(initial_boot_params); +} diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index c504b21..a53f8ec 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -605,6 +605,8 @@ void __init setup_arch(char **cmdline_p) resource_init(); plat_smp_setup(); + + cpu_cache_init(); } unsigned long kernelsp[NR_CPUS]; diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index ba9376bf..dc019a1 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -106,7 +106,7 @@ asmlinkage __cpuinit void start_secondary(void) #endif /* CONFIG_MIPS_MT_SMTC */ cpu_probe(); cpu_report(); - per_cpu_trap_init(); + per_cpu_trap_init(false); mips_clockevent_init(); mp_ops->init_secondary(); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index cfdaaa4..2d0c2a2 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -15,6 +15,7 @@ #include <linux/compiler.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/smp.h> @@ -91,7 +92,7 @@ void (*board_nmi_handler_setup)(void); void (*board_ejtag_handler_setup)(void); void (*board_bind_eic_interrupt)(int irq, int regset); void (*board_ebase_setup)(void); - +void __cpuinitdata(*board_cache_error_setup)(void); static void show_raw_backtrace(unsigned long reg29) { @@ -1490,7 +1491,6 @@ void *set_vi_handler(int n, vi_handler_t addr) return set_vi_srs_handler(n, addr, 0); } -extern void cpu_cache_init(void); extern void tlb_init(void); extern void flush_tlb_handlers(void); @@ -1517,7 +1517,7 @@ static int __init ulri_disable(char *s) } __setup("noulri", ulri_disable); -void __cpuinit per_cpu_trap_init(void) +void __cpuinit per_cpu_trap_init(bool is_boot_cpu) { unsigned int cpu = smp_processor_id(); unsigned int status_set = ST0_CU0; @@ -1616,7 +1616,9 @@ void __cpuinit per_cpu_trap_init(void) #ifdef CONFIG_MIPS_MT_SMTC if (bootTC) { #endif /* CONFIG_MIPS_MT_SMTC */ - cpu_cache_init(); + /* Boot CPU's cache setup in setup_arch(). */ + if (!is_boot_cpu) + cpu_cache_init(); tlb_init(); #ifdef CONFIG_MIPS_MT_SMTC } else if (!secondaryTC) { @@ -1632,7 +1634,7 @@ void __cpuinit per_cpu_trap_init(void) } /* Install CPU exception handler */ -void __init set_handler(unsigned long offset, void *addr, unsigned long size) +void __cpuinit set_handler(unsigned long offset, void *addr, unsigned long size) { memcpy((void *)(ebase + offset), addr, size); local_flush_icache_range(ebase + offset, ebase + offset + size); @@ -1693,7 +1695,7 @@ void __init trap_init(void) if (board_ebase_setup) board_ebase_setup(); - per_cpu_trap_init(); + per_cpu_trap_init(true); /* * Copy the generic exception handlers to their final destination. @@ -1797,6 +1799,9 @@ void __init trap_init(void) set_except_vector(26, handle_dsp); + if (board_cache_error_setup) + board_cache_error_setup(); + if (cpu_has_vce) /* Special exception: R4[04]00 uses also the divec space. */ memcpy((void *)(ebase + 0x180), &except_vec3_r4000, 0x100); diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig index 3fccf21..20bdf40 100644 --- a/arch/mips/lantiq/Kconfig +++ b/arch/mips/lantiq/Kconfig @@ -16,8 +16,22 @@ config SOC_XWAY bool "XWAY" select SOC_TYPE_XWAY select HW_HAS_PCI + +config SOC_FALCON + bool "FALCON" + +endchoice + +choice + prompt "Devicetree" + +config DT_EASY50712 + bool "Easy50712" + depends on SOC_XWAY endchoice -source "arch/mips/lantiq/xway/Kconfig" +config PCI_LANTIQ + bool "PCI Support" + depends on SOC_XWAY && PCI endif diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile index e5dae0e..d6bdc57 100644 --- a/arch/mips/lantiq/Makefile +++ b/arch/mips/lantiq/Makefile @@ -4,8 +4,11 @@ # under the terms of the GNU General Public License version 2 as published # by the Free Software Foundation. -obj-y := irq.o setup.o clk.o prom.o devices.o +obj-y := irq.o clk.o prom.o + +obj-y += dts/ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_SOC_TYPE_XWAY) += xway/ +obj-$(CONFIG_SOC_FALCON) += falcon/ diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform index f3dff05..b3ec498 100644 --- a/arch/mips/lantiq/Platform +++ b/arch/mips/lantiq/Platform @@ -6,3 +6,4 @@ platform-$(CONFIG_LANTIQ) += lantiq/ cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq load-$(CONFIG_LANTIQ) = 0xffffffff80002000 cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway +cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c index 412814f..d3bcc33 100644 --- a/arch/mips/lantiq/clk.c +++ b/arch/mips/lantiq/clk.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/clk.h> +#include <linux/clkdev.h> #include <linux/err.h> #include <linux/list.h> @@ -22,44 +23,32 @@ #include <lantiq_soc.h> #include "clk.h" +#include "prom.h" -struct clk { - const char *name; - unsigned long rate; - unsigned long (*get_rate) (void); -}; +/* lantiq socs have 3 static clocks */ +static struct clk cpu_clk_generic[3]; -static struct clk *cpu_clk; -static int cpu_clk_cnt; +void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io) +{ + cpu_clk_generic[0].rate = cpu; + cpu_clk_generic[1].rate = fpi; + cpu_clk_generic[2].rate = io; +} -/* lantiq socs have 3 static clocks */ -static struct clk cpu_clk_generic[] = { - { - .name = "cpu", - .get_rate = ltq_get_cpu_hz, - }, { - .name = "fpi", - .get_rate = ltq_get_fpi_hz, - }, { - .name = "io", - .get_rate = ltq_get_io_region_clock, - }, -}; - -static struct resource ltq_cgu_resource = { - .name = "cgu", - .start = LTQ_CGU_BASE_ADDR, - .end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -/* remapped clock register range */ -void __iomem *ltq_cgu_membase; - -void clk_init(void) +struct clk *clk_get_cpu(void) +{ + return &cpu_clk_generic[0]; +} + +struct clk *clk_get_fpi(void) +{ + return &cpu_clk_generic[1]; +} +EXPORT_SYMBOL_GPL(clk_get_fpi); + +struct clk *clk_get_io(void) { - cpu_clk = cpu_clk_generic; - cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic); + return &cpu_clk_generic[2]; } static inline int clk_good(struct clk *clk) @@ -82,38 +71,71 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -struct clk *clk_get(struct device *dev, const char *id) +int clk_set_rate(struct clk *clk, unsigned long rate) { - int i; - - for (i = 0; i < cpu_clk_cnt; i++) - if (!strcmp(id, cpu_clk[i].name)) - return &cpu_clk[i]; - BUG(); - return ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - /* not used */ + if (unlikely(!clk_good(clk))) + return 0; + if (clk->rates && *clk->rates) { + unsigned long *r = clk->rates; + + while (*r && (*r != rate)) + r++; + if (!*r) { + pr_err("clk %s.%s: trying to set invalid rate %ld\n", + clk->cl.dev_id, clk->cl.con_id, rate); + return -1; + } + } + clk->rate = rate; + return 0; } -EXPORT_SYMBOL(clk_put); +EXPORT_SYMBOL(clk_set_rate); int clk_enable(struct clk *clk) { - /* not used */ - return 0; + if (unlikely(!clk_good(clk))) + return -1; + + if (clk->enable) + return clk->enable(clk); + + return -1; } EXPORT_SYMBOL(clk_enable); void clk_disable(struct clk *clk) { - /* not used */ + if (unlikely(!clk_good(clk))) + return; + + if (clk->disable) + clk->disable(clk); } EXPORT_SYMBOL(clk_disable); -static inline u32 ltq_get_counter_resolution(void) +int clk_activate(struct clk *clk) +{ + if (unlikely(!clk_good(clk))) + return -1; + + if (clk->activate) + return clk->activate(clk); + + return -1; +} +EXPORT_SYMBOL(clk_activate); + +void clk_deactivate(struct clk *clk) +{ + if (unlikely(!clk_good(clk))) + return; + + if (clk->deactivate) + clk->deactivate(clk); +} +EXPORT_SYMBOL(clk_deactivate); + +static inline u32 get_counter_resolution(void) { u32 res; @@ -133,21 +155,11 @@ void __init plat_time_init(void) { struct clk *clk; - if (insert_resource(&iomem_resource, <q_cgu_resource) < 0) - panic("Failed to insert cgu memory"); + ltq_soc_init(); - if (request_mem_region(ltq_cgu_resource.start, - resource_size(<q_cgu_resource), "cgu") < 0) - panic("Failed to request cgu memory"); - - ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start, - resource_size(<q_cgu_resource)); - if (!ltq_cgu_membase) { - pr_err("Failed to remap cgu memory\n"); - unreachable(); - } - clk = clk_get(0, "cpu"); - mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution(); + clk = clk_get_cpu(); + mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution(); write_c0_compare(read_c0_count()); + pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); clk_put(clk); } diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h index 3328925..fa67060 100644 --- a/arch/mips/lantiq/clk.h +++ b/arch/mips/lantiq/clk.h @@ -9,10 +9,70 @@ #ifndef _LTQ_CLK_H__ #define _LTQ_CLK_H__ -extern void clk_init(void); +#include <linux/clkdev.h> -extern unsigned long ltq_get_cpu_hz(void); -extern unsigned long ltq_get_fpi_hz(void); -extern unsigned long ltq_get_io_region_clock(void); +/* clock speeds */ +#define CLOCK_33M 33333333 +#define CLOCK_60M 60000000 +#define CLOCK_62_5M 62500000 +#define CLOCK_83M 83333333 +#define CLOCK_83_5M 83500000 +#define CLOCK_98_304M 98304000 +#define CLOCK_100M 100000000 +#define CLOCK_111M 111111111 +#define CLOCK_125M 125000000 +#define CLOCK_133M 133333333 +#define CLOCK_150M 150000000 +#define CLOCK_166M 166666666 +#define CLOCK_167M 166666667 +#define CLOCK_196_608M 196608000 +#define CLOCK_200M 200000000 +#define CLOCK_250M 250000000 +#define CLOCK_266M 266666666 +#define CLOCK_300M 300000000 +#define CLOCK_333M 333333333 +#define CLOCK_393M 393215332 +#define CLOCK_400M 400000000 +#define CLOCK_500M 500000000 +#define CLOCK_600M 600000000 + +/* clock out speeds */ +#define CLOCK_32_768K 32768 +#define CLOCK_1_536M 1536000 +#define CLOCK_2_5M 2500000 +#define CLOCK_12M 12000000 +#define CLOCK_24M 24000000 +#define CLOCK_25M 25000000 +#define CLOCK_30M 30000000 +#define CLOCK_40M 40000000 +#define CLOCK_48M 48000000 +#define CLOCK_50M 50000000 +#define CLOCK_60M 60000000 + +struct clk { + struct clk_lookup cl; + unsigned long rate; + unsigned long *rates; + unsigned int module; + unsigned int bits; + unsigned long (*get_rate) (void); + int (*enable) (struct clk *clk); + void (*disable) (struct clk *clk); + int (*activate) (struct clk *clk); + void (*deactivate) (struct clk *clk); + void (*reboot) (struct clk *clk); +}; + +extern void clkdev_add_static(unsigned long cpu, unsigned long fpi, + unsigned long io); + +extern unsigned long ltq_danube_cpu_hz(void); +extern unsigned long ltq_danube_fpi_hz(void); + +extern unsigned long ltq_ar9_cpu_hz(void); +extern unsigned long ltq_ar9_fpi_hz(void); + +extern unsigned long ltq_vr9_cpu_hz(void); +extern unsigned long ltq_vr9_fpi_hz(void); #endif diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c deleted file mode 100644 index de1cb2b..0000000 --- a/arch/mips/lantiq/devices.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/init.h> -#include <linux/export.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/reboot.h> -#include <linux/platform_device.h> -#include <linux/leds.h> -#include <linux/etherdevice.h> -#include <linux/time.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <asm/bootinfo.h> -#include <asm/irq.h> - -#include <lantiq_soc.h> - -#include "devices.h" - -/* nor flash */ -static struct resource ltq_nor_resource = { - .name = "nor", - .start = LTQ_FLASH_START, - .end = LTQ_FLASH_START + LTQ_FLASH_MAX - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device ltq_nor = { - .name = "ltq_nor", - .resource = <q_nor_resource, - .num_resources = 1, -}; - -void __init ltq_register_nor(struct physmap_flash_data *data) -{ - ltq_nor.dev.platform_data = data; - platform_device_register(<q_nor); -} - -/* watchdog */ -static struct resource ltq_wdt_resource = { - .name = "watchdog", - .start = LTQ_WDT_BASE_ADDR, - .end = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -void __init ltq_register_wdt(void) -{ - platform_device_register_simple("ltq_wdt", 0, <q_wdt_resource, 1); -} - -/* asc ports */ -static struct resource ltq_asc0_resources[] = { - { - .name = "asc0", - .start = LTQ_ASC0_BASE_ADDR, - .end = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - IRQ_RES(tx, LTQ_ASC_TIR(0)), - IRQ_RES(rx, LTQ_ASC_RIR(0)), - IRQ_RES(err, LTQ_ASC_EIR(0)), -}; - -static struct resource ltq_asc1_resources[] = { - { - .name = "asc1", - .start = LTQ_ASC1_BASE_ADDR, - .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - IRQ_RES(tx, LTQ_ASC_TIR(1)), - IRQ_RES(rx, LTQ_ASC_RIR(1)), - IRQ_RES(err, LTQ_ASC_EIR(1)), -}; - -void __init ltq_register_asc(int port) -{ - switch (port) { - case 0: - platform_device_register_simple("ltq_asc", 0, - ltq_asc0_resources, ARRAY_SIZE(ltq_asc0_resources)); - break; - case 1: - platform_device_register_simple("ltq_asc", 1, - ltq_asc1_resources, ARRAY_SIZE(ltq_asc1_resources)); - break; - default: - break; - } -} - -#ifdef CONFIG_PCI -/* pci */ -static struct platform_device ltq_pci = { - .name = "ltq_pci", - .num_resources = 0, -}; - -void __init ltq_register_pci(struct ltq_pci_data *data) -{ - ltq_pci.dev.platform_data = data; - platform_device_register(<q_pci); -} -#else -void __init ltq_register_pci(struct ltq_pci_data *data) -{ - pr_err("kernel is compiled without PCI support\n"); -} -#endif diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h deleted file mode 100644 index 2947bb1..0000000 --- a/arch/mips/lantiq/devices.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#ifndef _LTQ_DEVICES_H__ -#define _LTQ_DEVICES_H__ - -#include <lantiq_platform.h> -#include <linux/mtd/physmap.h> - -#define IRQ_RES(resname, irq) \ - {.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ} - -extern void ltq_register_nor(struct physmap_flash_data *data); -extern void ltq_register_wdt(void); -extern void ltq_register_asc(int port); -extern void ltq_register_pci(struct ltq_pci_data *data); - -#endif diff --git a/arch/mips/lantiq/dts/Makefile b/arch/mips/lantiq/dts/Makefile new file mode 100644 index 0000000..674fca4 --- /dev/null +++ b/arch/mips/lantiq/dts/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o + +$(obj)/%.dtb: $(obj)/%.dts + $(call if_changed,dtc) diff --git a/arch/mips/lantiq/dts/danube.dtsi b/arch/mips/lantiq/dts/danube.dtsi new file mode 100644 index 0000000..3a4520f --- /dev/null +++ b/arch/mips/lantiq/dts/danube.dtsi @@ -0,0 +1,105 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "lantiq,xway", "lantiq,danube"; + + cpus { + cpu@0 { + compatible = "mips,mips24Kc"; + }; + }; + + biu@1F800000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "lantiq,biu", "simple-bus"; + reg = <0x1F800000 0x800000>; + ranges = <0x0 0x1F800000 0x7FFFFF>; + + icu0: icu@80200 { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "lantiq,icu"; + reg = <0x80200 0x120>; + }; + + watchdog@803F0 { + compatible = "lantiq,wdt"; + reg = <0x803F0 0x10>; + }; + }; + + sram@1F000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "lantiq,sram"; + reg = <0x1F000000 0x800000>; + ranges = <0x0 0x1F000000 0x7FFFFF>; + + eiu0: eiu@101000 { + #interrupt-cells = <1>; + interrupt-controller; + interrupt-parent; + compatible = "lantiq,eiu-xway"; + reg = <0x101000 0x1000>; + }; + + pmu0: pmu@102000 { + compatible = "lantiq,pmu-xway"; + reg = <0x102000 0x1000>; + }; + + cgu0: cgu@103000 { + compatible = "lantiq,cgu-xway"; + reg = <0x103000 0x1000>; + #clock-cells = <1>; + }; + + rcu0: rcu@203000 { + compatible = "lantiq,rcu-xway"; + reg = <0x203000 0x1000>; + }; + }; + + fpi@10000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "lantiq,fpi", "simple-bus"; + ranges = <0x0 0x10000000 0xEEFFFFF>; + reg = <0x10000000 0xEF00000>; + + gptu@E100A00 { + compatible = "lantiq,gptu-xway"; + reg = <0xE100A00 0x100>; + }; + + serial@E100C00 { + compatible = "lantiq,asc"; + reg = <0xE100C00 0x400>; + interrupt-parent = <&icu0>; + interrupts = <112 113 114>; + }; + + dma0: dma@E104100 { + compatible = "lantiq,dma-xway"; + reg = <0xE104100 0x800>; + }; + + ebu0: ebu@E105300 { + compatible = "lantiq,ebu-xway"; + reg = <0xE105300 0x100>; + }; + + pci0: pci@E105400 { + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + compatible = "lantiq,pci-xway"; + bus-range = <0x0 0x0>; + ranges = <0x2000000 0 0x8000000 0x8000000 0 0x2000000 /* pci memory */ + 0x1000000 0 0x00000000 0xAE00000 0 0x200000>; /* io space */ + reg = <0x7000000 0x8000 /* config space */ + 0xE105400 0x400>; /* pci bridge */ + }; + }; +}; diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts new file mode 100644 index 0000000..68c1731 --- /dev/null +++ b/arch/mips/lantiq/dts/easy50712.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "danube.dtsi" + +/ { + chosen { + bootargs = "console=ttyLTQ0,115200 init=/etc/preinit"; + }; + + memory@0 { + reg = <0x0 0x2000000>; + }; + + fpi@10000000 { + #address-cells = <1>; + #size-cells = <1>; + localbus@0 { + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x0 0x3ffffff /* addrsel0 */ + 1 0 0x4000000 0x4000010>; /* addsel1 */ + compatible = "lantiq,localbus", "simple-bus"; + + nor-boot@0 { + compatible = "lantiq,nor"; + bank-width = <2>; + reg = <0 0x0 0x2000000>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x00000 0x10000>; /* 64 KB */ + }; + + partition@10000 { + label = "uboot_env"; + reg = <0x10000 0x10000>; /* 64 KB */ + }; + + partition@20000 { + label = "linux"; + reg = <0x20000 0x3d0000>; + }; + + partition@400000 { + label = "rootfs"; + reg = <0x400000 0x400000>; + }; + }; + }; + + gpio: pinmux@E100B10 { + compatible = "lantiq,pinctrl-xway"; + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + #gpio-cells = <2>; + gpio-controller; + reg = <0xE100B10 0xA0>; + + state_default: pinmux { + stp { + lantiq,groups = "stp"; + lantiq,function = "stp"; + }; + exin { + lantiq,groups = "exin1"; + lantiq,function = "exin"; + }; + pci { + lantiq,groups = "gnt1"; + lantiq,function = "pci"; + }; + conf_out { + lantiq,pins = "io4", "io5", "io6"; /* stp */ + lantiq,open-drain; + lantiq,pull = <0>; + }; + }; + }; + + etop@E180000 { + compatible = "lantiq,etop-xway"; + reg = <0xE180000 0x40000>; + interrupt-parent = <&icu0>; + interrupts = <73 78>; + phy-mode = "rmii"; + mac-address = [ 00 11 22 33 44 55 ]; + }; + + stp0: stp@E100BB0 { + #gpio-cells = <2>; + compatible = "lantiq,gpio-stp-xway"; + gpio-controller; + reg = <0xE100BB0 0x40>; + + lantiq,shadow = <0xfff>; + lantiq,groups = <0x3>; + }; + + pci@E105400 { + lantiq,bus-clock = <33333333>; + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; + interrupt-map = < + 0x7000 0 0 1 &icu0 29 1 // slot 14, irq 29 + >; + gpios-reset = <&gpio 21 0>; + req-mask = <0x1>; /* GNT1 */ + }; + + }; +}; diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c index 972e05f..9b28d09 100644 --- a/arch/mips/lantiq/early_printk.c +++ b/arch/mips/lantiq/early_printk.c @@ -6,17 +6,16 @@ * Copyright (C) 2010 John Crispin <blogic@openwrt.org> */ -#include <linux/init.h> #include <linux/cpu.h> - -#include <lantiq.h> #include <lantiq_soc.h> -/* no ioremap possible at this early stage, lets use KSEG1 instead */ -#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR) #define ASC_BUF 1024 -#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048)) -#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020)) +#define LTQ_ASC_FSTAT ((u32 *)(LTQ_EARLY_ASC + 0x0048)) +#ifdef __BIG_ENDIAN +#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020 + 3)) +#else +#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020)) +#endif #define TXMASK 0x3F00 #define TXOFFSET 8 @@ -27,7 +26,7 @@ void prom_putchar(char c) local_irq_save(flags); do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET); if (c == '\n') - ltq_w32('\r', LTQ_ASC_TBUF); - ltq_w32(c, LTQ_ASC_TBUF); + ltq_w8('\r', LTQ_ASC_TBUF); + ltq_w8(c, LTQ_ASC_TBUF); local_irq_restore(flags); } diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile new file mode 100644 index 0000000..ff220f9 --- /dev/null +++ b/arch/mips/lantiq/falcon/Makefile @@ -0,0 +1 @@ +obj-y := prom.o reset.o sysctrl.o diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c new file mode 100644 index 0000000..c1d278f --- /dev/null +++ b/arch/mips/lantiq/falcon/prom.c @@ -0,0 +1,87 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com> + * Copyright (C) 2012 John Crispin <blogic@openwrt.org> + */ + +#include <linux/kernel.h> +#include <asm/io.h> + +#include <lantiq_soc.h> + +#include "../prom.h" + +#define SOC_FALCON "Falcon" +#define SOC_FALCON_D "Falcon-D" +#define SOC_FALCON_V "Falcon-V" +#define SOC_FALCON_M "Falcon-M" + +#define COMP_FALCON "lantiq,falcon" + +#define PART_SHIFT 12 +#define PART_MASK 0x0FFFF000 +#define REV_SHIFT 28 +#define REV_MASK 0xF0000000 +#define SREV_SHIFT 22 +#define SREV_MASK 0x03C00000 +#define TYPE_SHIFT 26 +#define TYPE_MASK 0x3C000000 + +/* reset, nmi and ejtag exception vectors */ +#define BOOT_REG_BASE (KSEG1 | 0x1F200000) +#define BOOT_RVEC (BOOT_REG_BASE | 0x00) +#define BOOT_NVEC (BOOT_REG_BASE | 0x04) +#define BOOT_EVEC (BOOT_REG_BASE | 0x08) + +void __init ltq_soc_nmi_setup(void) +{ + extern void (*nmi_handler)(void); + + ltq_w32((unsigned long)&nmi_handler, (void *)BOOT_NVEC); +} + +void __init ltq_soc_ejtag_setup(void) +{ + extern void (*ejtag_debug_handler)(void); + + ltq_w32((unsigned long)&ejtag_debug_handler, (void *)BOOT_EVEC); +} + +void __init ltq_soc_detect(struct ltq_soc_info *i) +{ + u32 type; + i->partnum = (ltq_r32(FALCON_CHIPID) & PART_MASK) >> PART_SHIFT; + i->rev = (ltq_r32(FALCON_CHIPID) & REV_MASK) >> REV_SHIFT; + i->srev = ((ltq_r32(FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT); + i->compatible = COMP_FALCON; + i->type = SOC_TYPE_FALCON; + sprintf(i->rev_type, "%c%d%d", (i->srev & 0x4) ? ('B') : ('A'), + i->rev & 0x7, (i->srev & 0x3) + 1); + + switch (i->partnum) { + case SOC_ID_FALCON: + type = (ltq_r32(FALCON_CHIPTYPE) & TYPE_MASK) >> TYPE_SHIFT; + switch (type) { + case 0: + i->name = SOC_FALCON_D; + break; + case 1: + i->name = SOC_FALCON_V; + break; + case 2: + i->name = SOC_FALCON_M; + break; + default: + i->name = SOC_FALCON; + break; + } + break; + + default: + unreachable(); + break; + } +} diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c new file mode 100644 index 0000000..5682482 --- /dev/null +++ b/arch/mips/lantiq/falcon/reset.c @@ -0,0 +1,90 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com> + * Copyright (C) 2012 John Crispin <blogic@openwrt.org> + */ + +#include <linux/init.h> +#include <linux/io.h> +#include <linux/pm.h> +#include <asm/reboot.h> +#include <linux/export.h> + +#include <lantiq_soc.h> + +/* CPU0 Reset Source Register */ +#define SYS1_CPU0RS 0x0040 +/* reset cause mask */ +#define CPU0RS_MASK 0x0003 +/* CPU0 Boot Mode Register */ +#define SYS1_BM 0x00a0 +/* boot mode mask */ +#define BM_MASK 0x0005 + +/* allow platform code to find out what surce we booted from */ +unsigned char ltq_boot_select(void) +{ + return ltq_sys1_r32(SYS1_BM) & BM_MASK; +} + +/* allow the watchdog driver to find out what the boot reason was */ +int ltq_reset_cause(void) +{ + return ltq_sys1_r32(SYS1_CPU0RS) & CPU0RS_MASK; +} +EXPORT_SYMBOL_GPL(ltq_reset_cause); + +#define BOOT_REG_BASE (KSEG1 | 0x1F200000) +#define BOOT_PW1_REG (BOOT_REG_BASE | 0x20) +#define BOOT_PW2_REG (BOOT_REG_BASE | 0x24) +#define BOOT_PW1 0x4C545100 +#define BOOT_PW2 0x0051544C + +#define WDT_REG_BASE (KSEG1 | 0x1F8803F0) +#define WDT_PW1 0x00BE0000 +#define WDT_PW2 0x00DC0000 + +static void machine_restart(char *command) +{ + local_irq_disable(); + + /* reboot magic */ + ltq_w32(BOOT_PW1, (void *)BOOT_PW1_REG); /* 'LTQ\0' */ + ltq_w32(BOOT_PW2, (void *)BOOT_PW2_REG); /* '\0QTL' */ + ltq_w32(0, (void *)BOOT_REG_BASE); /* reset Bootreg RVEC */ + + /* watchdog magic */ + ltq_w32(WDT_PW1, (void *)WDT_REG_BASE); + ltq_w32(WDT_PW2 | + (0x3 << 26) | /* PWL */ + (0x2 << 24) | /* CLKDIV */ + (0x1 << 31) | /* enable */ + (1), /* reload */ + (void *)WDT_REG_BASE); + unreachable(); +} + +static void machine_halt(void) +{ + local_irq_disable(); + unreachable(); +} + +static void machine_power_off(void) +{ + local_irq_disable(); + unreachable(); +} + +static int __init mips_reboot_setup(void) +{ + _machine_restart = machine_restart; + _machine_halt = machine_halt; + pm_power_off = machine_power_off; + return 0; +} + +arch_initcall(mips_reboot_setup); diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c new file mode 100644 index 0000000..ba0123d --- /dev/null +++ b/arch/mips/lantiq/falcon/sysctrl.c @@ -0,0 +1,260 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com> + * Copyright (C) 2011 John Crispin <blogic@openwrt.org> + */ + +#include <linux/ioport.h> +#include <linux/export.h> +#include <linux/clkdev.h> +#include <linux/of_address.h> +#include <asm/delay.h> + +#include <lantiq_soc.h> + +#include "../clk.h" + +/* infrastructure control register */ +#define SYS1_INFRAC 0x00bc +/* Configuration fuses for drivers and pll */ +#define STATUS_CONFIG 0x0040 + +/* GPE frequency selection */ +#define GPPC_OFFSET 24 +#define GPEFREQ_MASK 0x00000C0 +#define GPEFREQ_OFFSET 10 +/* Clock status register */ +#define SYSCTL_CLKS 0x0000 +/* Clock enable register */ +#define SYSCTL_CLKEN 0x0004 +/* Clock clear register */ +#define SYSCTL_CLKCLR 0x0008 +/* Activation Status Register */ +#define SYSCTL_ACTS 0x0020 +/* Activation Register */ +#define SYSCTL_ACT 0x0024 +/* Deactivation Register */ +#define SYSCTL_DEACT 0x0028 +/* reboot Register */ +#define SYSCTL_RBT 0x002c +/* CPU0 Clock Control Register */ +#define SYS1_CPU0CC 0x0040 +/* HRST_OUT_N Control Register */ +#define SYS1_HRSTOUTC 0x00c0 +/* clock divider bit */ +#define CPU0CC_CPUDIV 0x0001 + +/* Activation Status Register */ +#define ACTS_ASC1_ACT 0x00000800 +#define ACTS_I2C_ACT 0x00004000 +#define ACTS_P0 0x00010000 +#define ACTS_P1 0x00010000 +#define ACTS_P2 0x00020000 +#define ACTS_P3 0x00020000 +#define ACTS_P4 0x00040000 +#define ACTS_PADCTRL0 0x00100000 +#define ACTS_PADCTRL1 0x00100000 +#define ACTS_PADCTRL2 0x00200000 +#define ACTS_PADCTRL3 0x00200000 +#define ACTS_PADCTRL4 0x00400000 + +#define sysctl_w32(m, x, y) ltq_w32((x), sysctl_membase[m] + (y)) +#define sysctl_r32(m, x) ltq_r32(sysctl_membase[m] + (x)) +#define sysctl_w32_mask(m, clear, set, reg) \ + sysctl_w32(m, (sysctl_r32(m, reg) & ~(clear)) | (set), reg) + +#define status_w32(x, y) ltq_w32((x), status_membase + (y)) +#define status_r32(x) ltq_r32(status_membase + (x)) + +static void __iomem *sysctl_membase[3], *status_membase; +void __iomem *ltq_sys1_membase, *ltq_ebu_membase; + +void falcon_trigger_hrst(int level) +{ + sysctl_w32(SYSCTL_SYS1, level & 1, SYS1_HRSTOUTC); +} + +static inline void sysctl_wait(struct clk *clk, + unsigned int test, unsigned int reg) +{ + int err = 1000000; + + do {} while (--err && ((sysctl_r32(clk->module, reg) + & clk->bits) != test)); + if (!err) + pr_err("module de/activation failed %d %08X %08X %08X\n", + clk->module, clk->bits, test, + sysctl_r32(clk->module, reg) & clk->bits); +} + +static int sysctl_activate(struct clk *clk) +{ + sysctl_w32(clk->module, clk->bits, SYSCTL_CLKEN); + sysctl_w32(clk->module, clk->bits, SYSCTL_ACT); + sysctl_wait(clk, clk->bits, SYSCTL_ACTS); + return 0; +} + +static void sysctl_deactivate(struct clk *clk) +{ + sysctl_w32(clk->module, clk->bits, SYSCTL_CLKCLR); + sysctl_w32(clk->module, clk->bits, SYSCTL_DEACT); + sysctl_wait(clk, 0, SYSCTL_ACTS); +} + +static int sysctl_clken(struct clk *clk) +{ + sysctl_w32(clk->module, clk->bits, SYSCTL_CLKEN); + sysctl_wait(clk, clk->bits, SYSCTL_CLKS); + return 0; +} + +static void sysctl_clkdis(struct clk *clk) +{ + sysctl_w32(clk->module, clk->bits, SYSCTL_CLKCLR); + sysctl_wait(clk, 0, SYSCTL_CLKS); +} + +static void sysctl_reboot(struct clk *clk) +{ + unsigned int act; + unsigned int bits; + + act = sysctl_r32(clk->module, SYSCTL_ACT); + bits = ~act & clk->bits; + if (bits != 0) { + sysctl_w32(clk->module, bits, SYSCTL_CLKEN); + sysctl_w32(clk->module, bits, SYSCTL_ACT); + sysctl_wait(clk, bits, SYSCTL_ACTS); + } + sysctl_w32(clk->module, act & clk->bits, SYSCTL_RBT); + sysctl_wait(clk, clk->bits, SYSCTL_ACTS); +} + +/* enable the ONU core */ +static void falcon_gpe_enable(void) +{ + unsigned int freq; + unsigned int status; + + /* if if the clock is already enabled */ + status = sysctl_r32(SYSCTL_SYS1, SYS1_INFRAC); + if (status & (1 << (GPPC_OFFSET + 1))) + return; + + if (status_r32(STATUS_CONFIG) == 0) + freq = 1; /* use 625MHz on unfused chip */ + else + freq = (status_r32(STATUS_CONFIG) & + GPEFREQ_MASK) >> + GPEFREQ_OFFSET; + + /* apply new frequency */ + sysctl_w32_mask(SYSCTL_SYS1, 7 << (GPPC_OFFSET + 1), + freq << (GPPC_OFFSET + 2) , SYS1_INFRAC); + udelay(1); + + /* enable new frequency */ + sysctl_w32_mask(SYSCTL_SYS1, 0, 1 << (GPPC_OFFSET + 1), SYS1_INFRAC); + udelay(1); +} + +static inline void clkdev_add_sys(const char *dev, unsigned int module, + unsigned int bits) +{ + struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + + clk->cl.dev_id = dev; + clk->cl.con_id = NULL; + clk->cl.clk = clk; + clk->module = module; + clk->activate = sysctl_activate; + clk->deactivate = sysctl_deactivate; + clk->enable = sysctl_clken; + clk->disable = sysctl_clkdis; + clk->reboot = sysctl_reboot; + clkdev_add(&clk->cl); +} + +void __init ltq_soc_init(void) +{ + struct device_node *np_status = + of_find_compatible_node(NULL, NULL, "lantiq,status-falcon"); + struct device_node *np_ebu = + of_find_compatible_node(NULL, NULL, "lantiq,ebu-falcon"); + struct device_node *np_sys1 = + of_find_compatible_node(NULL, NULL, "lantiq,sys1-falcon"); + struct device_node *np_syseth = + of_find_compatible_node(NULL, NULL, "lantiq,syseth-falcon"); + struct device_node *np_sysgpe = + of_find_compatible_node(NULL, NULL, "lantiq,sysgpe-falcon"); + struct resource res_status, res_ebu, res_sys[3]; + int i; + + /* check if all the core register ranges are available */ + if (!np_status || !np_ebu || !np_sys1 || !np_syseth || !np_sysgpe) + panic("Failed to load core nodes from devicetree"); + + if (of_address_to_resource(np_status, 0, &res_status) || + of_address_to_resource(np_ebu, 0, &res_ebu) || + of_address_to_resource(np_sys1, 0, &res_sys[0]) || + of_address_to_resource(np_syseth, 0, &res_sys[1]) || + of_address_to_resource(np_sysgpe, 0, &res_sys[2])) + panic("Failed to get core resources"); + + if ((request_mem_region(res_status.start, resource_size(&res_status), + res_status.name) < 0) || + (request_mem_region(res_ebu.start, resource_size(&res_ebu), + res_ebu.name) < 0) || + (request_mem_region(res_sys[0].start, + resource_size(&res_sys[0]), + res_sys[0].name) < 0) || + (request_mem_region(res_sys[1].start, + resource_size(&res_sys[1]), + res_sys[1].name) < 0) || + (request_mem_region(res_sys[2].start, + resource_size(&res_sys[2]), + res_sys[2].name) < 0)) + pr_err("Failed to request core reources"); + + status_membase = ioremap_nocache(res_status.start, + resource_size(&res_status)); + ltq_ebu_membase = ioremap_nocache(res_ebu.start, + resource_size(&res_ebu)); + + if (!status_membase || !ltq_ebu_membase) + panic("Failed to remap core resources"); + + for (i = 0; i < 3; i++) { + sysctl_membase[i] = ioremap_nocache(res_sys[i].start, + resource_size(&res_sys[i])); + if (!sysctl_membase[i]) + panic("Failed to remap sysctrl resources"); + } + ltq_sys1_membase = sysctl_membase[0]; + + falcon_gpe_enable(); + + /* get our 3 static rates for cpu, fpi and io clocks */ + if (ltq_sys1_r32(SYS1_CPU0CC) & CPU0CC_CPUDIV) + clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M); + else + clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M); + + /* add our clock domains */ + clkdev_add_sys("1d810000.gpio", SYSCTL_SYSETH, ACTS_P0); + clkdev_add_sys("1d810100.gpio", SYSCTL_SYSETH, ACTS_P2); + clkdev_add_sys("1e800100.gpio", SYSCTL_SYS1, ACTS_P1); + clkdev_add_sys("1e800200.gpio", SYSCTL_SYS1, ACTS_P3); + clkdev_add_sys("1e800300.gpio", SYSCTL_SYS1, ACTS_P4); + clkdev_add_sys("1db01000.pad", SYSCTL_SYSETH, ACTS_PADCTRL0); + clkdev_add_sys("1db02000.pad", SYSCTL_SYSETH, ACTS_PADCTRL2); + clkdev_add_sys("1e800400.pad", SYSCTL_SYS1, ACTS_PADCTRL1); + clkdev_add_sys("1e800500.pad", SYSCTL_SYS1, ACTS_PADCTRL3); + clkdev_add_sys("1e800600.pad", SYSCTL_SYS1, ACTS_PADCTRL4); + clkdev_add_sys("1e100C00.serial", SYSCTL_SYS1, ACTS_ASC1_ACT); + clkdev_add_sys("1e200000.i2c", SYSCTL_SYS1, ACTS_I2C_ACT); +} diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index d673731..57c1a4e 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -9,6 +9,11 @@ #include <linux/interrupt.h> #include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/irqdomain.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/bootinfo.h> #include <asm/irq_cpu.h> @@ -16,7 +21,7 @@ #include <lantiq_soc.h> #include <irq.h> -/* register definitions */ +/* register definitions - internal irqs */ #define LTQ_ICU_IM0_ISR 0x0000 #define LTQ_ICU_IM0_IER 0x0008 #define LTQ_ICU_IM0_IOSR 0x0010 @@ -25,6 +30,7 @@ #define LTQ_ICU_IM1_ISR 0x0028 #define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR) +/* register definitions - external irqs */ #define LTQ_EIU_EXIN_C 0x0000 #define LTQ_EIU_EXIN_INIC 0x0004 #define LTQ_EIU_EXIN_INEN 0x000C @@ -37,10 +43,14 @@ #define LTQ_EIU_IR4 (INT_NUM_IM1_IRL0 + 1) #define LTQ_EIU_IR5 (INT_NUM_IM1_IRL0 + 2) #define LTQ_EIU_IR6 (INT_NUM_IM2_IRL0 + 30) - +#define XWAY_EXIN_COUNT 3 #define MAX_EIU 6 -/* irqs generated by device attached to the EBU need to be acked in +/* the performance counter */ +#define LTQ_PERF_IRQ (INT_NUM_IM4_IRL0 + 31) + +/* + * irqs generated by devices attached to the EBU need to be acked in * a special manner */ #define LTQ_ICU_EBU_IRQ 22 @@ -51,6 +61,17 @@ #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) +/* our 2 ipi interrupts for VSMP */ +#define MIPS_CPU_IPI_RESCHED_IRQ 0 +#define MIPS_CPU_IPI_CALL_IRQ 1 + +/* we have a cascade of 8 irqs */ +#define MIPS_CPU_IRQ_CASCADE 8 + +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) +int gic_present; +#endif + static unsigned short ltq_eiu_irq[MAX_EIU] = { LTQ_EIU_IR0, LTQ_EIU_IR1, @@ -60,64 +81,51 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = { LTQ_EIU_IR5, }; -static struct resource ltq_icu_resource = { - .name = "icu", - .start = LTQ_ICU_BASE_ADDR, - .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct resource ltq_eiu_resource = { - .name = "eiu", - .start = LTQ_EIU_BASE_ADDR, - .end = LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - +static int exin_avail; static void __iomem *ltq_icu_membase; static void __iomem *ltq_eiu_membase; void ltq_disable_irq(struct irq_data *d) { u32 ier = LTQ_ICU_IM0_IER; - int irq_nr = d->irq - INT_NUM_IRQ0; + int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; - ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); - irq_nr %= INT_NUM_IM_OFFSET; - ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier); + ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); + offset %= INT_NUM_IM_OFFSET; + ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier); } void ltq_mask_and_ack_irq(struct irq_data *d) { u32 ier = LTQ_ICU_IM0_IER; u32 isr = LTQ_ICU_IM0_ISR; - int irq_nr = d->irq - INT_NUM_IRQ0; + int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; - ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); - isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); - irq_nr %= INT_NUM_IM_OFFSET; - ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier); - ltq_icu_w32((1 << irq_nr), isr); + ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); + isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); + offset %= INT_NUM_IM_OFFSET; + ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier); + ltq_icu_w32(BIT(offset), isr); } static void ltq_ack_irq(struct irq_data *d) { u32 isr = LTQ_ICU_IM0_ISR; - int irq_nr = d->irq - INT_NUM_IRQ0; + int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; - isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); - irq_nr %= INT_NUM_IM_OFFSET; - ltq_icu_w32((1 << irq_nr), isr); + isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); + offset %= INT_NUM_IM_OFFSET; + ltq_icu_w32(BIT(offset), isr); } void ltq_enable_irq(struct irq_data *d) { u32 ier = LTQ_ICU_IM0_IER; - int irq_nr = d->irq - INT_NUM_IRQ0; + int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; - ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); - irq_nr %= INT_NUM_IM_OFFSET; - ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier); + ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); + offset %= INT_NUM_IM_OFFSET; + ltq_icu_w32(ltq_icu_r32(ier) | BIT(offset), ier); } static unsigned int ltq_startup_eiu_irq(struct irq_data *d) @@ -126,15 +134,15 @@ static unsigned int ltq_startup_eiu_irq(struct irq_data *d) ltq_enable_irq(d); for (i = 0; i < MAX_EIU; i++) { - if (d->irq == ltq_eiu_irq[i]) { + if (d->hwirq == ltq_eiu_irq[i]) { /* low level - we should really handle set_type */ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) | (0x6 << (i * 4)), LTQ_EIU_EXIN_C); /* clear all pending */ - ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~(1 << i), + ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~BIT(i), LTQ_EIU_EXIN_INIC); /* enable */ - ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | (1 << i), + ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | BIT(i), LTQ_EIU_EXIN_INEN); break; } @@ -149,9 +157,9 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d) ltq_disable_irq(d); for (i = 0; i < MAX_EIU; i++) { - if (d->irq == ltq_eiu_irq[i]) { + if (d->hwirq == ltq_eiu_irq[i]) { /* disable */ - ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i), + ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~BIT(i), LTQ_EIU_EXIN_INEN); break; } @@ -188,14 +196,15 @@ static void ltq_hw_irqdispatch(int module) if (irq == 0) return; - /* silicon bug causes only the msb set to 1 to be valid. all + /* + * silicon bug causes only the msb set to 1 to be valid. all * other bits might be bogus */ irq = __fls(irq); - do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module)); + do_IRQ((int)irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module)); /* if this is a EBU irq, we need to ack it or get a deadlock */ - if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0)) + if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10, LTQ_EBU_PCC_ISTAT); } @@ -216,6 +225,47 @@ static void ltq_hw5_irqdispatch(void) do_IRQ(MIPS_CPU_TIMER_IRQ); } +#ifdef CONFIG_MIPS_MT_SMP +void __init arch_init_ipiirq(int irq, struct irqaction *action) +{ + setup_irq(irq, action); + irq_set_handler(irq, handle_percpu_irq); +} + +static void ltq_sw0_irqdispatch(void) +{ + do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); +} + +static void ltq_sw1_irqdispatch(void) +{ + do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); +} +static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) +{ + scheduler_ipi(); + return IRQ_HANDLED; +} + +static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) +{ + smp_call_function_interrupt(); + return IRQ_HANDLED; +} + +static struct irqaction irq_resched = { + .handler = ipi_resched_interrupt, + .flags = IRQF_PERCPU, + .name = "IPI_resched" +}; + +static struct irqaction irq_call = { + .handler = ipi_call_interrupt, + .flags = IRQF_PERCPU, + .name = "IPI_call" +}; +#endif + asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; @@ -238,45 +288,75 @@ out: return; } +static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ + struct irq_chip *chip = <q_irq_type; + int i; + + for (i = 0; i < exin_avail; i++) + if (hw == ltq_eiu_irq[i]) + chip = <q_eiu_type; + + irq_set_chip_and_handler(hw, chip, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops irq_domain_ops = { + .xlate = irq_domain_xlate_onetwocell, + .map = icu_map, +}; + static struct irqaction cascade = { .handler = no_action, .name = "cascade", }; -void __init arch_init_irq(void) +int __init icu_of_init(struct device_node *node, struct device_node *parent) { + struct device_node *eiu_node; + struct resource res; int i; - if (insert_resource(&iomem_resource, <q_icu_resource) < 0) - panic("Failed to insert icu memory"); + if (of_address_to_resource(node, 0, &res)) + panic("Failed to get icu memory range"); - if (request_mem_region(ltq_icu_resource.start, - resource_size(<q_icu_resource), "icu") < 0) - panic("Failed to request icu memory"); + if (request_mem_region(res.start, resource_size(&res), res.name) < 0) + pr_err("Failed to request icu memory"); - ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start, - resource_size(<q_icu_resource)); + ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res)); if (!ltq_icu_membase) panic("Failed to remap icu memory"); - if (insert_resource(&iomem_resource, <q_eiu_resource) < 0) - panic("Failed to insert eiu memory"); - - if (request_mem_region(ltq_eiu_resource.start, - resource_size(<q_eiu_resource), "eiu") < 0) - panic("Failed to request eiu memory"); - - ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start, - resource_size(<q_eiu_resource)); - if (!ltq_eiu_membase) - panic("Failed to remap eiu memory"); + /* the external interrupts are optional and xway only */ + eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu"); + if (eiu_node && of_address_to_resource(eiu_node, 0, &res)) { + /* find out how many external irq sources we have */ + const __be32 *count = of_get_property(node, + "lantiq,count", NULL); + + if (count) + exin_avail = *count; + if (exin_avail > MAX_EIU) + exin_avail = MAX_EIU; + + if (request_mem_region(res.start, resource_size(&res), + res.name) < 0) + pr_err("Failed to request eiu memory"); + + ltq_eiu_membase = ioremap_nocache(res.start, + resource_size(&res)); + if (!ltq_eiu_membase) + panic("Failed to remap eiu memory"); + } - /* make sure all irqs are turned off by default */ - for (i = 0; i < 5; i++) + /* turn off all irqs by default */ + for (i = 0; i < 5; i++) { + /* make sure all irqs are turned off by default */ ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET)); - - /* clear all possibly pending interrupts */ - ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET)); + /* clear all possibly pending interrupts */ + ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET)); + } mips_cpu_irq_init(); @@ -293,20 +373,19 @@ void __init arch_init_irq(void) set_vi_handler(7, ltq_hw5_irqdispatch); } - for (i = INT_NUM_IRQ0; - i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++) - if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || - (i == LTQ_EIU_IR2)) - irq_set_chip_and_handler(i, <q_eiu_type, - handle_level_irq); - /* EIU3-5 only exist on ar9 and vr9 */ - else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) || - (i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9())) - irq_set_chip_and_handler(i, <q_eiu_type, - handle_level_irq); - else - irq_set_chip_and_handler(i, <q_irq_type, - handle_level_irq); + irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET, + &irq_domain_ops, 0); + +#if defined(CONFIG_MIPS_MT_SMP) + if (cpu_has_vint) { + pr_info("Setting up IPI vectored interrupts\n"); + set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch); + set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch); + } + arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ, + &irq_resched); + arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call); +#endif #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | @@ -315,9 +394,23 @@ void __init arch_init_irq(void) set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); #endif + + /* tell oprofile which irq to use */ + cp0_perfcount_irq = LTQ_PERF_IRQ; + return 0; } unsigned int __cpuinit get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; } + +static struct of_device_id __initdata of_irq_ids[] = { + { .compatible = "lantiq,icu", .data = icu_of_init }, + {}, +}; + +void __init arch_init_irq(void) +{ + of_irq_init(of_irq_ids); +} diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h deleted file mode 100644 index 7e01b8c..0000000 --- a/arch/mips/lantiq/machtypes.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#ifndef _LANTIQ_MACH_H__ -#define _LANTIQ_MACH_H__ - -#include <asm/mips_machine.h> - -enum lantiq_mach_type { - LTQ_MACH_GENERIC = 0, - LTQ_MACH_EASY50712, /* Danube evaluation board */ - LTQ_MACH_EASY50601, /* Amazon SE evaluation board */ -}; - -#endif diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index e34fcfd..d185e84 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -8,6 +8,7 @@ #include <linux/export.h> #include <linux/clk.h> +#include <linux/of_platform.h> #include <asm/bootinfo.h> #include <asm/time.h> @@ -16,19 +17,15 @@ #include "prom.h" #include "clk.h" -static struct ltq_soc_info soc_info; - -unsigned int ltq_get_cpu_ver(void) -{ - return soc_info.rev; -} -EXPORT_SYMBOL(ltq_get_cpu_ver); +/* access to the ebu needs to be locked between different drivers */ +DEFINE_SPINLOCK(ebu_lock); +EXPORT_SYMBOL_GPL(ebu_lock); -unsigned int ltq_get_soc_type(void) -{ - return soc_info.type; -} -EXPORT_SYMBOL(ltq_get_soc_type); +/* + * this struct is filled by the soc specific detection code and holds + * information about the specific soc type, revision and name + */ +static struct ltq_soc_info soc_info; const char *get_system_type(void) { @@ -45,27 +42,62 @@ static void __init prom_init_cmdline(void) char **argv = (char **) KSEG1ADDR(fw_arg1); int i; + arcs_cmdline[0] = '\0'; + for (i = 0; i < argc; i++) { - char *p = (char *) KSEG1ADDR(argv[i]); + char *p = (char *) KSEG1ADDR(argv[i]); - if (p && *p) { + if (CPHYSADDR(p) && *p) { strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); } } } -void __init prom_init(void) +void __init plat_mem_setup(void) { - struct clk *clk; + ioport_resource.start = IOPORT_RESOURCE_START; + ioport_resource.end = IOPORT_RESOURCE_END; + iomem_resource.start = IOMEM_RESOURCE_START; + iomem_resource.end = IOMEM_RESOURCE_END; + + set_io_port_base((unsigned long) KSEG1); + /* + * Load the builtin devicetree. This causes the chosen node to be + * parsed resulting in our memory appearing + */ + __dt_setup_arch(&__dtb_start); +} + +void __init prom_init(void) +{ + /* call the soc specific detetcion code and get it to fill soc_info */ ltq_soc_detect(&soc_info); - clk_init(); - clk = clk_get(0, "cpu"); - snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d", - soc_info.name, soc_info.rev); - clk_put(clk); + snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s", + soc_info.name, soc_info.rev_type); soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0'; pr_info("SoC: %s\n", soc_info.sys_type); prom_init_cmdline(); + +#if defined(CONFIG_MIPS_MT_SMP) + if (register_vsmp_smp_ops()) + panic("failed to register_vsmp_smp_ops()"); +#endif } + +int __init plat_of_setup(void) +{ + static struct of_device_id of_ids[3]; + + if (!of_have_populated_dt()) + panic("device tree not present"); + + strncpy(of_ids[0].compatible, soc_info.compatible, + sizeof(of_ids[0].compatible)); + strncpy(of_ids[1].compatible, "simple-bus", + sizeof(of_ids[1].compatible)); + return of_platform_bus_probe(NULL, of_ids, NULL); +} + +arch_initcall(plat_of_setup); diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h index b4229d9..a3fa1a2 100644 --- a/arch/mips/lantiq/prom.h +++ b/arch/mips/lantiq/prom.h @@ -10,16 +10,22 @@ #define _LTQ_PROM_H__ #define LTQ_SYS_TYPE_LEN 0x100 +#define LTQ_SYS_REV_LEN 0x10 struct ltq_soc_info { unsigned char *name; unsigned int rev; + unsigned char rev_type[LTQ_SYS_REV_LEN]; + unsigned int srev; unsigned int partnum; unsigned int type; unsigned char sys_type[LTQ_SYS_TYPE_LEN]; + unsigned char *compatible; }; extern void ltq_soc_detect(struct ltq_soc_info *i); -extern void ltq_soc_setup(void); +extern void ltq_soc_init(void); + +extern struct boot_param_header __dtb_start; #endif diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c deleted file mode 100644 index 1ff6c9d..0000000 --- a/arch/mips/lantiq/setup.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/kernel.h> -#include <linux/export.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <asm/bootinfo.h> - -#include <lantiq_soc.h> - -#include "machtypes.h" -#include "devices.h" -#include "prom.h" - -void __init plat_mem_setup(void) -{ - /* assume 16M as default incase uboot fails to pass proper ramsize */ - unsigned long memsize = 16; - char **envp = (char **) KSEG1ADDR(fw_arg2); - - ioport_resource.start = IOPORT_RESOURCE_START; - ioport_resource.end = IOPORT_RESOURCE_END; - iomem_resource.start = IOMEM_RESOURCE_START; - iomem_resource.end = IOMEM_RESOURCE_END; - - set_io_port_base((unsigned long) KSEG1); - - while (*envp) { - char *e = (char *)KSEG1ADDR(*envp); - if (!strncmp(e, "memsize=", 8)) { - e += 8; - if (strict_strtoul(e, 0, &memsize)) - pr_warn("bad memsize specified\n"); - } - envp++; - } - memsize *= 1024 * 1024; - add_memory_region(0x00000000, memsize, BOOT_MEM_RAM); -} - -static int __init -lantiq_setup(void) -{ - ltq_soc_setup(); - mips_machine_setup(); - return 0; -} - -arch_initcall(lantiq_setup); - -static void __init -lantiq_generic_init(void) -{ - /* Nothing to do */ -} - -MIPS_MACHINE(LTQ_MACH_GENERIC, - "Generic", - "Generic Lantiq based board", - lantiq_generic_init); diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig deleted file mode 100644 index 2b857de..0000000 --- a/arch/mips/lantiq/xway/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ -if SOC_XWAY - -menu "MIPS Machine" - -config LANTIQ_MACH_EASY50712 - bool "Easy50712 - Danube" - default y - -endmenu - -endif - -if SOC_AMAZON_SE - -menu "MIPS Machine" - -config LANTIQ_MACH_EASY50601 - bool "Easy50601 - Amazon SE" - default y - -endmenu - -endif diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile index c517f2e..dc3194f 100644 --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile @@ -1,7 +1 @@ -obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o - -obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o -obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o - -obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o -obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o +obj-y := prom.o sysctrl.o clk.o reset.o gpio.o dma.o diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c deleted file mode 100644 index 6522583..0000000 --- a/arch/mips/lantiq/xway/clk-ase.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2011 John Crispin <blogic@openwrt.org> - */ - -#include <linux/io.h> -#include <linux/export.h> -#include <linux/init.h> -#include <linux/clk.h> - -#include <asm/time.h> -#include <asm/irq.h> -#include <asm/div64.h> - -#include <lantiq_soc.h> - -/* cgu registers */ -#define LTQ_CGU_SYS 0x0010 - -unsigned int ltq_get_io_region_clock(void) -{ - return CLOCK_133M; -} -EXPORT_SYMBOL(ltq_get_io_region_clock); - -unsigned int ltq_get_fpi_bus_clock(int fpi) -{ - return CLOCK_133M; -} -EXPORT_SYMBOL(ltq_get_fpi_bus_clock); - -unsigned int ltq_get_cpu_hz(void) -{ - if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5)) - return CLOCK_266M; - else - return CLOCK_133M; -} -EXPORT_SYMBOL(ltq_get_cpu_hz); - -unsigned int ltq_get_fpi_hz(void) -{ - return CLOCK_133M; -} -EXPORT_SYMBOL(ltq_get_fpi_hz); diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c deleted file mode 100644 index 696b1a3..0000000 --- a/arch/mips/lantiq/xway/clk-xway.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/io.h> -#include <linux/export.h> -#include <linux/init.h> -#include <linux/clk.h> - -#include <asm/time.h> -#include <asm/irq.h> -#include <asm/div64.h> - -#include <lantiq_soc.h> - -static unsigned int ltq_ram_clocks[] = { - CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M }; -#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3] - -#define BASIC_FREQUENCY_1 35328000 -#define BASIC_FREQUENCY_2 36000000 -#define BASIS_REQUENCY_USB 12000000 - -#define GET_BITS(x, msb, lsb) \ - (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb)) - -#define LTQ_CGU_PLL0_CFG 0x0004 -#define LTQ_CGU_PLL1_CFG 0x0008 -#define LTQ_CGU_PLL2_CFG 0x000C -#define LTQ_CGU_SYS 0x0010 -#define LTQ_CGU_UPDATE 0x0014 -#define LTQ_CGU_IF_CLK 0x0018 -#define LTQ_CGU_OSC_CON 0x001C -#define LTQ_CGU_SMD 0x0020 -#define LTQ_CGU_CT1SR 0x0028 -#define LTQ_CGU_CT2SR 0x002C -#define LTQ_CGU_PCMCR 0x0030 -#define LTQ_CGU_PCI_CR 0x0034 -#define LTQ_CGU_PD_PC 0x0038 -#define LTQ_CGU_FMR 0x003C - -#define CGU_PLL0_PHASE_DIVIDER_ENABLE \ - (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31)) -#define CGU_PLL0_BYPASS \ - (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30)) -#define CGU_PLL0_CFG_DSMSEL \ - (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28)) -#define CGU_PLL0_CFG_FRAC_EN \ - (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27)) -#define CGU_PLL1_SRC \ - (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31)) -#define CGU_PLL2_PHASE_DIVIDER_ENABLE \ - (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20)) -#define CGU_SYS_FPI_SEL (1 << 6) -#define CGU_SYS_DDR_SEL 0x3 -#define CGU_PLL0_SRC (1 << 29) - -#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17) -#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6) -#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2) -#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17) -#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13) - -static unsigned int ltq_get_pll0_fdiv(void); - -static inline unsigned int get_input_clock(int pll) -{ - switch (pll) { - case 0: - if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC) - return BASIS_REQUENCY_USB; - else if (CGU_PLL0_PHASE_DIVIDER_ENABLE) - return BASIC_FREQUENCY_1; - else - return BASIC_FREQUENCY_2; - case 1: - if (CGU_PLL1_SRC) - return BASIS_REQUENCY_USB; - else if (CGU_PLL0_PHASE_DIVIDER_ENABLE) - return BASIC_FREQUENCY_1; - else - return BASIC_FREQUENCY_2; - case 2: - switch (CGU_PLL2_SRC) { - case 0: - return ltq_get_pll0_fdiv(); - case 1: - return CGU_PLL2_PHASE_DIVIDER_ENABLE ? - BASIC_FREQUENCY_1 : - BASIC_FREQUENCY_2; - case 2: - return BASIS_REQUENCY_USB; - } - default: - return 0; - } -} - -static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den) -{ - u64 res, clock = get_input_clock(pll); - - res = num * clock; - do_div(res, den); - return res; -} - -static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N, - unsigned int K) -{ - unsigned int num = ((N + 1) << 10) + K; - unsigned int den = (M + 1) << 10; - - return cal_dsm(pll, num, den); -} - -static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N, - unsigned int K) -{ - unsigned int num = ((N + 1) << 11) + K + 512; - unsigned int den = (M + 1) << 11; - - return cal_dsm(pll, num, den); -} - -static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N, - unsigned int K) -{ - unsigned int num = K >= 512 ? - ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584; - unsigned int den = (M + 1) << 12; - - return cal_dsm(pll, num, den); -} - -static inline unsigned int dsm(int pll, unsigned int M, unsigned int N, - unsigned int K, unsigned int dsmsel, unsigned int phase_div_en) -{ - if (!dsmsel) - return mash_dsm(pll, M, N, K); - else if (!phase_div_en) - return mash_dsm(pll, M, N, K); - else - return ssff_dsm_2(pll, M, N, K); -} - -static inline unsigned int ltq_get_pll0_fosc(void) -{ - if (CGU_PLL0_BYPASS) - return get_input_clock(0); - else - return !CGU_PLL0_CFG_FRAC_EN - ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0, - CGU_PLL0_CFG_DSMSEL, - CGU_PLL0_PHASE_DIVIDER_ENABLE) - : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, - CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL, - CGU_PLL0_PHASE_DIVIDER_ENABLE); -} - -static unsigned int ltq_get_pll0_fdiv(void) -{ - unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1; - - return (ltq_get_pll0_fosc() + (div >> 1)) / div; -} - -unsigned int ltq_get_io_region_clock(void) -{ - unsigned int ret = ltq_get_pll0_fosc(); - - switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) { - default: - case 0: - return (ret + 1) / 2; - case 1: - return (ret * 2 + 2) / 5; - case 2: - return (ret + 1) / 3; - case 3: - return (ret + 2) / 4; - } -} -EXPORT_SYMBOL(ltq_get_io_region_clock); - -unsigned int ltq_get_fpi_bus_clock(int fpi) -{ - unsigned int ret = ltq_get_io_region_clock(); - - if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL)) - ret >>= 1; - return ret; -} -EXPORT_SYMBOL(ltq_get_fpi_bus_clock); - -unsigned int ltq_get_cpu_hz(void) -{ - switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) { - case 0: - return CLOCK_333M; - case 4: - return DDR_HZ; - case 8: - return DDR_HZ << 1; - default: - return DDR_HZ >> 1; - } -} -EXPORT_SYMBOL(ltq_get_cpu_hz); - -unsigned int ltq_get_fpi_hz(void) -{ - unsigned int ddr_clock = DDR_HZ; - - if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40) - return ddr_clock >> 1; - return ddr_clock; -} -EXPORT_SYMBOL(ltq_get_fpi_hz); diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c new file mode 100644 index 0000000..9aa17f7 --- /dev/null +++ b/arch/mips/lantiq/xway/clk.c @@ -0,0 +1,151 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2010 John Crispin <blogic@openwrt.org> + */ + +#include <linux/io.h> +#include <linux/export.h> +#include <linux/init.h> +#include <linux/clk.h> + +#include <asm/time.h> +#include <asm/irq.h> +#include <asm/div64.h> + +#include <lantiq_soc.h> + +#include "../clk.h" + +static unsigned int ram_clocks[] = { + CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M }; +#define DDR_HZ ram_clocks[ltq_cgu_r32(CGU_SYS) & 0x3] + +/* legacy xway clock */ +#define CGU_SYS 0x10 + +/* vr9 clock */ +#define CGU_SYS_VR9 0x0c +#define CGU_IF_CLK_VR9 0x24 + +unsigned long ltq_danube_fpi_hz(void) +{ + unsigned long ddr_clock = DDR_HZ; + + if (ltq_cgu_r32(CGU_SYS) & 0x40) + return ddr_clock >> 1; + return ddr_clock; +} + +unsigned long ltq_danube_cpu_hz(void) +{ + switch (ltq_cgu_r32(CGU_SYS) & 0xc) { + case 0: + return CLOCK_333M; + case 4: + return DDR_HZ; + case 8: + return DDR_HZ << 1; + default: + return DDR_HZ >> 1; + } +} + +unsigned long ltq_ar9_sys_hz(void) +{ + if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2) + return CLOCK_393M; + return CLOCK_333M; +} + +unsigned long ltq_ar9_fpi_hz(void) +{ + unsigned long sys = ltq_ar9_sys_hz(); + + if (ltq_cgu_r32(CGU_SYS) & BIT(0)) + return sys; + return sys >> 1; +} + +unsigned long ltq_ar9_cpu_hz(void) +{ + if (ltq_cgu_r32(CGU_SYS) & BIT(2)) + return ltq_ar9_fpi_hz(); + else + return ltq_ar9_sys_hz(); +} + +unsigned long ltq_vr9_cpu_hz(void) +{ + unsigned int cpu_sel; + unsigned long clk; + + cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf; + + switch (cpu_sel) { + case 0: + clk = CLOCK_600M; + break; + case 1: + clk = CLOCK_500M; + break; + case 2: + clk = CLOCK_393M; + break; + case 3: + clk = CLOCK_333M; + break; + case 5: + case 6: + clk = CLOCK_196_608M; + break; + case 7: + clk = CLOCK_167M; + break; + case 4: + case 8: + case 9: + clk = CLOCK_125M; + break; + default: + clk = 0; + break; + } + + return clk; +} + +unsigned long ltq_vr9_fpi_hz(void) +{ + unsigned int ocp_sel, cpu_clk; + unsigned long clk; + + cpu_clk = ltq_vr9_cpu_hz(); + ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3; + + switch (ocp_sel) { + case 0: + /* OCP ratio 1 */ + clk = cpu_clk; + break; + case 2: + /* OCP ratio 2 */ + clk = cpu_clk / 2; + break; + case 3: + /* OCP ratio 2.5 */ + clk = (cpu_clk * 2) / 5; + break; + case 4: + /* OCP ratio 3 */ + clk = cpu_clk / 3; + break; + default: + clk = 0; + break; + } + + return clk; +} diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c deleted file mode 100644 index d614aa7..0000000 --- a/arch/mips/lantiq/xway/devices.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/init.h> -#include <linux/export.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/mtd/physmap.h> -#include <linux/kernel.h> -#include <linux/reboot.h> -#include <linux/platform_device.h> -#include <linux/leds.h> -#include <linux/etherdevice.h> -#include <linux/time.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <asm/bootinfo.h> -#include <asm/irq.h> - -#include <lantiq_soc.h> -#include <lantiq_irq.h> -#include <lantiq_platform.h> - -#include "devices.h" - -/* gpio */ -static struct resource ltq_gpio_resource[] = { - { - .name = "gpio0", - .start = LTQ_GPIO0_BASE_ADDR, - .end = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1, - .flags = IORESOURCE_MEM, - }, { - .name = "gpio1", - .start = LTQ_GPIO1_BASE_ADDR, - .end = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1, - .flags = IORESOURCE_MEM, - }, { - .name = "gpio2", - .start = LTQ_GPIO2_BASE_ADDR, - .end = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1, - .flags = IORESOURCE_MEM, - } -}; - -void __init ltq_register_gpio(void) -{ - platform_device_register_simple("ltq_gpio", 0, - <q_gpio_resource[0], 1); - platform_device_register_simple("ltq_gpio", 1, - <q_gpio_resource[1], 1); - - /* AR9 and VR9 have an extra gpio block */ - if (ltq_is_ar9() || ltq_is_vr9()) { - platform_device_register_simple("ltq_gpio", 2, - <q_gpio_resource[2], 1); - } -} - -/* serial to parallel conversion */ -static struct resource ltq_stp_resource = { - .name = "stp", - .start = LTQ_STP_BASE_ADDR, - .end = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -void __init ltq_register_gpio_stp(void) -{ - platform_device_register_simple("ltq_stp", 0, <q_stp_resource, 1); -} - -/* asc ports - amazon se has its own serial mapping */ -static struct resource ltq_ase_asc_resources[] = { - { - .name = "asc0", - .start = LTQ_ASC1_BASE_ADDR, - .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - IRQ_RES(tx, LTQ_ASC_ASE_TIR), - IRQ_RES(rx, LTQ_ASC_ASE_RIR), - IRQ_RES(err, LTQ_ASC_ASE_EIR), -}; - -void __init ltq_register_ase_asc(void) -{ - platform_device_register_simple("ltq_asc", 0, - ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources)); -} - -/* ethernet */ -static struct resource ltq_etop_resources = { - .name = "etop", - .start = LTQ_ETOP_BASE_ADDR, - .end = LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device ltq_etop = { - .name = "ltq_etop", - .resource = <q_etop_resources, - .num_resources = 1, -}; - -void __init -ltq_register_etop(struct ltq_eth_data *eth) -{ - if (eth) { - ltq_etop.dev.platform_data = eth; - platform_device_register(<q_etop); - } -} diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h deleted file mode 100644 index e904934..0000000 --- a/arch/mips/lantiq/xway/devices.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#ifndef _LTQ_DEVICES_XWAY_H__ -#define _LTQ_DEVICES_XWAY_H__ - -#include "../devices.h" -#include <linux/phy.h> - -extern void ltq_register_gpio(void); -extern void ltq_register_gpio_stp(void); -extern void ltq_register_ase_asc(void); -extern void ltq_register_etop(struct ltq_eth_data *eth); - -#endif diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c index b210e93..55d2c4f 100644 --- a/arch/mips/lantiq/xway/dma.c +++ b/arch/mips/lantiq/xway/dma.c @@ -19,7 +19,8 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/dma-mapping.h> -#include <linux/export.h> +#include <linux/module.h> +#include <linux/clk.h> #include <lantiq_soc.h> #include <xway_dma.h> @@ -55,13 +56,6 @@ #define ltq_dma_w32_mask(x, y, z) ltq_w32_mask(x, y, \ ltq_dma_membase + (z)) -static struct resource ltq_dma_resource = { - .name = "dma", - .start = LTQ_DMA_BASE_ADDR, - .end = LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - static void __iomem *ltq_dma_membase; void @@ -215,27 +209,28 @@ ltq_dma_init_port(int p) } EXPORT_SYMBOL_GPL(ltq_dma_init_port); -int __init -ltq_dma_init(void) +static int __devinit +ltq_dma_init(struct platform_device *pdev) { + struct clk *clk; + struct resource *res; int i; - /* insert and request the memory region */ - if (insert_resource(&iomem_resource, <q_dma_resource) < 0) - panic("Failed to insert dma memory"); - - if (request_mem_region(ltq_dma_resource.start, - resource_size(<q_dma_resource), "dma") < 0) - panic("Failed to request dma memory"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + panic("Failed to get dma resource"); /* remap dma register range */ - ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start, - resource_size(<q_dma_resource)); + ltq_dma_membase = devm_request_and_ioremap(&pdev->dev, res); if (!ltq_dma_membase) - panic("Failed to remap dma memory"); + panic("Failed to remap dma resource"); /* power up and reset the dma engine */ - ltq_pmu_enable(PMU_DMA); + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) + panic("Failed to get dma clock"); + + clk_enable(clk); ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL); /* disable all interrupts */ @@ -248,7 +243,29 @@ ltq_dma_init(void) ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); } + dev_info(&pdev->dev, "init done\n"); return 0; } -postcore_initcall(ltq_dma_init); +static const struct of_device_id dma_match[] = { + { .compatible = "lantiq,dma-xway" }, + {}, +}; +MODULE_DEVICE_TABLE(of, dma_match); + +static struct platform_driver dma_driver = { + .probe = ltq_dma_init, + .driver = { + .name = "dma-xway", + .owner = THIS_MODULE, + .of_match_table = dma_match, + }, +}; + +int __init +dma_init(void) +{ + return platform_driver_register(&dma_driver); +} + +postcore_initcall(dma_init); diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c deleted file mode 100644 index 862e3e8..0000000 --- a/arch/mips/lantiq/xway/ebu.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * EBU - the external bus unit attaches PCI, NOR and NAND - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/ioport.h> - -#include <lantiq_soc.h> - -/* all access to the ebu must be locked */ -DEFINE_SPINLOCK(ebu_lock); -EXPORT_SYMBOL_GPL(ebu_lock); - -static struct resource ltq_ebu_resource = { - .name = "ebu", - .start = LTQ_EBU_BASE_ADDR, - .end = LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -/* remapped base addr of the clock unit and external bus unit */ -void __iomem *ltq_ebu_membase; - -static int __init lantiq_ebu_init(void) -{ - /* insert and request the memory region */ - if (insert_resource(&iomem_resource, <q_ebu_resource) < 0) - panic("Failed to insert ebu memory"); - - if (request_mem_region(ltq_ebu_resource.start, - resource_size(<q_ebu_resource), "ebu") < 0) - panic("Failed to request ebu memory"); - - /* remap ebu register range */ - ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start, - resource_size(<q_ebu_resource)); - if (!ltq_ebu_membase) - panic("Failed to remap ebu memory"); - - /* make sure to unprotect the memory region where flash is located */ - ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0); - return 0; -} - -postcore_initcall(lantiq_ebu_init); diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c index d2fa98f..a8b2edc 100644 --- a/arch/mips/lantiq/xway/gpio.c +++ b/arch/mips/lantiq/xway/gpio.c @@ -36,18 +36,6 @@ struct ltq_gpio { static struct ltq_gpio ltq_gpio_port[MAX_PORTS]; -int gpio_to_irq(unsigned int gpio) -{ - return -EINVAL; -} -EXPORT_SYMBOL(gpio_to_irq); - -int irq_to_gpio(unsigned int gpio) -{ - return -EINVAL; -} -EXPORT_SYMBOL(irq_to_gpio); - int ltq_gpio_request(unsigned int pin, unsigned int alt0, unsigned int alt1, unsigned int dir, const char *name) { diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c deleted file mode 100644 index b91c7f1..0000000 --- a/arch/mips/lantiq/xway/gpio_ebu.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/init.h> -#include <linux/export.h> -#include <linux/types.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <linux/gpio.h> -#include <linux/io.h> - -#include <lantiq_soc.h> - -/* - * By attaching hardware latches to the EBU it is possible to create output - * only gpios. This driver configures a special memory address, which when - * written to outputs 16 bit to the latches. - */ - -#define LTQ_EBU_BUSCON 0x1e7ff /* 16 bit access, slowest timing */ -#define LTQ_EBU_WP 0x80000000 /* write protect bit */ - -/* we keep a shadow value of the last value written to the ebu */ -static int ltq_ebu_gpio_shadow = 0x0; -static void __iomem *ltq_ebu_gpio_membase; - -static void ltq_ebu_apply(void) -{ - unsigned long flags; - - spin_lock_irqsave(&ebu_lock, flags); - ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1); - *((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow; - ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1); - spin_unlock_irqrestore(&ebu_lock, flags); -} - -static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value) -{ - if (value) - ltq_ebu_gpio_shadow |= (1 << offset); - else - ltq_ebu_gpio_shadow &= ~(1 << offset); - ltq_ebu_apply(); -} - -static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - ltq_ebu_set(chip, offset, value); - - return 0; -} - -static struct gpio_chip ltq_ebu_chip = { - .label = "ltq_ebu", - .direction_output = ltq_ebu_direction_output, - .set = ltq_ebu_set, - .base = 72, - .ngpio = 16, - .can_sleep = 1, - .owner = THIS_MODULE, -}; - -static int ltq_ebu_probe(struct platform_device *pdev) -{ - int ret = 0; - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (!res) { - dev_err(&pdev->dev, "failed to get memory resource\n"); - return -ENOENT; - } - - res = devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), dev_name(&pdev->dev)); - if (!res) { - dev_err(&pdev->dev, "failed to request memory resource\n"); - return -EBUSY; - } - - ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); - if (!ltq_ebu_gpio_membase) { - dev_err(&pdev->dev, "Failed to ioremap mem region\n"); - return -ENOMEM; - } - - /* grab the default shadow value passed form the platform code */ - ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data; - - /* tell the ebu controller which memory address we will be using */ - ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1); - - /* write protect the region */ - ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1); - - ret = gpiochip_add(<q_ebu_chip); - if (!ret) - ltq_ebu_apply(); - return ret; -} - -static struct platform_driver ltq_ebu_driver = { - .probe = ltq_ebu_probe, - .driver = { - .name = "ltq_ebu", - .owner = THIS_MODULE, - }, -}; - -static int __init ltq_ebu_init(void) -{ - int ret = platform_driver_register(<q_ebu_driver); - - if (ret) - pr_info("ltq_ebu : Error registering platfom driver!"); - return ret; -} - -postcore_initcall(ltq_ebu_init); diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c deleted file mode 100644 index ff9991c..0000000 --- a/arch/mips/lantiq/xway/gpio_stp.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2007 John Crispin <blogic@openwrt.org> - * - */ - -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/export.h> -#include <linux/types.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <lantiq_soc.h> - -#define LTQ_STP_CON0 0x00 -#define LTQ_STP_CON1 0x04 -#define LTQ_STP_CPU0 0x08 -#define LTQ_STP_CPU1 0x0C -#define LTQ_STP_AR 0x10 - -#define LTQ_STP_CON_SWU (1 << 31) -#define LTQ_STP_2HZ 0 -#define LTQ_STP_4HZ (1 << 23) -#define LTQ_STP_8HZ (2 << 23) -#define LTQ_STP_10HZ (3 << 23) -#define LTQ_STP_SPEED_MASK (0xf << 23) -#define LTQ_STP_UPD_FPI (1 << 31) -#define LTQ_STP_UPD_MASK (3 << 30) -#define LTQ_STP_ADSL_SRC (3 << 24) - -#define LTQ_STP_GROUP0 (1 << 0) - -#define LTQ_STP_RISING 0 -#define LTQ_STP_FALLING (1 << 26) -#define LTQ_STP_EDGE_MASK (1 << 26) - -#define ltq_stp_r32(reg) __raw_readl(ltq_stp_membase + reg) -#define ltq_stp_w32(val, reg) __raw_writel(val, ltq_stp_membase + reg) -#define ltq_stp_w32_mask(clear, set, reg) \ - ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \ - ltq_stp_membase + (reg)) - -static int ltq_stp_shadow = 0xffff; -static void __iomem *ltq_stp_membase; - -static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value) -{ - if (value) - ltq_stp_shadow |= (1 << offset); - else - ltq_stp_shadow &= ~(1 << offset); - ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0); -} - -static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - ltq_stp_set(chip, offset, value); - - return 0; -} - -static struct gpio_chip ltq_stp_chip = { - .label = "ltq_stp", - .direction_output = ltq_stp_direction_output, - .set = ltq_stp_set, - .base = 48, - .ngpio = 24, - .can_sleep = 1, - .owner = THIS_MODULE, -}; - -static int ltq_stp_hw_init(void) -{ - /* the 3 pins used to control the external stp */ - ltq_gpio_request(4, 1, 0, 1, "stp-st"); - ltq_gpio_request(5, 1, 0, 1, "stp-d"); - ltq_gpio_request(6, 1, 0, 1, "stp-sh"); - - /* sane defaults */ - ltq_stp_w32(0, LTQ_STP_AR); - ltq_stp_w32(0, LTQ_STP_CPU0); - ltq_stp_w32(0, LTQ_STP_CPU1); - ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0); - ltq_stp_w32(0, LTQ_STP_CON1); - - /* rising or falling edge */ - ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0); - - /* per default stp 15-0 are set */ - ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1); - - /* stp are update periodically by the FPI bus */ - ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1); - - /* set stp update speed */ - ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1); - - /* tell the hardware that pin (led) 0 and 1 are controlled - * by the dsl arc - */ - ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0); - - ltq_pmu_enable(PMU_LED); - return 0; -} - -static int __devinit ltq_stp_probe(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int ret = 0; - - if (!res) - return -ENOENT; - res = devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), dev_name(&pdev->dev)); - if (!res) { - dev_err(&pdev->dev, "failed to request STP memory\n"); - return -EBUSY; - } - ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); - if (!ltq_stp_membase) { - dev_err(&pdev->dev, "failed to remap STP memory\n"); - return -ENOMEM; - } - ret = gpiochip_add(<q_stp_chip); - if (!ret) - ret = ltq_stp_hw_init(); - - return ret; -} - -static struct platform_driver ltq_stp_driver = { - .probe = ltq_stp_probe, - .driver = { - .name = "ltq_stp", - .owner = THIS_MODULE, - }, -}; - -int __init ltq_stp_init(void) -{ - int ret = platform_driver_register(<q_stp_driver); - - if (ret) - pr_info("ltq_stp: error registering platfom driver"); - return ret; -} - -postcore_initcall(ltq_stp_init); diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c deleted file mode 100644 index d5aaf63..0000000 --- a/arch/mips/lantiq/xway/mach-easy50601.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> -#include <linux/input.h> - -#include <lantiq.h> - -#include "../machtypes.h" -#include "devices.h" - -static struct mtd_partition easy50601_partitions[] = { - { - .name = "uboot", - .offset = 0x0, - .size = 0x10000, - }, - { - .name = "uboot_env", - .offset = 0x10000, - .size = 0x10000, - }, - { - .name = "linux", - .offset = 0x20000, - .size = 0xE0000, - }, - { - .name = "rootfs", - .offset = 0x100000, - .size = 0x300000, - }, -}; - -static struct physmap_flash_data easy50601_flash_data = { - .nr_parts = ARRAY_SIZE(easy50601_partitions), - .parts = easy50601_partitions, -}; - -static void __init easy50601_init(void) -{ - ltq_register_nor(&easy50601_flash_data); -} - -MIPS_MACHINE(LTQ_MACH_EASY50601, - "EASY50601", - "EASY50601 Eval Board", - easy50601_init); diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c deleted file mode 100644 index ea5027b..0000000 --- a/arch/mips/lantiq/xway/mach-easy50712.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> -#include <linux/input.h> -#include <linux/phy.h> - -#include <lantiq_soc.h> -#include <irq.h> - -#include "../machtypes.h" -#include "devices.h" - -static struct mtd_partition easy50712_partitions[] = { - { - .name = "uboot", - .offset = 0x0, - .size = 0x10000, - }, - { - .name = "uboot_env", - .offset = 0x10000, - .size = 0x10000, - }, - { - .name = "linux", - .offset = 0x20000, - .size = 0xe0000, - }, - { - .name = "rootfs", - .offset = 0x100000, - .size = 0x300000, - }, -}; - -static struct physmap_flash_data easy50712_flash_data = { - .nr_parts = ARRAY_SIZE(easy50712_partitions), - .parts = easy50712_partitions, -}; - -static struct ltq_pci_data ltq_pci_data = { - .clock = PCI_CLOCK_INT, - .gpio = PCI_GNT1 | PCI_REQ1, - .irq = { - [14] = INT_NUM_IM0_IRL0 + 22, - }, -}; - -static struct ltq_eth_data ltq_eth_data = { - .mii_mode = PHY_INTERFACE_MODE_MII, -}; - -static void __init easy50712_init(void) -{ - ltq_register_gpio_stp(); - ltq_register_nor(&easy50712_flash_data); - ltq_register_pci(<q_pci_data); - ltq_register_etop(<q_eth_data); -} - -MIPS_MACHINE(LTQ_MACH_EASY50712, - "EASY50712", - "EASY50712 Eval Board", - easy50712_init); diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c deleted file mode 100644 index fe85361..0000000 --- a/arch/mips/lantiq/xway/pmu.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/ioport.h> - -#include <lantiq_soc.h> - -/* PMU - the power management unit allows us to turn part of the core - * on and off - */ - -/* the enable / disable registers */ -#define LTQ_PMU_PWDCR 0x1C -#define LTQ_PMU_PWDSR 0x20 - -#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y)) -#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x)) - -static struct resource ltq_pmu_resource = { - .name = "pmu", - .start = LTQ_PMU_BASE_ADDR, - .end = LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static void __iomem *ltq_pmu_membase; - -void ltq_pmu_enable(unsigned int module) -{ - int err = 1000000; - - ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR); - do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module)); - - if (!err) - panic("activating PMU module failed!"); -} -EXPORT_SYMBOL(ltq_pmu_enable); - -void ltq_pmu_disable(unsigned int module) -{ - ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR); -} -EXPORT_SYMBOL(ltq_pmu_disable); - -int __init ltq_pmu_init(void) -{ - if (insert_resource(&iomem_resource, <q_pmu_resource) < 0) - panic("Failed to insert pmu memory"); - - if (request_mem_region(ltq_pmu_resource.start, - resource_size(<q_pmu_resource), "pmu") < 0) - panic("Failed to request pmu memory"); - - ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start, - resource_size(<q_pmu_resource)); - if (!ltq_pmu_membase) - panic("Failed to remap pmu memory"); - return 0; -} - -core_initcall(ltq_pmu_init); diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c deleted file mode 100644 index ae4959a..0000000 --- a/arch/mips/lantiq/xway/prom-ase.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/export.h> -#include <linux/clk.h> -#include <asm/bootinfo.h> -#include <asm/time.h> - -#include <lantiq_soc.h> - -#include "../prom.h" - -#define SOC_AMAZON_SE "Amazon_SE" - -#define PART_SHIFT 12 -#define PART_MASK 0x0FFFFFFF -#define REV_SHIFT 28 -#define REV_MASK 0xF0000000 - -void __init ltq_soc_detect(struct ltq_soc_info *i) -{ - i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT; - i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT; - switch (i->partnum) { - case SOC_ID_AMAZON_SE: - i->name = SOC_AMAZON_SE; - i->type = SOC_TYPE_AMAZON_SE; - break; - - default: - unreachable(); - break; - } -} diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c deleted file mode 100644 index 2228133..0000000 --- a/arch/mips/lantiq/xway/prom-xway.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2010 John Crispin <blogic@openwrt.org> - */ - -#include <linux/export.h> -#include <linux/clk.h> -#include <asm/bootinfo.h> -#include <asm/time.h> - -#include <lantiq_soc.h> - -#include "../prom.h" - -#define SOC_DANUBE "Danube" -#define SOC_TWINPASS "Twinpass" -#define SOC_AR9 "AR9" - -#define PART_SHIFT 12 -#define PART_MASK 0x0FFFFFFF -#define REV_SHIFT 28 -#define REV_MASK 0xF0000000 - -void __init ltq_soc_detect(struct ltq_soc_info *i) -{ - i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT; - i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT; - switch (i->partnum) { - case SOC_ID_DANUBE1: - case SOC_ID_DANUBE2: - i->name = SOC_DANUBE; - i->type = SOC_TYPE_DANUBE; - break; - - case SOC_ID_TWINPASS: - i->name = SOC_TWINPASS; - i->type = SOC_TYPE_DANUBE; - break; - - case SOC_ID_ARX188: - case SOC_ID_ARX168: - case SOC_ID_ARX182: - i->name = SOC_AR9; - i->type = SOC_TYPE_AR9; - break; - - default: - unreachable(); - break; - } -} diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c new file mode 100644 index 0000000..248429a --- /dev/null +++ b/arch/mips/lantiq/xway/prom.c @@ -0,0 +1,115 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2010 John Crispin <blogic@openwrt.org> + */ + +#include <linux/export.h> +#include <linux/clk.h> +#include <asm/bootinfo.h> +#include <asm/time.h> + +#include <lantiq_soc.h> + +#include "../prom.h" + +#define SOC_DANUBE "Danube" +#define SOC_TWINPASS "Twinpass" +#define SOC_AMAZON_SE "Amazon_SE" +#define SOC_AR9 "AR9" +#define SOC_GR9 "GR9" +#define SOC_VR9 "VR9" + +#define COMP_DANUBE "lantiq,danube" +#define COMP_TWINPASS "lantiq,twinpass" +#define COMP_AMAZON_SE "lantiq,ase" +#define COMP_AR9 "lantiq,ar9" +#define COMP_GR9 "lantiq,gr9" +#define COMP_VR9 "lantiq,vr9" + +#define PART_SHIFT 12 +#define PART_MASK 0x0FFFFFFF +#define REV_SHIFT 28 +#define REV_MASK 0xF0000000 + +void __init ltq_soc_detect(struct ltq_soc_info *i) +{ + i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT; + i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT; + sprintf(i->rev_type, "1.%d", i->rev); + switch (i->partnum) { + case SOC_ID_DANUBE1: + case SOC_ID_DANUBE2: + i->name = SOC_DANUBE; + i->type = SOC_TYPE_DANUBE; + i->compatible = COMP_DANUBE; + break; + + case SOC_ID_TWINPASS: + i->name = SOC_TWINPASS; + i->type = SOC_TYPE_DANUBE; + i->compatible = COMP_TWINPASS; + break; + + case SOC_ID_ARX188: + case SOC_ID_ARX168_1: + case SOC_ID_ARX168_2: + case SOC_ID_ARX182: + i->name = SOC_AR9; + i->type = SOC_TYPE_AR9; + i->compatible = COMP_AR9; + break; + + case SOC_ID_GRX188: + case SOC_ID_GRX168: + i->name = SOC_GR9; + i->type = SOC_TYPE_AR9; + i->compatible = COMP_GR9; + break; + + case SOC_ID_AMAZON_SE_1: + case SOC_ID_AMAZON_SE_2: +#ifdef CONFIG_PCI + panic("ase is only supported for non pci kernels"); +#endif + i->name = SOC_AMAZON_SE; + i->type = SOC_TYPE_AMAZON_SE; + i->compatible = COMP_AMAZON_SE; + break; + + case SOC_ID_VRX282: + case SOC_ID_VRX268: + case SOC_ID_VRX288: + i->name = SOC_VR9; + i->type = SOC_TYPE_VR9; + i->compatible = COMP_VR9; + break; + + case SOC_ID_GRX268: + case SOC_ID_GRX288: + i->name = SOC_GR9; + i->type = SOC_TYPE_VR9; + i->compatible = COMP_GR9; + break; + + case SOC_ID_VRX268_2: + case SOC_ID_VRX288_2: + i->name = SOC_VR9; + i->type = SOC_TYPE_VR9_2; + i->compatible = COMP_VR9; + break; + + case SOC_ID_GRX282_2: + case SOC_ID_GRX288_2: + i->name = SOC_GR9; + i->type = SOC_TYPE_VR9_2; + i->compatible = COMP_GR9; + break; + + default: + unreachable(); + break; + } +} diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 8b66bd8..22c55f7 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c @@ -11,26 +11,31 @@ #include <linux/ioport.h> #include <linux/pm.h> #include <linux/export.h> +#include <linux/delay.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> + #include <asm/reboot.h> #include <lantiq_soc.h> +#include "../prom.h" + #define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y)) #define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x)) -/* register definitions */ -#define LTQ_RCU_RST 0x0010 -#define LTQ_RCU_RST_ALL 0x40000000 - -#define LTQ_RCU_RST_STAT 0x0014 -#define LTQ_RCU_STAT_SHIFT 26 +/* reset request register */ +#define RCU_RST_REQ 0x0010 +/* reset status register */ +#define RCU_RST_STAT 0x0014 -static struct resource ltq_rcu_resource = { - .name = "rcu", - .start = LTQ_RCU_BASE_ADDR, - .end = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1, - .flags = IORESOURCE_MEM, -}; +/* reboot bit */ +#define RCU_RD_SRST BIT(30) +/* reset cause */ +#define RCU_STAT_SHIFT 26 +/* boot selection */ +#define RCU_BOOT_SEL_SHIFT 26 +#define RCU_BOOT_SEL_MASK 0x7 /* remapped base addr of the reset control unit */ static void __iomem *ltq_rcu_membase; @@ -38,48 +43,64 @@ static void __iomem *ltq_rcu_membase; /* This function is used by the watchdog driver */ int ltq_reset_cause(void) { - u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT); - return val >> LTQ_RCU_STAT_SHIFT; + u32 val = ltq_rcu_r32(RCU_RST_STAT); + return val >> RCU_STAT_SHIFT; } EXPORT_SYMBOL_GPL(ltq_reset_cause); +/* allow platform code to find out what source we booted from */ +unsigned char ltq_boot_select(void) +{ + u32 val = ltq_rcu_r32(RCU_RST_STAT); + return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK; +} + +/* reset a io domain for u micro seconds */ +void ltq_reset_once(unsigned int module, ulong u) +{ + ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ); + udelay(u); + ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ); +} + static void ltq_machine_restart(char *command) { - pr_notice("System restart\n"); local_irq_disable(); - ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST); + ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ); unreachable(); } static void ltq_machine_halt(void) { - pr_notice("System halted.\n"); local_irq_disable(); unreachable(); } static void ltq_machine_power_off(void) { - pr_notice("Please turn off the power now.\n"); local_irq_disable(); unreachable(); } static int __init mips_reboot_setup(void) { - /* insert and request the memory region */ - if (insert_resource(&iomem_resource, <q_rcu_resource) < 0) - panic("Failed to insert rcu memory"); + struct resource res; + struct device_node *np = + of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway"); + + /* check if all the reset register range is available */ + if (!np) + panic("Failed to load reset resources from devicetree"); + + if (of_address_to_resource(np, 0, &res)) + panic("Failed to get rcu memory range"); - if (request_mem_region(ltq_rcu_resource.start, - resource_size(<q_rcu_resource), "rcu") < 0) - panic("Failed to request rcu memory"); + if (request_mem_region(res.start, resource_size(&res), res.name) < 0) + pr_err("Failed to request rcu memory"); - /* remap rcu register range */ - ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start, - resource_size(<q_rcu_resource)); + ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res)); if (!ltq_rcu_membase) - panic("Failed to remap rcu memory"); + panic("Failed to remap core memory"); _machine_restart = ltq_machine_restart; _machine_halt = ltq_machine_halt; diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c deleted file mode 100644 index f6f3267..0000000 --- a/arch/mips/lantiq/xway/setup-ase.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2011 John Crispin <blogic@openwrt.org> - */ - -#include <lantiq_soc.h> - -#include "../prom.h" -#include "devices.h" - -void __init ltq_soc_setup(void) -{ - ltq_register_ase_asc(); - ltq_register_gpio(); - ltq_register_wdt(); -} diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c deleted file mode 100644 index c292f64..0000000 --- a/arch/mips/lantiq/xway/setup-xway.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2011 John Crispin <blogic@openwrt.org> - */ - -#include <lantiq_soc.h> - -#include "../prom.h" -#include "devices.h" - -void __init ltq_soc_setup(void) -{ - ltq_register_asc(0); - ltq_register_asc(1); - ltq_register_gpio(); - ltq_register_wdt(); -} diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c new file mode 100644 index 0000000..83780f7 --- /dev/null +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -0,0 +1,371 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org> + */ + +#include <linux/ioport.h> +#include <linux/export.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> + +#include <lantiq_soc.h> + +#include "../clk.h" +#include "../prom.h" + +/* clock control register */ +#define CGU_IFCCR 0x0018 +/* system clock register */ +#define CGU_SYS 0x0010 +/* pci control register */ +#define CGU_PCICR 0x0034 +/* ephy configuration register */ +#define CGU_EPHY 0x10 +/* power control register */ +#define PMU_PWDCR 0x1C +/* power status register */ +#define PMU_PWDSR 0x20 +/* power control register */ +#define PMU_PWDCR1 0x24 +/* power status register */ +#define PMU_PWDSR1 0x28 +/* power control register */ +#define PWDCR(x) ((x) ? (PMU_PWDCR1) : (PMU_PWDCR)) +/* power status register */ +#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR)) + +/* clock gates that we can en/disable */ +#define PMU_USB0_P BIT(0) +#define PMU_PCI BIT(4) +#define PMU_DMA BIT(5) +#define PMU_USB0 BIT(6) +#define PMU_ASC0 BIT(7) +#define PMU_EPHY BIT(7) /* ase */ +#define PMU_SPI BIT(8) +#define PMU_DFE BIT(9) +#define PMU_EBU BIT(10) +#define PMU_STP BIT(11) +#define PMU_GPT BIT(12) +#define PMU_AHBS BIT(13) /* vr9 */ +#define PMU_FPI BIT(14) +#define PMU_AHBM BIT(15) +#define PMU_ASC1 BIT(17) +#define PMU_PPE_QSB BIT(18) +#define PMU_PPE_SLL01 BIT(19) +#define PMU_PPE_TC BIT(21) +#define PMU_PPE_EMA BIT(22) +#define PMU_PPE_DPLUM BIT(23) +#define PMU_PPE_DPLUS BIT(24) +#define PMU_USB1_P BIT(26) +#define PMU_USB1 BIT(27) +#define PMU_SWITCH BIT(28) +#define PMU_PPE_TOP BIT(29) +#define PMU_GPHY BIT(30) +#define PMU_PCIE_CLK BIT(31) + +#define PMU1_PCIE_PHY BIT(0) +#define PMU1_PCIE_CTL BIT(1) +#define PMU1_PCIE_PDI BIT(4) +#define PMU1_PCIE_MSI BIT(5) + +#define pmu_w32(x, y) ltq_w32((x), pmu_membase + (y)) +#define pmu_r32(x) ltq_r32(pmu_membase + (x)) + +static void __iomem *pmu_membase; +void __iomem *ltq_cgu_membase; +void __iomem *ltq_ebu_membase; + +/* legacy function kept alive to ease clkdev transition */ +void ltq_pmu_enable(unsigned int module) +{ + int err = 1000000; + + pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR); + do {} while (--err && (pmu_r32(PMU_PWDSR) & module)); + + if (!err) + panic("activating PMU module failed!"); +} +EXPORT_SYMBOL(ltq_pmu_enable); + +/* legacy function kept alive to ease clkdev transition */ +void ltq_pmu_disable(unsigned int module) +{ + pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR); +} +EXPORT_SYMBOL(ltq_pmu_disable); + +/* enable a hw clock */ +static int cgu_enable(struct clk *clk) +{ + ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR); + return 0; +} + +/* disable a hw clock */ +static void cgu_disable(struct clk *clk) +{ + ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR); +} + +/* enable a clock gate */ +static int pmu_enable(struct clk *clk) +{ + int retry = 1000000; + + pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits, + PWDCR(clk->module)); + do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits)); + + if (!retry) + panic("activating PMU module failed!\n"); + + return 0; +} + +/* disable a clock gate */ +static void pmu_disable(struct clk *clk) +{ + pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits, + PWDCR(clk->module)); +} + +/* the pci enable helper */ +static int pci_enable(struct clk *clk) +{ + unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); + /* set bus clock speed */ + if (of_machine_is_compatible("lantiq,ar9")) { + ifccr &= ~0x1f00000; + if (clk->rate == CLOCK_33M) + ifccr |= 0xe00000; + else + ifccr |= 0x700000; /* 62.5M */ + } else { + ifccr &= ~0xf00000; + if (clk->rate == CLOCK_33M) + ifccr |= 0x800000; + else + ifccr |= 0x400000; /* 62.5M */ + } + ltq_cgu_w32(ifccr, CGU_IFCCR); + pmu_enable(clk); + return 0; +} + +/* enable the external clock as a source */ +static int pci_ext_enable(struct clk *clk) +{ + ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16), + CGU_IFCCR); + ltq_cgu_w32((1 << 30), CGU_PCICR); + return 0; +} + +/* disable the external clock as a source */ +static void pci_ext_disable(struct clk *clk) +{ + ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16), + CGU_IFCCR); + ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR); +} + +/* enable a clockout source */ +static int clkout_enable(struct clk *clk) +{ + int i; + + /* get the correct rate */ + for (i = 0; i < 4; i++) { + if (clk->rates[i] == clk->rate) { + int shift = 14 - (2 * clk->module); + unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); + + ifccr &= ~(3 << shift); + ifccr |= i << shift; + ltq_cgu_w32(ifccr, CGU_IFCCR); + return 0; + } + } + return -1; +} + +/* manage the clock gates via PMU */ +static void clkdev_add_pmu(const char *dev, const char *con, + unsigned int module, unsigned int bits) +{ + struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + + clk->cl.dev_id = dev; + clk->cl.con_id = con; + clk->cl.clk = clk; + clk->enable = pmu_enable; + clk->disable = pmu_disable; + clk->module = module; + clk->bits = bits; + clkdev_add(&clk->cl); +} + +/* manage the clock generator */ +static void clkdev_add_cgu(const char *dev, const char *con, + unsigned int bits) +{ + struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + + clk->cl.dev_id = dev; + clk->cl.con_id = con; + clk->cl.clk = clk; + clk->enable = cgu_enable; + clk->disable = cgu_disable; + clk->bits = bits; + clkdev_add(&clk->cl); +} + +/* pci needs its own enable function as the setup is a bit more complex */ +static unsigned long valid_pci_rates[] = {CLOCK_33M, CLOCK_62_5M, 0}; + +static void clkdev_add_pci(void) +{ + struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL); + + /* main pci clock */ + clk->cl.dev_id = "17000000.pci"; + clk->cl.con_id = NULL; + clk->cl.clk = clk; + clk->rate = CLOCK_33M; + clk->rates = valid_pci_rates; + clk->enable = pci_enable; + clk->disable = pmu_disable; + clk->module = 0; + clk->bits = PMU_PCI; + clkdev_add(&clk->cl); + + /* use internal/external bus clock */ + clk_ext->cl.dev_id = "17000000.pci"; + clk_ext->cl.con_id = "external"; + clk_ext->cl.clk = clk_ext; + clk_ext->enable = pci_ext_enable; + clk_ext->disable = pci_ext_disable; + clkdev_add(&clk_ext->cl); +} + +/* xway socs can generate clocks on gpio pins */ +static unsigned long valid_clkout_rates[4][5] = { + {CLOCK_32_768K, CLOCK_1_536M, CLOCK_2_5M, CLOCK_12M, 0}, + {CLOCK_40M, CLOCK_12M, CLOCK_24M, CLOCK_48M, 0}, + {CLOCK_25M, CLOCK_40M, CLOCK_30M, CLOCK_60M, 0}, + {CLOCK_12M, CLOCK_50M, CLOCK_32_768K, CLOCK_25M, 0}, +}; + +static void clkdev_add_clkout(void) +{ + int i; + + for (i = 0; i < 4; i++) { + struct clk *clk; + char *name; + + name = kzalloc(sizeof("clkout0"), GFP_KERNEL); + sprintf(name, "clkout%d", i); + + clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + clk->cl.dev_id = "1f103000.cgu"; + clk->cl.con_id = name; + clk->cl.clk = clk; + clk->rate = 0; + clk->rates = valid_clkout_rates[i]; + clk->enable = clkout_enable; + clk->module = i; + clkdev_add(&clk->cl); + } +} + +/* bring up all register ranges that we need for basic system control */ +void __init ltq_soc_init(void) +{ + struct resource res_pmu, res_cgu, res_ebu; + struct device_node *np_pmu = + of_find_compatible_node(NULL, NULL, "lantiq,pmu-xway"); + struct device_node *np_cgu = + of_find_compatible_node(NULL, NULL, "lantiq,cgu-xway"); + struct device_node *np_ebu = + of_find_compatible_node(NULL, NULL, "lantiq,ebu-xway"); + + /* check if all the core register ranges are available */ + if (!np_pmu || !np_cgu || !np_ebu) + panic("Failed to load core nodess from devicetree"); + + if (of_address_to_resource(np_pmu, 0, &res_pmu) || + of_address_to_resource(np_cgu, 0, &res_cgu) || + of_address_to_resource(np_ebu, 0, &res_ebu)) + panic("Failed to get core resources"); + + if ((request_mem_region(res_pmu.start, resource_size(&res_pmu), + res_pmu.name) < 0) || + (request_mem_region(res_cgu.start, resource_size(&res_cgu), + res_cgu.name) < 0) || + (request_mem_region(res_ebu.start, resource_size(&res_ebu), + res_ebu.name) < 0)) + pr_err("Failed to request core reources"); + + pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu)); + ltq_cgu_membase = ioremap_nocache(res_cgu.start, + resource_size(&res_cgu)); + ltq_ebu_membase = ioremap_nocache(res_ebu.start, + resource_size(&res_ebu)); + if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase) + panic("Failed to remap core resources"); + + /* make sure to unprotect the memory region where flash is located */ + ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0); + + /* add our generic xway clocks */ + clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI); + clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0); + clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT); + clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP); + clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA); + clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI); + clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU); + clkdev_add_clkout(); + + /* add the soc dependent clocks */ + if (!of_machine_is_compatible("lantiq,vr9")) + clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE); + + if (!of_machine_is_compatible("lantiq,ase")) { + clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1); + clkdev_add_pci(); + } + + if (of_machine_is_compatible("lantiq,ase")) { + if (ltq_cgu_r32(CGU_SYS) & (1 << 5)) + clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M); + else + clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M); + clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY), + clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY); + } else if (of_machine_is_compatible("lantiq,vr9")) { + clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), + ltq_vr9_fpi_hz()); + clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY); + clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK); + clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI); + clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI); + clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL); + clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS); + } else if (of_machine_is_compatible("lantiq,ar9")) { + clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), + ltq_ar9_fpi_hz()); + clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH); + } else { + clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), + ltq_danube_fpi_hz()); + } +} diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index 47037ec..44e69e7 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -21,6 +21,7 @@ #include <asm/page.h> #include <asm/pgtable.h> #include <asm/r4kcache.h> +#include <asm/traps.h> #include <asm/mmu_context.h> #include <asm/war.h> @@ -248,6 +249,11 @@ static void __cpuinit probe_octeon(void) } } +static void __cpuinit octeon_cache_error_setup(void) +{ + extern char except_vec2_octeon; + set_handler(0x100, &except_vec2_octeon, 0x80); +} /** * Setup the Octeon cache flush routines @@ -255,12 +261,6 @@ static void __cpuinit probe_octeon(void) */ void __cpuinit octeon_cache_init(void) { - extern unsigned long ebase; - extern char except_vec2_octeon; - - memcpy((void *)(ebase + 0x100), &except_vec2_octeon, 0x80); - octeon_flush_cache_sigtramp(ebase + 0x100); - probe_octeon(); shm_align_mask = PAGE_SIZE - 1; @@ -280,6 +280,8 @@ void __cpuinit octeon_cache_init(void) build_clear_page(); build_copy_page(); + + board_cache_error_setup = octeon_cache_error_setup; } /** diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index bda8eb2..5109be9 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -32,7 +32,7 @@ #include <asm/mmu_context.h> #include <asm/war.h> #include <asm/cacheflush.h> /* for run_uncached() */ - +#include <asm/traps.h> /* * Special Variant of smp_call_function for use by cache functions: @@ -1385,10 +1385,8 @@ static int __init setcoherentio(char *str) __setup("coherentio", setcoherentio); #endif -void __cpuinit r4k_cache_init(void) +static void __cpuinit r4k_cache_error_setup(void) { - extern void build_clear_page(void); - extern void build_copy_page(void); extern char __weak except_vec2_generic; extern char __weak except_vec2_sb1; struct cpuinfo_mips *c = ¤t_cpu_data; @@ -1403,6 +1401,13 @@ void __cpuinit r4k_cache_init(void) set_uncached_handler(0x100, &except_vec2_generic, 0x80); break; } +} + +void __cpuinit r4k_cache_init(void) +{ + extern void build_clear_page(void); + extern void build_copy_page(void); + struct cpuinfo_mips *c = ¤t_cpu_data; probe_pcache(); setup_scache(); @@ -1465,4 +1470,5 @@ void __cpuinit r4k_cache_init(void) local_r4k___flush_cache_all(NULL); #endif coherency_setup(); + board_cache_error_setup = r4k_cache_error_setup; } diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile index 29f2f13..1208c28 100644 --- a/arch/mips/oprofile/Makefile +++ b/arch/mips/oprofile/Makefile @@ -1,5 +1,3 @@ -ccflags-y := -Werror - obj-$(CONFIG_OPROFILE) += oprofile.o DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 54759f1..baba3bc 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -298,6 +298,11 @@ static void reset_counters(void *arg) } } +static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id) +{ + return mipsxx_perfcount_handler(); +} + static int __init mipsxx_init(void) { int counters; @@ -374,6 +379,10 @@ static int __init mipsxx_init(void) save_perf_irq = perf_irq; perf_irq = mipsxx_perfcount_handler; + if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq)) + return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int, + 0, "Perfcounter", save_perf_irq); + return 0; } @@ -381,6 +390,9 @@ static void mipsxx_exit(void) { int counters = op_model_mipsxx_ops.num_counters; + if ((cp0_perfcount_irq >= 0) && (cp0_compare_irq != cp0_perfcount_irq)) + free_irq(cp0_perfcount_irq, save_perf_irq); + counters = counters_per_cpu_to_total(counters); on_each_cpu(reset_counters, (void *)(long)counters, 1); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c3ac4b0..c703f43 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -19,7 +19,8 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ ops-bcm63xx.o obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o -obj-$(CONFIG_SOC_AR724X) += pci-ath724x.o +obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o +obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o # # These are still pretty much in the old state, watch, go blind. @@ -41,7 +42,8 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o -obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o +obj-$(CONFIG_LANTIQ) += fixup-lantiq.o +obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c new file mode 100644 index 0000000..6c829df --- /dev/null +++ b/arch/mips/pci/fixup-lantiq.c @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2012 John Crispin <blogic@openwrt.org> + */ + +#include <linux/of_irq.h> +#include <linux/of_pci.h> + +int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL; +int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL; + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + if (ltq_pci_plat_arch_init) + return ltq_pci_plat_arch_init(dev); + + if (ltq_pci_plat_dev_init) + return ltq_pci_plat_dev_init(dev); + + return 0; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct of_irq dev_irq; + int irq; + + if (of_irq_map_pci(dev, &dev_irq)) { + dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n", + slot, pin); + return 0; + } + irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier, + dev_irq.size); + dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq); + return irq; +} diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c new file mode 100644 index 0000000..1552522 --- /dev/null +++ b/arch/mips/pci/pci-ar71xx.c @@ -0,0 +1,375 @@ +/* + * Atheros AR71xx PCI host controller driver + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/resource.h> +#include <linux/types.h> +#include <linux/delay.h> +#include <linux/bitops.h> +#include <linux/pci.h> +#include <linux/pci_regs.h> +#include <linux/interrupt.h> + +#include <asm/mach-ath79/ar71xx_regs.h> +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/pci.h> + +#define AR71XX_PCI_MEM_BASE 0x10000000 +#define AR71XX_PCI_MEM_SIZE 0x08000000 + +#define AR71XX_PCI_WIN0_OFFS 0x10000000 +#define AR71XX_PCI_WIN1_OFFS 0x11000000 +#define AR71XX_PCI_WIN2_OFFS 0x12000000 +#define AR71XX_PCI_WIN3_OFFS 0x13000000 +#define AR71XX_PCI_WIN4_OFFS 0x14000000 +#define AR71XX_PCI_WIN5_OFFS 0x15000000 +#define AR71XX_PCI_WIN6_OFFS 0x16000000 +#define AR71XX_PCI_WIN7_OFFS 0x07000000 + +#define AR71XX_PCI_CFG_BASE \ + (AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) +#define AR71XX_PCI_CFG_SIZE 0x100 + +#define AR71XX_PCI_REG_CRP_AD_CBE 0x00 +#define AR71XX_PCI_REG_CRP_WRDATA 0x04 +#define AR71XX_PCI_REG_CRP_RDDATA 0x08 +#define AR71XX_PCI_REG_CFG_AD 0x0c +#define AR71XX_PCI_REG_CFG_CBE 0x10 +#define AR71XX_PCI_REG_CFG_WRDATA 0x14 +#define AR71XX_PCI_REG_CFG_RDDATA 0x18 +#define AR71XX_PCI_REG_PCI_ERR 0x1c +#define AR71XX_PCI_REG_PCI_ERR_ADDR 0x20 +#define AR71XX_PCI_REG_AHB_ERR 0x24 +#define AR71XX_PCI_REG_AHB_ERR_ADDR 0x28 + +#define AR71XX_PCI_CRP_CMD_WRITE 0x00010000 +#define AR71XX_PCI_CRP_CMD_READ 0x00000000 +#define AR71XX_PCI_CFG_CMD_READ 0x0000000a +#define AR71XX_PCI_CFG_CMD_WRITE 0x0000000b + +#define AR71XX_PCI_INT_CORE BIT(4) +#define AR71XX_PCI_INT_DEV2 BIT(2) +#define AR71XX_PCI_INT_DEV1 BIT(1) +#define AR71XX_PCI_INT_DEV0 BIT(0) + +#define AR71XX_PCI_IRQ_COUNT 5 + +static DEFINE_SPINLOCK(ar71xx_pci_lock); +static void __iomem *ar71xx_pcicfg_base; + +/* Byte lane enable bits */ +static const u8 ar71xx_pci_ble_table[4][4] = { + {0x0, 0xf, 0xf, 0xf}, + {0xe, 0xd, 0xb, 0x7}, + {0xc, 0xf, 0x3, 0xf}, + {0xf, 0xf, 0xf, 0xf}, +}; + +static const u32 ar71xx_pci_read_mask[8] = { + 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 +}; + +static inline u32 ar71xx_pci_get_ble(int where, int size, int local) +{ + u32 t; + + t = ar71xx_pci_ble_table[size & 3][where & 3]; + BUG_ON(t == 0xf); + t <<= (local) ? 20 : 4; + + return t; +} + +static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn, + int where) +{ + u32 ret; + + if (!bus->number) { + /* type 0 */ + ret = (1 << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) | + (where & ~3); + } else { + /* type 1 */ + ret = (bus->number << 16) | (PCI_SLOT(devfn) << 11) | + (PCI_FUNC(devfn) << 8) | (where & ~3) | 1; + } + + return ret; +} + +static int ar71xx_pci_check_error(int quiet) +{ + void __iomem *base = ar71xx_pcicfg_base; + u32 pci_err; + u32 ahb_err; + + pci_err = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR) & 3; + if (pci_err) { + if (!quiet) { + u32 addr; + + addr = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR_ADDR); + pr_crit("ar71xx: %s bus error %d at addr 0x%x\n", + "PCI", pci_err, addr); + } + + /* clear PCI error status */ + __raw_writel(pci_err, base + AR71XX_PCI_REG_PCI_ERR); + } + + ahb_err = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR) & 1; + if (ahb_err) { + if (!quiet) { + u32 addr; + + addr = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR_ADDR); + pr_crit("ar71xx: %s bus error %d at addr 0x%x\n", + "AHB", ahb_err, addr); + } + + /* clear AHB error status */ + __raw_writel(ahb_err, base + AR71XX_PCI_REG_AHB_ERR); + } + + return !!(ahb_err | pci_err); +} + +static inline void ar71xx_pci_local_write(int where, int size, u32 value) +{ + void __iomem *base = ar71xx_pcicfg_base; + u32 ad_cbe; + + value = value << (8 * (where & 3)); + + ad_cbe = AR71XX_PCI_CRP_CMD_WRITE | (where & ~3); + ad_cbe |= ar71xx_pci_get_ble(where, size, 1); + + __raw_writel(ad_cbe, base + AR71XX_PCI_REG_CRP_AD_CBE); + __raw_writel(value, base + AR71XX_PCI_REG_CRP_WRDATA); +} + +static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus, + unsigned int devfn, + int where, int size, u32 cmd) +{ + void __iomem *base = ar71xx_pcicfg_base; + u32 addr; + + addr = ar71xx_pci_bus_addr(bus, devfn, where); + + __raw_writel(addr, base + AR71XX_PCI_REG_CFG_AD); + __raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0), + base + AR71XX_PCI_REG_CFG_CBE); + + return ar71xx_pci_check_error(1); +} + +static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + void __iomem *base = ar71xx_pcicfg_base; + unsigned long flags; + u32 data; + int err; + int ret; + + ret = PCIBIOS_SUCCESSFUL; + data = ~0; + + spin_lock_irqsave(&ar71xx_pci_lock, flags); + + err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, + AR71XX_PCI_CFG_CMD_READ); + if (err) + ret = PCIBIOS_DEVICE_NOT_FOUND; + else + data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); + + spin_unlock_irqrestore(&ar71xx_pci_lock, flags); + + *value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; + + return ret; +} + +static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + void __iomem *base = ar71xx_pcicfg_base; + unsigned long flags; + int err; + int ret; + + value = value << (8 * (where & 3)); + ret = PCIBIOS_SUCCESSFUL; + + spin_lock_irqsave(&ar71xx_pci_lock, flags); + + err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, + AR71XX_PCI_CFG_CMD_WRITE); + if (err) + ret = PCIBIOS_DEVICE_NOT_FOUND; + else + __raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); + + spin_unlock_irqrestore(&ar71xx_pci_lock, flags); + + return ret; +} + +static struct pci_ops ar71xx_pci_ops = { + .read = ar71xx_pci_read_config, + .write = ar71xx_pci_write_config, +}; + +static struct resource ar71xx_pci_io_resource = { + .name = "PCI IO space", + .start = 0, + .end = 0, + .flags = IORESOURCE_IO, +}; + +static struct resource ar71xx_pci_mem_resource = { + .name = "PCI memory space", + .start = AR71XX_PCI_MEM_BASE, + .end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +static struct pci_controller ar71xx_pci_controller = { + .pci_ops = &ar71xx_pci_ops, + .mem_resource = &ar71xx_pci_mem_resource, + .io_resource = &ar71xx_pci_io_resource, +}; + +static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + void __iomem *base = ath79_reset_base; + u32 pending; + + pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + if (pending & AR71XX_PCI_INT_DEV0) + generic_handle_irq(ATH79_PCI_IRQ(0)); + + else if (pending & AR71XX_PCI_INT_DEV1) + generic_handle_irq(ATH79_PCI_IRQ(1)); + + else if (pending & AR71XX_PCI_INT_DEV2) + generic_handle_irq(ATH79_PCI_IRQ(2)); + + else if (pending & AR71XX_PCI_INT_CORE) + generic_handle_irq(ATH79_PCI_IRQ(4)); + + else + spurious_interrupt(); +} + +static void ar71xx_pci_irq_unmask(struct irq_data *d) +{ + unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; + void __iomem *base = ath79_reset_base; + u32 t; + + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + /* flush write */ + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +} + +static void ar71xx_pci_irq_mask(struct irq_data *d) +{ + unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; + void __iomem *base = ath79_reset_base; + u32 t; + + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + /* flush write */ + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +} + +static struct irq_chip ar71xx_pci_irq_chip = { + .name = "AR71XX PCI", + .irq_mask = ar71xx_pci_irq_mask, + .irq_unmask = ar71xx_pci_irq_unmask, + .irq_mask_ack = ar71xx_pci_irq_mask, +}; + +static __init void ar71xx_pci_irq_init(void) +{ + void __iomem *base = ath79_reset_base; + int i; + + __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); + + BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); + + for (i = ATH79_PCI_IRQ_BASE; + i < ATH79_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) + irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, + handle_level_irq); + + irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar71xx_pci_irq_handler); +} + +static __init void ar71xx_pci_reset(void) +{ + void __iomem *ddr_base = ath79_ddr_base; + + ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); + mdelay(100); + + ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); + mdelay(100); + + __raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0); + __raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1); + __raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2); + __raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3); + __raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4); + __raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5); + __raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6); + __raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7); + + mdelay(100); +} + +__init int ar71xx_pcibios_init(void) +{ + u32 t; + + ar71xx_pcicfg_base = ioremap(AR71XX_PCI_CFG_BASE, AR71XX_PCI_CFG_SIZE); + if (ar71xx_pcicfg_base == NULL) + return -ENOMEM; + + ar71xx_pci_reset(); + + /* setup COMMAND register */ + t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; + ar71xx_pci_local_write(PCI_COMMAND, 4, t); + + /* clear bus errors */ + ar71xx_pci_check_error(1); + + ar71xx_pci_irq_init(); + + register_pci_controller(&ar71xx_pci_controller); + + return 0; +} diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c new file mode 100644 index 0000000..414a745 --- /dev/null +++ b/arch/mips/pci/pci-ar724x.c @@ -0,0 +1,292 @@ +/* + * Atheros AR724X PCI host controller driver + * + * Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com> + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/irq.h> +#include <linux/pci.h> +#include <asm/mach-ath79/ath79.h> +#include <asm/mach-ath79/ar71xx_regs.h> +#include <asm/mach-ath79/pci.h> + +#define AR724X_PCI_CFG_BASE 0x14000000 +#define AR724X_PCI_CFG_SIZE 0x1000 +#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) +#define AR724X_PCI_CTRL_SIZE 0x100 + +#define AR724X_PCI_MEM_BASE 0x10000000 +#define AR724X_PCI_MEM_SIZE 0x08000000 + +#define AR724X_PCI_REG_INT_STATUS 0x4c +#define AR724X_PCI_REG_INT_MASK 0x50 + +#define AR724X_PCI_INT_DEV0 BIT(14) + +#define AR724X_PCI_IRQ_COUNT 1 + +#define AR7240_BAR0_WAR_VALUE 0xffff + +static DEFINE_SPINLOCK(ar724x_pci_lock); +static void __iomem *ar724x_pci_devcfg_base; +static void __iomem *ar724x_pci_ctrl_base; + +static u32 ar724x_pci_bar0_value; +static bool ar724x_pci_bar0_is_cached; + +static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t *value) +{ + unsigned long flags; + void __iomem *base; + u32 data; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + + base = ar724x_pci_devcfg_base; + + spin_lock_irqsave(&ar724x_pci_lock, flags); + data = __raw_readl(base + (where & ~3)); + + switch (size) { + case 1: + if (where & 1) + data >>= 8; + if (where & 2) + data >>= 16; + data &= 0xff; + break; + case 2: + if (where & 2) + data >>= 16; + data &= 0xffff; + break; + case 4: + break; + default: + spin_unlock_irqrestore(&ar724x_pci_lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&ar724x_pci_lock, flags); + + if (where == PCI_BASE_ADDRESS_0 && size == 4 && + ar724x_pci_bar0_is_cached) { + /* use the cached value */ + *value = ar724x_pci_bar0_value; + } else { + *value = data; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t value) +{ + unsigned long flags; + void __iomem *base; + u32 data; + int s; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) { + if (value != 0xffffffff) { + /* + * WAR for a hw issue. If the BAR0 register of the + * device is set to the proper base address, the + * memory space of the device is not accessible. + * + * Cache the intended value so it can be read back, + * and write a SoC specific constant value to the + * BAR0 register in order to make the device memory + * accessible. + */ + ar724x_pci_bar0_is_cached = true; + ar724x_pci_bar0_value = value; + + value = AR7240_BAR0_WAR_VALUE; + } else { + ar724x_pci_bar0_is_cached = false; + } + } + + base = ar724x_pci_devcfg_base; + + spin_lock_irqsave(&ar724x_pci_lock, flags); + data = __raw_readl(base + (where & ~3)); + + switch (size) { + case 1: + s = ((where & 3) * 8); + data &= ~(0xff << s); + data |= ((value & 0xff) << s); + break; + case 2: + s = ((where & 2) * 8); + data &= ~(0xffff << s); + data |= ((value & 0xffff) << s); + break; + case 4: + data = value; + break; + default: + spin_unlock_irqrestore(&ar724x_pci_lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + __raw_writel(data, base + (where & ~3)); + /* flush write */ + __raw_readl(base + (where & ~3)); + spin_unlock_irqrestore(&ar724x_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops ar724x_pci_ops = { + .read = ar724x_pci_read, + .write = ar724x_pci_write, +}; + +static struct resource ar724x_io_resource = { + .name = "PCI IO space", + .start = 0, + .end = 0, + .flags = IORESOURCE_IO, +}; + +static struct resource ar724x_mem_resource = { + .name = "PCI memory space", + .start = AR724X_PCI_MEM_BASE, + .end = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller ar724x_pci_controller = { + .pci_ops = &ar724x_pci_ops, + .io_resource = &ar724x_io_resource, + .mem_resource = &ar724x_mem_resource, +}; + +static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + void __iomem *base; + u32 pending; + + base = ar724x_pci_ctrl_base; + + pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & + __raw_readl(base + AR724X_PCI_REG_INT_MASK); + + if (pending & AR724X_PCI_INT_DEV0) + generic_handle_irq(ATH79_PCI_IRQ(0)); + + else + spurious_interrupt(); +} + +static void ar724x_pci_irq_unmask(struct irq_data *d) +{ + void __iomem *base; + u32 t; + + base = ar724x_pci_ctrl_base; + + switch (d->irq) { + case ATH79_PCI_IRQ(0): + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); + __raw_writel(t | AR724X_PCI_INT_DEV0, + base + AR724X_PCI_REG_INT_MASK); + /* flush write */ + __raw_readl(base + AR724X_PCI_REG_INT_MASK); + } +} + +static void ar724x_pci_irq_mask(struct irq_data *d) +{ + void __iomem *base; + u32 t; + + base = ar724x_pci_ctrl_base; + + switch (d->irq) { + case ATH79_PCI_IRQ(0): + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); + __raw_writel(t & ~AR724X_PCI_INT_DEV0, + base + AR724X_PCI_REG_INT_MASK); + + /* flush write */ + __raw_readl(base + AR724X_PCI_REG_INT_MASK); + + t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS); + __raw_writel(t | AR724X_PCI_INT_DEV0, + base + AR724X_PCI_REG_INT_STATUS); + + /* flush write */ + __raw_readl(base + AR724X_PCI_REG_INT_STATUS); + } +} + +static struct irq_chip ar724x_pci_irq_chip = { + .name = "AR724X PCI ", + .irq_mask = ar724x_pci_irq_mask, + .irq_unmask = ar724x_pci_irq_unmask, + .irq_mask_ack = ar724x_pci_irq_mask, +}; + +static void __init ar724x_pci_irq_init(int irq) +{ + void __iomem *base; + int i; + + base = ar724x_pci_ctrl_base; + + __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); + __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); + + BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT); + + for (i = ATH79_PCI_IRQ_BASE; + i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++) + irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, + handle_level_irq); + + irq_set_chained_handler(irq, ar724x_pci_irq_handler); +} + +int __init ar724x_pcibios_init(int irq) +{ + int ret; + + ret = -ENOMEM; + + ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE, + AR724X_PCI_CFG_SIZE); + if (ar724x_pci_devcfg_base == NULL) + goto err; + + ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE, + AR724X_PCI_CTRL_SIZE); + if (ar724x_pci_ctrl_base == NULL) + goto err_unmap_devcfg; + + ar724x_pci_irq_init(irq); + register_pci_controller(&ar724x_pci_controller); + + return PCIBIOS_SUCCESSFUL; + +err_unmap_devcfg: + iounmap(ar724x_pci_devcfg_base); +err: + return ret; +} diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c deleted file mode 100644 index a4dd24a..0000000 --- a/arch/mips/pci/pci-ath724x.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Atheros 724x PCI support - * - * Copyright (C) 2011 RenĂ© Bolldorf <xsecute@googlemail.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include <linux/pci.h> -#include <asm/mach-ath79/pci-ath724x.h> - -#define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) -#define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) - -#define ATH724X_PCI_DEV_BASE 0x14000000 -#define ATH724X_PCI_MEM_BASE 0x10000000 -#define ATH724X_PCI_MEM_SIZE 0x08000000 - -static DEFINE_SPINLOCK(ath724x_pci_lock); -static struct ath724x_pci_data *pci_data; -static int pci_data_size; - -static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, uint32_t *value) -{ - unsigned long flags, addr, tval, mask; - - if (devfn) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - spin_lock_irqsave(&ath724x_pci_lock, flags); - - switch (size) { - case 1: - addr = where & ~3; - mask = 0xff000000 >> ((where % 4) * 8); - tval = reg_read(ATH724X_PCI_DEV_BASE + addr); - tval = tval & ~mask; - *value = (tval >> ((4 - (where % 4))*8)); - break; - case 2: - addr = where & ~3; - mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(ATH724X_PCI_DEV_BASE + addr); - tval = tval & ~mask; - *value = (tval >> ((4 - (where % 4))*8)); - break; - case 4: - *value = reg_read(ATH724X_PCI_DEV_BASE + where); - break; - default: - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_SUCCESSFUL; -} - -static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, uint32_t value) -{ - unsigned long flags, tval, addr, mask; - - if (devfn) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - spin_lock_irqsave(&ath724x_pci_lock, flags); - - switch (size) { - case 1: - addr = (ATH724X_PCI_DEV_BASE + where) & ~3; - mask = 0xff000000 >> ((where % 4)*8); - tval = reg_read(addr); - tval = tval & ~mask; - tval |= (value << ((4 - (where % 4))*8)) & mask; - reg_write(addr, tval); - break; - case 2: - addr = (ATH724X_PCI_DEV_BASE + where) & ~3; - mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(addr); - tval = tval & ~mask; - tval |= (value << ((4 - (where % 4))*8)) & mask; - reg_write(addr, tval); - break; - case 4: - reg_write((ATH724X_PCI_DEV_BASE + where), value); - break; - default: - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops ath724x_pci_ops = { - .read = ath724x_pci_read, - .write = ath724x_pci_write, -}; - -static struct resource ath724x_io_resource = { - .name = "PCI IO space", - .start = 0, - .end = 0, - .flags = IORESOURCE_IO, -}; - -static struct resource ath724x_mem_resource = { - .name = "PCI memory space", - .start = ATH724X_PCI_MEM_BASE, - .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct pci_controller ath724x_pci_controller = { - .pci_ops = &ath724x_pci_ops, - .io_resource = &ath724x_io_resource, - .mem_resource = &ath724x_mem_resource, -}; - -void ath724x_pci_add_data(struct ath724x_pci_data *data, int size) -{ - pci_data = data; - pci_data_size = size; -} - -int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) -{ - unsigned int devfn = dev->devfn; - int irq = -1; - - if (devfn > pci_data_size - 1) - return irq; - - irq = pci_data[devfn].irq; - - return irq; -} - -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - unsigned int devfn = dev->devfn; - - if (devfn > pci_data_size - 1) - return PCIBIOS_DEVICE_NOT_FOUND; - - dev->dev.platform_data = pci_data[devfn].pdata; - - return PCIBIOS_SUCCESSFUL; -} - -static int __init ath724x_pcibios_init(void) -{ - register_pci_controller(&ath724x_pci_controller); - - return PCIBIOS_SUCCESSFUL; -} - -arch_initcall(ath724x_pcibios_init); diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 030c77e..ea45353 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -13,8 +13,12 @@ #include <linux/delay.h> #include <linux/mm.h> #include <linux/vmalloc.h> -#include <linux/export.h> -#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> +#include <linux/of_irq.h> +#include <linux/of_pci.h> #include <asm/pci.h> #include <asm/gpio.h> @@ -22,17 +26,9 @@ #include <lantiq_soc.h> #include <lantiq_irq.h> -#include <lantiq_platform.h> #include "pci-lantiq.h" -#define LTQ_PCI_CFG_BASE 0x17000000 -#define LTQ_PCI_CFG_SIZE 0x00008000 -#define LTQ_PCI_MEM_BASE 0x18000000 -#define LTQ_PCI_MEM_SIZE 0x02000000 -#define LTQ_PCI_IO_BASE 0x1AE00000 -#define LTQ_PCI_IO_SIZE 0x00200000 - #define PCI_CR_FCI_ADDR_MAP0 0x00C0 #define PCI_CR_FCI_ADDR_MAP1 0x00C4 #define PCI_CR_FCI_ADDR_MAP2 0x00C8 @@ -68,79 +64,27 @@ #define ltq_pci_cfg_w32(x, y) ltq_w32((x), ltq_pci_mapped_cfg + (y)) #define ltq_pci_cfg_r32(x) ltq_r32(ltq_pci_mapped_cfg + (x)) -struct ltq_pci_gpio_map { - int pin; - int alt0; - int alt1; - int dir; - char *name; -}; - -/* the pci core can make use of the following gpios */ -static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = { - { 0, 1, 0, 0, "pci-exin0" }, - { 1, 1, 0, 0, "pci-exin1" }, - { 2, 1, 0, 0, "pci-exin2" }, - { 39, 1, 0, 0, "pci-exin3" }, - { 10, 1, 0, 0, "pci-exin4" }, - { 9, 1, 0, 0, "pci-exin5" }, - { 30, 1, 0, 1, "pci-gnt1" }, - { 23, 1, 0, 1, "pci-gnt2" }, - { 19, 1, 0, 1, "pci-gnt3" }, - { 38, 1, 0, 1, "pci-gnt4" }, - { 29, 1, 0, 0, "pci-req1" }, - { 31, 1, 0, 0, "pci-req2" }, - { 3, 1, 0, 0, "pci-req3" }, - { 37, 1, 0, 0, "pci-req4" }, -}; - __iomem void *ltq_pci_mapped_cfg; static __iomem void *ltq_pci_membase; -int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL; - -/* Since the PCI REQ pins can be reused for other functionality, make it - possible to exclude those from interpretation by the PCI controller */ -static int ltq_pci_req_mask = 0xf; - -static int *ltq_pci_irq_map; - -struct pci_ops ltq_pci_ops = { +static int reset_gpio; +static struct clk *clk_pci, *clk_external; +static struct resource pci_io_resource; +static struct resource pci_mem_resource; +static struct pci_ops pci_ops = { .read = ltq_pci_read_config_dword, .write = ltq_pci_write_config_dword }; -static struct resource pci_io_resource = { - .name = "pci io space", - .start = LTQ_PCI_IO_BASE, - .end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1, - .flags = IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - .name = "pci memory space", - .start = LTQ_PCI_MEM_BASE, - .end = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM -}; - -static struct pci_controller ltq_pci_controller = { - .pci_ops = <q_pci_ops, +static struct pci_controller pci_controller = { + .pci_ops = &pci_ops, .mem_resource = &pci_mem_resource, .mem_offset = 0x00000000UL, .io_resource = &pci_io_resource, .io_offset = 0x00000000UL, }; -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - if (ltqpci_plat_dev_init) - return ltqpci_plat_dev_init(dev); - - return 0; -} - -static u32 ltq_calc_bar11mask(void) +static inline u32 ltq_calc_bar11mask(void) { u32 mem, bar11mask; @@ -151,48 +95,42 @@ static u32 ltq_calc_bar11mask(void) return bar11mask; } -static void ltq_pci_setup_gpio(int gpio) -{ - int i; - for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) { - if (gpio & (1 << i)) { - ltq_gpio_request(ltq_pci_gpio_map[i].pin, - ltq_pci_gpio_map[i].alt0, - ltq_pci_gpio_map[i].alt1, - ltq_pci_gpio_map[i].dir, - ltq_pci_gpio_map[i].name); - } - } - ltq_gpio_request(21, 0, 0, 1, "pci-reset"); - ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK; -} - -static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) +static int __devinit ltq_pci_startup(struct platform_device *pdev) { + struct device_node *node = pdev->dev.of_node; + const __be32 *req_mask, *bus_clk; u32 temp_buffer; - /* set clock to 33Mhz */ - if (ltq_is_ar9()) { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR); - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR); - } else { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR); - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR); + /* get our clocks */ + clk_pci = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk_pci)) { + dev_err(&pdev->dev, "failed to get pci clock\n"); + return PTR_ERR(clk_pci); } - /* external or internal clock ? */ - if (conf->clock) { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16), - LTQ_CGU_IFCCR); - ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR); - } else { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16), - LTQ_CGU_IFCCR); - ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR); + clk_external = clk_get(&pdev->dev, "external"); + if (IS_ERR(clk_external)) { + clk_put(clk_pci); + dev_err(&pdev->dev, "failed to get external pci clock\n"); + return PTR_ERR(clk_external); } - /* setup pci clock and gpis used by pci */ - ltq_pci_setup_gpio(conf->gpio); + /* read the bus speed that we want */ + bus_clk = of_get_property(node, "lantiq,bus-clock", NULL); + if (bus_clk) + clk_set_rate(clk_pci, *bus_clk); + + /* and enable the clocks */ + clk_enable(clk_pci); + if (of_find_property(node, "lantiq,external-clock", NULL)) + clk_enable(clk_external); + else + clk_disable(clk_external); + + /* setup reset gpio used by pci */ + reset_gpio = of_get_named_gpio(node, "gpio-reset", 0); + if (reset_gpio > 0) + devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset"); /* enable auto-switching between PCI and EBU */ ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); @@ -205,7 +143,12 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) /* enable external 2 PCI masters */ temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB); - temp_buffer &= (~(ltq_pci_req_mask << 16)); + /* setup the request mask */ + req_mask = of_get_property(node, "req-mask", NULL); + if (req_mask) + temp_buffer &= ~((*req_mask & 0xf) << 16); + else + temp_buffer &= ~0xf0000; /* enable internal arbiter */ temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT); /* enable internal PCI master reqest */ @@ -249,47 +192,55 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN); /* toggle reset pin */ - __gpio_set_value(21, 0); - wmb(); - mdelay(1); - __gpio_set_value(21, 1); - return 0; -} - -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - if (ltq_pci_irq_map[slot]) - return ltq_pci_irq_map[slot]; - printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n", - slot); - + if (reset_gpio > 0) { + __gpio_set_value(reset_gpio, 0); + wmb(); + mdelay(1); + __gpio_set_value(reset_gpio, 1); + } return 0; } static int __devinit ltq_pci_probe(struct platform_device *pdev) { - struct ltq_pci_data *ltq_pci_data = - (struct ltq_pci_data *) pdev->dev.platform_data; + struct resource *res_cfg, *res_bridge; pci_clear_flags(PCI_PROBE_ONLY); - ltq_pci_irq_map = ltq_pci_data->irq; - ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE); - ltq_pci_mapped_cfg = - ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE); - ltq_pci_controller.io_map_base = - (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1); - ltq_pci_startup(ltq_pci_data); - register_pci_controller(<q_pci_controller); + res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res_bridge = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res_cfg || !res_bridge) { + dev_err(&pdev->dev, "missing memory reources\n"); + return -EINVAL; + } + + ltq_pci_membase = devm_request_and_ioremap(&pdev->dev, res_bridge); + ltq_pci_mapped_cfg = devm_request_and_ioremap(&pdev->dev, res_cfg); + + if (!ltq_pci_membase || !ltq_pci_mapped_cfg) { + dev_err(&pdev->dev, "failed to remap resources\n"); + return -ENOMEM; + } + + ltq_pci_startup(pdev); + + pci_load_of_ranges(&pci_controller, pdev->dev.of_node); + register_pci_controller(&pci_controller); return 0; } -static struct platform_driver -ltq_pci_driver = { +static const struct of_device_id ltq_pci_match[] = { + { .compatible = "lantiq,pci-xway" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_pci_match); + +static struct platform_driver ltq_pci_driver = { .probe = ltq_pci_probe, .driver = { - .name = "ltq_pci", + .name = "pci-xway", .owner = THIS_MODULE, + .of_match_table = ltq_pci_match, }, }; @@ -297,7 +248,7 @@ int __init pcibios_init(void) { int ret = platform_driver_register(<q_pci_driver); if (ret) - printk(KERN_INFO "ltq_pci: Error registering platfom driver!"); + pr_info("pci-xway: Error registering platform driver!"); return ret; } diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 0514866..271e8c4a 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/pci.h> +#include <linux/of_address.h> #include <asm/cpu-info.h> @@ -114,9 +115,63 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose) pci_bus_assign_resources(bus); pci_enable_bridges(bus); } + bus->dev.of_node = hose->of_node; } } +#ifdef CONFIG_OF +void __devinit pci_load_of_ranges(struct pci_controller *hose, + struct device_node *node) +{ + const __be32 *ranges; + int rlen; + int pna = of_n_addr_cells(node); + int np = pna + 5; + + pr_info("PCI host bridge %s ranges:\n", node->full_name); + ranges = of_get_property(node, "ranges", &rlen); + if (ranges == NULL) + return; + hose->of_node = node; + + while ((rlen -= np * 4) >= 0) { + u32 pci_space; + struct resource *res = NULL; + u64 addr, size; + + pci_space = be32_to_cpup(&ranges[0]); + addr = of_translate_address(node, ranges + 3); + size = of_read_number(ranges + pna + 3, 2); + ranges += np; + switch ((pci_space >> 24) & 0x3) { + case 1: /* PCI IO space */ + pr_info(" IO 0x%016llx..0x%016llx\n", + addr, addr + size - 1); + hose->io_map_base = + (unsigned long)ioremap(addr, size); + res = hose->io_resource; + res->flags = IORESOURCE_IO; + break; + case 2: /* PCI Memory space */ + case 3: /* PCI 64 bits Memory space */ + pr_info(" MEM 0x%016llx..0x%016llx\n", + addr, addr + size - 1); + res = hose->mem_resource; + res->flags = IORESOURCE_MEM; + break; + } + if (res != NULL) { + res->start = addr; + res->name = node->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + } +} +#endif + static DEFINE_MUTEX(pci_scan_mutex); void __devinit register_pci_controller(struct pci_controller *hose) diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile index 02f5fb9..5af95ec 100644 --- a/arch/mips/pmc-sierra/yosemite/Makefile +++ b/arch/mips/pmc-sierra/yosemite/Makefile @@ -5,5 +5,3 @@ obj-y += irq.o prom.o py-console.o setup.o obj-$(CONFIG_SMP) += smp.o - -ccflags-y := -Werror diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 3498ac9..b6472fc 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -27,6 +27,7 @@ #include <linux/bcd.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/export.h> #include <linux/types.h> #include <linux/mm.h> #include <linux/bootmem.h> diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile index 348d2e8..39ca9f8 100644 --- a/arch/mips/powertv/Makefile +++ b/arch/mips/powertv/Makefile @@ -27,5 +27,3 @@ obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \ asic/ pci/ obj-$(CONFIG_USB) += powertv-usb.o - -ccflags-y := -Wall diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile index d810a33..35dcc53 100644 --- a/arch/mips/powertv/asic/Makefile +++ b/arch/mips/powertv/asic/Makefile @@ -19,5 +19,3 @@ obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \ asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \ prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o - -ccflags-y := -Wall -Werror diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile index 5783201..2610a6a 100644 --- a/arch/mips/powertv/pci/Makefile +++ b/arch/mips/powertv/pci/Makefile @@ -17,5 +17,3 @@ # obj-$(CONFIG_PCI) += fixup-powertv.o - -ccflags-y := -Wall -Werror diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index a969eb82..ea77428 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ #include <linux/kernel.h> +#include <linux/export.h> #include <linux/init.h> #include <linux/ctype.h> #include <linux/string.h> diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index d16b462..413f17f 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -10,6 +10,7 @@ */ #include <linux/eisa.h> #include <linux/init.h> +#include <linux/export.h> #include <linux/console.h> #include <linux/fb.h> #include <linux/screen_info.h> |