summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig4
-rw-r--r--arch/mips/Makefile34
-rw-r--r--arch/mips/ath79/clock.c258
-rw-r--r--arch/mips/ath79/common.h2
-rw-r--r--arch/mips/ath79/dev-common.c10
-rw-r--r--arch/mips/ath79/setup.c23
-rw-r--r--arch/mips/boot/.gitignore1
-rw-r--r--arch/mips/boot/Makefile15
-rw-r--r--arch/mips/boot/compressed/Makefile2
l---------arch/mips/boot/dts/include/dt-bindings1
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c2
-rw-r--r--arch/mips/cavium-octeon/setup.c28
-rw-r--r--arch/mips/cavium-octeon/smp.c4
-rw-r--r--arch/mips/configs/xway_defconfig159
-rw-r--r--arch/mips/include/asm/Kbuild13
-rw-r--r--arch/mips/include/asm/bmips.h55
-rw-r--r--arch/mips/include/asm/cpu.h6
-rw-r--r--arch/mips/include/asm/cputime.h6
-rw-r--r--arch/mips/include/asm/current.h1
-rw-r--r--arch/mips/include/asm/emergency-restart.h6
-rw-r--r--arch/mips/include/asm/local64.h1
-rw-r--r--arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h2
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/gpio.h21
-rw-r--r--arch/mips/include/asm/mach-lantiq/falcon/cpu-feature-overrides.h58
-rw-r--r--arch/mips/include/asm/mach-ralink/mt7620.h40
-rw-r--r--arch/mips/include/asm/mach-ralink/mt7620/cpu-feature-overrides.h57
-rw-r--r--arch/mips/include/asm/mutex.h9
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/bridge.h4
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/iomap.h10
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pic.h5
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/sys.h31
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/xlp.h17
-rw-r--r--arch/mips/include/asm/netlogic/xlr/pic.h2
-rw-r--r--arch/mips/include/asm/octeon/octeon.h2
-rw-r--r--arch/mips/include/asm/parport.h1
-rw-r--r--arch/mips/include/asm/percpu.h6
-rw-r--r--arch/mips/include/asm/scatterlist.h6
-rw-r--r--arch/mips/include/asm/sections.h6
-rw-r--r--arch/mips/include/asm/segment.h6
-rw-r--r--arch/mips/include/asm/serial.h1
-rw-r--r--arch/mips/include/asm/ucontext.h1
-rw-r--r--arch/mips/include/asm/xor.h1
-rw-r--r--arch/mips/include/uapi/asm/Kbuild5
-rw-r--r--arch/mips/include/uapi/asm/auxvec.h4
-rw-r--r--arch/mips/include/uapi/asm/ipcbuf.h1
-rw-r--r--arch/mips/kernel/cpu-probe.c12
-rw-r--r--arch/mips/kernel/idle.c1
-rw-r--r--arch/mips/kernel/vmlinux.lds.S1
-rw-r--r--arch/mips/lantiq/falcon/sysctrl.c5
-rw-r--r--arch/mips/lantiq/xway/Makefile2
-rw-r--r--arch/mips/lantiq/xway/dcdc.c63
-rw-r--r--arch/mips/lasat/image/Makefile6
-rw-r--r--arch/mips/math-emu/cp1emu.c27
-rw-r--r--arch/mips/mm/c-octeon.c14
-rw-r--r--arch/mips/mm/dma-default.c16
-rw-r--r--arch/mips/mm/tlb-funcs.S2
-rw-r--r--arch/mips/mm/tlbex.c2
-rw-r--r--arch/mips/netlogic/Kconfig9
-rw-r--r--arch/mips/netlogic/common/smp.c4
-rw-r--r--arch/mips/netlogic/common/time.c3
-rw-r--r--arch/mips/netlogic/dts/Makefile1
-rw-r--r--arch/mips/netlogic/dts/xlp_evp.dts9
-rw-r--r--arch/mips/netlogic/dts/xlp_fvp.dts118
-rw-r--r--arch/mips/netlogic/dts/xlp_svp.dts9
-rw-r--r--arch/mips/netlogic/xlp/Makefile1
-rw-r--r--arch/mips/netlogic/xlp/dt.c8
-rw-r--r--arch/mips/netlogic/xlp/nlm_hal.c237
-rw-r--r--arch/mips/netlogic/xlp/setup.c50
-rw-r--r--arch/mips/netlogic/xlp/usb-init-xlp2.c218
-rw-r--r--arch/mips/netlogic/xlp/usb-init.c6
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c10
-rw-r--r--arch/mips/pci/Makefile1
-rw-r--r--arch/mips/pci/pci-octeon.c9
-rw-r--r--arch/mips/pci/pci-rt3883.c636
-rw-r--r--arch/mips/ralink/Kconfig10
-rw-r--r--arch/mips/ralink/Makefile4
-rw-r--r--arch/mips/ralink/Platform1
-rw-r--r--arch/mips/ralink/cevt-rt3352.c145
-rw-r--r--arch/mips/ralink/clk.c1
-rw-r--r--arch/mips/ralink/common.h2
-rw-r--r--arch/mips/ralink/mt7620.c205
-rw-r--r--arch/mips/ralink/of.c3
-rw-r--r--arch/mips/ralink/reset.c62
-rw-r--r--arch/mips/ralink/timer.c185
84 files changed, 2652 insertions, 373 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b69b4e4f55df..c2917906caaa 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
@@ -444,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)"
@@ -728,6 +731,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
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 37f9ef324f2f..75a36ad11ff5 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 765ef30e3e1c..26479f437675 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 561906c2345e..648d2dafbc56 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 a3a2741d0688..c3b04c929f29 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 80f4ecd42b0d..64807a4809d0 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 f210b09ececc..a73d6e2c4f64 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 851261e9fdc0..1466c0026093 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 bb1dbf4abb9d..0048c0897896 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 000000000000..68ae3887b3e5
--- /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 9d36774bded1..25fbfae06c1f 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 48b08eb9d9e4..b212ae12e5ac 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 138cc80c5928..24a2167db778 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 000000000000..8987846240f7
--- /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/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9b54b7a403d4..454ddf9bb76f 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 552a65a0cf2b..27bd060d716e 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 632bbe5a79ea..71b9f1998be7 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 c00eacbdd979..000000000000
--- 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 4c51401b5537..000000000000
--- 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 108d8c48e42e..000000000000
--- 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 36c93b5cc239..000000000000
--- 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 ddb947e9221f..0089a740e5ae 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 000000000000..34e9f7aabab4
--- /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 000000000000..096a10072430
--- /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 9809972ea882..6f9b24f51157 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 000000000000..f7bb8cfc5eb1
--- /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 458c1f7fbc18..000000000000
--- 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 790f0f1e55c6..4e8eacb9588a 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 9fac46fb7913..55eee77adaca 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 4b5108dfaa16..105389b79f09 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 470e52bfc061..fcf2833c16ca 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 f4ea0f7f3965..17daffb280a3 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 63c99176dffe..3c80a75233bd 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 a2eed23c49a9..f5d77b91537f 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 cf252af64590..000000000000
--- 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 844e763e9332..000000000000
--- 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 7ee0e646d82c..000000000000
--- 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 b7e37262c246..000000000000
--- 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 92ac001fc483..000000000000
--- 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 a0cb0caff152..000000000000
--- 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 9bc07b9f30fb..000000000000
--- 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 c82eb12a5b18..000000000000
--- 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 350ccccadcb9..be7196eacb88 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 7cf7f2d21943..000000000000
--- 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 84c7e51cb6d0..000000000000
--- 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 4c6167a17875..37663c7862a5 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/idle.c b/arch/mips/kernel/idle.c
index 0c655deeea4a..42f8875d2444 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/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 05826d20a792..3b46f7ce9ca7 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 ff4894a833ee..8f1866d8124d 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 7a13660d630d..087497d97357 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 000000000000..7688ac0f06d0
--- /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 dfb509d21d8e..fd32075679c6 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/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 46048d24328c..efe008846ed0 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 a0bcdbb81d41..729e7702b1de 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 aaccf1c10699..468f7f967f97 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);
+ current_cpu_type() == CPU_R12000 ||
+ current_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/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index 30a494db99c2..79bca3130bd1 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 556cb4815770..821b45175dc1 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 2447bf97d35a..852a4ee09954 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 4e35d9c453e2..6f8feb9efcff 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 045a396c57ce..13391b8a6031 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 aecb6fa9a9c3..0b9be5fd2e46 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 06407033678e..89ad04808c02 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 000000000000..63e62b7bd758
--- /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 9c5db102df53..1ebd00edaacc 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 85ac4a892ced..ed9a93c04650 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 a15cdbb8d0bd..88df445dda76 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 87560e4db35f..56c50ba43c9b 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 7b638f7be491..76a7131e486e 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 000000000000..36e9c22afc46
--- /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 ef3897ef0dc7..f8117985f0f8 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 0cce37cbffef..682d5638dc01 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 c382042911dd..719e4557e22e 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 95c2ea815cac..59cccd95688b 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 000000000000..95c9d41382e7
--- /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/ralink/Kconfig b/arch/mips/ralink/Kconfig
index 026e823d871d..424f03496d14 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 38cf1a880aaa..98ae349827be 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 cda4b6645c50..6d9c8c499f98 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 000000000000..cc17566d1934
--- /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 8dfa22ff300b..bba0cdfd83bc 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 83144c3fc5ac..42dfd6100a2d 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 0018b1a661f6..d217509e5300 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 f25ea5b45051..ce38d11f9da5 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 22120e512e7e..55c7ec59df3c 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 000000000000..e49241a2c39a
--- /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");
OpenPOWER on IntegriCloud