diff options
Diffstat (limited to 'arch')
98 files changed, 2732 insertions, 484 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 71f15e7..a9668d4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -95,6 +95,7 @@ config ATH79 select CSRC_R4K select DMA_NONCOHERENT select HAVE_CLK + select CLKDEV_LOOKUP select IRQ_CPU select MIPS_MACHINE select SYS_HAS_CPU_MIPS32_R2 @@ -131,7 +132,6 @@ config BCM63XX select IRQ_CPU select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348 - select NR_CPUS_DEFAULT_2 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_HAS_EARLY_PRINTK @@ -445,6 +445,8 @@ config RALINK select SYS_HAS_EARLY_PRINTK select HAVE_MACH_CLKDEV select CLKDEV_LOOKUP + select ARCH_HAS_RESET_CONTROLLER + select RESET_CONTROLLER config SGI_IP22 bool "SGI IP22 (Indy/Indigo2)" @@ -609,7 +611,6 @@ config SIBYTE_SWARM select BOOT_ELF32 select DMA_COHERENT select HAVE_PATA_PLATFORM - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -623,7 +624,6 @@ config SIBYTE_LITTLESUR select BOOT_ELF32 select DMA_COHERENT select HAVE_PATA_PLATFORM - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -635,7 +635,6 @@ config SIBYTE_SENTOSA bool "Sibyte BCM91250E-Sentosa" select BOOT_ELF32 select DMA_COHERENT - select NR_CPUS_DEFAULT_2 select SIBYTE_SB1250 select SWAP_IO_SPACE select SYS_HAS_CPU_SB1 @@ -731,6 +730,7 @@ config CAVIUM_OCTEON_SOC select USB_ARCH_HAS_OHCI select USB_ARCH_HAS_EHCI select HOLES_IN_ZONE + select ARCH_REQUIRE_GPIOLIB help This option supports all of the Octeon reference boards from Cavium Networks. It builds a kernel that dynamically determines the Octeon @@ -1860,7 +1860,6 @@ config MIPS_MT_SMP select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI select MIPS_MT - select NR_CPUS_DEFAULT_2 select SMP select SYS_SUPPORTS_SCHED_SMT if SMP select SYS_SUPPORTS_SMP @@ -2171,12 +2170,6 @@ config SYS_SUPPORTS_MIPS_CMP config SYS_SUPPORTS_SMP bool -config NR_CPUS_DEFAULT_1 - bool - -config NR_CPUS_DEFAULT_2 - bool - config NR_CPUS_DEFAULT_4 bool @@ -2194,10 +2187,8 @@ config NR_CPUS_DEFAULT_64 config NR_CPUS int "Maximum number of CPUs (2-64)" - range 1 64 if NR_CPUS_DEFAULT_1 + range 2 64 depends on SMP - default "1" if NR_CPUS_DEFAULT_1 - default "2" if NR_CPUS_DEFAULT_2 default "4" if NR_CPUS_DEFAULT_4 default "8" if NR_CPUS_DEFAULT_8 default "16" if NR_CPUS_DEFAULT_16 diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 37f9ef3..75a36ad 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -194,6 +194,8 @@ include $(srctree)/arch/mips/Kbuild.platforms ifdef CONFIG_PHYSICAL_START load-y = $(CONFIG_PHYSICAL_START) endif +entry-y = 0x$(shell $(NM) vmlinux 2>/dev/null \ + | grep "\bkernel_entry\b" | cut -f1 -d \ ) cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ @@ -225,6 +227,9 @@ KBUILD_CFLAGS += $(cflags-y) KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y) KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0) +bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \ + VMLINUX_ENTRY_ADDRESS=$(entry-y) + LDFLAGS += -m $(ld-emul) ifdef CONFIG_CC_STACKPROTECTOR @@ -254,9 +259,25 @@ drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/ # suspend and hibernation support drivers-$(CONFIG_PM) += arch/mips/power/ +# boot image targets (arch/mips/boot/) +boot-y := vmlinux.bin +boot-y += vmlinux.ecoff +boot-y += vmlinux.srec +ifeq ($(shell expr $(load-y) \< 0xffffffff80000000 2> /dev/null), 0) +boot-y += uImage +boot-y += uImage.gz +endif + +# compressed boot image targets (arch/mips/boot/compressed/) +bootz-y := vmlinuz +bootz-y += vmlinuz.bin +bootz-y += vmlinuz.ecoff +bootz-y += vmlinuz.srec + ifdef CONFIG_LASAT rom.bin rom.sw: vmlinux - $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@ + $(Q)$(MAKE) $(build)=arch/mips/lasat/image \ + $(bootvars-y) $@ endif # @@ -280,13 +301,14 @@ vmlinux.64: vmlinux all: $(all-y) # boot -vmlinux.bin vmlinux.ecoff vmlinux.srec: $(vmlinux-32) FORCE - $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) arch/mips/boot/$@ +$(boot-y): $(vmlinux-32) FORCE + $(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \ + $(bootvars-y) arch/mips/boot/$@ # boot/compressed -vmlinuz vmlinuz.bin vmlinuz.ecoff vmlinuz.srec: $(vmlinux-32) FORCE +$(bootz-y): $(vmlinux-32) FORCE $(Q)$(MAKE) $(build)=arch/mips/boot/compressed \ - VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $@ + $(bootvars-y) 32bit-bfd=$(32bit-bfd) $@ CLEAN_FILES += vmlinux.32 vmlinux.64 @@ -323,6 +345,8 @@ define archhelp echo ' vmlinuz.ecoff - ECOFF zboot image' echo ' vmlinuz.bin - Raw binary zboot image' echo ' vmlinuz.srec - SREC zboot image' + echo ' uImage - U-Boot image' + echo ' uImage.gz - U-Boot image (gzip)' echo echo ' These will be default as appropriate for a configured platform.' endef diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 765ef30..26479f4 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/clkdev.h> #include <asm/div64.h> @@ -31,92 +32,132 @@ struct clk { unsigned long rate; }; -static struct clk ath79_ref_clk; -static struct clk ath79_cpu_clk; -static struct clk ath79_ddr_clk; -static struct clk ath79_ahb_clk; -static struct clk ath79_wdt_clk; -static struct clk ath79_uart_clk; +static void __init ath79_add_sys_clkdev(const char *id, unsigned long rate) +{ + struct clk *clk; + int err; + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk) + panic("failed to allocate %s clock structure", id); + + clk->rate = rate; + + err = clk_register_clkdev(clk, id, NULL); + if (err) + panic("unable to register %s clock device", id); +} static void __init ar71xx_clocks_init(void) { + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; u32 pll; u32 freq; u32 div; - ath79_ref_clk.rate = AR71XX_BASE_FREQ; + ref_rate = AR71XX_BASE_FREQ; pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; - freq = div * ath79_ref_clk.rate; + freq = div * ref_rate; div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; - ath79_cpu_clk.rate = freq / div; + cpu_rate = freq / div; div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; - ath79_ddr_clk.rate = freq / div; + ddr_rate = freq / div; div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; - ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; + ahb_rate = cpu_rate / div; + + ath79_add_sys_clkdev("ref", ref_rate); + ath79_add_sys_clkdev("cpu", cpu_rate); + ath79_add_sys_clkdev("ddr", ddr_rate); + ath79_add_sys_clkdev("ahb", ahb_rate); - ath79_wdt_clk.rate = ath79_ahb_clk.rate; - ath79_uart_clk.rate = ath79_ahb_clk.rate; + clk_add_alias("wdt", NULL, "ahb", NULL); + clk_add_alias("uart", NULL, "ahb", NULL); } static void __init ar724x_clocks_init(void) { + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; u32 pll; u32 freq; u32 div; - ath79_ref_clk.rate = AR724X_BASE_FREQ; + ref_rate = AR724X_BASE_FREQ; pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK); - freq = div * ath79_ref_clk.rate; + freq = div * ref_rate; div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); freq *= div; - ath79_cpu_clk.rate = freq; + cpu_rate = freq; div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; - ath79_ddr_clk.rate = freq / div; + ddr_rate = freq / div; div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; - ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; + ahb_rate = cpu_rate / div; + + ath79_add_sys_clkdev("ref", ref_rate); + ath79_add_sys_clkdev("cpu", cpu_rate); + ath79_add_sys_clkdev("ddr", ddr_rate); + ath79_add_sys_clkdev("ahb", ahb_rate); - ath79_wdt_clk.rate = ath79_ahb_clk.rate; - ath79_uart_clk.rate = ath79_ahb_clk.rate; + clk_add_alias("wdt", NULL, "ahb", NULL); + clk_add_alias("uart", NULL, "ahb", NULL); } static void __init ar913x_clocks_init(void) { + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; u32 pll; u32 freq; u32 div; - ath79_ref_clk.rate = AR913X_BASE_FREQ; + ref_rate = AR913X_BASE_FREQ; pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG); div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK); - freq = div * ath79_ref_clk.rate; + freq = div * ref_rate; - ath79_cpu_clk.rate = freq; + cpu_rate = freq; div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1; - ath79_ddr_clk.rate = freq / div; + ddr_rate = freq / div; div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2; - ath79_ahb_clk.rate = ath79_cpu_clk.rate / div; + ahb_rate = cpu_rate / div; - ath79_wdt_clk.rate = ath79_ahb_clk.rate; - ath79_uart_clk.rate = ath79_ahb_clk.rate; + ath79_add_sys_clkdev("ref", ref_rate); + ath79_add_sys_clkdev("cpu", cpu_rate); + ath79_add_sys_clkdev("ddr", ddr_rate); + ath79_add_sys_clkdev("ahb", ahb_rate); + + clk_add_alias("wdt", NULL, "ahb", NULL); + clk_add_alias("uart", NULL, "ahb", NULL); } static void __init ar933x_clocks_init(void) { + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; u32 clock_ctrl; u32 cpu_config; u32 freq; @@ -124,21 +165,21 @@ static void __init ar933x_clocks_init(void) t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); if (t & AR933X_BOOTSTRAP_REF_CLK_40) - ath79_ref_clk.rate = (40 * 1000 * 1000); + ref_rate = (40 * 1000 * 1000); else - ath79_ref_clk.rate = (25 * 1000 * 1000); + ref_rate = (25 * 1000 * 1000); clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG); if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { - ath79_cpu_clk.rate = ath79_ref_clk.rate; - ath79_ahb_clk.rate = ath79_ref_clk.rate; - ath79_ddr_clk.rate = ath79_ref_clk.rate; + cpu_rate = ref_rate; + ahb_rate = ref_rate; + ddr_rate = ref_rate; } else { cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG); t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & AR933X_PLL_CPU_CONFIG_REFDIV_MASK; - freq = ath79_ref_clk.rate / t; + freq = ref_rate / t; t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & AR933X_PLL_CPU_CONFIG_NINT_MASK; @@ -153,19 +194,24 @@ static void __init ar933x_clocks_init(void) t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; - ath79_cpu_clk.rate = freq / t; + cpu_rate = freq / t; t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; - ath79_ddr_clk.rate = freq / t; + ddr_rate = freq / t; t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; - ath79_ahb_clk.rate = freq / t; + ahb_rate = freq / t; } - ath79_wdt_clk.rate = ath79_ref_clk.rate; - ath79_uart_clk.rate = ath79_ref_clk.rate; + ath79_add_sys_clkdev("ref", ref_rate); + ath79_add_sys_clkdev("cpu", cpu_rate); + ath79_add_sys_clkdev("ddr", ddr_rate); + ath79_add_sys_clkdev("ahb", ahb_rate); + + clk_add_alias("wdt", NULL, "ahb", NULL); + clk_add_alias("uart", NULL, "ref", NULL); } static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, @@ -174,12 +220,12 @@ static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, u64 t; u32 ret; - t = ath79_ref_clk.rate; + t = ref; t *= nint; do_div(t, ref_div); ret = t; - t = ath79_ref_clk.rate; + t = ref; t *= nfrac; do_div(t, ref_div * frac); ret += t; @@ -190,6 +236,10 @@ static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, static void __init ar934x_clocks_init(void) { + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; u32 cpu_pll, ddr_pll; u32 bootstrap; @@ -199,9 +249,9 @@ static void __init ar934x_clocks_init(void) bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) - ath79_ref_clk.rate = 40 * 1000 * 1000; + ref_rate = 40 * 1000 * 1000; else - ath79_ref_clk.rate = 25 * 1000 * 1000; + ref_rate = 25 * 1000 * 1000; pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { @@ -227,7 +277,7 @@ static void __init ar934x_clocks_init(void) frac = 1 << 6; } - cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, + cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, nfrac, frac, out_div); pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); @@ -254,7 +304,7 @@ static void __init ar934x_clocks_init(void) frac = 1 << 10; } - ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint, + ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, nfrac, frac, out_div); clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); @@ -263,49 +313,58 @@ static void __init ar934x_clocks_init(void) 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; + cpu_rate = ref_rate; else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) - ath79_cpu_clk.rate = cpu_pll / (postdiv + 1); + cpu_rate = cpu_pll / (postdiv + 1); else - ath79_cpu_clk.rate = ddr_pll / (postdiv + 1); + cpu_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; + ddr_rate = ref_rate; else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) - ath79_ddr_clk.rate = ddr_pll / (postdiv + 1); + ddr_rate = ddr_pll / (postdiv + 1); else - ath79_ddr_clk.rate = cpu_pll / (postdiv + 1); + ddr_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; + ahb_rate = ref_rate; else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) - ath79_ahb_clk.rate = ddr_pll / (postdiv + 1); + ahb_rate = ddr_pll / (postdiv + 1); else - ath79_ahb_clk.rate = cpu_pll / (postdiv + 1); + ahb_rate = cpu_pll / (postdiv + 1); + + ath79_add_sys_clkdev("ref", ref_rate); + ath79_add_sys_clkdev("cpu", cpu_rate); + ath79_add_sys_clkdev("ddr", ddr_rate); + ath79_add_sys_clkdev("ahb", ahb_rate); - ath79_wdt_clk.rate = ath79_ref_clk.rate; - ath79_uart_clk.rate = ath79_ref_clk.rate; + clk_add_alias("wdt", NULL, "ref", NULL); + clk_add_alias("uart", NULL, "ref", NULL); iounmap(dpll_base); } static void __init qca955x_clocks_init(void) { + unsigned long ref_rate; + unsigned long cpu_rate; + unsigned long ddr_rate; + unsigned long ahb_rate; u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; u32 cpu_pll, ddr_pll; u32 bootstrap; bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) - ath79_ref_clk.rate = 40 * 1000 * 1000; + ref_rate = 40 * 1000 * 1000; else - ath79_ref_clk.rate = 25 * 1000 * 1000; + ref_rate = 25 * 1000 * 1000; pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & @@ -317,8 +376,8 @@ static void __init qca955x_clocks_init(void) frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; - cpu_pll = nint * ath79_ref_clk.rate / ref_div; - cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6)); + cpu_pll = nint * ref_rate / ref_div; + cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); cpu_pll /= (1 << out_div); pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); @@ -331,8 +390,8 @@ static void __init qca955x_clocks_init(void) frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; - ddr_pll = nint * ath79_ref_clk.rate / ref_div; - ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10)); + ddr_pll = nint * ref_rate / ref_div; + ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); ddr_pll /= (1 << out_div); clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); @@ -341,34 +400,39 @@ static void __init qca955x_clocks_init(void) QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) - ath79_cpu_clk.rate = ath79_ref_clk.rate; + cpu_rate = ref_rate; else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) - ath79_cpu_clk.rate = ddr_pll / (postdiv + 1); + cpu_rate = ddr_pll / (postdiv + 1); else - ath79_cpu_clk.rate = cpu_pll / (postdiv + 1); + cpu_rate = cpu_pll / (postdiv + 1); postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) - ath79_ddr_clk.rate = ath79_ref_clk.rate; + ddr_rate = ref_rate; else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) - ath79_ddr_clk.rate = cpu_pll / (postdiv + 1); + ddr_rate = cpu_pll / (postdiv + 1); else - ath79_ddr_clk.rate = ddr_pll / (postdiv + 1); + ddr_rate = ddr_pll / (postdiv + 1); postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) - ath79_ahb_clk.rate = ath79_ref_clk.rate; + ahb_rate = ref_rate; else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) - ath79_ahb_clk.rate = ddr_pll / (postdiv + 1); + ahb_rate = ddr_pll / (postdiv + 1); else - ath79_ahb_clk.rate = cpu_pll / (postdiv + 1); + ahb_rate = cpu_pll / (postdiv + 1); - ath79_wdt_clk.rate = ath79_ref_clk.rate; - ath79_uart_clk.rate = ath79_ref_clk.rate; + ath79_add_sys_clkdev("ref", ref_rate); + ath79_add_sys_clkdev("cpu", cpu_rate); + ath79_add_sys_clkdev("ddr", ddr_rate); + ath79_add_sys_clkdev("ahb", ahb_rate); + + clk_add_alias("wdt", NULL, "ref", NULL); + clk_add_alias("uart", NULL, "ref", NULL); } void __init ath79_clocks_init(void) @@ -387,46 +451,27 @@ void __init ath79_clocks_init(void) qca955x_clocks_init(); else BUG(); - - pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, " - "Ref:%lu.%03luMHz", - ath79_cpu_clk.rate / 1000000, - (ath79_cpu_clk.rate / 1000) % 1000, - ath79_ddr_clk.rate / 1000000, - (ath79_ddr_clk.rate / 1000) % 1000, - ath79_ahb_clk.rate / 1000000, - (ath79_ahb_clk.rate / 1000) % 1000, - ath79_ref_clk.rate / 1000000, - (ath79_ref_clk.rate / 1000) % 1000); } -/* - * Linux clock API - */ -struct clk *clk_get(struct device *dev, const char *id) +unsigned long __init +ath79_get_sys_clk_rate(const char *id) { - if (!strcmp(id, "ref")) - return &ath79_ref_clk; - - if (!strcmp(id, "cpu")) - return &ath79_cpu_clk; - - if (!strcmp(id, "ddr")) - return &ath79_ddr_clk; - - if (!strcmp(id, "ahb")) - return &ath79_ahb_clk; + struct clk *clk; + unsigned long rate; - if (!strcmp(id, "wdt")) - return &ath79_wdt_clk; + clk = clk_get(NULL, id); + if (IS_ERR(clk)) + panic("unable to get %s clock, err=%d", id, (int) PTR_ERR(clk)); - if (!strcmp(id, "uart")) - return &ath79_uart_clk; + rate = clk_get_rate(clk); + clk_put(clk); - return ERR_PTR(-ENOENT); + return rate; } -EXPORT_SYMBOL(clk_get); +/* + * Linux clock API + */ int clk_enable(struct clk *clk) { return 0; @@ -443,8 +488,3 @@ unsigned long clk_get_rate(struct clk *clk) return clk->rate; } EXPORT_SYMBOL(clk_get_rate); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h index 561906c..648d2da 100644 --- a/arch/mips/ath79/common.h +++ b/arch/mips/ath79/common.h @@ -21,6 +21,8 @@ #define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024) void ath79_clocks_init(void); +unsigned long ath79_get_sys_clk_rate(const char *id); + void ath79_ddr_wb_flush(unsigned int reg); void ath79_gpio_function_enable(u32 mask); diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c index a3a2741..c3b04c9 100644 --- a/arch/mips/ath79/dev-common.c +++ b/arch/mips/ath79/dev-common.c @@ -81,21 +81,19 @@ static struct platform_device ar933x_uart_device = { void __init ath79_register_uart(void) { - struct clk *clk; + unsigned long uart_clk_rate; - clk = clk_get(NULL, "uart"); - if (IS_ERR(clk)) - panic("unable to get UART clock, err=%ld", PTR_ERR(clk)); + uart_clk_rate = ath79_get_sys_clk_rate("uart"); if (soc_is_ar71xx() || soc_is_ar724x() || soc_is_ar913x() || soc_is_ar934x() || soc_is_qca955x()) { - ath79_uart_data[0].uartclk = clk_get_rate(clk); + ath79_uart_data[0].uartclk = uart_clk_rate; platform_device_register(&ath79_uart_device); } else if (soc_is_ar933x()) { - ar933x_uart_data.uartclk = clk_get_rate(clk); + ar933x_uart_data.uartclk = uart_clk_rate; platform_device_register(&ar933x_uart_device); } else { BUG(); diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 80f4ecd..64807a4 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -200,7 +200,6 @@ void __init plat_mem_setup(void) ath79_detect_sys_type(); detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); - ath79_clocks_init(); _machine_restart = ath79_restart; _machine_halt = ath79_halt; @@ -209,13 +208,25 @@ void __init plat_mem_setup(void) void __init plat_time_init(void) { - struct clk *clk; + unsigned long cpu_clk_rate; + unsigned long ahb_clk_rate; + unsigned long ddr_clk_rate; + unsigned long ref_clk_rate; + + ath79_clocks_init(); + + cpu_clk_rate = ath79_get_sys_clk_rate("cpu"); + ahb_clk_rate = ath79_get_sys_clk_rate("ahb"); + ddr_clk_rate = ath79_get_sys_clk_rate("ddr"); + ref_clk_rate = ath79_get_sys_clk_rate("ref"); - clk = clk_get(NULL, "cpu"); - if (IS_ERR(clk)) - panic("unable to get CPU clock, err=%ld", PTR_ERR(clk)); + pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz", + cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000, + ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000, + ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000, + ref_clk_rate / 1000000, (ref_clk_rate / 1000) % 1000); - mips_hpt_frequency = clk_get_rate(clk) / 2; + mips_hpt_frequency = cpu_clk_rate / 2; } static int __init ath79_setup(void) diff --git a/arch/mips/boot/.gitignore b/arch/mips/boot/.gitignore index f210b09..a73d6e2 100644 --- a/arch/mips/boot/.gitignore +++ b/arch/mips/boot/.gitignore @@ -4,3 +4,4 @@ vmlinux.* zImage zImage.tmp calc_vmlinuz_load_addr +uImage diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index 851261e..1466c00 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -40,3 +40,18 @@ quiet_cmd_srec = OBJCOPY $@ cmd_srec = $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $@ $(obj)/vmlinux.srec: $(VMLINUX) FORCE $(call if_changed,srec) + +UIMAGE_LOADADDR = $(VMLINUX_LOAD_ADDRESS) +UIMAGE_ENTRYADDR = $(VMLINUX_ENTRY_ADDRESS) + +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) + +targets += uImage.gz +$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE + $(call if_changed,uimage,gzip) + +targets += uImage +$(obj)/uImage: $(obj)/uImage.gz FORCE + @ln -sf $(notdir $<) $@ + @echo ' Image $@ is ready' diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index bb1dbf4..0048c08 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -25,7 +25,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ \ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \ - -DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | grep " kernel_entry" | cut -f1 -d \ ) + -DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS) targets := head.o decompress.o dbg.o uart-16550.o uart-alchemy.o diff --git a/arch/mips/boot/dts/include/dt-bindings b/arch/mips/boot/dts/include/dt-bindings new file mode 120000 index 0000000..68ae388 --- /dev/null +++ b/arch/mips/boot/dts/include/dt-bindings @@ -0,0 +1 @@ +../../../../../include/dt-bindings diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 9d36774..25fbfae 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1776,7 +1776,7 @@ asmlinkage void plat_irq_dispatch(void) #ifdef CONFIG_HOTPLUG_CPU -void fixup_irqs(void) +void octeon_fixup_irqs(void) { irq_cpu_offline(); } diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 48b08eb..b212ae1 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -8,6 +8,7 @@ * written by Ralf Baechle <ralf@linux-mips.org> */ #include <linux/compiler.h> +#include <linux/vmalloc.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/console.h> @@ -1139,3 +1140,30 @@ static int __init edac_devinit(void) return err; } device_initcall(edac_devinit); + +static void __initdata *octeon_dummy_iospace; + +static int __init octeon_no_pci_init(void) +{ + /* + * Initially assume there is no PCI. The PCI/PCIe platform code will + * later re-initialize these to correct values if they are present. + */ + octeon_dummy_iospace = vzalloc(IO_SPACE_LIMIT); + set_io_port_base((unsigned long)octeon_dummy_iospace); + ioport_resource.start = MAX_RESOURCE; + ioport_resource.end = 0; + return 0; +} +core_initcall(octeon_no_pci_init); + +static int __init octeon_no_pci_release(void) +{ + /* + * Release the allocated memory if a real IO space is there. + */ + if ((unsigned long)octeon_dummy_iospace != mips_io_port_base) + vfree(octeon_dummy_iospace); + return 0; +} +late_initcall(octeon_no_pci_release); diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 138cc80..24a2167 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -255,8 +255,6 @@ static void octeon_cpus_done(void) /* State of each CPU. */ DEFINE_PER_CPU(int, cpu_state); -extern void fixup_irqs(void); - static int octeon_cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -267,7 +265,7 @@ static int octeon_cpu_disable(void) set_cpu_online(cpu, false); cpu_clear(cpu, cpu_callin_map); local_irq_disable(); - fixup_irqs(); + octeon_fixup_irqs(); local_irq_enable(); flush_cache_all(); diff --git a/arch/mips/configs/xway_defconfig b/arch/mips/configs/xway_defconfig new file mode 100644 index 0000000..8987846 --- /dev/null +++ b/arch/mips/configs/xway_defconfig @@ -0,0 +1,159 @@ +CONFIG_LANTIQ=y +CONFIG_XRX200_PHY_FW=y +CONFIG_CPU_MIPS32_R2=y +# CONFIG_COMPACTION is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_HZ_100=y +# CONFIG_SECCOMP is not set +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_GZIP is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_AIO is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_COREDUMP is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_BRIDGE_NETFILTER is not set +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_RAW=m +CONFIG_BRIDGE=y +# CONFIG_BRIDGE_IGMP_SNOOPING is not set +CONFIG_VLAN_8021Q=y +CONFIG_NET_SCHED=y +CONFIG_HAMRADIO=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_LANTIQ=y +CONFIG_EEPROM_93CX6=m +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_NETDEVICES=y +CONFIG_LANTIQ_ETOP=y +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y +CONFIG_PPP=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=m +CONFIG_PPP_ASYNC=m +CONFIG_ISDN=y +CONFIG_INPUT=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SPI=y +CONFIG_GPIO_MM_LANTIQ=y +CONFIG_GPIO_STP_XWAY=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_HID is not set +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_STAGING=y +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +# CONFIG_JFFS2_FS_POSIX_ACL is not set +# CONFIG_JFFS2_FS_SECURITY is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +# CONFIG_JFFS2_ZLIB is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_ZLIB is not set +CONFIG_SQUASHFS_XZ=y +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_STRIP_ASM_SYMS=y +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_ITU_T=m +CONFIG_CRC32_SARWATE=y +CONFIG_AVERAGE=y diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index ea57f39..56ebc7f 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -126,12 +126,13 @@ int rtc_mips_set_mmss(unsigned long nowtime) void __init plat_time_init(void) { u32 start, end; - int i = HZ / 10; + int i = HZ / 8; /* Set up the rate of periodic DS1287 interrupts. */ ds1287_set_base_clock(HZ); if (cpu_has_counter) { + ds1287_timer_state(); while (!ds1287_timer_state()) ; @@ -143,7 +144,7 @@ void __init plat_time_init(void) end = read_c0_count(); - mips_hpt_frequency = (end - start) * 10; + mips_hpt_frequency = (end - start) * 8; printk(KERN_INFO "MIPS counter frequency %dHz\n", mips_hpt_frequency); } else if (IOASIC) diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index 9b54b7a..454ddf9 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -1,2 +1,15 @@ # MIPS headers +generic-y += cputime.h +generic-y += current.h +generic-y += emergency-restart.h +generic-y += local64.h +generic-y += mutex.h +generic-y += parport.h +generic-y += percpu.h +generic-y += scatterlist.h +generic-y += sections.h +generic-y += segment.h +generic-y += serial.h generic-y += trace_clock.h +generic-y += ucontext.h +generic-y += xor.h diff --git a/arch/mips/include/asm/bmips.h b/arch/mips/include/asm/bmips.h index 552a65a..27bd060 100644 --- a/arch/mips/include/asm/bmips.h +++ b/arch/mips/include/asm/bmips.h @@ -65,44 +65,33 @@ static inline unsigned long bmips_read_zscm_reg(unsigned int offset) { unsigned long ret; - __asm__ __volatile__( - ".set push\n" - ".set noreorder\n" - "cache %1, 0(%2)\n" - "sync\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - "mfc0 %0, $28, 3\n" - "_ssnop\n" - ".set pop\n" - : "=&r" (ret) - : "i" (Index_Load_Tag_S), "r" (ZSCM_REG_BASE + offset) - : "memory"); + barrier(); + cache_op(Index_Load_Tag_S, ZSCM_REG_BASE + offset); + __sync(); + _ssnop(); + _ssnop(); + _ssnop(); + _ssnop(); + _ssnop(); + _ssnop(); + _ssnop(); + ret = read_c0_ddatalo(); + _ssnop(); + return ret; } static inline void bmips_write_zscm_reg(unsigned int offset, unsigned long data) { - __asm__ __volatile__( - ".set push\n" - ".set noreorder\n" - "mtc0 %0, $28, 3\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - "cache %1, 0(%2)\n" - "_ssnop\n" - "_ssnop\n" - "_ssnop\n" - : /* no outputs */ - : "r" (data), - "i" (Index_Store_Tag_S), "r" (ZSCM_REG_BASE + offset) - : "memory"); + write_c0_ddatalo(data); + _ssnop(); + _ssnop(); + _ssnop(); + cache_op(Index_Store_Tag_S, ZSCM_REG_BASE + offset); + _ssnop(); + _ssnop(); + _ssnop(); + barrier(); } #endif /* !defined(__ASSEMBLY__) */ diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 632bbe5..71b9f19 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -141,6 +141,9 @@ #define PRID_IMP_CAVIUM_CN68XX 0x9100 #define PRID_IMP_CAVIUM_CN66XX 0x9200 #define PRID_IMP_CAVIUM_CN61XX 0x9300 +#define PRID_IMP_CAVIUM_CNF71XX 0x9400 +#define PRID_IMP_CAVIUM_CN78XX 0x9500 +#define PRID_IMP_CAVIUM_CN70XX 0x9600 /* * These are the PRID's for when 23:16 == PRID_COMP_INGENIC @@ -176,6 +179,7 @@ #define PRID_IMP_NETLOGIC_XLP8XX 0x1000 #define PRID_IMP_NETLOGIC_XLP3XX 0x1100 +#define PRID_IMP_NETLOGIC_XLP2XX 0x1200 /* * Definitions for 7:0 on legacy processors @@ -272,7 +276,7 @@ enum cpu_type_enum { */ CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2, - CPU_XLR, CPU_XLP, + CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP, CPU_LAST }; diff --git a/arch/mips/include/asm/cputime.h b/arch/mips/include/asm/cputime.h deleted file mode 100644 index c00eacb..0000000 --- a/arch/mips/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __MIPS_CPUTIME_H -#define __MIPS_CPUTIME_H - -#include <asm-generic/cputime.h> - -#endif /* __MIPS_CPUTIME_H */ diff --git a/arch/mips/include/asm/current.h b/arch/mips/include/asm/current.h deleted file mode 100644 index 4c51401..0000000 --- a/arch/mips/include/asm/current.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/current.h> diff --git a/arch/mips/include/asm/emergency-restart.h b/arch/mips/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c4..0000000 --- a/arch/mips/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include <asm-generic/emergency-restart.h> - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/mips/include/asm/local64.h b/arch/mips/include/asm/local64.h deleted file mode 100644 index 36c93b5..0000000 --- a/arch/mips/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local64.h> diff --git a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h index ddb947e..0089a74 100644 --- a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h @@ -42,8 +42,6 @@ #define cpu_has_mips64r1 0 #define cpu_has_mips64r2 0 -#define cpu_has_dsp 0 -#define cpu_has_dsp2 0 #define cpu_has_mipsmt 0 #define cpu_has_64bits 0 diff --git a/arch/mips/include/asm/mach-cavium-octeon/gpio.h b/arch/mips/include/asm/mach-cavium-octeon/gpio.h new file mode 100644 index 0000000..34e9f7a --- /dev/null +++ b/arch/mips/include/asm/mach-cavium-octeon/gpio.h @@ -0,0 +1,21 @@ +#ifndef __ASM_MACH_CAVIUM_OCTEON_GPIO_H +#define __ASM_MACH_CAVIUM_OCTEON_GPIO_H + +#ifdef CONFIG_GPIOLIB +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#else +int gpio_request(unsigned gpio, const char *label); +void gpio_free(unsigned gpio); +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +void gpio_set_value(unsigned gpio, int value); +#endif + +#include <asm-generic/gpio.h> + +#define gpio_to_irq __gpio_to_irq + +#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/arch/mips/include/asm/mach-lantiq/falcon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-lantiq/falcon/cpu-feature-overrides.h new file mode 100644 index 0000000..096a100 --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/falcon/cpu-feature-overrides.h @@ -0,0 +1,58 @@ +/* + * Lantiq FALCON specific CPU feature overrides + * + * Copyright (C) 2013 Thomas Langer, Lantiq Deutschland + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * 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_FALCON_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_FALCON_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 + +#define cpu_has_prefetch 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 1 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 1 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 1 +#define cpu_has_mipsmt 1 + +#define cpu_has_vint 1 +#define cpu_has_veic 1 + +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 + +#endif /* __ASM_MACH_FALCON_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h index 9809972..6f9b24f 100644 --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -20,6 +20,8 @@ #define SYSC_REG_CHIP_REV 0x0c #define SYSC_REG_SYSTEM_CONFIG0 0x10 #define SYSC_REG_SYSTEM_CONFIG1 0x14 +#define SYSC_REG_CLKCFG0 0x2c +#define SYSC_REG_CPU_SYS_CLKCFG 0x3c #define SYSC_REG_CPLL_CONFIG0 0x54 #define SYSC_REG_CPLL_CONFIG1 0x58 @@ -29,20 +31,42 @@ #define MT7620A_CHIP_NAME0 0x3637544d #define MT7620A_CHIP_NAME1 0x20203032 +#define SYSCFG0_XTAL_FREQ_SEL BIT(6) + #define CHIP_REV_PKG_MASK 0x1 #define CHIP_REV_PKG_SHIFT 16 #define CHIP_REV_VER_MASK 0xf #define CHIP_REV_VER_SHIFT 8 #define CHIP_REV_ECO_MASK 0xf -#define CPLL_SW_CONFIG_SHIFT 31 -#define CPLL_SW_CONFIG_MASK 0x1 -#define CPLL_CPU_CLK_SHIFT 24 -#define CPLL_CPU_CLK_MASK 0x1 -#define CPLL_MULT_RATIO_SHIFT 16 -#define CPLL_MULT_RATIO 0x7 -#define CPLL_DIV_RATIO_SHIFT 10 -#define CPLL_DIV_RATIO 0x3 +#define CLKCFG0_PERI_CLK_SEL BIT(4) + +#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 +#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf +#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ +#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ +#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ +#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 +#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f +#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 +#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f + +#define CPLL_CFG0_SW_CFG BIT(31) +#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 +#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 +#define CPLL_CFG0_LC_CURFCK BIT(15) +#define CPLL_CFG0_BYPASS_REF_CLK BIT(14) +#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 +#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 + +#define CPLL_CFG1_CPU_AUX1 BIT(25) +#define CPLL_CFG1_CPU_AUX0 BIT(24) #define SYSCFG0_DRAM_TYPE_MASK 0x3 #define SYSCFG0_DRAM_TYPE_SHIFT 4 diff --git a/arch/mips/include/asm/mach-ralink/mt7620/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/mt7620/cpu-feature-overrides.h new file mode 100644 index 0000000..f7bb8cf --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/mt7620/cpu-feature-overrides.h @@ -0,0 +1,57 @@ +/* + * Ralink MT7620 specific CPU feature overrides + * + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * 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 _MT7620_CPU_FEATURE_OVERRIDES_H +#define _MT7620_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 + +#define cpu_has_prefetch 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 1 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 1 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 1 +#define cpu_has_dsp2 0 +#define cpu_has_mipsmt 0 + +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 + +#endif /* _MT7620_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mutex.h b/arch/mips/include/asm/mutex.h deleted file mode 100644 index 458c1f7..0000000 --- a/arch/mips/include/asm/mutex.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Pull in the generic implementation for the mutex fastpath. - * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) - */ - -#include <asm-generic/mutex-dec.h> diff --git a/arch/mips/include/asm/netlogic/xlp-hal/bridge.h b/arch/mips/include/asm/netlogic/xlp-hal/bridge.h index 790f0f1..4e8eacb 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/bridge.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/bridge.h @@ -88,6 +88,7 @@ #define BRIDGE_DRAM_LIMIT6 0x22 #define BRIDGE_DRAM_LIMIT7 0x23 +#define BRIDGE_DRAM_NODE_TRANSLN(i) (0x24 + (i)) #define BRIDGE_DRAM_NODE_TRANSLN0 0x24 #define BRIDGE_DRAM_NODE_TRANSLN1 0x25 #define BRIDGE_DRAM_NODE_TRANSLN2 0x26 @@ -96,6 +97,8 @@ #define BRIDGE_DRAM_NODE_TRANSLN5 0x29 #define BRIDGE_DRAM_NODE_TRANSLN6 0x2a #define BRIDGE_DRAM_NODE_TRANSLN7 0x2b + +#define BRIDGE_DRAM_CHNL_TRANSLN(i) (0x2c + (i)) #define BRIDGE_DRAM_CHNL_TRANSLN0 0x2c #define BRIDGE_DRAM_CHNL_TRANSLN1 0x2d #define BRIDGE_DRAM_CHNL_TRANSLN2 0x2e @@ -104,6 +107,7 @@ #define BRIDGE_DRAM_CHNL_TRANSLN5 0x31 #define BRIDGE_DRAM_CHNL_TRANSLN6 0x32 #define BRIDGE_DRAM_CHNL_TRANSLN7 0x33 + #define BRIDGE_PCIEMEM_BASE0 0x34 #define BRIDGE_PCIEMEM_BASE1 0x35 #define BRIDGE_PCIEMEM_BASE2 0x36 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h index 9fac46f..55eee77 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h @@ -72,6 +72,12 @@ #define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 4) #define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 5) +/* XLP2xx has an updated USB block */ +#define XLP2XX_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 4, i) +#define XLP2XX_IO_USB_XHCI0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 1) +#define XLP2XX_IO_USB_XHCI1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 2) +#define XLP2XX_IO_USB_XHCI2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 3) + #define XLP_IO_NAE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 0) #define XLP_IO_POE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 1) @@ -88,6 +94,9 @@ #define XLP_IO_I2C0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 2) #define XLP_IO_I2C1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 3) #define XLP_IO_GPIO_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 4) +/* on 2XX, all I2C busses are on the same block */ +#define XLP2XX_IO_I2C_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 7) + /* system management */ #define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 5) #define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 6) @@ -145,6 +154,7 @@ #define PCI_DEVICE_ID_NLM_NOR 0x1015 #define PCI_DEVICE_ID_NLM_NAND 0x1016 #define PCI_DEVICE_ID_NLM_MMC 0x1018 +#define PCI_DEVICE_ID_NLM_XHCI 0x101d #ifndef __ASSEMBLY__ diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index 4b5108d..105389b 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -208,13 +208,14 @@ #define PIC_LOCAL_SCHEDULING 1 #define PIC_GLOBAL_SCHEDULING 0 -#define PIC_CLK_HZ 133333333 - #define nlm_read_pic_reg(b, r) nlm_read_reg64(b, r) #define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v) #define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node)) #define nlm_get_pic_regbase(node) (nlm_get_pic_pcibase(node) + XLP_IO_PCI_HDRSZ) +/* We use PIC on node 0 as a timer */ +#define pic_timer_freq() nlm_get_pic_frequency(0) + /* IRT and h/w interrupt routines */ static inline int nlm_pic_read_irt(uint64_t base, int irt_index) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h index 470e52b..fcf2833 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h @@ -117,6 +117,36 @@ #define SYS_SCRTCH2 0x4b #define SYS_SCRTCH3 0x4c +/* PLL registers XLP2XX */ +#define SYS_PLL_CTRL0 0x240 +#define SYS_PLL_CTRL1 0x241 +#define SYS_PLL_CTRL2 0x242 +#define SYS_PLL_CTRL3 0x243 +#define SYS_DMC_PLL_CTRL0 0x244 +#define SYS_DMC_PLL_CTRL1 0x245 +#define SYS_DMC_PLL_CTRL2 0x246 +#define SYS_DMC_PLL_CTRL3 0x247 + +#define SYS_PLL_CTRL0_DEVX(x) (0x248 + (x) * 4) +#define SYS_PLL_CTRL1_DEVX(x) (0x249 + (x) * 4) +#define SYS_PLL_CTRL2_DEVX(x) (0x24a + (x) * 4) +#define SYS_PLL_CTRL3_DEVX(x) (0x24b + (x) * 4) + +#define SYS_CPU_PLL_CHG_CTRL 0x288 +#define SYS_PLL_CHG_CTRL 0x289 +#define SYS_CLK_DEV_DIS 0x28a +#define SYS_CLK_DEV_SEL 0x28b +#define SYS_CLK_DEV_DIV 0x28c +#define SYS_CLK_DEV_CHG 0x28d +#define SYS_CLK_DEV_SEL_REG 0x28e +#define SYS_CLK_DEV_DIV_REG 0x28f +#define SYS_CPU_PLL_LOCK 0x29f +#define SYS_SYS_PLL_LOCK 0x2a0 +#define SYS_PLL_MEM_CMD 0x2a1 +#define SYS_CPU_PLL_MEM_REQ 0x2a2 +#define SYS_SYS_PLL_MEM_REQ 0x2a3 +#define SYS_PLL_MEM_STAT 0x2a4 + #ifndef __ASSEMBLY__ #define nlm_read_sys_reg(b, r) nlm_read_reg(b, r) @@ -124,5 +154,6 @@ #define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node)) #define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ) +unsigned int nlm_get_pic_frequency(int node); #endif #endif diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index f4ea0f7..17daffb2 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -41,15 +41,22 @@ #define PIC_PCIE_LINK_1_IRQ 20 #define PIC_PCIE_LINK_2_IRQ 21 #define PIC_PCIE_LINK_3_IRQ 22 + #define PIC_EHCI_0_IRQ 23 #define PIC_EHCI_1_IRQ 24 #define PIC_OHCI_0_IRQ 25 #define PIC_OHCI_1_IRQ 26 #define PIC_OHCI_2_IRQ 27 #define PIC_OHCI_3_IRQ 28 +#define PIC_2XX_XHCI_0_IRQ 23 +#define PIC_2XX_XHCI_1_IRQ 24 +#define PIC_2XX_XHCI_2_IRQ 25 + #define PIC_MMC_IRQ 29 #define PIC_I2C_0_IRQ 30 #define PIC_I2C_1_IRQ 31 +#define PIC_I2C_2_IRQ 32 +#define PIC_I2C_3_IRQ 33 #ifndef __ASSEMBLY__ @@ -59,7 +66,17 @@ void xlp_wakeup_secondary_cpus(void); void xlp_mmu_init(void); void nlm_hal_init(void); +int xlp_get_dram_map(int n, uint64_t *dram_map); + +/* Device tree related */ void *xlp_dt_init(void *fdtp); +static inline int cpu_is_xlpii(void) +{ + int chip = read_c0_prid() & 0xff00; + + return chip == PRID_IMP_NETLOGIC_XLP2XX; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_NLM_XLP_H */ diff --git a/arch/mips/include/asm/netlogic/xlr/pic.h b/arch/mips/include/asm/netlogic/xlr/pic.h index 63c9917..3c80a75 100644 --- a/arch/mips/include/asm/netlogic/xlr/pic.h +++ b/arch/mips/include/asm/netlogic/xlr/pic.h @@ -36,6 +36,8 @@ #define _ASM_NLM_XLR_PIC_H #define PIC_CLK_HZ 66666666 +#define pic_timer_freq() PIC_CLK_HZ + /* PIC hardware interrupt numbers */ #define PIC_IRT_WD_INDEX 0 #define PIC_IRT_TIMER_0_INDEX 1 diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index a2eed23..f5d77b9 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -251,4 +251,6 @@ extern void (*octeon_irq_setup_secondary)(void); typedef void (*octeon_irq_ip4_handler_t)(void); void octeon_irq_set_ip4_handler(octeon_irq_ip4_handler_t); +extern void octeon_fixup_irqs(void); + #endif /* __ASM_OCTEON_OCTEON_H */ diff --git a/arch/mips/include/asm/parport.h b/arch/mips/include/asm/parport.h deleted file mode 100644 index cf252af..0000000 --- a/arch/mips/include/asm/parport.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/parport.h> diff --git a/arch/mips/include/asm/percpu.h b/arch/mips/include/asm/percpu.h deleted file mode 100644 index 844e763..0000000 --- a/arch/mips/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_PERCPU_H -#define __ASM_PERCPU_H - -#include <asm-generic/percpu.h> - -#endif /* __ASM_PERCPU_H */ diff --git a/arch/mips/include/asm/scatterlist.h b/arch/mips/include/asm/scatterlist.h deleted file mode 100644 index 7ee0e64..0000000 --- a/arch/mips/include/asm/scatterlist.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SCATTERLIST_H -#define __ASM_SCATTERLIST_H - -#include <asm-generic/scatterlist.h> - -#endif /* __ASM_SCATTERLIST_H */ diff --git a/arch/mips/include/asm/sections.h b/arch/mips/include/asm/sections.h deleted file mode 100644 index b7e3726..0000000 --- a/arch/mips/include/asm/sections.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_SECTIONS_H -#define _ASM_SECTIONS_H - -#include <asm-generic/sections.h> - -#endif /* _ASM_SECTIONS_H */ diff --git a/arch/mips/include/asm/segment.h b/arch/mips/include/asm/segment.h deleted file mode 100644 index 92ac001..0000000 --- a/arch/mips/include/asm/segment.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_SEGMENT_H -#define _ASM_SEGMENT_H - -/* Only here because we have some old header files that expect it.. */ - -#endif /* _ASM_SEGMENT_H */ diff --git a/arch/mips/include/asm/serial.h b/arch/mips/include/asm/serial.h deleted file mode 100644 index a0cb0ca..0000000 --- a/arch/mips/include/asm/serial.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/serial.h> diff --git a/arch/mips/include/asm/ucontext.h b/arch/mips/include/asm/ucontext.h deleted file mode 100644 index 9bc07b9..0000000 --- a/arch/mips/include/asm/ucontext.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ucontext.h> diff --git a/arch/mips/include/asm/xor.h b/arch/mips/include/asm/xor.h deleted file mode 100644 index c82eb12..0000000 --- a/arch/mips/include/asm/xor.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/xor.h> diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild index 350cccc..be7196e 100644 --- a/arch/mips/include/uapi/asm/Kbuild +++ b/arch/mips/include/uapi/asm/Kbuild @@ -1,7 +1,9 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm -header-y += auxvec.h +generic-y += auxvec.h +generic-y += ipcbuf.h + header-y += bitsperlong.h header-y += break.h header-y += byteorder.h @@ -11,7 +13,6 @@ header-y += fcntl.h header-y += inst.h header-y += ioctl.h header-y += ioctls.h -header-y += ipcbuf.h header-y += kvm_para.h header-y += mman.h header-y += msgbuf.h diff --git a/arch/mips/include/uapi/asm/auxvec.h b/arch/mips/include/uapi/asm/auxvec.h deleted file mode 100644 index 7cf7f2d..0000000 --- a/arch/mips/include/uapi/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _ASM_AUXVEC_H -#define _ASM_AUXVEC_H - -#endif /* _ASM_AUXVEC_H */ diff --git a/arch/mips/include/uapi/asm/ipcbuf.h b/arch/mips/include/uapi/asm/ipcbuf.h deleted file mode 100644 index 84c7e51..0000000 --- a/arch/mips/include/uapi/asm/ipcbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ipcbuf.h> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 4c6167a..37663c7 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -852,10 +852,17 @@ platform: case PRID_IMP_CAVIUM_CN63XX: case PRID_IMP_CAVIUM_CN66XX: case PRID_IMP_CAVIUM_CN68XX: + case PRID_IMP_CAVIUM_CNF71XX: c->cputype = CPU_CAVIUM_OCTEON2; __cpu_name[cpu] = "Cavium Octeon II"; set_elf_platform(cpu, "octeon2"); break; + case PRID_IMP_CAVIUM_CN70XX: + case PRID_IMP_CAVIUM_CN78XX: + c->cputype = CPU_CAVIUM_OCTEON3; + __cpu_name[cpu] = "Cavium Octeon III"; + set_elf_platform(cpu, "octeon3"); + break; default: printk(KERN_INFO "Unknown Octeon chip!\n"); c->cputype = CPU_UNKNOWN; @@ -899,6 +906,11 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) MIPS_CPU_LLSC); switch (c->processor_id & 0xff00) { + case PRID_IMP_NETLOGIC_XLP2XX: + c->cputype = CPU_XLP; + __cpu_name[cpu] = "Broadcom XLPII"; + break; + case PRID_IMP_NETLOGIC_XLP8XX: case PRID_IMP_NETLOGIC_XLP3XX: c->cputype = CPU_XLP; diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c index 0654bff..87e88fe 100644 --- a/arch/mips/kernel/csrc-ioasic.c +++ b/arch/mips/kernel/csrc-ioasic.c @@ -41,9 +41,9 @@ void __init dec_ioasic_clocksource_init(void) { unsigned int freq; u32 start, end; - int i = HZ / 10; - + int i = HZ / 8; + ds1287_timer_state(); while (!ds1287_timer_state()) ; @@ -55,7 +55,7 @@ void __init dec_ioasic_clocksource_init(void) end = dec_ioasic_hpt_read(&clocksource_dec); - freq = (end - start) * 10; + freq = (end - start) * 8; printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq); clocksource_dec.rating = 200 + freq / 10000000; diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 0c655de..42f8875 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -166,6 +166,7 @@ void __init check_wait(void) case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: + case CPU_CAVIUM_OCTEON3: case CPU_JZRISC: case CPU_LOONGSON1: case CPU_XLR: diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index a03e93c..539b629 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -83,7 +83,7 @@ _mcount: PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp) #endif - move a0, ra /* arg1: self return address */ + PTR_SUBU a0, ra, 8 /* arg1: self address */ .globl ftrace_call ftrace_call: nop /* a placeholder for the call to a real tracing function */ diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S index 43d2d78..74bab9d 100644 --- a/arch/mips/kernel/relocate_kernel.S +++ b/arch/mips/kernel/relocate_kernel.S @@ -26,6 +26,12 @@ process_entry: PTR_L s2, (s0) PTR_ADD s0, s0, SZREG + /* + * In case of a kdump/crash kernel, the indirection page is not + * populated as the kernel is directly copied to a reserved location + */ + beqz s2, done + /* destination page */ and s3, s2, 0x1 beq s3, zero, 1f diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index c7f9051..c538d6e 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -552,6 +552,52 @@ static void __init arch_mem_addpart(phys_t mem, phys_t end, int type) add_memory_region(mem, size, type); } +#ifdef CONFIG_KEXEC +static inline unsigned long long get_total_mem(void) +{ + unsigned long long total; + + total = max_pfn - min_low_pfn; + return total << PAGE_SHIFT; +} + +static void __init mips_parse_crashkernel(void) +{ + unsigned long long total_mem; + unsigned long long crash_size, crash_base; + int ret; + + total_mem = get_total_mem(); + ret = parse_crashkernel(boot_command_line, total_mem, + &crash_size, &crash_base); + if (ret != 0 || crash_size <= 0) + return; + + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size - 1; +} + +static void __init request_crashkernel(struct resource *res) +{ + int ret; + + ret = request_resource(res, &crashk_res); + if (!ret) + pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", + (unsigned long)((crashk_res.end - + crashk_res.start + 1) >> 20), + (unsigned long)(crashk_res.start >> 20)); +} +#else /* !defined(CONFIG_KEXEC) */ +static void __init mips_parse_crashkernel(void) +{ +} + +static void __init request_crashkernel(struct resource *res) +{ +} +#endif /* !defined(CONFIG_KEXEC) */ + static void __init arch_mem_init(char **cmdline_p) { extern void plat_mem_setup(void); @@ -608,6 +654,8 @@ static void __init arch_mem_init(char **cmdline_p) BOOTMEM_DEFAULT); } #endif + + mips_parse_crashkernel(); #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) reserve_bootmem(crashk_res.start, @@ -620,52 +668,6 @@ static void __init arch_mem_init(char **cmdline_p) paging_init(); } -#ifdef CONFIG_KEXEC -static inline unsigned long long get_total_mem(void) -{ - unsigned long long total; - - total = max_pfn - min_low_pfn; - return total << PAGE_SHIFT; -} - -static void __init mips_parse_crashkernel(void) -{ - unsigned long long total_mem; - unsigned long long crash_size, crash_base; - int ret; - - total_mem = get_total_mem(); - ret = parse_crashkernel(boot_command_line, total_mem, - &crash_size, &crash_base); - if (ret != 0 || crash_size <= 0) - return; - - crashk_res.start = crash_base; - crashk_res.end = crash_base + crash_size - 1; -} - -static void __init request_crashkernel(struct resource *res) -{ - int ret; - - ret = request_resource(res, &crashk_res); - if (!ret) - pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", - (unsigned long)((crashk_res.end - - crashk_res.start + 1) >> 20), - (unsigned long)(crashk_res.start >> 20)); -} -#else /* !defined(CONFIG_KEXEC) */ -static void __init mips_parse_crashkernel(void) -{ -} - -static void __init request_crashkernel(struct resource *res) -{ -} -#endif /* !defined(CONFIG_KEXEC) */ - static void __init resource_init(void) { int i; @@ -678,11 +680,6 @@ static void __init resource_init(void) data_resource.start = __pa_symbol(&_etext); data_resource.end = __pa_symbol(&_edata) - 1; - /* - * Request address space for all standard RAM. - */ - mips_parse_crashkernel(); - for (i = 0; i < boot_mem_map.nr_map; i++) { struct resource *res; unsigned long start, end; diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 9d686bf..364d26a 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -121,6 +121,14 @@ void __init time_init(void) { plat_time_init(); - if (!mips_clockevent_init() || !cpu_has_mfc0_count_bug()) + /* + * The use of the R4k timer as a clock event takes precedence; + * if reading the Count register might interfere with the timer + * interrupt, then we don't use the timer as a clock source. + * We may still use the timer as a clock source though if the + * timer interrupt isn't reliable; the interference doesn't + * matter then, because we don't use the interrupt. + */ + if (mips_clockevent_init() != 0 || !cpu_has_mfc0_count_bug()) init_mips_clocksource(); } diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 05826d2..3b46f7c 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -179,5 +179,6 @@ SECTIONS *(.options) *(.pdr) *(.reginfo) + *(.eh_frame) } } diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index ff4894a..8f1866d 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c @@ -48,6 +48,7 @@ #define CPU0CC_CPUDIV 0x0001 /* Activation Status Register */ +#define ACTS_ASC0_ACT 0x00001000 #define ACTS_ASC1_ACT 0x00000800 #define ACTS_I2C_ACT 0x00004000 #define ACTS_P0 0x00010000 @@ -108,6 +109,7 @@ static void sysctl_deactivate(struct clk *clk) static int sysctl_clken(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_CLKS); return 0; } @@ -256,6 +258,7 @@ void __init ltq_soc_init(void) 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("1e100b00.serial", SYSCTL_SYS1, ACTS_ASC1_ACT); + clkdev_add_sys("1e100c00.serial", SYSCTL_SYS1, ACTS_ASC0_ACT); clkdev_add_sys("1e200000.i2c", SYSCTL_SYS1, ACTS_I2C_ACT); } diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile index 7a13660..087497d 100644 --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile @@ -1,3 +1,3 @@ -obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o +obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o dcdc.o obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o diff --git a/arch/mips/lantiq/xway/dcdc.c b/arch/mips/lantiq/xway/dcdc.c new file mode 100644 index 0000000..7688ac0 --- /dev/null +++ b/arch/mips/lantiq/xway/dcdc.c @@ -0,0 +1,63 @@ +/* + * 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> + * Copyright (C) 2010 Sameer Ahmad, Lantiq GmbH + */ + +#include <linux/ioport.h> +#include <linux/of_platform.h> + +#include <lantiq_soc.h> + +/* Bias and regulator Setup Register */ +#define DCDC_BIAS_VREG0 0xa +/* Bias and regulator Setup Register */ +#define DCDC_BIAS_VREG1 0xb + +#define dcdc_w8(x, y) ltq_w8((x), dcdc_membase + (y)) +#define dcdc_r8(x) ltq_r8(dcdc_membase + (x)) + +static void __iomem *dcdc_membase; + +static int dcdc_probe(struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dcdc_membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dcdc_membase)) + return PTR_ERR(dcdc_membase); + + dev_info(&pdev->dev, "Core Voltage : %d mV\n", + dcdc_r8(DCDC_BIAS_VREG1) * 8); + + return 0; +} + +static const struct of_device_id dcdc_match[] = { + { .compatible = "lantiq,dcdc-xrx200" }, + {}, +}; + +static struct platform_driver dcdc_driver = { + .probe = dcdc_probe, + .driver = { + .name = "dcdc-xrx200", + .owner = THIS_MODULE, + .of_match_table = dcdc_match, + }, +}; + +int __init dcdc_init(void) +{ + int ret = platform_driver_register(&dcdc_driver); + + if (ret) + pr_info("dcdc: Error registering platform driver\n"); + return ret; +} + +arch_initcall(dcdc_init); diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile index dfb509d..fd32075 100644 --- a/arch/mips/lasat/image/Makefile +++ b/arch/mips/lasat/image/Makefile @@ -13,13 +13,11 @@ endif MKLASATIMG = mklasatimg MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200 KERNEL_IMAGE = vmlinux -KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ ) -KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ ) LDSCRIPT= -L$(srctree)/$(src) -Tromscript.normal -HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \ - -D_kernel_entry=0x$(KERNEL_ENTRY) \ +HEAD_DEFINES := -D_kernel_start=$(VMLINUX_LOAD_ADDRESS) \ + -D_kernel_entry=$(VMLINUX_ENTRY_ADDRESS) \ -D VERSION="\"$(Version)\"" \ -D TIMESTAMP=$(shell date +%s) diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index 4c57b3e..9e4484c 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -3,8 +3,9 @@ # obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ - pci.o bonito-irq.o mem.o machtype.o platform.o + bonito-irq.o mem.o machtype.o platform.o obj-$(CONFIG_GPIOLIB) += gpio.o +obj-$(CONFIG_PCI) += pci.o # # Serial port support diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 46048d2..efe0088 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -436,7 +436,6 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr) break; default: return SIGILL; - break; } break; case mm_32f_74_op: /* c.cond.fmt */ @@ -451,12 +450,10 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr) break; default: return SIGILL; - break; } break; default: return SIGILL; - break; } *insn_ptr = mips32_insn; @@ -491,7 +488,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.next_pc_inc; *contpc = regs->regs[insn.mm_i_format.rs]; return 1; - break; } } break; @@ -513,7 +509,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_bgezals_op: case mm_bgezal_op: regs->regs[31] = regs->cp0_epc + @@ -530,7 +525,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_blez_op: if ((long)regs->regs[insn.mm_i_format.rs] <= 0) *contpc = regs->cp0_epc + @@ -541,7 +535,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_bgtz_op: if ((long)regs->regs[insn.mm_i_format.rs] <= 0) *contpc = regs->cp0_epc + @@ -552,7 +545,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_bc2f_op: case mm_bc1f_op: bc_false = 1; @@ -580,7 +572,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; } break; case mm_pool16c_op: @@ -593,7 +584,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, case mm_jr16_op: *contpc = regs->regs[insn.mm_i_format.rs]; return 1; - break; } break; case mm_beqz16_op: @@ -605,7 +595,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_bnez16_op: if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0) *contpc = regs->cp0_epc + @@ -615,12 +604,10 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_b16_op: *contpc = regs->cp0_epc + dec_insn.pc_inc + (insn.mm_b0_format.simmediate << 1); return 1; - break; case mm_beq32_op: if (regs->regs[insn.mm_i_format.rs] == regs->regs[insn.mm_i_format.rt]) @@ -632,7 +619,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_bne32_op: if (regs->regs[insn.mm_i_format.rs] != regs->regs[insn.mm_i_format.rt]) @@ -643,7 +629,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case mm_jalx32_op: regs->regs[31] = regs->cp0_epc + dec_insn.pc_inc + dec_insn.next_pc_inc; @@ -652,7 +637,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc <<= 28; *contpc |= (insn.j_format.target << 2); return 1; - break; case mm_jals32_op: case mm_jal32_op: regs->regs[31] = regs->cp0_epc + @@ -665,7 +649,6 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, *contpc |= (insn.j_format.target << 1); set_isa16_mode(*contpc); return 1; - break; } return 0; } @@ -694,7 +677,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, case jr_op: *contpc = regs->regs[insn.r_format.rs]; return 1; - break; } break; case bcond_op: @@ -716,7 +698,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case bgezal_op: case bgezall_op: regs->regs[31] = regs->cp0_epc + @@ -734,7 +715,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; } break; case jalx_op: @@ -752,7 +732,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, /* Set microMIPS mode bit: XOR for jalx. */ *contpc ^= bit; return 1; - break; case beq_op: case beql_op: if (regs->regs[insn.i_format.rs] == @@ -765,7 +744,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case bne_op: case bnel_op: if (regs->regs[insn.i_format.rs] != @@ -778,7 +756,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case blez_op: case blezl_op: if ((long)regs->regs[insn.i_format.rs] <= 0) @@ -790,7 +767,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case bgtz_op: case bgtzl_op: if ((long)regs->regs[insn.i_format.rs] > 0) @@ -802,7 +778,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; #ifdef CONFIG_CPU_CAVIUM_OCTEON case lwc2_op: /* This is bbit0 on Octeon */ if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0) @@ -856,7 +831,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; case 1: /* bc1t */ case 3: /* bc1tl */ if (fcr31 & (1 << bit)) @@ -868,7 +842,6 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, dec_insn.pc_inc + dec_insn.next_pc_inc; return 1; - break; } } break; diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index a0bcdbb..729e770 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -224,6 +224,20 @@ static void probe_octeon(void) c->options |= MIPS_CPU_PREFETCH; break; + case CPU_CAVIUM_OCTEON3: + c->icache.linesz = 128; + c->icache.sets = 16; + c->icache.ways = 39; + c->icache.flags |= MIPS_CACHE_VTAG; + icache_size = c->icache.sets * c->icache.ways * c->icache.linesz; + + c->dcache.linesz = 128; + c->dcache.ways = 32; + c->dcache.sets = 8; + dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz; + c->options |= MIPS_CPU_PREFETCH; + break; + default: panic("Unsupported Cavium Networks CPU type"); break; diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index aaccf1c..664e523 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -50,16 +50,20 @@ static inline struct page *dma_addr_to_page(struct device *dev, } /* + * The affected CPUs below in 'cpu_needs_post_dma_flush()' can + * speculatively fill random cachelines with stale data at any time, + * requiring an extra flush post-DMA. + * * Warning on the terminology - Linux calls an uncached area coherent; * MIPS terminology calls memory areas with hardware maintained coherency * coherent. */ - -static inline int cpu_is_noncoherent_r10000(struct device *dev) +static inline int cpu_needs_post_dma_flush(struct device *dev) { return !plat_device_is_coherent(dev) && - (current_cpu_type() == CPU_R10000 || - current_cpu_type() == CPU_R12000); + (boot_cpu_type() == CPU_R10000 || + boot_cpu_type() == CPU_R12000 || + boot_cpu_type() == CPU_BMIPS5000); } static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) @@ -230,7 +234,7 @@ static inline void __dma_sync(struct page *page, static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { - if (cpu_is_noncoherent_r10000(dev)) + if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_addr), dma_addr & ~PAGE_MASK, size, direction); @@ -284,7 +288,7 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, static void mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - if (cpu_is_noncoherent_r10000(dev)) + if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_handle), dma_handle & ~PAGE_MASK, size, direction); } @@ -305,7 +309,7 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { - if (cpu_is_noncoherent_r10000(dev)) + if (cpu_needs_post_dma_flush(dev)) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); } diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index d4ea5c9..06ce17c 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c @@ -12,6 +12,7 @@ #include <linux/swap.h> #include <linux/hugetlb.h> +#include <asm/cpu-features.h> #include <asm/pgtable.h> static inline pte_t gup_get_pte(pte_t *ptep) @@ -273,7 +274,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (end < start) + if (end < start || cpu_has_dc_aliases) goto slow_irqon; /* XXX: batch / limit 'nr' */ diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 4e73f10..e205ef5 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -254,6 +254,7 @@ void copy_from_user_page(struct vm_area_struct *vma, SetPageDcacheDirty(page); } } +EXPORT_SYMBOL_GPL(copy_from_user_page); void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S index 30a494d..79bca31 100644 --- a/arch/mips/mm/tlb-funcs.S +++ b/arch/mips/mm/tlb-funcs.S @@ -16,10 +16,12 @@ #define FASTPATH_SIZE 128 +#ifdef CONFIG_MIPS_PGD_C0_CONTEXT LEAF(tlbmiss_handler_setup_pgd) .space 16 * 4 END(tlbmiss_handler_setup_pgd) EXPORT(tlbmiss_handler_setup_pgd_end) +#endif LEAF(handle_tlbm) .space FASTPATH_SIZE * 4 diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 556cb48..821b451 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -85,6 +85,7 @@ static int use_bbit_insns(void) case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: + case CPU_CAVIUM_OCTEON3: return 1; default: return 0; @@ -95,6 +96,7 @@ static int use_lwx_insns(void) { switch (current_cpu_type()) { case CPU_CAVIUM_OCTEON2: + case CPU_CAVIUM_OCTEON3: return 1; default: return 0; diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index 2447bf9..852a4ee 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -19,6 +19,15 @@ config DT_XLP_SVP pointer to the kernel. The corresponding DTS file is at arch/mips/netlogic/dts/xlp_svp.dts +config DT_XLP_FVP + bool "Built-in device tree for XLP FVP boards" + default y + help + Add an FDT blob for XLP FVP board into the kernel. + This DTB will be used if the firmware does not pass in a DTB + pointer to the kernel. The corresponding DTS file is at + arch/mips/netlogic/dts/xlp_fvp.dts + config NLM_MULTINODE bool "Support for multi-chip boards" depends on NLM_XLP_BOARD diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index 4e35d9c..6f8feb9 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -106,9 +106,7 @@ void nlm_early_init_secondary(int cpu) { change_c0_config(CONF_CM_CMASK, 0x3); #ifdef CONFIG_CPU_XLP - /* mmu init, once per core */ - if (cpu % NLM_THREADS_PER_CORE == 0) - xlp_mmu_init(); + xlp_mmu_init(); #endif write_c0_ebase(nlm_current_node()->ebase); } diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c index 045a396..13391b8 100644 --- a/arch/mips/netlogic/common/time.c +++ b/arch/mips/netlogic/common/time.c @@ -45,6 +45,7 @@ #if defined(CONFIG_CPU_XLP) #include <asm/netlogic/xlp-hal/iomap.h> #include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/sys.h> #include <asm/netlogic/xlp-hal/pic.h> #elif defined(CONFIG_CPU_XLR) #include <asm/netlogic/xlr/iomap.h> @@ -91,7 +92,7 @@ static void nlm_init_pic_timer(void) csrc_pic.read = nlm_get_pic_timer; } csrc_pic.rating = 1000; - clocksource_register_hz(&csrc_pic, PIC_CLK_HZ); + clocksource_register_hz(&csrc_pic, pic_timer_freq()); } void __init plat_time_init(void) diff --git a/arch/mips/netlogic/dts/Makefile b/arch/mips/netlogic/dts/Makefile index aecb6fa..0b9be5f 100644 --- a/arch/mips/netlogic/dts/Makefile +++ b/arch/mips/netlogic/dts/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o obj-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb.o +obj-$(CONFIG_DT_XLP_FVP) += xlp_fvp.dtb.o diff --git a/arch/mips/netlogic/dts/xlp_evp.dts b/arch/mips/netlogic/dts/xlp_evp.dts index 0640703..89ad048 100644 --- a/arch/mips/netlogic/dts/xlp_evp.dts +++ b/arch/mips/netlogic/dts/xlp_evp.dts @@ -9,19 +9,12 @@ #address-cells = <2>; #size-cells = <2>; - memory { - device_type = "memory"; - reg = <0 0x00100000 0 0x0FF00000 // 255M at 1M - 0 0x20000000 0 0xa0000000 // 2560M at 512M - 0 0xe0000000 1 0x00000000>; - }; - soc { #address-cells = <2>; #size-cells = <1>; compatible = "simple-bus"; ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG - 1 0 0 0x16000000 0x01000000>; // GBU chipselects + 1 0 0 0x16000000 0x02000000>; // GBU chipselects serial0: serial@30000 { device_type = "serial"; diff --git a/arch/mips/netlogic/dts/xlp_fvp.dts b/arch/mips/netlogic/dts/xlp_fvp.dts new file mode 100644 index 0000000..63e62b7 --- /dev/null +++ b/arch/mips/netlogic/dts/xlp_fvp.dts @@ -0,0 +1,118 @@ +/* + * XLP2XX Device Tree Source for FVP boards + */ + +/dts-v1/; +/ { + model = "netlogic,XLP-FVP"; + compatible = "netlogic,xlp"; + #address-cells = <2>; + #size-cells = <2>; + + soc { + #address-cells = <2>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG + 1 0 0 0x16000000 0x02000000>; // GBU chipselects + + serial0: serial@30000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0 0x30100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <133333333>; + interrupt-parent = <&pic>; + interrupts = <17>; + }; + serial1: serial@31000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0 0x31100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <133333333>; + interrupt-parent = <&pic>; + interrupts = <18>; + }; + i2c0: ocores@37100 { + compatible = "opencores,i2c-ocores"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0 0x37100 0x20>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <32000000>; + interrupt-parent = <&pic>; + interrupts = <30>; + }; + i2c1: ocores@37120 { + compatible = "opencores,i2c-ocores"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0 0x37120 0x20>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <32000000>; + interrupt-parent = <&pic>; + interrupts = <31>; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + }; + + dtt@4c { + compatible = "national,lm90"; + reg = <0x4c>; + }; + }; + pic: pic@4000 { + compatible = "netlogic,xlp-pic"; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0 0x4000 0x200>; + interrupt-controller; + }; + + nor_flash@1,0 { + compatible = "cfi-flash"; + #address-cells = <1>; + #size-cells = <1>; + bank-width = <2>; + reg = <1 0 0x1000000>; + + partition@0 { + label = "x-loader"; + reg = <0x0 0x100000>; /* 1M */ + read-only; + }; + + partition@100000 { + label = "u-boot"; + reg = <0x100000 0x100000>; /* 1M */ + }; + + partition@200000 { + label = "kernel"; + reg = <0x200000 0x500000>; /* 5M */ + }; + + partition@700000 { + label = "rootfs"; + reg = <0x700000 0x800000>; /* 8M */ + }; + + partition@f00000 { + label = "env"; + reg = <0xf00000 0x100000>; /* 1M */ + read-only; + }; + }; + }; + + chosen { + bootargs = "console=ttyS0,115200 rdinit=/sbin/init"; + }; +}; diff --git a/arch/mips/netlogic/dts/xlp_svp.dts b/arch/mips/netlogic/dts/xlp_svp.dts index 9c5db10..1ebd00ed 100644 --- a/arch/mips/netlogic/dts/xlp_svp.dts +++ b/arch/mips/netlogic/dts/xlp_svp.dts @@ -9,19 +9,12 @@ #address-cells = <2>; #size-cells = <2>; - memory { - device_type = "memory"; - reg = <0 0x00100000 0 0x0FF00000 // 255M at 1M - 0 0x20000000 0 0xa0000000 // 2560M at 512M - 0 0xe0000000 0 0x40000000>; - }; - soc { #address-cells = <2>; #size-cells = <1>; compatible = "simple-bus"; ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG - 1 0 0 0x16000000 0x01000000>; // GBU chipselects + 1 0 0 0x16000000 0x02000000>; // GBU chipselects serial0: serial@30000 { device_type = "serial"; diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index 85ac4a8..ed9a93c 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -1,3 +1,4 @@ obj-y += setup.o nlm_hal.o cop2-ex.o dt.o obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_USB) += usb-init.o +obj-$(CONFIG_USB) += usb-init-xlp2.o diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c index a15cdbb..88df445 100644 --- a/arch/mips/netlogic/xlp/dt.c +++ b/arch/mips/netlogic/xlp/dt.c @@ -39,12 +39,18 @@ #include <linux/of_platform.h> #include <linux/of_device.h> -extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[]; +extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], + __dtb_xlp_fvp_begin[], __dtb_start[]; void __init *xlp_dt_init(void *fdtp) { if (!fdtp) { switch (current_cpu_data.processor_id & 0xff00) { +#ifdef CONFIG_DT_XLP_FVP + case PRID_IMP_NETLOGIC_XLP2XX: + fdtp = __dtb_xlp_fvp_begin; + break; +#endif #ifdef CONFIG_DT_XLP_SVP case PRID_IMP_NETLOGIC_XLP3XX: fdtp = __dtb_xlp_svp_begin; diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 87560e4..56c50ba 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -44,6 +44,7 @@ #include <asm/netlogic/haldefs.h> #include <asm/netlogic/xlp-hal/iomap.h> #include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/bridge.h> #include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/sys.h> @@ -64,6 +65,7 @@ int nlm_irq_to_irt(int irq) uint64_t pcibase; int devoff, irt; + devoff = 0; switch (irq) { case PIC_UART_0_IRQ: devoff = XLP_IO_UART0_OFFSET(0); @@ -71,44 +73,68 @@ int nlm_irq_to_irt(int irq) case PIC_UART_1_IRQ: devoff = XLP_IO_UART1_OFFSET(0); break; - case PIC_EHCI_0_IRQ: - devoff = XLP_IO_USB_EHCI0_OFFSET(0); - break; - case PIC_EHCI_1_IRQ: - devoff = XLP_IO_USB_EHCI1_OFFSET(0); - break; - case PIC_OHCI_0_IRQ: - devoff = XLP_IO_USB_OHCI0_OFFSET(0); - break; - case PIC_OHCI_1_IRQ: - devoff = XLP_IO_USB_OHCI1_OFFSET(0); - break; - case PIC_OHCI_2_IRQ: - devoff = XLP_IO_USB_OHCI2_OFFSET(0); - break; - case PIC_OHCI_3_IRQ: - devoff = XLP_IO_USB_OHCI3_OFFSET(0); - break; case PIC_MMC_IRQ: devoff = XLP_IO_SD_OFFSET(0); break; - case PIC_I2C_0_IRQ: - devoff = XLP_IO_I2C0_OFFSET(0); - break; + case PIC_I2C_0_IRQ: /* I2C will be fixed up */ case PIC_I2C_1_IRQ: - devoff = XLP_IO_I2C1_OFFSET(0); + case PIC_I2C_2_IRQ: + case PIC_I2C_3_IRQ: + if (cpu_is_xlpii()) + devoff = XLP2XX_IO_I2C_OFFSET(0); + else + devoff = XLP_IO_I2C0_OFFSET(0); break; default: - devoff = 0; - break; + if (cpu_is_xlpii()) { + switch (irq) { + /* XLP2XX has three XHCI USB controller */ + case PIC_2XX_XHCI_0_IRQ: + devoff = XLP2XX_IO_USB_XHCI0_OFFSET(0); + break; + case PIC_2XX_XHCI_1_IRQ: + devoff = XLP2XX_IO_USB_XHCI1_OFFSET(0); + break; + case PIC_2XX_XHCI_2_IRQ: + devoff = XLP2XX_IO_USB_XHCI2_OFFSET(0); + break; + } + } else { + switch (irq) { + case PIC_EHCI_0_IRQ: + devoff = XLP_IO_USB_EHCI0_OFFSET(0); + break; + case PIC_EHCI_1_IRQ: + devoff = XLP_IO_USB_EHCI1_OFFSET(0); + break; + case PIC_OHCI_0_IRQ: + devoff = XLP_IO_USB_OHCI0_OFFSET(0); + break; + case PIC_OHCI_1_IRQ: + devoff = XLP_IO_USB_OHCI1_OFFSET(0); + break; + case PIC_OHCI_2_IRQ: + devoff = XLP_IO_USB_OHCI2_OFFSET(0); + break; + case PIC_OHCI_3_IRQ: + devoff = XLP_IO_USB_OHCI3_OFFSET(0); + break; + } + } } if (devoff != 0) { pcibase = nlm_pcicfg_base(devoff); irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff; - /* HW bug, I2C 1 irt entry is off by one */ - if (irq == PIC_I2C_1_IRQ) - irt = irt + 1; + /* HW weirdness, I2C IRT entry has to be fixed up */ + switch (irq) { + case PIC_I2C_1_IRQ: + irt = irt + 1; break; + case PIC_I2C_2_IRQ: + irt = irt + 2; break; + case PIC_I2C_3_IRQ: + irt = irt + 3; break; + } } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) { /* HW bug, PCI IRT entries are bad on early silicon, fix */ irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ); @@ -126,19 +152,160 @@ unsigned int nlm_get_core_frequency(int node, int core) sysbase = nlm_get_node(node)->sysbase; rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); - dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); - pll_divf = ((rstval >> 10) & 0x7f) + 1; - pll_divr = ((rstval >> 8) & 0x3) + 1; - ext_div = ((rstval >> 30) & 0x3) + 1; - dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; - - num = 800000000ULL * pll_divf; - denom = 3 * pll_divr * ext_div * dfs_div; + if (cpu_is_xlpii()) { + num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26)); + denom = 3; + } else { + dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); + pll_divf = ((rstval >> 10) & 0x7f) + 1; + pll_divr = ((rstval >> 8) & 0x3) + 1; + ext_div = ((rstval >> 30) & 0x3) + 1; + dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; + + num = 800000000ULL * pll_divf; + denom = 3 * pll_divr * ext_div * dfs_div; + } do_div(num, denom); return (unsigned int)num; } +/* Calculate Frequency to the PIC from PLL. + * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) / + * ((2^ctrl0[7:5]) * Table(ctrl0[26:24])) + */ +static unsigned int nlm_2xx_get_pic_frequency(int node) +{ + u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div; + u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div; + u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select; + + sysbase = nlm_get_node(node)->sysbase; + + /* Find ref_clk_base */ + ref_clk_select = + (nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3; + switch (ref_clk_select) { + case 0: + ref_clk = 200000000ULL; + ref_div = 3; + break; + case 1: + ref_clk = 100000000ULL; + ref_div = 1; + break; + case 2: + ref_clk = 125000000ULL; + ref_div = 1; + break; + case 3: + ref_clk = 400000000ULL; + ref_div = 3; + break; + } + + /* Find the clock source PLL device for PIC */ + reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3; + switch (reg_select) { + case 0: + ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0); + ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2); + break; + case 1: + ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0)); + ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0)); + break; + case 2: + ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1)); + ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1)); + break; + case 3: + ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2)); + ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2)); + break; + } + + vco_post_div = (ctrl_val0 >> 5) & 0x7; + pll_post_div = (ctrl_val0 >> 24) & 0x7; + mdiv = ctrl_val2 & 0xff; + fdiv = (ctrl_val2 >> 8) & 0xfff; + + /* Find PLL post divider value */ + switch (pll_post_div) { + case 1: + pll_post_div = 2; + break; + case 3: + pll_post_div = 4; + break; + case 7: + pll_post_div = 8; + break; + case 6: + pll_post_div = 16; + break; + case 0: + default: + pll_post_div = 1; + break; + } + + fdiv = fdiv/(1 << 13); + pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv; + pll_out_freq_den = (1 << vco_post_div) * pll_post_div * 3; + + if (pll_out_freq_den > 0) + do_div(pll_out_freq_num, pll_out_freq_den); + + /* PIC post divider, which happens after PLL */ + pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3; + do_div(pll_out_freq_num, 1 << pic_div); + + return pll_out_freq_num; +} + +unsigned int nlm_get_pic_frequency(int node) +{ + if (cpu_is_xlpii()) + return nlm_2xx_get_pic_frequency(node); + else + return 133333333; +} + unsigned int nlm_get_cpu_frequency(void) { return nlm_get_core_frequency(0, 0); } + +/* + * Fills upto 8 pairs of entries containing the DRAM map of a node + * if n < 0, get dram map for all nodes + */ +int xlp_get_dram_map(int n, uint64_t *dram_map) +{ + uint64_t bridgebase, base, lim; + uint32_t val; + int i, node, rv; + + /* Look only at mapping on Node 0, we don't handle crazy configs */ + bridgebase = nlm_get_bridge_regbase(0); + rv = 0; + for (i = 0; i < 8; i++) { + val = nlm_read_bridge_reg(bridgebase, + BRIDGE_DRAM_NODE_TRANSLN(i)); + node = (val >> 1) & 0x3; + if (n >= 0 && n != node) + continue; + val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i)); + val = (val >> 12) & 0xfffff; + base = (uint64_t) val << 20; + val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i)); + val = (val >> 12) & 0xfffff; + if (val == 0) /* BAR not used */ + continue; + lim = ((uint64_t)val + 1) << 20; + dram_map[rv] = base; + dram_map[rv + 1] = lim; + rv += 2; + } + return rv; +} diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 7b638f7..76a7131 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -73,6 +73,23 @@ static void nlm_fixup_mem(void) } } +static void __init xlp_init_mem_from_bars(void) +{ + uint64_t map[16]; + int i, n; + + n = xlp_get_dram_map(-1, map); /* -1: info for all nodes */ + for (i = 0; i < n; i += 2) { + /* exclude 0x1000_0000-0x2000_0000, u-boot device */ + if (map[i] <= 0x10000000 && map[i+1] > 0x10000000) + map[i+1] = 0x10000000; + if (map[i] > 0x10000000 && map[i] < 0x20000000) + map[i] = 0x20000000; + + add_memory_region(map[i], map[i+1] - map[i], BOOT_MEM_RAM); + } +} + void __init plat_mem_setup(void) { panic_timeout = 5; @@ -82,12 +99,23 @@ void __init plat_mem_setup(void) /* memory and bootargs from DT */ early_init_devtree(initial_boot_params); + + if (boot_mem_map.nr_map == 0) { + pr_info("Using DRAM BARs for memory map.\n"); + xlp_init_mem_from_bars(); + } + /* Calculate and setup wired entries for mapped kernel */ nlm_fixup_mem(); } const char *get_system_type(void) { - return "Netlogic XLP Series"; + switch (read_c0_prid() & 0xff00) { + case PRID_IMP_NETLOGIC_XLP2XX: + return "Broadcom XLPII Series"; + default: + return "Netlogic XLP Series"; + } } void __init prom_free_prom_memory(void) @@ -97,12 +125,20 @@ void __init prom_free_prom_memory(void) void xlp_mmu_init(void) { - /* enable extended TLB and Large Fixed TLB */ - write_c0_config6(read_c0_config6() | 0x24); - - /* set page mask of Fixed TLB in config7 */ - write_c0_config7(PM_DEFAULT_MASK >> - (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); + u32 conf4; + + if (cpu_is_xlpii()) { + /* XLPII series has extended pagesize in config 4 */ + conf4 = read_c0_config4() & ~0x1f00u; + write_c0_config4(conf4 | ((PAGE_SHIFT - 10) / 2 << 8)); + } else { + /* enable extended TLB and Large Fixed TLB */ + write_c0_config6(read_c0_config6() | 0x24); + + /* set page mask of extended Fixed TLB in config7 */ + write_c0_config7(PM_DEFAULT_MASK >> + (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2))); + } } void nlm_percpu_init(int hwcpuid) diff --git a/arch/mips/netlogic/xlp/usb-init-xlp2.c b/arch/mips/netlogic/xlp/usb-init-xlp2.c new file mode 100644 index 0000000..36e9c22 --- /dev/null +++ b/arch/mips/netlogic/xlp/usb-init-xlp2.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2003-2013 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/dma-mapping.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/irq.h> + +#include <asm/netlogic/common.h> +#include <asm/netlogic/haldefs.h> +#include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/xlp.h> + +#define XLPII_USB3_CTL_0 0xc0 +#define XLPII_VAUXRST BIT(0) +#define XLPII_VCCRST BIT(1) +#define XLPII_NUM2PORT 9 +#define XLPII_NUM3PORT 13 +#define XLPII_RTUNEREQ BIT(20) +#define XLPII_MS_CSYSREQ BIT(21) +#define XLPII_XS_CSYSREQ BIT(22) +#define XLPII_RETENABLEN BIT(23) +#define XLPII_TX2RX BIT(24) +#define XLPII_XHCIREV BIT(25) +#define XLPII_ECCDIS BIT(26) + +#define XLPII_USB3_INT_REG 0xc2 +#define XLPII_USB3_INT_MASK 0xc3 + +#define XLPII_USB_PHY_TEST 0xc6 +#define XLPII_PRESET BIT(0) +#define XLPII_ATERESET BIT(1) +#define XLPII_LOOPEN BIT(2) +#define XLPII_TESTPDHSP BIT(3) +#define XLPII_TESTPDSSP BIT(4) +#define XLPII_TESTBURNIN BIT(5) + +#define XLPII_USB_PHY_LOS_LV 0xc9 +#define XLPII_LOSLEV 0 +#define XLPII_LOSBIAS 5 +#define XLPII_SQRXTX 8 +#define XLPII_TXBOOST 11 +#define XLPII_RSLKSEL 16 +#define XLPII_FSEL 20 + +#define XLPII_USB_RFCLK_REG 0xcc +#define XLPII_VVLD 30 + +#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) + +#define nlm_xlpii_get_usb_pcibase(node, inst) \ + nlm_pcicfg_base(XLP2XX_IO_USB_OFFSET(node, inst)) +#define nlm_xlpii_get_usb_regbase(node, inst) \ + (nlm_xlpii_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) + +static void xlpii_usb_ack(struct irq_data *data) +{ + u64 port_addr; + + switch (data->irq) { + case PIC_2XX_XHCI_0_IRQ: + port_addr = nlm_xlpii_get_usb_regbase(0, 1); + break; + case PIC_2XX_XHCI_1_IRQ: + port_addr = nlm_xlpii_get_usb_regbase(0, 2); + break; + case PIC_2XX_XHCI_2_IRQ: + port_addr = nlm_xlpii_get_usb_regbase(0, 3); + break; + default: + pr_err("No matching USB irq!\n"); + return; + } + nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); +} + +static void nlm_xlpii_usb_hw_reset(int node, int port) +{ + u64 port_addr, xhci_base, pci_base; + void __iomem *corebase; + u32 val; + + port_addr = nlm_xlpii_get_usb_regbase(node, port); + + /* Set frequency */ + val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV); + val &= ~(0x3f << XLPII_FSEL); + val |= (0x27 << XLPII_FSEL); + nlm_write_usb_reg(port_addr, XLPII_USB_PHY_LOS_LV, val); + + val = nlm_read_usb_reg(port_addr, XLPII_USB_RFCLK_REG); + val |= (1 << XLPII_VVLD); + nlm_write_usb_reg(port_addr, XLPII_USB_RFCLK_REG, val); + + /* PHY reset */ + val = nlm_read_usb_reg(port_addr, XLPII_USB_PHY_TEST); + val &= (XLPII_ATERESET | XLPII_LOOPEN | XLPII_TESTPDHSP + | XLPII_TESTPDSSP | XLPII_TESTBURNIN); + nlm_write_usb_reg(port_addr, XLPII_USB_PHY_TEST, val); + + /* Setup control register */ + val = XLPII_VAUXRST | XLPII_VCCRST | (1 << XLPII_NUM2PORT) + | (1 << XLPII_NUM3PORT) | XLPII_MS_CSYSREQ | XLPII_XS_CSYSREQ + | XLPII_RETENABLEN | XLPII_XHCIREV; + nlm_write_usb_reg(port_addr, XLPII_USB3_CTL_0, val); + + /* Enable interrupts */ + nlm_write_usb_reg(port_addr, XLPII_USB3_INT_MASK, 0x00000001); + + /* Clear all interrupts */ + nlm_write_usb_reg(port_addr, XLPII_USB3_INT_REG, 0xffffffff); + + udelay(2000); + + /* XHCI configuration at PCI mem */ + pci_base = nlm_xlpii_get_usb_pcibase(node, port); + xhci_base = nlm_read_usb_reg(pci_base, 0x4) & ~0xf; + corebase = ioremap(xhci_base, 0x10000); + if (!corebase) + return; + + writel(0x240002, corebase + 0xc2c0); + /* GCTL 0xc110 */ + val = readl(corebase + 0xc110); + val &= ~(0x3 << 12); + val |= (1 << 12); + writel(val, corebase + 0xc110); + udelay(100); + + /* PHYCFG 0xc200 */ + val = readl(corebase + 0xc200); + val &= ~(1 << 6); + writel(val, corebase + 0xc200); + udelay(100); + + /* PIPECTL 0xc2c0 */ + val = readl(corebase + 0xc2c0); + val &= ~(1 << 17); + writel(val, corebase + 0xc2c0); + + iounmap(corebase); +} + +static int __init nlm_platform_xlpii_usb_init(void) +{ + if (!cpu_is_xlpii()) + return 0; + + pr_info("Initializing 2XX USB Interface\n"); + nlm_xlpii_usb_hw_reset(0, 1); + nlm_xlpii_usb_hw_reset(0, 2); + nlm_xlpii_usb_hw_reset(0, 3); + nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_0_IRQ, xlpii_usb_ack); + nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_1_IRQ, xlpii_usb_ack); + nlm_set_pic_extra_ack(0, PIC_2XX_XHCI_2_IRQ, xlpii_usb_ack); + + return 0; +} + +arch_initcall(nlm_platform_xlpii_usb_init); + +static u64 xlp_usb_dmamask = ~(u32)0; + +/* Fixup IRQ for USB devices on XLP the SoC PCIe bus */ +static void nlm_usb_fixup_final(struct pci_dev *dev) +{ + dev->dev.dma_mask = &xlp_usb_dmamask; + dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + switch (dev->devfn) { + case 0x21: + dev->irq = PIC_2XX_XHCI_0_IRQ; + break; + case 0x22: + dev->irq = PIC_2XX_XHCI_1_IRQ; + break; + case 0x23: + dev->irq = PIC_2XX_XHCI_2_IRQ; + break; + } +} + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_XHCI, + nlm_usb_fixup_final); diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c index ef3897e..f811798 100644 --- a/arch/mips/netlogic/xlp/usb-init.c +++ b/arch/mips/netlogic/xlp/usb-init.c @@ -75,8 +75,7 @@ static void nlm_usb_intr_en(int node, int port) port_addr = nlm_get_usb_regbase(node, port); val = nlm_read_usb_reg(port_addr, USB_INT_EN); val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN | - USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN | - USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN; + USB_OHCI_INTERRUPT1_EN | USB_OHCI_INTERRUPT2_EN; nlm_write_usb_reg(port_addr, USB_INT_EN, val); } @@ -100,6 +99,9 @@ static void nlm_usb_hw_reset(int node, int port) static int __init nlm_platform_usb_init(void) { + if (cpu_is_xlpii()) + return 0; + pr_info("Initializing USB Interface\n"); nlm_usb_hw_reset(0, 0); nlm_usb_hw_reset(0, 3); diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 0cce37c..682d563 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -58,10 +58,12 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core) coremask = (1 << core); - /* Enable CPU clock */ - value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL); - value &= ~coremask; - nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); + /* Enable CPU clock in case of 8xx/3xx */ + if (!cpu_is_xlpii()) { + value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL); + value &= ~coremask; + nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); + } /* Remove CPU Reset */ value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c382042..719e455 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o obj-$(CONFIG_LANTIQ) += fixup-lantiq.o obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o +obj-$(CONFIG_SOC_RT3883) += pci-rt3883.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/pci-octeon.c b/arch/mips/pci/pci-octeon.c index 95c2ea8..59cccd9 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c @@ -586,15 +586,16 @@ static int __init octeon_pci_setup(void) else octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG; - /* PCI I/O and PCI MEM values */ - set_io_port_base(OCTEON_PCI_IOSPACE_BASE); - ioport_resource.start = 0; - ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; if (!octeon_is_pci_host()) { pr_notice("Not in host mode, PCI Controller not initialized\n"); return 0; } + /* PCI I/O and PCI MEM values */ + set_io_port_base(OCTEON_PCI_IOSPACE_BASE); + ioport_resource.start = 0; + ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; + pr_notice("%s Octeon big bar support\n", (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling"); diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c new file mode 100644 index 0000000..95c9d41 --- /dev/null +++ b/arch/mips/pci/pci-rt3883.c @@ -0,0 +1,636 @@ +/* + * Ralink RT3662/RT3883 SoC PCI support + * + * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> + * + * Parts of this file are based on Ralink's 2.6.21 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/types.h> +#include <linux/pci.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_pci.h> +#include <linux/platform_device.h> + +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/ralink_regs.h> + +#define RT3883_MEMORY_BASE 0x00000000 +#define RT3883_MEMORY_SIZE 0x02000000 + +#define RT3883_PCI_REG_PCICFG 0x00 +#define RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf +#define RT3883_PCICFG_P2P_BR_DEVNUM_S 16 +#define RT3883_PCICFG_PCIRST BIT(1) +#define RT3883_PCI_REG_PCIRAW 0x04 +#define RT3883_PCI_REG_PCIINT 0x08 +#define RT3883_PCI_REG_PCIENA 0x0c + +#define RT3883_PCI_REG_CFGADDR 0x20 +#define RT3883_PCI_REG_CFGDATA 0x24 +#define RT3883_PCI_REG_MEMBASE 0x28 +#define RT3883_PCI_REG_IOBASE 0x2c +#define RT3883_PCI_REG_ARBCTL 0x80 + +#define RT3883_PCI_REG_BASE(_x) (0x1000 + (_x) * 0x1000) +#define RT3883_PCI_REG_BAR0SETUP(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10) +#define RT3883_PCI_REG_IMBASEBAR0(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18) +#define RT3883_PCI_REG_ID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x30) +#define RT3883_PCI_REG_CLASS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x34) +#define RT3883_PCI_REG_SUBID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x38) +#define RT3883_PCI_REG_STATUS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x50) + +#define RT3883_PCI_MODE_NONE 0 +#define RT3883_PCI_MODE_PCI BIT(0) +#define RT3883_PCI_MODE_PCIE BIT(1) +#define RT3883_PCI_MODE_BOTH (RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE) + +#define RT3883_PCI_IRQ_COUNT 32 + +#define RT3883_P2P_BR_DEVNUM 1 + +struct rt3883_pci_controller { + void __iomem *base; + spinlock_t lock; + + struct device_node *intc_of_node; + struct irq_domain *irq_domain; + + struct pci_controller pci_controller; + struct resource io_res; + struct resource mem_res; + + bool pcie_ready; +}; + +static inline struct rt3883_pci_controller * +pci_bus_to_rt3883_controller(struct pci_bus *bus) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *) bus->sysdata; + return container_of(hose, struct rt3883_pci_controller, pci_controller); +} + +static inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc, + unsigned reg) +{ + return ioread32(rpc->base + reg); +} + +static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc, + u32 val, unsigned reg) +{ + iowrite32(val, rpc->base + reg); +} + +static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot, + unsigned int func, unsigned int where) +{ + return (bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | + 0x80000000; +} + +static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc, + unsigned bus, unsigned slot, + unsigned func, unsigned reg) +{ + unsigned long flags; + u32 address; + u32 ret; + + address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); + + return ret; +} + +static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc, + unsigned bus, unsigned slot, + unsigned func, unsigned reg, u32 val) +{ + unsigned long flags; + u32 address; + + address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); +} + +static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct rt3883_pci_controller *rpc; + u32 pending; + + rpc = irq_get_handler_data(irq); + + pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) & + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + + if (!pending) { + spurious_interrupt(); + return; + } + + while (pending) { + unsigned bit = __ffs(pending); + + irq = irq_find_mapping(rpc->irq_domain, bit); + generic_handle_irq(irq); + + pending &= ~BIT(bit); + } +} + +static void rt3883_pci_irq_unmask(struct irq_data *d) +{ + struct rt3883_pci_controller *rpc; + u32 t; + + rpc = irq_data_get_irq_chip_data(d); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA); + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); +} + +static void rt3883_pci_irq_mask(struct irq_data *d) +{ + struct rt3883_pci_controller *rpc; + u32 t; + + rpc = irq_data_get_irq_chip_data(d); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA); + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); +} + +static struct irq_chip rt3883_pci_irq_chip = { + .name = "RT3883 PCI", + .irq_mask = rt3883_pci_irq_mask, + .irq_unmask = rt3883_pci_irq_unmask, + .irq_mask_ack = rt3883_pci_irq_mask, +}; + +static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq); + irq_set_chip_data(irq, d->host_data); + + return 0; +} + +static const struct irq_domain_ops rt3883_pci_irq_domain_ops = { + .map = rt3883_pci_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int rt3883_pci_irq_init(struct device *dev, + struct rt3883_pci_controller *rpc) +{ + int irq; + + irq = irq_of_parse_and_map(rpc->intc_of_node, 0); + if (irq == 0) { + dev_err(dev, "%s has no IRQ", + of_node_full_name(rpc->intc_of_node)); + return -EINVAL; + } + + /* disable all interrupts */ + rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA); + + rpc->irq_domain = + irq_domain_add_linear(rpc->intc_of_node, RT3883_PCI_IRQ_COUNT, + &rt3883_pci_irq_domain_ops, + rpc); + if (!rpc->irq_domain) { + dev_err(dev, "unable to add IRQ domain\n"); + return -ENODEV; + } + + irq_set_handler_data(irq, rpc); + irq_set_chained_handler(irq, rt3883_pci_irq_handler); + + return 0; +} + +static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct rt3883_pci_controller *rpc; + unsigned long flags; + u32 address; + u32 data; + + rpc = pci_bus_to_rt3883_controller(bus); + + if (!rpc->pcie_ready && bus->number == 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + *val = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + *val = data; + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct rt3883_pci_controller *rpc; + unsigned long flags; + u32 address; + u32 data; + + rpc = pci_bus_to_rt3883_controller(bus); + + if (!rpc->pcie_ready && bus->number == 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + + switch (size) { + case 1: + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + data = val; + break; + } + + rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops rt3883_pci_ops = { + .read = rt3883_pci_config_read, + .write = rt3883_pci_config_write, +}; + +static void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode) +{ + u32 syscfg1; + u32 rstctrl; + u32 clkcfg1; + u32 t; + + rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); + clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + + if (mode & RT3883_PCI_MODE_PCIE) { + rstctrl |= RT3883_RSTCTRL_PCIE; + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + + /* setup PCI PAD drive mode */ + syscfg1 &= ~(0x30); + syscfg1 |= (2 << 4); + rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t &= ~BIT(31); + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); + t &= 0x80ffffff; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); + t |= 0xa << 24; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t |= BIT(31); + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + + msleep(50); + + rstctrl &= ~RT3883_RSTCTRL_PCIE; + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + } + + syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE); + + clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN); + + if (mode & RT3883_PCI_MODE_PCI) { + clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN; + rstctrl &= ~RT3883_RSTCTRL_PCI; + } + + if (mode & RT3883_PCI_MODE_PCIE) { + clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN; + rstctrl &= ~RT3883_RSTCTRL_PCIE; + } + + rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1); + + msleep(500); + + /* + * setup the device number of the P2P bridge + * and de-assert the reset line + */ + t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S); + rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG); + + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG); + msleep(500); + + if (mode & RT3883_PCI_MODE_PCIE) { + msleep(500); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1)); + + rpc->pcie_ready = t & BIT(0); + + if (!rpc->pcie_ready) { + /* reset the PCIe block */ + t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_PCIE; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + t &= ~RT3883_RSTCTRL_PCIE; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + + /* turn off PCIe clock */ + t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + t &= ~RT3883_CLKCFG1_PCIE_CLK_EN; + rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t &= ~0xf000c080; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + } + } + + /* enable PCI arbiter */ + rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL); +} + +static int rt3883_pci_probe(struct platform_device *pdev) +{ + struct rt3883_pci_controller *rpc; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + struct device_node *child; + u32 val; + int err; + int mode; + + rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + rpc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(rpc->base)) + return PTR_ERR(rpc->base); + + /* find the interrupt controller child node */ + for_each_child_of_node(np, child) { + if (of_get_property(child, "interrupt-controller", NULL) && + of_node_get(child)) { + rpc->intc_of_node = child; + break; + } + } + + if (!rpc->intc_of_node) { + dev_err(dev, "%s has no %s child node", + of_node_full_name(rpc->intc_of_node), + "interrupt controller"); + return -EINVAL; + } + + /* find the PCI host bridge child node */ + for_each_child_of_node(np, child) { + if (child->type && + of_node_cmp(child->type, "pci") == 0 && + of_node_get(child)) { + rpc->pci_controller.of_node = child; + break; + } + } + + if (!rpc->pci_controller.of_node) { + dev_err(dev, "%s has no %s child node", + of_node_full_name(rpc->intc_of_node), + "PCI host bridge"); + err = -EINVAL; + goto err_put_intc_node; + } + + mode = RT3883_PCI_MODE_NONE; + for_each_available_child_of_node(rpc->pci_controller.of_node, child) { + int devfn; + + if (!child->type || + of_node_cmp(child->type, "pci") != 0) + continue; + + devfn = of_pci_get_devfn(child); + if (devfn < 0) + continue; + + switch (PCI_SLOT(devfn)) { + case 1: + mode |= RT3883_PCI_MODE_PCIE; + break; + + case 17: + case 18: + mode |= RT3883_PCI_MODE_PCI; + break; + } + } + + if (mode == RT3883_PCI_MODE_NONE) { + dev_err(dev, "unable to determine PCI mode\n"); + err = -EINVAL; + goto err_put_hb_node; + } + + dev_info(dev, "mode:%s%s\n", + (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "", + (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : ""); + + rt3883_pci_preinit(rpc, mode); + + rpc->pci_controller.pci_ops = &rt3883_pci_ops; + rpc->pci_controller.io_resource = &rpc->io_res; + rpc->pci_controller.mem_resource = &rpc->mem_res; + + /* Load PCI I/O and memory resources from DT */ + pci_load_of_ranges(&rpc->pci_controller, + rpc->pci_controller.of_node); + + rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE); + rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE); + + ioport_resource.start = rpc->io_res.start; + ioport_resource.end = rpc->io_res.end; + + /* PCI */ + rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0)); + rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0)); + rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0)); + rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0)); + rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0)); + + /* PCIe */ + rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1)); + rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1)); + rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1)); + rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1)); + rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1)); + + err = rt3883_pci_irq_init(dev, rpc); + if (err) + goto err_put_hb_node; + + /* PCIe */ + val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND); + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val); + + /* PCI */ + val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND); + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val); + + if (mode == RT3883_PCI_MODE_PCIE) { + rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0)); + rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1)); + + rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_BASE_ADDRESS_0, + RT3883_MEMORY_BASE); + /* flush write */ + rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_BASE_ADDRESS_0); + } else { + rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_IO_BASE, 0x00000101); + } + + register_pci_controller(&rpc->pci_controller); + + return 0; + +err_put_hb_node: + of_node_put(rpc->pci_controller.of_node); +err_put_intc_node: + of_node_put(rpc->intc_of_node); + return err; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct of_irq dev_irq; + int err; + int irq; + + err = of_irq_map_pci(dev, &dev_irq); + if (err) { + pr_err("pci %s: unable to get irq map, err=%d\n", + pci_name((struct pci_dev *) dev), err); + return 0; + } + + irq = irq_create_of_mapping(dev_irq.controller, + dev_irq.specifier, + dev_irq.size); + + 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) +{ + return 0; +} + +static const struct of_device_id rt3883_pci_ids[] = { + { .compatible = "ralink,rt3883-pci" }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt3883_pci_ids); + +static struct platform_driver rt3883_pci_driver = { + .probe = rt3883_pci_probe, + .driver = { + .name = "rt3883-pci", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rt3883_pci_ids), + }, +}; + +static int __init rt3883_pci_init(void) +{ + return platform_driver_register(&rt3883_pci_driver); +} + +postcore_initcall(rt3883_pci_init); diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig index 1a1b03e..dd91fba 100644 --- a/arch/mips/powertv/Kconfig +++ b/arch/mips/powertv/Kconfig @@ -1,14 +1,7 @@ -config BOOTLOADER_DRIVER - bool "PowerTV Bootloader Driver Support" - default n - depends on POWERTV - help - Use this option if you want to load bootloader driver. - config BOOTLOADER_FAMILY string "POWERTV Bootloader Family string" default "85" - depends on POWERTV && !BOOTLOADER_DRIVER + depends on POWERTV help This value should be specified when the bootloader driver is disabled and must be exactly two characters long. Families supported are: diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index 0238af1..8380605 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -147,20 +147,10 @@ static __init noinline void platform_set_family(void) if (check_forcefamily(forced_family) == 0) bootldr_family = BOOTLDRFAMILY(forced_family[0], forced_family[1]); - else { - -#ifdef CONFIG_BOOTLOADER_DRIVER - bootldr_family = (unsigned short) kbldr_GetSWFamily(); -#else -#if defined(CONFIG_BOOTLOADER_FAMILY) + else bootldr_family = (unsigned short) BOOTLDRFAMILY( CONFIG_BOOTLOADER_FAMILY[0], CONFIG_BOOTLOADER_FAMILY[1]); -#else -#error "Unknown Bootloader Family" -#endif -#endif - } pr_info("Bootloader Family = 0x%04X\n", bootldr_family); diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c index a01baff..4989263 100644 --- a/arch/mips/powertv/init.c +++ b/arch/mips/powertv/init.c @@ -87,8 +87,4 @@ void __init prom_init(void) configure_platform(); prom_meminit(); - -#ifndef CONFIG_BOOTLOADER_DRIVER - pr_info("\nBootloader driver isn't loaded...\n"); -#endif } diff --git a/arch/mips/powertv/reset.c b/arch/mips/powertv/reset.c index 0007652..11c32fb 100644 --- a/arch/mips/powertv/reset.c +++ b/arch/mips/powertv/reset.c @@ -21,24 +21,12 @@ #include <linux/io.h> #include <asm/reboot.h> /* Not included by linux/reboot.h */ -#ifdef CONFIG_BOOTLOADER_DRIVER -#include <asm/mach-powertv/kbldr.h> -#endif - #include <asm/mach-powertv/asic_regs.h> #include "reset.h" static void mips_machine_restart(char *command) { -#ifdef CONFIG_BOOTLOADER_DRIVER - /* - * Call the bootloader's reset function to ensure - * that persistent data is flushed before hard reset - */ - kbldr_SetCauseAndReset(); -#else writel(0x1, asic_reg_addr(watchdog)); -#endif } void mips_reboot_setup(void) diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index 026e823..424f034 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -1,5 +1,12 @@ if RALINK +config CLKEVT_RT3352 + bool + depends on SOC_RT305X || SOC_MT7620 + default y + select CLKSRC_OF + select CLKSRC_MMIO + choice prompt "Ralink SoC selection" default SOC_RT305X @@ -19,9 +26,12 @@ choice bool "RT3883" select USB_ARCH_HAS_OHCI select USB_ARCH_HAS_EHCI + select HW_HAS_PCI config SOC_MT7620 bool "MT7620" + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI endchoice diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index 38cf1a8..98ae349 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile @@ -6,7 +6,9 @@ # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> # Copyright (C) 2013 John Crispin <blogic@openwrt.org> -obj-y := prom.o of.o reset.o clk.o irq.o +obj-y := prom.o of.o reset.o clk.o irq.o timer.o + +obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o obj-$(CONFIG_SOC_RT288X) += rt288x.o obj-$(CONFIG_SOC_RT305X) += rt305x.o diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform index cda4b66..6d9c8c4 100644 --- a/arch/mips/ralink/Platform +++ b/arch/mips/ralink/Platform @@ -26,3 +26,4 @@ cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt # Ralink MT7620 # load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000 +cflags-$(CONFIG_SOC_MT7620) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7620 diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c new file mode 100644 index 0000000..cc17566 --- /dev/null +++ b/arch/mips/ralink/cevt-rt3352.c @@ -0,0 +1,145 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 by John Crispin <blogic@openwrt.org> + */ + +#include <linux/clockchips.h> +#include <linux/clocksource.h> +#include <linux/interrupt.h> +#include <linux/reset.h> +#include <linux/init.h> +#include <linux/time.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_address.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#define SYSTICK_FREQ (50 * 1000) + +#define SYSTICK_CONFIG 0x00 +#define SYSTICK_COMPARE 0x04 +#define SYSTICK_COUNT 0x08 + +/* route systick irq to mips irq 7 instead of the r4k-timer */ +#define CFG_EXT_STK_EN 0x2 +/* enable the counter */ +#define CFG_CNT_EN 0x1 + +struct systick_device { + void __iomem *membase; + struct clock_event_device dev; + int irq_requested; + int freq_scale; +}; + +static void systick_set_clock_mode(enum clock_event_mode mode, + struct clock_event_device *evt); + +static int systick_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + struct systick_device *sdev; + u32 count; + + sdev = container_of(evt, struct systick_device, dev); + count = ioread32(sdev->membase + SYSTICK_COUNT); + count = (count + delta) % SYSTICK_FREQ; + iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE); + + return 0; +} + +static void systick_event_handler(struct clock_event_device *dev) +{ + /* noting to do here */ +} + +static irqreturn_t systick_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *dev = (struct clock_event_device *) dev_id; + + dev->event_handler(dev); + + return IRQ_HANDLED; +} + +static struct systick_device systick = { + .dev = { + /* + * cevt-r4k uses 300, make sure systick + * gets used if available + */ + .rating = 310, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = systick_next_event, + .set_mode = systick_set_clock_mode, + .event_handler = systick_event_handler, + }, +}; + +static struct irqaction systick_irqaction = { + .handler = systick_interrupt, + .flags = IRQF_PERCPU | IRQF_TIMER, + .dev_id = &systick.dev, +}; + +static void systick_set_clock_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + struct systick_device *sdev; + + sdev = container_of(evt, struct systick_device, dev); + + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + if (!sdev->irq_requested) + setup_irq(systick.dev.irq, &systick_irqaction); + sdev->irq_requested = 1; + iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN, + systick.membase + SYSTICK_CONFIG); + break; + + case CLOCK_EVT_MODE_SHUTDOWN: + if (sdev->irq_requested) + free_irq(systick.dev.irq, &systick_irqaction); + sdev->irq_requested = 0; + iowrite32(0, systick.membase + SYSTICK_CONFIG); + break; + + default: + pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name); + break; + } +} + +static void __init ralink_systick_init(struct device_node *np) +{ + systick.membase = of_iomap(np, 0); + if (!systick.membase) + return; + + systick_irqaction.name = np->name; + systick.dev.name = np->name; + clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); + systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); + systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); + systick.dev.irq = irq_of_parse_and_map(np, 0); + if (!systick.dev.irq) { + pr_err("%s: request_irq failed", np->name); + return; + } + + clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, + SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up); + + clockevents_register_device(&systick.dev); + + pr_info("%s: runing - mult: %d, shift: %d\n", + np->name, systick.dev.mult, systick.dev.shift); +} + +CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init); diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index 8dfa22f..bba0cdf 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c @@ -69,4 +69,5 @@ void __init plat_time_init(void) pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); mips_hpt_frequency = clk_get_rate(clk) / 2; clk_put(clk); + clocksource_of_init(); } diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h index 83144c3..42dfd61 100644 --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h @@ -46,6 +46,8 @@ extern void ralink_of_remap(void); extern void ralink_clk_init(void); extern void ralink_clk_add(const char *dev, unsigned long rate); +extern void ralink_rst_init(void); + extern void prom_soc_init(struct ralink_soc_info *soc_info); __iomem void *plat_of_remap_node(const char *node); diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index 0018b1a..d217509 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -23,9 +23,6 @@ /* does the board have sdram or ddram */ static int dram_type; -/* the pll dividers */ -static u32 mt7620_clk_divider[] = { 2, 3, 4, 8 }; - static struct ralink_pinmux_grp mode_mux[] = { { .name = "i2c", @@ -140,34 +137,189 @@ struct ralink_pinmux rt_gpio_pinmux = { .uart_mask = MT7620_GPIO_MODE_UART0_MASK, }; -void __init ralink_clk_init(void) +static __init u32 +mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) { - unsigned long cpu_rate, sys_rate; - u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); - u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); - u32 swconfig = (c0 >> CPLL_SW_CONFIG_SHIFT) & CPLL_SW_CONFIG_MASK; - u32 cpu_clk = (c1 >> CPLL_CPU_CLK_SHIFT) & CPLL_CPU_CLK_MASK; - - if (cpu_clk) { - cpu_rate = 480000000; - } else if (!swconfig) { - cpu_rate = 600000000; - } else { - u32 m = (c0 >> CPLL_MULT_RATIO_SHIFT) & CPLL_MULT_RATIO; - u32 d = (c0 >> CPLL_DIV_RATIO_SHIFT) & CPLL_DIV_RATIO; + u64 t; - cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000; - } + t = ref_rate; + t *= mul; + do_div(t, div); + + return t; +} + +#define MHZ(x) ((x) * 1000 * 1000) + +static __init unsigned long +mt7620_get_xtal_rate(void) +{ + u32 reg; + + reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); + if (reg & SYSCFG0_XTAL_FREQ_SEL) + return MHZ(40); + + return MHZ(20); +} + +static __init unsigned long +mt7620_get_periph_rate(unsigned long xtal_rate) +{ + u32 reg; + + reg = rt_sysc_r32(SYSC_REG_CLKCFG0); + if (reg & CLKCFG0_PERI_CLK_SEL) + return xtal_rate; + + return MHZ(40); +} + +static const u32 mt7620_clk_divider[] __initconst = { 2, 3, 4, 8 }; + +static __init unsigned long +mt7620_get_cpu_pll_rate(unsigned long xtal_rate) +{ + u32 reg; + u32 mul; + u32 div; + + reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); + if (reg & CPLL_CFG0_BYPASS_REF_CLK) + return xtal_rate; + + if ((reg & CPLL_CFG0_SW_CFG) == 0) + return MHZ(600); + + mul = (reg >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & + CPLL_CFG0_PLL_MULT_RATIO_MASK; + mul += 24; + if (reg & CPLL_CFG0_LC_CURFCK) + mul *= 2; + + div = (reg >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & + CPLL_CFG0_PLL_DIV_RATIO_MASK; + + WARN_ON(div >= ARRAY_SIZE(mt7620_clk_divider)); + + return mt7620_calc_rate(xtal_rate, mul, mt7620_clk_divider[div]); +} + +static __init unsigned long +mt7620_get_pll_rate(unsigned long xtal_rate, unsigned long cpu_pll_rate) +{ + u32 reg; + + reg = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); + if (reg & CPLL_CFG1_CPU_AUX1) + return xtal_rate; + + if (reg & CPLL_CFG1_CPU_AUX0) + return MHZ(480); + return cpu_pll_rate; +} + +static __init unsigned long +mt7620_get_cpu_rate(unsigned long pll_rate) +{ + u32 reg; + u32 mul; + u32 div; + + reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); + + mul = reg & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; + div = (reg >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & + CPU_SYS_CLKCFG_CPU_FDIV_MASK; + + return mt7620_calc_rate(pll_rate, mul, div); +} + +static const u32 mt7620_ocp_dividers[16] __initconst = { + [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, + [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, + [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, + [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, + [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, +}; + +static __init unsigned long +mt7620_get_dram_rate(unsigned long pll_rate) +{ if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) - sys_rate = cpu_rate / 4; - else - sys_rate = cpu_rate / 3; + return pll_rate / 4; + + return pll_rate / 3; +} + +static __init unsigned long +mt7620_get_sys_rate(unsigned long cpu_rate) +{ + u32 reg; + u32 ocp_ratio; + u32 div; + + reg = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); + + ocp_ratio = (reg >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & + CPU_SYS_CLKCFG_OCP_RATIO_MASK; + + if (WARN_ON(ocp_ratio >= ARRAY_SIZE(mt7620_ocp_dividers))) + return cpu_rate; + + div = mt7620_ocp_dividers[ocp_ratio]; + if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) + return cpu_rate; + + return cpu_rate / div; +} + +void __init ralink_clk_init(void) +{ + unsigned long xtal_rate; + unsigned long cpu_pll_rate; + unsigned long pll_rate; + unsigned long cpu_rate; + unsigned long sys_rate; + unsigned long dram_rate; + unsigned long periph_rate; + + xtal_rate = mt7620_get_xtal_rate(); + + cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); + pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); + + cpu_rate = mt7620_get_cpu_rate(pll_rate); + dram_rate = mt7620_get_dram_rate(pll_rate); + sys_rate = mt7620_get_sys_rate(cpu_rate); + periph_rate = mt7620_get_periph_rate(xtal_rate); + +#define RFMT(label) label ":%lu.%03luMHz " +#define RINT(x) ((x) / 1000000) +#define RFRAC(x) (((x) / 1000) % 1000) + + pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), + RINT(xtal_rate), RFRAC(xtal_rate), + RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), + RINT(pll_rate), RFRAC(pll_rate)); + + pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), + RINT(cpu_rate), RFRAC(cpu_rate), + RINT(dram_rate), RFRAC(dram_rate), + RINT(sys_rate), RFRAC(sys_rate), + RINT(periph_rate), RFRAC(periph_rate)); + +#undef RFRAC +#undef RINT +#undef RFMT ralink_clk_add("cpu", cpu_rate); - ralink_clk_add("10000100.timer", 40000000); - ralink_clk_add("10000500.uart", 40000000); - ralink_clk_add("10000c00.uartlite", 40000000); + ralink_clk_add("10000100.timer", periph_rate); + ralink_clk_add("10000120.watchdog", periph_rate); + ralink_clk_add("10000500.uart", periph_rate); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000c00.uartlite", periph_rate); } void __init ralink_of_remap(void) @@ -214,16 +366,19 @@ void prom_soc_init(struct ralink_soc_info *soc_info) switch (dram_type) { case SYSCFG0_DRAM_TYPE_SDRAM: + pr_info("Board has SDRAM\n"); soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; break; case SYSCFG0_DRAM_TYPE_DDR1: + pr_info("Board has DDR1\n"); soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; break; case SYSCFG0_DRAM_TYPE_DDR2: + pr_info("Board has DDR2\n"); soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; break; diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index f25ea5b..ce38d11 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -110,6 +110,9 @@ static int __init plat_of_setup(void) if (of_platform_populate(NULL, of_ids, NULL, NULL)) panic("failed to populate DT\n"); + /* make sure ithat the reset controller is setup early */ + ralink_rst_init(); + return 0; } diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c index 22120e5..55c7ec5 100644 --- a/arch/mips/ralink/reset.c +++ b/arch/mips/ralink/reset.c @@ -10,6 +10,8 @@ #include <linux/pm.h> #include <linux/io.h> +#include <linux/of.h> +#include <linux/reset-controller.h> #include <asm/reboot.h> @@ -19,6 +21,66 @@ #define SYSC_REG_RESET_CTRL 0x034 #define RSTCTL_RESET_SYSTEM BIT(0) +static int ralink_assert_device(struct reset_controller_dev *rcdev, + unsigned long id) +{ + u32 val; + + if (id < 8) + return -1; + + val = rt_sysc_r32(SYSC_REG_RESET_CTRL); + val |= BIT(id); + rt_sysc_w32(val, SYSC_REG_RESET_CTRL); + + return 0; +} + +static int ralink_deassert_device(struct reset_controller_dev *rcdev, + unsigned long id) +{ + u32 val; + + if (id < 8) + return -1; + + val = rt_sysc_r32(SYSC_REG_RESET_CTRL); + val &= ~BIT(id); + rt_sysc_w32(val, SYSC_REG_RESET_CTRL); + + return 0; +} + +static int ralink_reset_device(struct reset_controller_dev *rcdev, + unsigned long id) +{ + ralink_assert_device(rcdev, id); + return ralink_deassert_device(rcdev, id); +} + +static struct reset_control_ops reset_ops = { + .reset = ralink_reset_device, + .assert = ralink_assert_device, + .deassert = ralink_deassert_device, +}; + +static struct reset_controller_dev reset_dev = { + .ops = &reset_ops, + .owner = THIS_MODULE, + .nr_resets = 32, + .of_reset_n_cells = 1, +}; + +void ralink_rst_init(void) +{ + reset_dev.of_node = of_find_compatible_node(NULL, NULL, + "ralink,rt2880-reset"); + if (!reset_dev.of_node) + pr_err("Failed to find reset controller node"); + else + reset_controller_register(&reset_dev); +} + static void ralink_restart(char *command) { local_irq_disable(); diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c new file mode 100644 index 0000000..e49241a --- /dev/null +++ b/arch/mips/ralink/timer.c @@ -0,0 +1,185 @@ +/* + * 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) 2013 John Crispin <blogic@openwrt.org> +*/ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/timer.h> +#include <linux/of_gpio.h> +#include <linux/clk.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#define TIMER_REG_TMRSTAT 0x00 +#define TIMER_REG_TMR0LOAD 0x10 +#define TIMER_REG_TMR0CTL 0x18 + +#define TMRSTAT_TMR0INT BIT(0) + +#define TMR0CTL_ENABLE BIT(7) +#define TMR0CTL_MODE_PERIODIC BIT(4) +#define TMR0CTL_PRESCALER 1 +#define TMR0CTL_PRESCALE_VAL (0xf - TMR0CTL_PRESCALER) +#define TMR0CTL_PRESCALE_DIV (65536 / BIT(TMR0CTL_PRESCALER)) + +struct rt_timer { + struct device *dev; + void __iomem *membase; + int irq; + unsigned long timer_freq; + unsigned long timer_div; +}; + +static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val) +{ + __raw_writel(val, rt->membase + reg); +} + +static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg) +{ + return __raw_readl(rt->membase + reg); +} + +static irqreturn_t rt_timer_irq(int irq, void *_rt) +{ + struct rt_timer *rt = (struct rt_timer *) _rt; + + rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); + rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT); + + return IRQ_HANDLED; +} + + +static int rt_timer_request(struct rt_timer *rt) +{ + int err = request_irq(rt->irq, rt_timer_irq, IRQF_DISABLED, + dev_name(rt->dev), rt); + if (err) { + dev_err(rt->dev, "failed to request irq\n"); + } else { + u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL; + rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); + } + return err; +} + +static void rt_timer_free(struct rt_timer *rt) +{ + free_irq(rt->irq, rt); +} + +static int rt_timer_config(struct rt_timer *rt, unsigned long divisor) +{ + if (rt->timer_freq < divisor) + rt->timer_div = rt->timer_freq; + else + rt->timer_div = divisor; + + rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); + + return 0; +} + +static int rt_timer_enable(struct rt_timer *rt) +{ + u32 t; + + rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); + + t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); + t |= TMR0CTL_ENABLE; + rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); + + return 0; +} + +static void rt_timer_disable(struct rt_timer *rt) +{ + u32 t; + + t = rt_timer_r32(rt, TIMER_REG_TMR0CTL); + t &= ~TMR0CTL_ENABLE; + rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); +} + +static int rt_timer_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct rt_timer *rt; + struct clk *clk; + + rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL); + if (!rt) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + rt->irq = platform_get_irq(pdev, 0); + if (!rt->irq) { + dev_err(&pdev->dev, "failed to load irq\n"); + return -ENOENT; + } + + rt->membase = devm_request_and_ioremap(&pdev->dev, res); + if (IS_ERR(rt->membase)) + return PTR_ERR(rt->membase); + + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed get clock rate\n"); + return PTR_ERR(clk); + } + + rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV; + if (!rt->timer_freq) + return -EINVAL; + + rt->dev = &pdev->dev; + platform_set_drvdata(pdev, rt); + + rt_timer_request(rt); + rt_timer_config(rt, 2); + rt_timer_enable(rt); + + dev_info(&pdev->dev, "maximum frequncy is %luHz\n", rt->timer_freq); + + return 0; +} + +static int rt_timer_remove(struct platform_device *pdev) +{ + struct rt_timer *rt = platform_get_drvdata(pdev); + + rt_timer_disable(rt); + rt_timer_free(rt); + + return 0; +} + +static const struct of_device_id rt_timer_match[] = { + { .compatible = "ralink,rt2880-timer" }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt_timer_match); + +static struct platform_driver rt_timer_driver = { + .probe = rt_timer_probe, + .remove = rt_timer_remove, + .driver = { + .name = "rt-timer", + .owner = THIS_MODULE, + .of_match_table = rt_timer_match + }, +}; + +module_platform_driver(rt_timer_driver); + +MODULE_DESCRIPTION("Ralink RT2880 timer"); +MODULE_AUTHOR("John Crispin <blogic@openwrt.org"); +MODULE_LICENSE("GPL"); diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 681e7f8..2b0b83c 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -350,7 +350,7 @@ static void __init select_board(void) } /* select "default" board */ -#ifdef CONFIG_CPU_TX39XX +#ifdef CONFIG_TOSHIBA_JMR3927 txx9_board_vec = &jmr3927_vec; #endif #ifdef CONFIG_CPU_TX49XX |