diff options
123 files changed, 4470 insertions, 3686 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mm-lantiq.txt b/Documentation/devicetree/bindings/gpio/gpio-mm-lantiq.txt new file mode 100644 index 0000000..f93d514 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-mm-lantiq.txt @@ -0,0 +1,38 @@ +Lantiq SoC External Bus memory mapped GPIO controller + +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. + +The node describing the memory mapped GPIOs needs to be a child of the node +describing the "lantiq,localbus". + +Required properties: +- compatible : Should be "lantiq,gpio-mm-lantiq" +- reg : Address and length of the register set for the device +- #gpio-cells : Should be two. The first cell is the pin number and + the second cell is used to specify optional parameters (currently + unused). +- gpio-controller : Marks the device node as a gpio controller. + +Optional properties: +- lantiq,shadow : The default value that we shall assume as already set on the + shift register cascade. + +Example: + +localbus@0 { + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x0 0x3ffffff /* addrsel0 */ + 1 0 0x4000000 0x4000010>; /* addsel1 */ + compatible = "lantiq,localbus", "simple-bus"; + + gpio_mm0: gpio@4000000 { + compatible = "lantiq,gpio-mm"; + reg = <1 0x0 0x10>; + gpio-controller; + #gpio-cells = <2>; + lantiq,shadow = <0x77f> + }; +} diff --git a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt new file mode 100644 index 0000000..854de13 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt @@ -0,0 +1,42 @@ +Lantiq SoC Serial To Parallel (STP) GPIO controller + +The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a +peripheral controller used to drive external shift register cascades. At most +3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem +to drive the 2 LSBs of the cascade automatically. + + +Required properties: +- compatible : Should be "lantiq,gpio-stp-xway" +- reg : Address and length of the register set for the device +- #gpio-cells : Should be two. The first cell is the pin number and + the second cell is used to specify optional parameters (currently + unused). +- gpio-controller : Marks the device node as a gpio controller. + +Optional properties: +- lantiq,shadow : The default value that we shall assume as already set on the + shift register cascade. +- lantiq,groups : Set the 3 bit mask to select which of the 3 groups are enabled + in the shift register cascade. +- lantiq,dsl : The dsl core can control the 2 LSBs of the gpio cascade. This 2 bit + property can enable this feature. +- lantiq,phy1 : The gphy1 core can control 3 bits of the gpio cascade. +- lantiq,phy2 : The gphy2 core can control 3 bits of the gpio cascade. +- lantiq,rising : use rising instead of falling edge for the shift register + +Example: + +gpio1: stp@E100BB0 { + compatible = "lantiq,gpio-stp-xway"; + reg = <0xE100BB0 0x40>; + #gpio-cells = <2>; + gpio-controller; + + lantiq,shadow = <0xffff>; + lantiq,groups = <0x7>; + lantiq,dsl = <0x3>; + lantiq,phy1 = <0x7>; + lantiq,phy2 = <0x7>; + /* lantiq,rising; */ +}; diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ce30e2f..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" @@ -1786,10 +1787,12 @@ endchoice config FORCE_MAX_ZONEORDER int "Maximum zone order" - range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB - default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB - range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB - default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB + range 14 64 if HUGETLB_PAGE && PAGE_SIZE_64KB + default "14" if HUGETLB_PAGE && PAGE_SIZE_64KB + range 13 64 if HUGETLB_PAGE && PAGE_SIZE_32KB + default "13" if HUGETLB_PAGE && PAGE_SIZE_32KB + range 12 64 if HUGETLB_PAGE && PAGE_SIZE_16KB + default "12" if HUGETLB_PAGE && PAGE_SIZE_16KB range 11 64 default "11" help 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/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/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-bcm63xx/bcm63xx_gpio.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h index 3d5de96d..1d7dd96 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h @@ -2,6 +2,7 @@ #define BCM63XX_GPIO_H #include <linux/init.h> +#include <bcm63xx_cpu.h> int __init bcm63xx_gpio_init(void); 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/octeon/cvmx-pcieep-defs.h b/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h deleted file mode 100644 index d553f8e..0000000 --- a/arch/mips/include/asm/octeon/cvmx-pcieep-defs.h +++ /dev/null @@ -1,1365 +0,0 @@ -/***********************license start*************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK - * - * Copyright (c) 2003-2008 Cavium Networks - * - * This file 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. - * - * This file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information - ***********************license end**************************************/ - -#ifndef __CVMX_PCIEEP_DEFS_H__ -#define __CVMX_PCIEEP_DEFS_H__ - -#define CVMX_PCIEEP_CFG000 \ - (0x0000000000000000ull) -#define CVMX_PCIEEP_CFG001 \ - (0x0000000000000004ull) -#define CVMX_PCIEEP_CFG002 \ - (0x0000000000000008ull) -#define CVMX_PCIEEP_CFG003 \ - (0x000000000000000Cull) -#define CVMX_PCIEEP_CFG004 \ - (0x0000000000000010ull) -#define CVMX_PCIEEP_CFG004_MASK \ - (0x0000000080000010ull) -#define CVMX_PCIEEP_CFG005 \ - (0x0000000000000014ull) -#define CVMX_PCIEEP_CFG005_MASK \ - (0x0000000080000014ull) -#define CVMX_PCIEEP_CFG006 \ - (0x0000000000000018ull) -#define CVMX_PCIEEP_CFG006_MASK \ - (0x0000000080000018ull) -#define CVMX_PCIEEP_CFG007 \ - (0x000000000000001Cull) -#define CVMX_PCIEEP_CFG007_MASK \ - (0x000000008000001Cull) -#define CVMX_PCIEEP_CFG008 \ - (0x0000000000000020ull) -#define CVMX_PCIEEP_CFG008_MASK \ - (0x0000000080000020ull) -#define CVMX_PCIEEP_CFG009 \ - (0x0000000000000024ull) -#define CVMX_PCIEEP_CFG009_MASK \ - (0x0000000080000024ull) -#define CVMX_PCIEEP_CFG010 \ - (0x0000000000000028ull) -#define CVMX_PCIEEP_CFG011 \ - (0x000000000000002Cull) -#define CVMX_PCIEEP_CFG012 \ - (0x0000000000000030ull) -#define CVMX_PCIEEP_CFG012_MASK \ - (0x0000000080000030ull) -#define CVMX_PCIEEP_CFG013 \ - (0x0000000000000034ull) -#define CVMX_PCIEEP_CFG015 \ - (0x000000000000003Cull) -#define CVMX_PCIEEP_CFG016 \ - (0x0000000000000040ull) -#define CVMX_PCIEEP_CFG017 \ - (0x0000000000000044ull) -#define CVMX_PCIEEP_CFG020 \ - (0x0000000000000050ull) -#define CVMX_PCIEEP_CFG021 \ - (0x0000000000000054ull) -#define CVMX_PCIEEP_CFG022 \ - (0x0000000000000058ull) -#define CVMX_PCIEEP_CFG023 \ - (0x000000000000005Cull) -#define CVMX_PCIEEP_CFG028 \ - (0x0000000000000070ull) -#define CVMX_PCIEEP_CFG029 \ - (0x0000000000000074ull) -#define CVMX_PCIEEP_CFG030 \ - (0x0000000000000078ull) -#define CVMX_PCIEEP_CFG031 \ - (0x000000000000007Cull) -#define CVMX_PCIEEP_CFG032 \ - (0x0000000000000080ull) -#define CVMX_PCIEEP_CFG033 \ - (0x0000000000000084ull) -#define CVMX_PCIEEP_CFG034 \ - (0x0000000000000088ull) -#define CVMX_PCIEEP_CFG037 \ - (0x0000000000000094ull) -#define CVMX_PCIEEP_CFG038 \ - (0x0000000000000098ull) -#define CVMX_PCIEEP_CFG039 \ - (0x000000000000009Cull) -#define CVMX_PCIEEP_CFG040 \ - (0x00000000000000A0ull) -#define CVMX_PCIEEP_CFG041 \ - (0x00000000000000A4ull) -#define CVMX_PCIEEP_CFG042 \ - (0x00000000000000A8ull) -#define CVMX_PCIEEP_CFG064 \ - (0x0000000000000100ull) -#define CVMX_PCIEEP_CFG065 \ - (0x0000000000000104ull) -#define CVMX_PCIEEP_CFG066 \ - (0x0000000000000108ull) -#define CVMX_PCIEEP_CFG067 \ - (0x000000000000010Cull) -#define CVMX_PCIEEP_CFG068 \ - (0x0000000000000110ull) -#define CVMX_PCIEEP_CFG069 \ - (0x0000000000000114ull) -#define CVMX_PCIEEP_CFG070 \ - (0x0000000000000118ull) -#define CVMX_PCIEEP_CFG071 \ - (0x000000000000011Cull) -#define CVMX_PCIEEP_CFG072 \ - (0x0000000000000120ull) -#define CVMX_PCIEEP_CFG073 \ - (0x0000000000000124ull) -#define CVMX_PCIEEP_CFG074 \ - (0x0000000000000128ull) -#define CVMX_PCIEEP_CFG448 \ - (0x0000000000000700ull) -#define CVMX_PCIEEP_CFG449 \ - (0x0000000000000704ull) -#define CVMX_PCIEEP_CFG450 \ - (0x0000000000000708ull) -#define CVMX_PCIEEP_CFG451 \ - (0x000000000000070Cull) -#define CVMX_PCIEEP_CFG452 \ - (0x0000000000000710ull) -#define CVMX_PCIEEP_CFG453 \ - (0x0000000000000714ull) -#define CVMX_PCIEEP_CFG454 \ - (0x0000000000000718ull) -#define CVMX_PCIEEP_CFG455 \ - (0x000000000000071Cull) -#define CVMX_PCIEEP_CFG456 \ - (0x0000000000000720ull) -#define CVMX_PCIEEP_CFG458 \ - (0x0000000000000728ull) -#define CVMX_PCIEEP_CFG459 \ - (0x000000000000072Cull) -#define CVMX_PCIEEP_CFG460 \ - (0x0000000000000730ull) -#define CVMX_PCIEEP_CFG461 \ - (0x0000000000000734ull) -#define CVMX_PCIEEP_CFG462 \ - (0x0000000000000738ull) -#define CVMX_PCIEEP_CFG463 \ - (0x000000000000073Cull) -#define CVMX_PCIEEP_CFG464 \ - (0x0000000000000740ull) -#define CVMX_PCIEEP_CFG465 \ - (0x0000000000000744ull) -#define CVMX_PCIEEP_CFG466 \ - (0x0000000000000748ull) -#define CVMX_PCIEEP_CFG467 \ - (0x000000000000074Cull) -#define CVMX_PCIEEP_CFG468 \ - (0x0000000000000750ull) -#define CVMX_PCIEEP_CFG490 \ - (0x00000000000007A8ull) -#define CVMX_PCIEEP_CFG491 \ - (0x00000000000007ACull) -#define CVMX_PCIEEP_CFG492 \ - (0x00000000000007B0ull) -#define CVMX_PCIEEP_CFG516 \ - (0x0000000000000810ull) -#define CVMX_PCIEEP_CFG517 \ - (0x0000000000000814ull) - -union cvmx_pcieep_cfg000 { - uint32_t u32; - struct cvmx_pcieep_cfg000_s { - uint32_t devid:16; - uint32_t vendid:16; - } s; - struct cvmx_pcieep_cfg000_s cn52xx; - struct cvmx_pcieep_cfg000_s cn52xxp1; - struct cvmx_pcieep_cfg000_s cn56xx; - struct cvmx_pcieep_cfg000_s cn56xxp1; -}; - -union cvmx_pcieep_cfg001 { - uint32_t u32; - struct cvmx_pcieep_cfg001_s { - uint32_t dpe:1; - uint32_t sse:1; - uint32_t rma:1; - uint32_t rta:1; - uint32_t sta:1; - uint32_t devt:2; - uint32_t mdpe:1; - uint32_t fbb:1; - uint32_t reserved_22_22:1; - uint32_t m66:1; - uint32_t cl:1; - uint32_t i_stat:1; - uint32_t reserved_11_18:8; - uint32_t i_dis:1; - uint32_t fbbe:1; - uint32_t see:1; - uint32_t ids_wcc:1; - uint32_t per:1; - uint32_t vps:1; - uint32_t mwice:1; - uint32_t scse:1; - uint32_t me:1; - uint32_t msae:1; - uint32_t isae:1; - } s; - struct cvmx_pcieep_cfg001_s cn52xx; - struct cvmx_pcieep_cfg001_s cn52xxp1; - struct cvmx_pcieep_cfg001_s cn56xx; - struct cvmx_pcieep_cfg001_s cn56xxp1; -}; - -union cvmx_pcieep_cfg002 { - uint32_t u32; - struct cvmx_pcieep_cfg002_s { - uint32_t bcc:8; - uint32_t sc:8; - uint32_t pi:8; - uint32_t rid:8; - } s; - struct cvmx_pcieep_cfg002_s cn52xx; - struct cvmx_pcieep_cfg002_s cn52xxp1; - struct cvmx_pcieep_cfg002_s cn56xx; - struct cvmx_pcieep_cfg002_s cn56xxp1; -}; - -union cvmx_pcieep_cfg003 { - uint32_t u32; - struct cvmx_pcieep_cfg003_s { - uint32_t bist:8; - uint32_t mfd:1; - uint32_t chf:7; - uint32_t lt:8; - uint32_t cls:8; - } s; - struct cvmx_pcieep_cfg003_s cn52xx; - struct cvmx_pcieep_cfg003_s cn52xxp1; - struct cvmx_pcieep_cfg003_s cn56xx; - struct cvmx_pcieep_cfg003_s cn56xxp1; -}; - -union cvmx_pcieep_cfg004 { - uint32_t u32; - struct cvmx_pcieep_cfg004_s { - uint32_t lbab:18; - uint32_t reserved_4_13:10; - uint32_t pf:1; - uint32_t typ:2; - uint32_t mspc:1; - } s; - struct cvmx_pcieep_cfg004_s cn52xx; - struct cvmx_pcieep_cfg004_s cn52xxp1; - struct cvmx_pcieep_cfg004_s cn56xx; - struct cvmx_pcieep_cfg004_s cn56xxp1; -}; - -union cvmx_pcieep_cfg004_mask { - uint32_t u32; - struct cvmx_pcieep_cfg004_mask_s { - uint32_t lmask:31; - uint32_t enb:1; - } s; - struct cvmx_pcieep_cfg004_mask_s cn52xx; - struct cvmx_pcieep_cfg004_mask_s cn52xxp1; - struct cvmx_pcieep_cfg004_mask_s cn56xx; - struct cvmx_pcieep_cfg004_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg005 { - uint32_t u32; - struct cvmx_pcieep_cfg005_s { - uint32_t ubab:32; - } s; - struct cvmx_pcieep_cfg005_s cn52xx; - struct cvmx_pcieep_cfg005_s cn52xxp1; - struct cvmx_pcieep_cfg005_s cn56xx; - struct cvmx_pcieep_cfg005_s cn56xxp1; -}; - -union cvmx_pcieep_cfg005_mask { - uint32_t u32; - struct cvmx_pcieep_cfg005_mask_s { - uint32_t umask:32; - } s; - struct cvmx_pcieep_cfg005_mask_s cn52xx; - struct cvmx_pcieep_cfg005_mask_s cn52xxp1; - struct cvmx_pcieep_cfg005_mask_s cn56xx; - struct cvmx_pcieep_cfg005_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg006 { - uint32_t u32; - struct cvmx_pcieep_cfg006_s { - uint32_t lbab:6; - uint32_t reserved_4_25:22; - uint32_t pf:1; - uint32_t typ:2; - uint32_t mspc:1; - } s; - struct cvmx_pcieep_cfg006_s cn52xx; - struct cvmx_pcieep_cfg006_s cn52xxp1; - struct cvmx_pcieep_cfg006_s cn56xx; - struct cvmx_pcieep_cfg006_s cn56xxp1; -}; - -union cvmx_pcieep_cfg006_mask { - uint32_t u32; - struct cvmx_pcieep_cfg006_mask_s { - uint32_t lmask:31; - uint32_t enb:1; - } s; - struct cvmx_pcieep_cfg006_mask_s cn52xx; - struct cvmx_pcieep_cfg006_mask_s cn52xxp1; - struct cvmx_pcieep_cfg006_mask_s cn56xx; - struct cvmx_pcieep_cfg006_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg007 { - uint32_t u32; - struct cvmx_pcieep_cfg007_s { - uint32_t ubab:32; - } s; - struct cvmx_pcieep_cfg007_s cn52xx; - struct cvmx_pcieep_cfg007_s cn52xxp1; - struct cvmx_pcieep_cfg007_s cn56xx; - struct cvmx_pcieep_cfg007_s cn56xxp1; -}; - -union cvmx_pcieep_cfg007_mask { - uint32_t u32; - struct cvmx_pcieep_cfg007_mask_s { - uint32_t umask:32; - } s; - struct cvmx_pcieep_cfg007_mask_s cn52xx; - struct cvmx_pcieep_cfg007_mask_s cn52xxp1; - struct cvmx_pcieep_cfg007_mask_s cn56xx; - struct cvmx_pcieep_cfg007_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg008 { - uint32_t u32; - struct cvmx_pcieep_cfg008_s { - uint32_t reserved_4_31:28; - uint32_t pf:1; - uint32_t typ:2; - uint32_t mspc:1; - } s; - struct cvmx_pcieep_cfg008_s cn52xx; - struct cvmx_pcieep_cfg008_s cn52xxp1; - struct cvmx_pcieep_cfg008_s cn56xx; - struct cvmx_pcieep_cfg008_s cn56xxp1; -}; - -union cvmx_pcieep_cfg008_mask { - uint32_t u32; - struct cvmx_pcieep_cfg008_mask_s { - uint32_t lmask:31; - uint32_t enb:1; - } s; - struct cvmx_pcieep_cfg008_mask_s cn52xx; - struct cvmx_pcieep_cfg008_mask_s cn52xxp1; - struct cvmx_pcieep_cfg008_mask_s cn56xx; - struct cvmx_pcieep_cfg008_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg009 { - uint32_t u32; - struct cvmx_pcieep_cfg009_s { - uint32_t ubab:25; - uint32_t reserved_0_6:7; - } s; - struct cvmx_pcieep_cfg009_s cn52xx; - struct cvmx_pcieep_cfg009_s cn52xxp1; - struct cvmx_pcieep_cfg009_s cn56xx; - struct cvmx_pcieep_cfg009_s cn56xxp1; -}; - -union cvmx_pcieep_cfg009_mask { - uint32_t u32; - struct cvmx_pcieep_cfg009_mask_s { - uint32_t umask:32; - } s; - struct cvmx_pcieep_cfg009_mask_s cn52xx; - struct cvmx_pcieep_cfg009_mask_s cn52xxp1; - struct cvmx_pcieep_cfg009_mask_s cn56xx; - struct cvmx_pcieep_cfg009_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg010 { - uint32_t u32; - struct cvmx_pcieep_cfg010_s { - uint32_t cisp:32; - } s; - struct cvmx_pcieep_cfg010_s cn52xx; - struct cvmx_pcieep_cfg010_s cn52xxp1; - struct cvmx_pcieep_cfg010_s cn56xx; - struct cvmx_pcieep_cfg010_s cn56xxp1; -}; - -union cvmx_pcieep_cfg011 { - uint32_t u32; - struct cvmx_pcieep_cfg011_s { - uint32_t ssid:16; - uint32_t ssvid:16; - } s; - struct cvmx_pcieep_cfg011_s cn52xx; - struct cvmx_pcieep_cfg011_s cn52xxp1; - struct cvmx_pcieep_cfg011_s cn56xx; - struct cvmx_pcieep_cfg011_s cn56xxp1; -}; - -union cvmx_pcieep_cfg012 { - uint32_t u32; - struct cvmx_pcieep_cfg012_s { - uint32_t eraddr:16; - uint32_t reserved_1_15:15; - uint32_t er_en:1; - } s; - struct cvmx_pcieep_cfg012_s cn52xx; - struct cvmx_pcieep_cfg012_s cn52xxp1; - struct cvmx_pcieep_cfg012_s cn56xx; - struct cvmx_pcieep_cfg012_s cn56xxp1; -}; - -union cvmx_pcieep_cfg012_mask { - uint32_t u32; - struct cvmx_pcieep_cfg012_mask_s { - uint32_t mask:31; - uint32_t enb:1; - } s; - struct cvmx_pcieep_cfg012_mask_s cn52xx; - struct cvmx_pcieep_cfg012_mask_s cn52xxp1; - struct cvmx_pcieep_cfg012_mask_s cn56xx; - struct cvmx_pcieep_cfg012_mask_s cn56xxp1; -}; - -union cvmx_pcieep_cfg013 { - uint32_t u32; - struct cvmx_pcieep_cfg013_s { - uint32_t reserved_8_31:24; - uint32_t cp:8; - } s; - struct cvmx_pcieep_cfg013_s cn52xx; - struct cvmx_pcieep_cfg013_s cn52xxp1; - struct cvmx_pcieep_cfg013_s cn56xx; - struct cvmx_pcieep_cfg013_s cn56xxp1; -}; - -union cvmx_pcieep_cfg015 { - uint32_t u32; - struct cvmx_pcieep_cfg015_s { - uint32_t ml:8; - uint32_t mg:8; - uint32_t inta:8; - uint32_t il:8; - } s; - struct cvmx_pcieep_cfg015_s cn52xx; - struct cvmx_pcieep_cfg015_s cn52xxp1; - struct cvmx_pcieep_cfg015_s cn56xx; - struct cvmx_pcieep_cfg015_s cn56xxp1; -}; - -union cvmx_pcieep_cfg016 { - uint32_t u32; - struct cvmx_pcieep_cfg016_s { - uint32_t pmes:5; - uint32_t d2s:1; - uint32_t d1s:1; - uint32_t auxc:3; - uint32_t dsi:1; - uint32_t reserved_20_20:1; - uint32_t pme_clock:1; - uint32_t pmsv:3; - uint32_t ncp:8; - uint32_t pmcid:8; - } s; - struct cvmx_pcieep_cfg016_s cn52xx; - struct cvmx_pcieep_cfg016_s cn52xxp1; - struct cvmx_pcieep_cfg016_s cn56xx; - struct cvmx_pcieep_cfg016_s cn56xxp1; -}; - -union cvmx_pcieep_cfg017 { - uint32_t u32; - struct cvmx_pcieep_cfg017_s { - uint32_t pmdia:8; - uint32_t bpccee:1; - uint32_t bd3h:1; - uint32_t reserved_16_21:6; - uint32_t pmess:1; - uint32_t pmedsia:2; - uint32_t pmds:4; - uint32_t pmeens:1; - uint32_t reserved_4_7:4; - uint32_t nsr:1; - uint32_t reserved_2_2:1; - uint32_t ps:2; - } s; - struct cvmx_pcieep_cfg017_s cn52xx; - struct cvmx_pcieep_cfg017_s cn52xxp1; - struct cvmx_pcieep_cfg017_s cn56xx; - struct cvmx_pcieep_cfg017_s cn56xxp1; -}; - -union cvmx_pcieep_cfg020 { - uint32_t u32; - struct cvmx_pcieep_cfg020_s { - uint32_t reserved_24_31:8; - uint32_t m64:1; - uint32_t mme:3; - uint32_t mmc:3; - uint32_t msien:1; - uint32_t ncp:8; - uint32_t msicid:8; - } s; - struct cvmx_pcieep_cfg020_s cn52xx; - struct cvmx_pcieep_cfg020_s cn52xxp1; - struct cvmx_pcieep_cfg020_s cn56xx; - struct cvmx_pcieep_cfg020_s cn56xxp1; -}; - -union cvmx_pcieep_cfg021 { - uint32_t u32; - struct cvmx_pcieep_cfg021_s { - uint32_t lmsi:30; - uint32_t reserved_0_1:2; - } s; - struct cvmx_pcieep_cfg021_s cn52xx; - struct cvmx_pcieep_cfg021_s cn52xxp1; - struct cvmx_pcieep_cfg021_s cn56xx; - struct cvmx_pcieep_cfg021_s cn56xxp1; -}; - -union cvmx_pcieep_cfg022 { - uint32_t u32; - struct cvmx_pcieep_cfg022_s { - uint32_t umsi:32; - } s; - struct cvmx_pcieep_cfg022_s cn52xx; - struct cvmx_pcieep_cfg022_s cn52xxp1; - struct cvmx_pcieep_cfg022_s cn56xx; - struct cvmx_pcieep_cfg022_s cn56xxp1; -}; - -union cvmx_pcieep_cfg023 { - uint32_t u32; - struct cvmx_pcieep_cfg023_s { - uint32_t reserved_16_31:16; - uint32_t msimd:16; - } s; - struct cvmx_pcieep_cfg023_s cn52xx; - struct cvmx_pcieep_cfg023_s cn52xxp1; - struct cvmx_pcieep_cfg023_s cn56xx; - struct cvmx_pcieep_cfg023_s cn56xxp1; -}; - -union cvmx_pcieep_cfg028 { - uint32_t u32; - struct cvmx_pcieep_cfg028_s { - uint32_t reserved_30_31:2; - uint32_t imn:5; - uint32_t si:1; - uint32_t dpt:4; - uint32_t pciecv:4; - uint32_t ncp:8; - uint32_t pcieid:8; - } s; - struct cvmx_pcieep_cfg028_s cn52xx; - struct cvmx_pcieep_cfg028_s cn52xxp1; - struct cvmx_pcieep_cfg028_s cn56xx; - struct cvmx_pcieep_cfg028_s cn56xxp1; -}; - -union cvmx_pcieep_cfg029 { - uint32_t u32; - struct cvmx_pcieep_cfg029_s { - uint32_t reserved_28_31:4; - uint32_t cspls:2; - uint32_t csplv:8; - uint32_t reserved_16_17:2; - uint32_t rber:1; - uint32_t reserved_12_14:3; - uint32_t el1al:3; - uint32_t el0al:3; - uint32_t etfs:1; - uint32_t pfs:2; - uint32_t mpss:3; - } s; - struct cvmx_pcieep_cfg029_s cn52xx; - struct cvmx_pcieep_cfg029_s cn52xxp1; - struct cvmx_pcieep_cfg029_s cn56xx; - struct cvmx_pcieep_cfg029_s cn56xxp1; -}; - -union cvmx_pcieep_cfg030 { - uint32_t u32; - struct cvmx_pcieep_cfg030_s { - uint32_t reserved_22_31:10; - uint32_t tp:1; - uint32_t ap_d:1; - uint32_t ur_d:1; - uint32_t fe_d:1; - uint32_t nfe_d:1; - uint32_t ce_d:1; - uint32_t reserved_15_15:1; - uint32_t mrrs:3; - uint32_t ns_en:1; - uint32_t ap_en:1; - uint32_t pf_en:1; - uint32_t etf_en:1; - uint32_t mps:3; - uint32_t ro_en:1; - uint32_t ur_en:1; - uint32_t fe_en:1; - uint32_t nfe_en:1; - uint32_t ce_en:1; - } s; - struct cvmx_pcieep_cfg030_s cn52xx; - struct cvmx_pcieep_cfg030_s cn52xxp1; - struct cvmx_pcieep_cfg030_s cn56xx; - struct cvmx_pcieep_cfg030_s cn56xxp1; -}; - -union cvmx_pcieep_cfg031 { - uint32_t u32; - struct cvmx_pcieep_cfg031_s { - uint32_t pnum:8; - uint32_t reserved_22_23:2; - uint32_t lbnc:1; - uint32_t dllarc:1; - uint32_t sderc:1; - uint32_t cpm:1; - uint32_t l1el:3; - uint32_t l0el:3; - uint32_t aslpms:2; - uint32_t mlw:6; - uint32_t mls:4; - } s; - struct cvmx_pcieep_cfg031_s cn52xx; - struct cvmx_pcieep_cfg031_s cn52xxp1; - struct cvmx_pcieep_cfg031_s cn56xx; - struct cvmx_pcieep_cfg031_s cn56xxp1; -}; - -union cvmx_pcieep_cfg032 { - uint32_t u32; - struct cvmx_pcieep_cfg032_s { - uint32_t reserved_30_31:2; - uint32_t dlla:1; - uint32_t scc:1; - uint32_t lt:1; - uint32_t reserved_26_26:1; - uint32_t nlw:6; - uint32_t ls:4; - uint32_t reserved_10_15:6; - uint32_t hawd:1; - uint32_t ecpm:1; - uint32_t es:1; - uint32_t ccc:1; - uint32_t rl:1; - uint32_t ld:1; - uint32_t rcb:1; - uint32_t reserved_2_2:1; - uint32_t aslpc:2; - } s; - struct cvmx_pcieep_cfg032_s cn52xx; - struct cvmx_pcieep_cfg032_s cn52xxp1; - struct cvmx_pcieep_cfg032_s cn56xx; - struct cvmx_pcieep_cfg032_s cn56xxp1; -}; - -union cvmx_pcieep_cfg033 { - uint32_t u32; - struct cvmx_pcieep_cfg033_s { - uint32_t ps_num:13; - uint32_t nccs:1; - uint32_t emip:1; - uint32_t sp_ls:2; - uint32_t sp_lv:8; - uint32_t hp_c:1; - uint32_t hp_s:1; - uint32_t pip:1; - uint32_t aip:1; - uint32_t mrlsp:1; - uint32_t pcp:1; - uint32_t abp:1; - } s; - struct cvmx_pcieep_cfg033_s cn52xx; - struct cvmx_pcieep_cfg033_s cn52xxp1; - struct cvmx_pcieep_cfg033_s cn56xx; - struct cvmx_pcieep_cfg033_s cn56xxp1; -}; - -union cvmx_pcieep_cfg034 { - uint32_t u32; - struct cvmx_pcieep_cfg034_s { - uint32_t reserved_25_31:7; - uint32_t dlls_c:1; - uint32_t emis:1; - uint32_t pds:1; - uint32_t mrlss:1; - uint32_t ccint_d:1; - uint32_t pd_c:1; - uint32_t mrls_c:1; - uint32_t pf_d:1; - uint32_t abp_d:1; - uint32_t reserved_13_15:3; - uint32_t dlls_en:1; - uint32_t emic:1; - uint32_t pcc:1; - uint32_t pic:2; - uint32_t aic:2; - uint32_t hpint_en:1; - uint32_t ccint_en:1; - uint32_t pd_en:1; - uint32_t mrls_en:1; - uint32_t pf_en:1; - uint32_t abp_en:1; - } s; - struct cvmx_pcieep_cfg034_s cn52xx; - struct cvmx_pcieep_cfg034_s cn52xxp1; - struct cvmx_pcieep_cfg034_s cn56xx; - struct cvmx_pcieep_cfg034_s cn56xxp1; -}; - -union cvmx_pcieep_cfg037 { - uint32_t u32; - struct cvmx_pcieep_cfg037_s { - uint32_t reserved_5_31:27; - uint32_t ctds:1; - uint32_t ctrs:4; - } s; - struct cvmx_pcieep_cfg037_s cn52xx; - struct cvmx_pcieep_cfg037_s cn52xxp1; - struct cvmx_pcieep_cfg037_s cn56xx; - struct cvmx_pcieep_cfg037_s cn56xxp1; -}; - -union cvmx_pcieep_cfg038 { - uint32_t u32; - struct cvmx_pcieep_cfg038_s { - uint32_t reserved_5_31:27; - uint32_t ctd:1; - uint32_t ctv:4; - } s; - struct cvmx_pcieep_cfg038_s cn52xx; - struct cvmx_pcieep_cfg038_s cn52xxp1; - struct cvmx_pcieep_cfg038_s cn56xx; - struct cvmx_pcieep_cfg038_s cn56xxp1; -}; - -union cvmx_pcieep_cfg039 { - uint32_t u32; - struct cvmx_pcieep_cfg039_s { - uint32_t reserved_0_31:32; - } s; - struct cvmx_pcieep_cfg039_s cn52xx; - struct cvmx_pcieep_cfg039_s cn52xxp1; - struct cvmx_pcieep_cfg039_s cn56xx; - struct cvmx_pcieep_cfg039_s cn56xxp1; -}; - -union cvmx_pcieep_cfg040 { - uint32_t u32; - struct cvmx_pcieep_cfg040_s { - uint32_t reserved_0_31:32; - } s; - struct cvmx_pcieep_cfg040_s cn52xx; - struct cvmx_pcieep_cfg040_s cn52xxp1; - struct cvmx_pcieep_cfg040_s cn56xx; - struct cvmx_pcieep_cfg040_s cn56xxp1; -}; - -union cvmx_pcieep_cfg041 { - uint32_t u32; - struct cvmx_pcieep_cfg041_s { - uint32_t reserved_0_31:32; - } s; - struct cvmx_pcieep_cfg041_s cn52xx; - struct cvmx_pcieep_cfg041_s cn52xxp1; - struct cvmx_pcieep_cfg041_s cn56xx; - struct cvmx_pcieep_cfg041_s cn56xxp1; -}; - -union cvmx_pcieep_cfg042 { - uint32_t u32; - struct cvmx_pcieep_cfg042_s { - uint32_t reserved_0_31:32; - } s; - struct cvmx_pcieep_cfg042_s cn52xx; - struct cvmx_pcieep_cfg042_s cn52xxp1; - struct cvmx_pcieep_cfg042_s cn56xx; - struct cvmx_pcieep_cfg042_s cn56xxp1; -}; - -union cvmx_pcieep_cfg064 { - uint32_t u32; - struct cvmx_pcieep_cfg064_s { - uint32_t nco:12; - uint32_t cv:4; - uint32_t pcieec:16; - } s; - struct cvmx_pcieep_cfg064_s cn52xx; - struct cvmx_pcieep_cfg064_s cn52xxp1; - struct cvmx_pcieep_cfg064_s cn56xx; - struct cvmx_pcieep_cfg064_s cn56xxp1; -}; - -union cvmx_pcieep_cfg065 { - uint32_t u32; - struct cvmx_pcieep_cfg065_s { - uint32_t reserved_21_31:11; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; - } s; - struct cvmx_pcieep_cfg065_s cn52xx; - struct cvmx_pcieep_cfg065_s cn52xxp1; - struct cvmx_pcieep_cfg065_s cn56xx; - struct cvmx_pcieep_cfg065_s cn56xxp1; -}; - -union cvmx_pcieep_cfg066 { - uint32_t u32; - struct cvmx_pcieep_cfg066_s { - uint32_t reserved_21_31:11; - uint32_t urem:1; - uint32_t ecrcem:1; - uint32_t mtlpm:1; - uint32_t rom:1; - uint32_t ucm:1; - uint32_t cam:1; - uint32_t ctm:1; - uint32_t fcpem:1; - uint32_t ptlpm:1; - uint32_t reserved_6_11:6; - uint32_t sdem:1; - uint32_t dlpem:1; - uint32_t reserved_0_3:4; - } s; - struct cvmx_pcieep_cfg066_s cn52xx; - struct cvmx_pcieep_cfg066_s cn52xxp1; - struct cvmx_pcieep_cfg066_s cn56xx; - struct cvmx_pcieep_cfg066_s cn56xxp1; -}; - -union cvmx_pcieep_cfg067 { - uint32_t u32; - struct cvmx_pcieep_cfg067_s { - uint32_t reserved_21_31:11; - uint32_t ures:1; - uint32_t ecrces:1; - uint32_t mtlps:1; - uint32_t ros:1; - uint32_t ucs:1; - uint32_t cas:1; - uint32_t cts:1; - uint32_t fcpes:1; - uint32_t ptlps:1; - uint32_t reserved_6_11:6; - uint32_t sdes:1; - uint32_t dlpes:1; - uint32_t reserved_0_3:4; - } s; - struct cvmx_pcieep_cfg067_s cn52xx; - struct cvmx_pcieep_cfg067_s cn52xxp1; - struct cvmx_pcieep_cfg067_s cn56xx; - struct cvmx_pcieep_cfg067_s cn56xxp1; -}; - -union cvmx_pcieep_cfg068 { - uint32_t u32; - struct cvmx_pcieep_cfg068_s { - uint32_t reserved_14_31:18; - uint32_t anfes:1; - uint32_t rtts:1; - uint32_t reserved_9_11:3; - uint32_t rnrs:1; - uint32_t bdllps:1; - uint32_t btlps:1; - uint32_t reserved_1_5:5; - uint32_t res:1; - } s; - struct cvmx_pcieep_cfg068_s cn52xx; - struct cvmx_pcieep_cfg068_s cn52xxp1; - struct cvmx_pcieep_cfg068_s cn56xx; - struct cvmx_pcieep_cfg068_s cn56xxp1; -}; - -union cvmx_pcieep_cfg069 { - uint32_t u32; - struct cvmx_pcieep_cfg069_s { - uint32_t reserved_14_31:18; - uint32_t anfem:1; - uint32_t rttm:1; - uint32_t reserved_9_11:3; - uint32_t rnrm:1; - uint32_t bdllpm:1; - uint32_t btlpm:1; - uint32_t reserved_1_5:5; - uint32_t rem:1; - } s; - struct cvmx_pcieep_cfg069_s cn52xx; - struct cvmx_pcieep_cfg069_s cn52xxp1; - struct cvmx_pcieep_cfg069_s cn56xx; - struct cvmx_pcieep_cfg069_s cn56xxp1; -}; - -union cvmx_pcieep_cfg070 { - uint32_t u32; - struct cvmx_pcieep_cfg070_s { - uint32_t reserved_9_31:23; - uint32_t ce:1; - uint32_t cc:1; - uint32_t ge:1; - uint32_t gc:1; - uint32_t fep:5; - } s; - struct cvmx_pcieep_cfg070_s cn52xx; - struct cvmx_pcieep_cfg070_s cn52xxp1; - struct cvmx_pcieep_cfg070_s cn56xx; - struct cvmx_pcieep_cfg070_s cn56xxp1; -}; - -union cvmx_pcieep_cfg071 { - uint32_t u32; - struct cvmx_pcieep_cfg071_s { - uint32_t dword1:32; - } s; - struct cvmx_pcieep_cfg071_s cn52xx; - struct cvmx_pcieep_cfg071_s cn52xxp1; - struct cvmx_pcieep_cfg071_s cn56xx; - struct cvmx_pcieep_cfg071_s cn56xxp1; -}; - -union cvmx_pcieep_cfg072 { - uint32_t u32; - struct cvmx_pcieep_cfg072_s { - uint32_t dword2:32; - } s; - struct cvmx_pcieep_cfg072_s cn52xx; - struct cvmx_pcieep_cfg072_s cn52xxp1; - struct cvmx_pcieep_cfg072_s cn56xx; - struct cvmx_pcieep_cfg072_s cn56xxp1; -}; - -union cvmx_pcieep_cfg073 { - uint32_t u32; - struct cvmx_pcieep_cfg073_s { - uint32_t dword3:32; - } s; - struct cvmx_pcieep_cfg073_s cn52xx; - struct cvmx_pcieep_cfg073_s cn52xxp1; - struct cvmx_pcieep_cfg073_s cn56xx; - struct cvmx_pcieep_cfg073_s cn56xxp1; -}; - -union cvmx_pcieep_cfg074 { - uint32_t u32; - struct cvmx_pcieep_cfg074_s { - uint32_t dword4:32; - } s; - struct cvmx_pcieep_cfg074_s cn52xx; - struct cvmx_pcieep_cfg074_s cn52xxp1; - struct cvmx_pcieep_cfg074_s cn56xx; - struct cvmx_pcieep_cfg074_s cn56xxp1; -}; - -union cvmx_pcieep_cfg448 { - uint32_t u32; - struct cvmx_pcieep_cfg448_s { - uint32_t rtl:16; - uint32_t rtltl:16; - } s; - struct cvmx_pcieep_cfg448_s cn52xx; - struct cvmx_pcieep_cfg448_s cn52xxp1; - struct cvmx_pcieep_cfg448_s cn56xx; - struct cvmx_pcieep_cfg448_s cn56xxp1; -}; - -union cvmx_pcieep_cfg449 { - uint32_t u32; - struct cvmx_pcieep_cfg449_s { - uint32_t omr:32; - } s; - struct cvmx_pcieep_cfg449_s cn52xx; - struct cvmx_pcieep_cfg449_s cn52xxp1; - struct cvmx_pcieep_cfg449_s cn56xx; - struct cvmx_pcieep_cfg449_s cn56xxp1; -}; - -union cvmx_pcieep_cfg450 { - uint32_t u32; - struct cvmx_pcieep_cfg450_s { - uint32_t lpec:8; - uint32_t reserved_22_23:2; - uint32_t link_state:6; - uint32_t force_link:1; - uint32_t reserved_8_14:7; - uint32_t link_num:8; - } s; - struct cvmx_pcieep_cfg450_s cn52xx; - struct cvmx_pcieep_cfg450_s cn52xxp1; - struct cvmx_pcieep_cfg450_s cn56xx; - struct cvmx_pcieep_cfg450_s cn56xxp1; -}; - -union cvmx_pcieep_cfg451 { - uint32_t u32; - struct cvmx_pcieep_cfg451_s { - uint32_t reserved_30_31:2; - uint32_t l1el:3; - uint32_t l0el:3; - uint32_t n_fts_cc:8; - uint32_t n_fts:8; - uint32_t ack_freq:8; - } s; - struct cvmx_pcieep_cfg451_s cn52xx; - struct cvmx_pcieep_cfg451_s cn52xxp1; - struct cvmx_pcieep_cfg451_s cn56xx; - struct cvmx_pcieep_cfg451_s cn56xxp1; -}; - -union cvmx_pcieep_cfg452 { - uint32_t u32; - struct cvmx_pcieep_cfg452_s { - uint32_t reserved_26_31:6; - uint32_t eccrc:1; - uint32_t reserved_22_24:3; - uint32_t lme:6; - uint32_t reserved_8_15:8; - uint32_t flm:1; - uint32_t reserved_6_6:1; - uint32_t dllle:1; - uint32_t reserved_4_4:1; - uint32_t ra:1; - uint32_t le:1; - uint32_t sd:1; - uint32_t omr:1; - } s; - struct cvmx_pcieep_cfg452_s cn52xx; - struct cvmx_pcieep_cfg452_s cn52xxp1; - struct cvmx_pcieep_cfg452_s cn56xx; - struct cvmx_pcieep_cfg452_s cn56xxp1; -}; - -union cvmx_pcieep_cfg453 { - uint32_t u32; - struct cvmx_pcieep_cfg453_s { - uint32_t dlld:1; - uint32_t reserved_26_30:5; - uint32_t ack_nak:1; - uint32_t fcd:1; - uint32_t ilst:24; - } s; - struct cvmx_pcieep_cfg453_s cn52xx; - struct cvmx_pcieep_cfg453_s cn52xxp1; - struct cvmx_pcieep_cfg453_s cn56xx; - struct cvmx_pcieep_cfg453_s cn56xxp1; -}; - -union cvmx_pcieep_cfg454 { - uint32_t u32; - struct cvmx_pcieep_cfg454_s { - uint32_t reserved_29_31:3; - uint32_t tmfcwt:5; - uint32_t tmanlt:5; - uint32_t tmrt:5; - uint32_t reserved_11_13:3; - uint32_t nskps:3; - uint32_t reserved_4_7:4; - uint32_t ntss:4; - } s; - struct cvmx_pcieep_cfg454_s cn52xx; - struct cvmx_pcieep_cfg454_s cn52xxp1; - struct cvmx_pcieep_cfg454_s cn56xx; - struct cvmx_pcieep_cfg454_s cn56xxp1; -}; - -union cvmx_pcieep_cfg455 { - uint32_t u32; - struct cvmx_pcieep_cfg455_s { - uint32_t m_cfg0_filt:1; - uint32_t m_io_filt:1; - uint32_t msg_ctrl:1; - uint32_t m_cpl_ecrc_filt:1; - uint32_t m_ecrc_filt:1; - uint32_t m_cpl_len_err:1; - uint32_t m_cpl_attr_err:1; - uint32_t m_cpl_tc_err:1; - uint32_t m_cpl_fun_err:1; - uint32_t m_cpl_rid_err:1; - uint32_t m_cpl_tag_err:1; - uint32_t m_lk_filt:1; - uint32_t m_cfg1_filt:1; - uint32_t m_bar_match:1; - uint32_t m_pois_filt:1; - uint32_t m_fun:1; - uint32_t dfcwt:1; - uint32_t reserved_11_14:4; - uint32_t skpiv:11; - } s; - struct cvmx_pcieep_cfg455_s cn52xx; - struct cvmx_pcieep_cfg455_s cn52xxp1; - struct cvmx_pcieep_cfg455_s cn56xx; - struct cvmx_pcieep_cfg455_s cn56xxp1; -}; - -union cvmx_pcieep_cfg456 { - uint32_t u32; - struct cvmx_pcieep_cfg456_s { - uint32_t reserved_2_31:30; - uint32_t m_vend1_drp:1; - uint32_t m_vend0_drp:1; - } s; - struct cvmx_pcieep_cfg456_s cn52xx; - struct cvmx_pcieep_cfg456_s cn52xxp1; - struct cvmx_pcieep_cfg456_s cn56xx; - struct cvmx_pcieep_cfg456_s cn56xxp1; -}; - -union cvmx_pcieep_cfg458 { - uint32_t u32; - struct cvmx_pcieep_cfg458_s { - uint32_t dbg_info_l32:32; - } s; - struct cvmx_pcieep_cfg458_s cn52xx; - struct cvmx_pcieep_cfg458_s cn52xxp1; - struct cvmx_pcieep_cfg458_s cn56xx; - struct cvmx_pcieep_cfg458_s cn56xxp1; -}; - -union cvmx_pcieep_cfg459 { - uint32_t u32; - struct cvmx_pcieep_cfg459_s { - uint32_t dbg_info_u32:32; - } s; - struct cvmx_pcieep_cfg459_s cn52xx; - struct cvmx_pcieep_cfg459_s cn52xxp1; - struct cvmx_pcieep_cfg459_s cn56xx; - struct cvmx_pcieep_cfg459_s cn56xxp1; -}; - -union cvmx_pcieep_cfg460 { - uint32_t u32; - struct cvmx_pcieep_cfg460_s { - uint32_t reserved_20_31:12; - uint32_t tphfcc:8; - uint32_t tpdfcc:12; - } s; - struct cvmx_pcieep_cfg460_s cn52xx; - struct cvmx_pcieep_cfg460_s cn52xxp1; - struct cvmx_pcieep_cfg460_s cn56xx; - struct cvmx_pcieep_cfg460_s cn56xxp1; -}; - -union cvmx_pcieep_cfg461 { - uint32_t u32; - struct cvmx_pcieep_cfg461_s { - uint32_t reserved_20_31:12; - uint32_t tchfcc:8; - uint32_t tcdfcc:12; - } s; - struct cvmx_pcieep_cfg461_s cn52xx; - struct cvmx_pcieep_cfg461_s cn52xxp1; - struct cvmx_pcieep_cfg461_s cn56xx; - struct cvmx_pcieep_cfg461_s cn56xxp1; -}; - -union cvmx_pcieep_cfg462 { - uint32_t u32; - struct cvmx_pcieep_cfg462_s { - uint32_t reserved_20_31:12; - uint32_t tchfcc:8; - uint32_t tcdfcc:12; - } s; - struct cvmx_pcieep_cfg462_s cn52xx; - struct cvmx_pcieep_cfg462_s cn52xxp1; - struct cvmx_pcieep_cfg462_s cn56xx; - struct cvmx_pcieep_cfg462_s cn56xxp1; -}; - -union cvmx_pcieep_cfg463 { - uint32_t u32; - struct cvmx_pcieep_cfg463_s { - uint32_t reserved_3_31:29; - uint32_t rqne:1; - uint32_t trbne:1; - uint32_t rtlpfccnr:1; - } s; - struct cvmx_pcieep_cfg463_s cn52xx; - struct cvmx_pcieep_cfg463_s cn52xxp1; - struct cvmx_pcieep_cfg463_s cn56xx; - struct cvmx_pcieep_cfg463_s cn56xxp1; -}; - -union cvmx_pcieep_cfg464 { - uint32_t u32; - struct cvmx_pcieep_cfg464_s { - uint32_t wrr_vc3:8; - uint32_t wrr_vc2:8; - uint32_t wrr_vc1:8; - uint32_t wrr_vc0:8; - } s; - struct cvmx_pcieep_cfg464_s cn52xx; - struct cvmx_pcieep_cfg464_s cn52xxp1; - struct cvmx_pcieep_cfg464_s cn56xx; - struct cvmx_pcieep_cfg464_s cn56xxp1; -}; - -union cvmx_pcieep_cfg465 { - uint32_t u32; - struct cvmx_pcieep_cfg465_s { - uint32_t wrr_vc7:8; - uint32_t wrr_vc6:8; - uint32_t wrr_vc5:8; - uint32_t wrr_vc4:8; - } s; - struct cvmx_pcieep_cfg465_s cn52xx; - struct cvmx_pcieep_cfg465_s cn52xxp1; - struct cvmx_pcieep_cfg465_s cn56xx; - struct cvmx_pcieep_cfg465_s cn56xxp1; -}; - -union cvmx_pcieep_cfg466 { - uint32_t u32; - struct cvmx_pcieep_cfg466_s { - uint32_t rx_queue_order:1; - uint32_t type_ordering:1; - uint32_t reserved_24_29:6; - uint32_t queue_mode:3; - uint32_t reserved_20_20:1; - uint32_t header_credits:8; - uint32_t data_credits:12; - } s; - struct cvmx_pcieep_cfg466_s cn52xx; - struct cvmx_pcieep_cfg466_s cn52xxp1; - struct cvmx_pcieep_cfg466_s cn56xx; - struct cvmx_pcieep_cfg466_s cn56xxp1; -}; - -union cvmx_pcieep_cfg467 { - uint32_t u32; - struct cvmx_pcieep_cfg467_s { - uint32_t reserved_24_31:8; - uint32_t queue_mode:3; - uint32_t reserved_20_20:1; - uint32_t header_credits:8; - uint32_t data_credits:12; - } s; - struct cvmx_pcieep_cfg467_s cn52xx; - struct cvmx_pcieep_cfg467_s cn52xxp1; - struct cvmx_pcieep_cfg467_s cn56xx; - struct cvmx_pcieep_cfg467_s cn56xxp1; -}; - -union cvmx_pcieep_cfg468 { - uint32_t u32; - struct cvmx_pcieep_cfg468_s { - uint32_t reserved_24_31:8; - uint32_t queue_mode:3; - uint32_t reserved_20_20:1; - uint32_t header_credits:8; - uint32_t data_credits:12; - } s; - struct cvmx_pcieep_cfg468_s cn52xx; - struct cvmx_pcieep_cfg468_s cn52xxp1; - struct cvmx_pcieep_cfg468_s cn56xx; - struct cvmx_pcieep_cfg468_s cn56xxp1; -}; - -union cvmx_pcieep_cfg490 { - uint32_t u32; - struct cvmx_pcieep_cfg490_s { - uint32_t reserved_26_31:6; - uint32_t header_depth:10; - uint32_t reserved_14_15:2; - uint32_t data_depth:14; - } s; - struct cvmx_pcieep_cfg490_s cn52xx; - struct cvmx_pcieep_cfg490_s cn52xxp1; - struct cvmx_pcieep_cfg490_s cn56xx; - struct cvmx_pcieep_cfg490_s cn56xxp1; -}; - -union cvmx_pcieep_cfg491 { - uint32_t u32; - struct cvmx_pcieep_cfg491_s { - uint32_t reserved_26_31:6; - uint32_t header_depth:10; - uint32_t reserved_14_15:2; - uint32_t data_depth:14; - } s; - struct cvmx_pcieep_cfg491_s cn52xx; - struct cvmx_pcieep_cfg491_s cn52xxp1; - struct cvmx_pcieep_cfg491_s cn56xx; - struct cvmx_pcieep_cfg491_s cn56xxp1; -}; - -union cvmx_pcieep_cfg492 { - uint32_t u32; - struct cvmx_pcieep_cfg492_s { - uint32_t reserved_26_31:6; - uint32_t header_depth:10; - uint32_t reserved_14_15:2; - uint32_t data_depth:14; - } s; - struct cvmx_pcieep_cfg492_s cn52xx; - struct cvmx_pcieep_cfg492_s cn52xxp1; - struct cvmx_pcieep_cfg492_s cn56xx; - struct cvmx_pcieep_cfg492_s cn56xxp1; -}; - -union cvmx_pcieep_cfg516 { - uint32_t u32; - struct cvmx_pcieep_cfg516_s { - uint32_t phy_stat:32; - } s; - struct cvmx_pcieep_cfg516_s cn52xx; - struct cvmx_pcieep_cfg516_s cn52xxp1; - struct cvmx_pcieep_cfg516_s cn56xx; - struct cvmx_pcieep_cfg516_s cn56xxp1; -}; - -union cvmx_pcieep_cfg517 { - uint32_t u32; - struct cvmx_pcieep_cfg517_s { - uint32_t phy_ctrl:32; - } s; - struct cvmx_pcieep_cfg517_s cn52xx; - struct cvmx_pcieep_cfg517_s cn52xxp1; - struct cvmx_pcieep_cfg517_s cn56xx; - struct cvmx_pcieep_cfg517_s cn56xxp1; -}; - -#endif 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/sparsemem.h b/arch/mips/include/asm/sparsemem.h index 7165333..4461198 100644 --- a/arch/mips/include/asm/sparsemem.h +++ b/arch/mips/include/asm/sparsemem.h @@ -6,7 +6,11 @@ * SECTION_SIZE_BITS 2^N: how big each section will be * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space */ -#define SECTION_SIZE_BITS 28 +#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PAGE_SIZE_64KB) +# define SECTION_SIZE_BITS 29 +#else +# define SECTION_SIZE_BITS 28 +#endif #define MAX_PHYSMEM_BITS 35 #endif /* CONFIG_SPARSEMEM */ 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/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/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/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/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c index d657ee0..afd2211 100644 --- a/arch/mips/pci/ops-loongson2.c +++ b/arch/mips/pci/ops-loongson2.c @@ -15,6 +15,7 @@ #include <linux/pci.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/export.h> #include <loongson.h> 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/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/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> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e03653d..8fae079 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -96,6 +96,14 @@ config GPIO_EP93XX depends on ARCH_EP93XX select GPIO_GENERIC +config GPIO_MM_LANTIQ + bool "Lantiq Memory mapped GPIOs" + depends on LANTIQ && SOC_XWAY + help + This enables support for memory mapped GPIOs on the External Bus Unit + (EBU) found on Lantiq SoCs. The gpios are output only as they are + created by attaching a 16bit latch to the bus. + config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx @@ -306,6 +314,16 @@ config GPIO_STMPE This enables support for the GPIOs found on the STMPE I/O Expanders. +config GPIO_STP_XWAY + bool "XWAY STP GPIOs" + depends on SOC_XWAY + help + This enables support for the Serial To Parallel (STP) unit found on + XWAY SoC. The STP allows the SoC to drive a shift registers cascade, + that can be up to 24 bit. This peripheral is aimed at driving leds. + Some of the gpios/leds can be auto updated by the soc with dsl and + phy status. + config GPIO_TC3589X bool "TC3589X GPIOs" depends on MFD_TC3589X diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 007f54b..ed1c96d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o +obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o @@ -49,6 +50,7 @@ obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o +obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c new file mode 100644 index 0000000..2983dfb --- /dev/null +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -0,0 +1,158 @@ +/* + * 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/init.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/mutex.h> +#include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/io.h> +#include <linux/slab.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 */ + +struct ltq_mm { + struct of_mm_gpio_chip mmchip; + u16 shadow; /* shadow the latches state */ +}; + +/** + * ltq_mm_apply() - write the shadow value to the ebu address. + * @chip: Pointer to our private data structure. + * + * Write the shadow value to the EBU to set the gpios. We need to set the + * global EBU lock to make sure that PCI/MTD dont break. + */ +static void ltq_mm_apply(struct ltq_mm *chip) +{ + unsigned long flags; + + spin_lock_irqsave(&ebu_lock, flags); + ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1); + __raw_writew(chip->shadow, chip->mmchip.regs); + ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1); + spin_unlock_irqrestore(&ebu_lock, flags); +} + +/** + * ltq_mm_set() - gpio_chip->set - set gpios. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * Set the shadow value and call ltq_mm_apply. + */ +static void ltq_mm_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct ltq_mm *chip = + container_of(mm_gc, struct ltq_mm, mmchip); + + if (value) + chip->shadow |= (1 << offset); + else + chip->shadow &= ~(1 << offset); + ltq_mm_apply(chip); +} + +/** + * ltq_mm_dir_out() - gpio_chip->dir_out - set gpio direction. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * Same as ltq_mm_set, always returns 0. + */ +static int ltq_mm_dir_out(struct gpio_chip *gc, unsigned offset, int value) +{ + ltq_mm_set(gc, offset, value); + + return 0; +} + +/** + * ltq_mm_save_regs() - Set initial values of GPIO pins + * @mm_gc: pointer to memory mapped GPIO chip structure + */ +static void ltq_mm_save_regs(struct of_mm_gpio_chip *mm_gc) +{ + struct ltq_mm *chip = + container_of(mm_gc, struct ltq_mm, mmchip); + + /* tell the ebu controller which memory address we will be using */ + ltq_ebu_w32(CPHYSADDR(chip->mmchip.regs) | 0x1, LTQ_EBU_ADDRSEL1); + + ltq_mm_apply(chip); +} + +static int ltq_mm_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct ltq_mm *chip; + const __be32 *shadow; + int ret = 0; + + if (!res) { + dev_err(&pdev->dev, "failed to get memory resource\n"); + return -ENOENT; + } + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->mmchip.gc.ngpio = 16; + chip->mmchip.gc.label = "gpio-mm-ltq"; + chip->mmchip.gc.direction_output = ltq_mm_dir_out; + chip->mmchip.gc.set = ltq_mm_set; + chip->mmchip.save_regs = ltq_mm_save_regs; + + /* store the shadow value if one was passed by the devicetree */ + shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL); + if (shadow) + chip->shadow = be32_to_cpu(*shadow); + + ret = of_mm_gpiochip_add(pdev->dev.of_node, &chip->mmchip); + if (ret) + kfree(chip); + return ret; +} + +static const struct of_device_id ltq_mm_match[] = { + { .compatible = "lantiq,gpio-mm" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_mm_match); + +static struct platform_driver ltq_mm_driver = { + .probe = ltq_mm_probe, + .driver = { + .name = "gpio-mm-ltq", + .owner = THIS_MODULE, + .of_match_table = ltq_mm_match, + }, +}; + +static int __init ltq_mm_init(void) +{ + return platform_driver_register(<q_mm_driver); +} + +subsys_initcall(ltq_mm_init); diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c new file mode 100644 index 0000000..e35096b --- /dev/null +++ b/drivers/gpio/gpio-stp-xway.c @@ -0,0 +1,301 @@ +/* + * 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/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/of_platform.h> +#include <linux/mutex.h> +#include <linux/gpio.h> +#include <linux/io.h> +#include <linux/of_gpio.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <lantiq_soc.h> + +/* + * The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a + * peripheral controller used to drive external shift register cascades. At most + * 3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem + * to drive the 2 LSBs of the cascade automatically. + */ + +/* control register 0 */ +#define XWAY_STP_CON0 0x00 +/* control register 1 */ +#define XWAY_STP_CON1 0x04 +/* data register 0 */ +#define XWAY_STP_CPU0 0x08 +/* data register 1 */ +#define XWAY_STP_CPU1 0x0C +/* access register */ +#define XWAY_STP_AR 0x10 + +/* software or hardware update select bit */ +#define XWAY_STP_CON_SWU BIT(31) + +/* automatic update rates */ +#define XWAY_STP_2HZ 0 +#define XWAY_STP_4HZ BIT(23) +#define XWAY_STP_8HZ BIT(24) +#define XWAY_STP_10HZ (BIT(24) | BIT(23)) +#define XWAY_STP_SPEED_MASK (0xf << 23) + +/* clock source for automatic update */ +#define XWAY_STP_UPD_FPI BIT(31) +#define XWAY_STP_UPD_MASK (BIT(31) | BIT(30)) + +/* let the adsl core drive the 2 LSBs */ +#define XWAY_STP_ADSL_SHIFT 24 +#define XWAY_STP_ADSL_MASK 0x3 + +/* 2 groups of 3 bits can be driven by the phys */ +#define XWAY_STP_PHY_MASK 0x3 +#define XWAY_STP_PHY1_SHIFT 27 +#define XWAY_STP_PHY2_SHIFT 15 + +/* STP has 3 groups of 8 bits */ +#define XWAY_STP_GROUP0 BIT(0) +#define XWAY_STP_GROUP1 BIT(1) +#define XWAY_STP_GROUP2 BIT(2) +#define XWAY_STP_GROUP_MASK (0x7) + +/* Edge configuration bits */ +#define XWAY_STP_FALLING BIT(26) +#define XWAY_STP_EDGE_MASK BIT(26) + +#define xway_stp_r32(m, reg) __raw_readl(m + reg) +#define xway_stp_w32(m, val, reg) __raw_writel(val, m + reg) +#define xway_stp_w32_mask(m, clear, set, reg) \ + ltq_w32((ltq_r32(m + reg) & ~(clear)) | (set), \ + m + reg) + +struct xway_stp { + struct gpio_chip gc; + void __iomem *virt; + u32 edge; /* rising or falling edge triggered shift register */ + u16 shadow; /* shadow the shift registers state */ + u8 groups; /* we can drive 1-3 groups of 8bit each */ + u8 dsl; /* the 2 LSBs can be driven by the dsl core */ + u8 phy1; /* 3 bits can be driven by phy1 */ + u8 phy2; /* 3 bits can be driven by phy2 */ + u8 reserved; /* mask out the hw driven bits in gpio_request */ +}; + +/** + * xway_stp_set() - gpio_chip->set - set gpios. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * Set the shadow value and call ltq_ebu_apply. + */ +static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val) +{ + struct xway_stp *chip = + container_of(gc, struct xway_stp, gc); + + if (val) + chip->shadow |= BIT(gpio); + else + chip->shadow &= ~BIT(gpio); + xway_stp_w32(chip->virt, chip->shadow, XWAY_STP_CPU0); + xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0); +} + +/** + * xway_stp_dir_out() - gpio_chip->dir_out - set gpio direction. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * Same as xway_stp_set, always returns 0. + */ +static int xway_stp_dir_out(struct gpio_chip *gc, unsigned gpio, int val) +{ + xway_stp_set(gc, gpio, val); + + return 0; +} + +/** + * xway_stp_request() - gpio_chip->request + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * + * We mask out the HW driven pins + */ +static int xway_stp_request(struct gpio_chip *gc, unsigned gpio) +{ + struct xway_stp *chip = + container_of(gc, struct xway_stp, gc); + + if ((gpio < 8) && (chip->reserved & BIT(gpio))) { + dev_err(gc->dev, "GPIO %d is driven by hardware\n", gpio); + return -ENODEV; + } + + return 0; +} + +/** + * xway_stp_hw_init() - Configure the STP unit and enable the clock gate + * @virt: pointer to the remapped register range + */ +static int xway_stp_hw_init(struct xway_stp *chip) +{ + /* sane defaults */ + xway_stp_w32(chip->virt, 0, XWAY_STP_AR); + xway_stp_w32(chip->virt, 0, XWAY_STP_CPU0); + xway_stp_w32(chip->virt, 0, XWAY_STP_CPU1); + xway_stp_w32(chip->virt, XWAY_STP_CON_SWU, XWAY_STP_CON0); + xway_stp_w32(chip->virt, 0, XWAY_STP_CON1); + + /* apply edge trigger settings for the shift register */ + xway_stp_w32_mask(chip->virt, XWAY_STP_EDGE_MASK, + chip->edge, XWAY_STP_CON0); + + /* apply led group settings */ + xway_stp_w32_mask(chip->virt, XWAY_STP_GROUP_MASK, + chip->groups, XWAY_STP_CON1); + + /* tell the hardware which pins are controlled by the dsl modem */ + xway_stp_w32_mask(chip->virt, + XWAY_STP_ADSL_MASK << XWAY_STP_ADSL_SHIFT, + chip->dsl << XWAY_STP_ADSL_SHIFT, + XWAY_STP_CON0); + + /* tell the hardware which pins are controlled by the phys */ + xway_stp_w32_mask(chip->virt, + XWAY_STP_PHY_MASK << XWAY_STP_PHY1_SHIFT, + chip->phy1 << XWAY_STP_PHY1_SHIFT, + XWAY_STP_CON0); + xway_stp_w32_mask(chip->virt, + XWAY_STP_PHY_MASK << XWAY_STP_PHY2_SHIFT, + chip->phy2 << XWAY_STP_PHY2_SHIFT, + XWAY_STP_CON1); + + /* mask out the hw driven bits in gpio_request */ + chip->reserved = (chip->phy2 << 5) | (chip->phy1 << 2) | chip->dsl; + + /* + * if we have pins that are driven by hw, we need to tell the stp what + * clock to use as a timer. + */ + if (chip->reserved) + xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK, + XWAY_STP_UPD_FPI, XWAY_STP_CON1); + + return 0; +} + +static int __devinit xway_stp_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const __be32 *shadow, *groups, *dsl, *phy; + struct xway_stp *chip; + struct clk *clk; + int ret = 0; + + if (!res) { + dev_err(&pdev->dev, "failed to request STP resource\n"); + return -ENOENT; + } + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->virt = devm_request_and_ioremap(&pdev->dev, res); + if (!chip->virt) { + dev_err(&pdev->dev, "failed to remap STP memory\n"); + return -ENOMEM; + } + chip->gc.dev = &pdev->dev; + chip->gc.label = "stp-xway"; + chip->gc.direction_output = xway_stp_dir_out; + chip->gc.set = xway_stp_set; + chip->gc.request = xway_stp_request; + chip->gc.base = -1; + chip->gc.owner = THIS_MODULE; + + /* store the shadow value if one was passed by the devicetree */ + shadow = of_get_property(pdev->dev.of_node, "lantiq,shadow", NULL); + if (shadow) + chip->shadow = be32_to_cpu(*shadow); + + /* find out which gpio groups should be enabled */ + groups = of_get_property(pdev->dev.of_node, "lantiq,groups", NULL); + if (groups) + chip->groups = be32_to_cpu(*groups) & XWAY_STP_GROUP_MASK; + else + chip->groups = XWAY_STP_GROUP0; + chip->gc.ngpio = fls(chip->groups) * 8; + + /* find out which gpios are controlled by the dsl core */ + dsl = of_get_property(pdev->dev.of_node, "lantiq,dsl", NULL); + if (dsl) + chip->dsl = be32_to_cpu(*dsl) & XWAY_STP_ADSL_MASK; + + /* find out which gpios are controlled by the phys */ + if (of_machine_is_compatible("lantiq,ar9") || + of_machine_is_compatible("lantiq,gr9") || + of_machine_is_compatible("lantiq,vr9")) { + phy = of_get_property(pdev->dev.of_node, "lantiq,phy1", NULL); + if (phy) + chip->phy1 = be32_to_cpu(*phy) & XWAY_STP_PHY_MASK; + phy = of_get_property(pdev->dev.of_node, "lantiq,phy2", NULL); + if (phy) + chip->phy2 = be32_to_cpu(*phy) & XWAY_STP_PHY_MASK; + } + + /* check which edge trigger we should use, default to a falling edge */ + if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL)) + chip->edge = XWAY_STP_FALLING; + + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Failed to get clock\n"); + return PTR_ERR(clk); + } + clk_enable(clk); + + ret = xway_stp_hw_init(chip); + if (!ret) + ret = gpiochip_add(&chip->gc); + + if (!ret) + dev_info(&pdev->dev, "Init done\n"); + + return ret; +} + +static const struct of_device_id xway_stp_match[] = { + { .compatible = "lantiq,gpio-stp-xway" }, + {}, +}; +MODULE_DEVICE_TABLE(of, xway_stp_match); + +static struct platform_driver xway_stp_driver = { + .probe = xway_stp_probe, + .driver = { + .name = "gpio-stp-xway", + .owner = THIS_MODULE, + .of_match_table = xway_stp_match, + }, +}; + +int __init xway_stp_init(void) +{ + return platform_driver_register(&xway_stp_driver); +} + +subsys_initcall(xway_stp_init); diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index b5401e3..c03456f 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c @@ -19,9 +19,9 @@ #include <linux/mtd/cfi.h> #include <linux/platform_device.h> #include <linux/mtd/physmap.h> +#include <linux/of.h> #include <lantiq_soc.h> -#include <lantiq_platform.h> /* * The NOR flash is connected to the same external bus unit (EBU) as PCI. @@ -44,8 +44,9 @@ struct ltq_mtd { struct map_info *map; }; -static char ltq_map_name[] = "ltq_nor"; -static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL }; +static const char ltq_map_name[] = "ltq_nor"; +static const char *ltq_probe_types[] __devinitconst = { + "cmdlinepart", "ofpart", NULL }; static map_word ltq_read16(struct map_info *map, unsigned long adr) @@ -108,42 +109,38 @@ ltq_copy_to(struct map_info *map, unsigned long to, spin_unlock_irqrestore(&ebu_lock, flags); } -static int __init +static int __devinit ltq_mtd_probe(struct platform_device *pdev) { - struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev); + struct mtd_part_parser_data ppdata; struct ltq_mtd *ltq_mtd; - struct resource *res; struct cfi_private *cfi; int err; + if (of_machine_is_compatible("lantiq,falcon") && + (ltq_boot_select() != BS_FLASH)) { + dev_err(&pdev->dev, "invalid bootstrap options\n"); + return -ENODEV; + } + ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL); platform_set_drvdata(pdev, ltq_mtd); ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!ltq_mtd->res) { - dev_err(&pdev->dev, "failed to get memory resource"); + dev_err(&pdev->dev, "failed to get memory resource\n"); err = -ENOENT; goto err_out; } - res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start, - resource_size(ltq_mtd->res), dev_name(&pdev->dev)); - if (!ltq_mtd->res) { - dev_err(&pdev->dev, "failed to request mem resource"); - err = -EBUSY; - goto err_out; - } - ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL); - ltq_mtd->map->phys = res->start; - ltq_mtd->map->size = resource_size(res); - ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev, - ltq_mtd->map->phys, ltq_mtd->map->size); + ltq_mtd->map->phys = ltq_mtd->res->start; + ltq_mtd->map->size = resource_size(ltq_mtd->res); + ltq_mtd->map->virt = devm_request_and_ioremap(&pdev->dev, ltq_mtd->res); if (!ltq_mtd->map->virt) { - dev_err(&pdev->dev, "failed to ioremap!\n"); - err = -ENOMEM; - goto err_free; + dev_err(&pdev->dev, "failed to remap mem resource\n"); + err = -EBUSY; + goto err_out; } ltq_mtd->map->name = ltq_map_name; @@ -169,9 +166,9 @@ ltq_mtd_probe(struct platform_device *pdev) cfi->addr_unlock1 ^= 1; cfi->addr_unlock2 ^= 1; - err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, NULL, - ltq_mtd_data->parts, - ltq_mtd_data->nr_parts); + ppdata.of_node = pdev->dev.of_node; + err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, + &ppdata, NULL, 0); if (err) { dev_err(&pdev->dev, "failed to add partitions\n"); goto err_destroy; @@ -204,32 +201,23 @@ ltq_mtd_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id ltq_mtd_match[] = { + { .compatible = "lantiq,nor" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_mtd_match); + static struct platform_driver ltq_mtd_driver = { + .probe = ltq_mtd_probe, .remove = __devexit_p(ltq_mtd_remove), .driver = { - .name = "ltq_nor", + .name = "ltq-nor", .owner = THIS_MODULE, + .of_match_table = ltq_mtd_match, }, }; -static int __init -init_ltq_mtd(void) -{ - int ret = platform_driver_probe(<q_mtd_driver, ltq_mtd_probe); - - if (ret) - pr_err("ltq_nor: error registering platform driver"); - return ret; -} - -static void __exit -exit_ltq_mtd(void) -{ - platform_driver_unregister(<q_mtd_driver); -} - -module_init(init_ltq_mtd); -module_exit(exit_ltq_mtd); +module_platform_driver(ltq_mtd_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c index 9312516..6770538 100644 --- a/drivers/of/of_pci_irq.c +++ b/drivers/of/of_pci_irq.c @@ -15,7 +15,7 @@ * PCI tree until an device-node is found, at which point it will finish * resolving using the OF tree walking. */ -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) +int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq) { struct device_node *dn, *ppnode; struct pci_dev *ppdev; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 111569c..8b91fe7 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2369,7 +2369,7 @@ void pci_enable_acs(struct pci_dev *dev) * number is always 0 (see the Implementation Note in section 2.2.8.1 of * the PCI Express Base Specification, Revision 2.1) */ -u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin) +u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin) { int slot; diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index 96c1cac..02da071 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -31,16 +31,19 @@ #include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> -#include <linux/platform_device.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/gpio.h> #include <lantiq_soc.h> #define PORT_LTQ_ASC 111 #define MAXPORTS 2 #define UART_DUMMY_UER_RX 1 -#define DRVNAME "ltq_asc" +#define DRVNAME "lantiq,asc" #ifdef __BIG_ENDIAN #define LTQ_ASC_TBUF (0x0020 + 3) #define LTQ_ASC_RBUF (0x0024 + 3) @@ -114,6 +117,9 @@ static DEFINE_SPINLOCK(ltq_asc_lock); struct ltq_uart_port { struct uart_port port; + /* clock used to derive divider */ + struct clk *fpiclk; + /* clock gating of the ASC core */ struct clk *clk; unsigned int tx_irq; unsigned int rx_irq; @@ -316,7 +322,9 @@ lqasc_startup(struct uart_port *port) struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); int retval; - port->uartclk = clk_get_rate(ltq_port->clk); + if (ltq_port->clk) + clk_enable(ltq_port->clk); + port->uartclk = clk_get_rate(ltq_port->fpiclk); ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), port->membase + LTQ_ASC_CLC); @@ -382,6 +390,8 @@ lqasc_shutdown(struct uart_port *port) port->membase + LTQ_ASC_RXFCON); ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, port->membase + LTQ_ASC_TXFCON); + if (ltq_port->clk) + clk_disable(ltq_port->clk); } static void @@ -630,7 +640,7 @@ lqasc_console_setup(struct console *co, char *options) port = <q_port->port; - port->uartclk = clk_get_rate(ltq_port->clk); + port->uartclk = clk_get_rate(ltq_port->fpiclk); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); @@ -668,37 +678,32 @@ static struct uart_driver lqasc_reg = { static int __init lqasc_probe(struct platform_device *pdev) { + struct device_node *node = pdev->dev.of_node; struct ltq_uart_port *ltq_port; struct uart_port *port; - struct resource *mmres, *irqres; - int tx_irq, rx_irq, err_irq; - struct clk *clk; + struct resource *mmres, irqres[3]; + int line = 0; int ret; mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!mmres || !irqres) + ret = of_irq_to_resource_table(node, irqres, 3); + if (!mmres || (ret != 3)) { + dev_err(&pdev->dev, + "failed to get memory/irq for serial port\n"); return -ENODEV; + } - if (pdev->id >= MAXPORTS) - return -EBUSY; + /* check if this is the console port */ + if (mmres->start != CPHYSADDR(LTQ_EARLY_ASC)) + line = 1; - if (lqasc_port[pdev->id] != NULL) + if (lqasc_port[line]) { + dev_err(&pdev->dev, "port %d already allocated\n", line); return -EBUSY; - - clk = clk_get(&pdev->dev, "fpi"); - if (IS_ERR(clk)) { - pr_err("failed to get fpi clk\n"); - return -ENOENT; } - tx_irq = platform_get_irq_byname(pdev, "tx"); - rx_irq = platform_get_irq_byname(pdev, "rx"); - err_irq = platform_get_irq_byname(pdev, "err"); - if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0)) - return -ENODEV; - - ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL); + ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port), + GFP_KERNEL); if (!ltq_port) return -ENOMEM; @@ -709,19 +714,26 @@ lqasc_probe(struct platform_device *pdev) port->ops = &lqasc_pops; port->fifosize = 16; port->type = PORT_LTQ_ASC, - port->line = pdev->id; + port->line = line; port->dev = &pdev->dev; - - port->irq = tx_irq; /* unused, just to be backward-compatibe */ + /* unused, just to be backward-compatible */ + port->irq = irqres[0].start; port->mapbase = mmres->start; - ltq_port->clk = clk; + ltq_port->fpiclk = clk_get_fpi(); + if (IS_ERR(ltq_port->fpiclk)) { + pr_err("failed to get fpi clk\n"); + return -ENOENT; + } - ltq_port->tx_irq = tx_irq; - ltq_port->rx_irq = rx_irq; - ltq_port->err_irq = err_irq; + /* not all asc ports have clock gates, lets ignore the return code */ + ltq_port->clk = clk_get(&pdev->dev, NULL); - lqasc_port[pdev->id] = ltq_port; + ltq_port->tx_irq = irqres[0].start; + ltq_port->rx_irq = irqres[1].start; + ltq_port->err_irq = irqres[2].start; + + lqasc_port[line] = ltq_port; platform_set_drvdata(pdev, ltq_port); ret = uart_add_one_port(&lqasc_reg, port); @@ -729,10 +741,17 @@ lqasc_probe(struct platform_device *pdev) return ret; } +static const struct of_device_id ltq_asc_match[] = { + { .compatible = DRVNAME }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_asc_match); + static struct platform_driver lqasc_driver = { .driver = { .name = DRVNAME, .owner = THIS_MODULE, + .of_match_table = ltq_asc_match, }, }; diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 0be8a2f..f76b1688 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -31,6 +31,7 @@ #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/major.h> #include <linux/serial.h> #include <linux/serial_core.h> diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index 4001eee..92c00b2 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -57,6 +57,7 @@ #include <linux/ioport.h> #include <linux/irqflags.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/major.h> #include <linux/serial.h> #include <linux/serial_core.h> diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c index a9593a3..2e74c3a 100644 --- a/drivers/watchdog/lantiq_wdt.c +++ b/drivers/watchdog/lantiq_wdt.c @@ -13,14 +13,15 @@ #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> -#include <linux/platform_device.h> +#include <linux/of_platform.h> #include <linux/uaccess.h> #include <linux/clk.h> #include <linux/io.h> -#include <lantiq.h> +#include <lantiq_soc.h> -/* Section 3.4 of the datasheet +/* + * Section 3.4 of the datasheet * The password sequence protects the WDT control register from unintended * write actions, which might cause malfunction of the WDT. * @@ -70,7 +71,8 @@ ltq_wdt_disable(void) { /* write the first password magic */ ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR); - /* write the second password magic with no config + /* + * write the second password magic with no config * this turns the watchdog off */ ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR); @@ -184,7 +186,7 @@ static struct miscdevice ltq_wdt_miscdev = { .fops = <q_wdt_fops, }; -static int __init +static int __devinit ltq_wdt_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -194,28 +196,27 @@ ltq_wdt_probe(struct platform_device *pdev) dev_err(&pdev->dev, "cannot obtain I/O memory region"); return -ENOENT; } - res = devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), dev_name(&pdev->dev)); - if (!res) { - dev_err(&pdev->dev, "cannot request I/O memory region"); - return -EBUSY; - } - ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); + + ltq_wdt_membase = devm_request_and_ioremap(&pdev->dev, res); if (!ltq_wdt_membase) { dev_err(&pdev->dev, "cannot remap I/O memory region\n"); return -ENOMEM; } /* we do not need to enable the clock as it is always running */ - clk = clk_get(&pdev->dev, "io"); - WARN_ON(!clk); + clk = clk_get_io(); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Failed to get clock\n"); + return -ENOENT; + } ltq_io_region_clk_rate = clk_get_rate(clk); clk_put(clk); + /* find out if the watchdog caused the last reboot */ if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST) ltq_wdt_bootstatus = WDIOF_CARDRESET; + dev_info(&pdev->dev, "Init done\n"); return misc_register(<q_wdt_miscdev); } @@ -227,33 +228,26 @@ ltq_wdt_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id ltq_wdt_match[] = { + { .compatible = "lantiq,wdt" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_wdt_match); static struct platform_driver ltq_wdt_driver = { + .probe = ltq_wdt_probe, .remove = __devexit_p(ltq_wdt_remove), .driver = { - .name = "ltq_wdt", + .name = "wdt", .owner = THIS_MODULE, + .of_match_table = ltq_wdt_match, }, }; -static int __init -init_ltq_wdt(void) -{ - return platform_driver_probe(<q_wdt_driver, ltq_wdt_probe); -} - -static void __exit -exit_ltq_wdt(void) -{ - return platform_driver_unregister(<q_wdt_driver); -} - -module_init(init_ltq_wdt); -module_exit(exit_ltq_wdt); +module_platform_driver(ltq_wdt_driver); module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); - MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); MODULE_DESCRIPTION("Lantiq SoC Watchdog"); MODULE_LICENSE("GPL"); diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h index f93e217..bb115de 100644 --- a/include/linux/of_pci.h +++ b/include/linux/of_pci.h @@ -5,7 +5,7 @@ struct pci_dev; struct of_irq; -int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); +int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq); struct device_node; struct device_node *of_pci_find_child_device(struct device_node *parent, diff --git a/include/linux/pci.h b/include/linux/pci.h index e444f5b..3bbc77e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -680,7 +680,7 @@ int __must_check pci_bus_add_device(struct pci_dev *dev); void pci_read_bridge_bases(struct pci_bus *child); struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res); -u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin); +u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin); int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge); u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp); extern struct pci_dev *pci_dev_get(struct pci_dev *dev); @@ -1685,7 +1685,8 @@ extern void pci_release_bus_of_node(struct pci_bus *bus); /* Arch may override this (weak) */ extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus); -static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) +static inline struct device_node * +pci_device_to_OF_node(const struct pci_dev *pdev) { return pdev ? pdev->dev.of_node : NULL; } |