--- /dev/null
+From dd4bb7e821d112bff981016fd4e7c014ca9425f9 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 11 Apr 2013 05:34:59 +0000
+Subject: [PATCH 100/137] MIPS: move mips_{set,get}_machine_name() to a more
+ generic place
+
+Previously this functionality was only available to users of the mips_machine
+api. Moving the code to prom.c allows us to also add a OF wrapper.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5164/
+---
+ arch/mips/include/asm/mips_machine.h | 4 ----
+ arch/mips/include/asm/prom.h | 3 +++
+ arch/mips/kernel/mips_machine.c | 21 ---------------------
+ arch/mips/kernel/proc.c | 2 +-
+ arch/mips/kernel/prom.c | 31 +++++++++++++++++++++++++++++++
+ 5 files changed, 35 insertions(+), 26 deletions(-)
+
+--- a/arch/mips/include/asm/mips_machine.h
++++ b/arch/mips/include/asm/mips_machine.h
+@@ -42,13 +42,9 @@ extern long __mips_machines_end;
+ #ifdef CONFIG_MIPS_MACHINE
+ int mips_machtype_setup(char *id) __init;
+ void mips_machine_setup(void) __init;
+-void mips_set_machine_name(const char *name) __init;
+-char *mips_get_machine_name(void);
+ #else
+ static inline int mips_machtype_setup(char *id) { return 1; }
+ static inline void mips_machine_setup(void) { }
+-static inline void mips_set_machine_name(const char *name) { }
+-static inline char *mips_get_machine_name(void) { return NULL; }
+ #endif /* CONFIG_MIPS_MACHINE */
+
+ #endif /* __ASM_MIPS_MACHINE_H */
+--- a/arch/mips/include/asm/prom.h
++++ b/arch/mips/include/asm/prom.h
+@@ -48,4 +48,7 @@ extern void __dt_setup_arch(struct boot_
+ static inline void device_tree_init(void) { }
+ #endif /* CONFIG_OF */
+
++extern char *mips_get_machine_name(void);
++extern void mips_set_machine_name(const char *name);
++
+ #endif /* __ASM_PROM_H */
+--- a/arch/mips/kernel/mips_machine.c
++++ b/arch/mips/kernel/mips_machine.c
+@@ -13,7 +13,6 @@
+ #include <asm/mips_machine.h>
+
+ static struct mips_machine *mips_machine __initdata;
+-static char *mips_machine_name = "Unknown";
+
+ #define for_each_machine(mach) \
+ for ((mach) = (struct mips_machine *)&__mips_machines_start; \
+@@ -21,25 +20,6 @@ static char *mips_machine_name = "Unknow
+ (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \
+ (mach)++)
+
+-__init void mips_set_machine_name(const char *name)
+-{
+- char *p;
+-
+- if (name == NULL)
+- return;
+-
+- p = kstrdup(name, GFP_KERNEL);
+- if (!p)
+- pr_err("MIPS: no memory for machine_name\n");
+-
+- mips_machine_name = p;
+-}
+-
+-char *mips_get_machine_name(void)
+-{
+- return mips_machine_name;
+-}
+-
+ __init int mips_machtype_setup(char *id)
+ {
+ struct mips_machine *mach;
+@@ -79,7 +59,6 @@ __init void mips_machine_setup(void)
+ return;
+
+ mips_set_machine_name(mips_machine->mach_name);
+- pr_info("MIPS: machine is %s\n", mips_machine_name);
+
+ if (mips_machine->mach_setup)
+ mips_machine->mach_setup();
+--- a/arch/mips/kernel/proc.c
++++ b/arch/mips/kernel/proc.c
+@@ -12,7 +12,7 @@
+ #include <asm/cpu-features.h>
+ #include <asm/mipsregs.h>
+ #include <asm/processor.h>
+-#include <asm/mips_machine.h>
++#include <asm/prom.h>
+
+ unsigned int vced_count, vcei_count;
+
+--- a/arch/mips/kernel/prom.c
++++ b/arch/mips/kernel/prom.c
+@@ -23,6 +23,22 @@
+ #include <asm/page.h>
+ #include <asm/prom.h>
+
++static char mips_machine_name[64] = "Unknown";
++
++__init void mips_set_machine_name(const char *name)
++{
++ if (name == NULL)
++ return;
++
++ strncpy(mips_machine_name, name, sizeof(mips_machine_name));
++ pr_info("MIPS: machine is %s\n", mips_get_machine_name());
++}
++
++char *mips_get_machine_name(void)
++{
++ return mips_machine_name;
++}
++
+ int __init early_init_dt_scan_memory_arch(unsigned long node,
+ const char *uname, int depth,
+ void *data)
+@@ -50,6 +66,18 @@ void __init early_init_dt_setup_initrd_a
+ }
+ #endif
+
++int __init early_init_dt_scan_model(unsigned long node, const char *uname,
++ int depth, void *data)
++{
++ if (!depth) {
++ char *model = of_get_flat_dt_prop(node, "model", NULL);
++
++ if (model)
++ mips_set_machine_name(model);
++ }
++ return 0;
++}
++
+ void __init early_init_devtree(void *params)
+ {
+ /* Setup flat device-tree pointer */
+@@ -65,6 +93,9 @@ void __init early_init_devtree(void *par
+ /* Scan memory nodes */
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+ of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
++
++ /* try to load the mips machine name */
++ of_scan_flat_dt(early_init_dt_scan_model, NULL);
+ }
+
+ void __init __dt_setup_arch(struct boot_param_header *bph)
+++ /dev/null
-From eb8d7fbba907df0a51e504930c00b2c9ec837b54 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 22 Mar 2013 19:25:59 +0100
-Subject: [PATCH 100/121] MIPS: ralink: fix RT305x clock setup
-
-Add a few missing clocks and remove the unused sys clock.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/rt305x.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
---- a/arch/mips/ralink/rt305x.c
-+++ b/arch/mips/ralink/rt305x.c
-@@ -125,6 +125,7 @@ void __init ralink_clk_init(void)
- {
- unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate;
- u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
-+ int wmac_20mhz = 0;
-
- if (soc_is_rt305x() || soc_is_rt3350()) {
- t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) &
-@@ -176,11 +177,24 @@ void __init ralink_clk_init(void)
- BUG();
- }
-
-+ if (soc_is_rt3352() || soc_is_rt5350()) {
-+ u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0);
-+ if ((val & RT3352_CLKCFG0_XTAL_SEL) == 0)
-+ wmac_20mhz = 1;
-+ }
-+
- ralink_clk_add("cpu", cpu_rate);
- ralink_clk_add("10000b00.spi", sys_rate);
- ralink_clk_add("10000100.timer", wdt_rate);
-+ ralink_clk_add("10000120.watchdog", wdt_rate);
- ralink_clk_add("10000500.uart", uart_rate);
- ralink_clk_add("10000c00.uartlite", uart_rate);
-+ ralink_clk_add("10100000.ethernet", sys_rate);
-+
-+ if (wmac_20mhz)
-+ ralink_clk_add("10180000.wmac", 20000000);
-+ else
-+ ralink_clk_add("10180000.wmac", 40000000);
- }
-
- void __init ralink_of_remap(void)
--- /dev/null
+From 16d9eaf22f30ed0b0deddfe8e11426889ccdb556 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 10 Apr 2013 09:07:27 +0200
+Subject: [PATCH 101/137] MIPS: ralink: add PCI IRQ handling
+
+The Ralink IRQ code was not handling the PCI IRQ yet. Add this functionaility
+to make PCI work on rt3883.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5165/
+---
+ arch/mips/ralink/irq.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/mips/ralink/irq.c
++++ b/arch/mips/ralink/irq.c
+@@ -31,6 +31,7 @@
+ #define INTC_INT_GLOBAL BIT(31)
+
+ #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2)
++#define RALINK_CPU_IRQ_PCI (MIPS_CPU_IRQ_BASE + 4)
+ #define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5)
+ #define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6)
+ #define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7)
+@@ -104,6 +105,9 @@ asmlinkage void plat_irq_dispatch(void)
+ else if (pending & STATUSF_IP6)
+ do_IRQ(RALINK_CPU_IRQ_WIFI);
+
++ else if (pending & STATUSF_IP4)
++ do_IRQ(RALINK_CPU_IRQ_PCI);
++
+ else if (pending & STATUSF_IP2)
+ do_IRQ(RALINK_CPU_IRQ_INTC);
+
+++ /dev/null
-From 68dba842ed23c9688340444b44951c448f4ff9ba Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 16 Mar 2013 16:28:54 +0100
-Subject: [PATCH 101/121] MIPS: ralink: add missing comment in irq driver
-
-Trivial patch that adds a comment that makes the code more readable.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/irq.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/mips/ralink/irq.c
-+++ b/arch/mips/ralink/irq.c
-@@ -162,6 +162,7 @@ static int __init intc_of_init(struct de
- irq_set_chained_handler(irq, ralink_intc_irq_handler);
- irq_set_handler_data(irq, domain);
-
-+ /* tell the kernel which irq is used for performance monitoring */
- cp0_perfcount_irq = irq_create_mapping(domain, 9);
-
- return 0;
--- /dev/null
+From e6bcdad6f0811daedc2a448f5d7fb98c116a5241 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 21 Mar 2013 19:01:49 +0100
+Subject: [PATCH 102/137] MIPS: ralink: add RT3352 register defines
+
+Add a few missing defines that are needed to make USB and clock detection work
+on the RT3352.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5166/
+---
+ arch/mips/include/asm/mach-ralink/rt305x.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ralink/rt305x.h
++++ b/arch/mips/include/asm/mach-ralink/rt305x.h
+@@ -136,4 +136,17 @@ static inline int soc_is_rt5350(void)
+ #define RT305X_GPIO_MODE_SDRAM BIT(8)
+ #define RT305X_GPIO_MODE_RGMII BIT(9)
+
++#define RT3352_SYSC_REG_SYSCFG0 0x010
++#define RT3352_SYSC_REG_SYSCFG1 0x014
++#define RT3352_SYSC_REG_CLKCFG1 0x030
++#define RT3352_SYSC_REG_RSTCTRL 0x034
++#define RT3352_SYSC_REG_USB_PS 0x05c
++
++#define RT3352_CLKCFG0_XTAL_SEL BIT(20)
++#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18)
++#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20)
++#define RT3352_RSTCTRL_UHST BIT(22)
++#define RT3352_RSTCTRL_UDEV BIT(25)
++#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10)
++
+ #endif
+++ /dev/null
-From ac2614707be7ddceb0f0b623d55d200f28695d5f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 25 Mar 2013 11:19:58 +0100
-Subject: [PATCH 102/121] MIPS: ralink: add RT5350 sdram register defines
-
-Add a few missing defines that are needed to make memory detection work on the
-RT5350.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/include/asm/mach-ralink/rt305x.h | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/arch/mips/include/asm/mach-ralink/rt305x.h
-+++ b/arch/mips/include/asm/mach-ralink/rt305x.h
-@@ -97,6 +97,14 @@ static inline int soc_is_rt5350(void)
- #define RT5350_SYSCFG0_CPUCLK_320 0x2
- #define RT5350_SYSCFG0_CPUCLK_300 0x3
-
-+#define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12
-+#define RT5350_SYSCFG0_DRAM_SIZE_MASK 7
-+#define RT5350_SYSCFG0_DRAM_SIZE_2M 0
-+#define RT5350_SYSCFG0_DRAM_SIZE_8M 1
-+#define RT5350_SYSCFG0_DRAM_SIZE_16M 2
-+#define RT5350_SYSCFG0_DRAM_SIZE_32M 3
-+#define RT5350_SYSCFG0_DRAM_SIZE_64M 4
-+
- /* multi function gpio pins */
- #define RT305X_GPIO_I2C_SD 1
- #define RT305X_GPIO_I2C_SCLK 2
+++ /dev/null
-From 5157985fbc0f071276b0c3381ac8ed191878358a Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 19:01:49 +0100
-Subject: [PATCH 103/121] MIPS: ralink: add RT3352 usb register defines
-
-Add a few missing defines that are needed to make USB work on the RT3352
-and RT5350.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/include/asm/mach-ralink/rt305x.h | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
---- a/arch/mips/include/asm/mach-ralink/rt305x.h
-+++ b/arch/mips/include/asm/mach-ralink/rt305x.h
-@@ -144,4 +144,18 @@ static inline int soc_is_rt5350(void)
- #define RT305X_GPIO_MODE_SDRAM BIT(8)
- #define RT305X_GPIO_MODE_RGMII BIT(9)
-
-+#define RT3352_SYSC_REG_SYSCFG1 0x014
-+#define RT3352_SYSC_REG_CLKCFG1 0x030
-+#define RT3352_SYSC_REG_RSTCTRL 0x034
-+#define RT3352_SYSC_REG_USB_PS 0x05c
-+
-+#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18)
-+#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20)
-+#define RT3352_RSTCTRL_UHST BIT(22)
-+#define RT3352_RSTCTRL_UDEV BIT(25)
-+#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10)
-+
-+#define RT3352_SYSC_REG_SYSCFG0 0x010
-+#define RT3352_CLKCFG0_XTAL_SEL BIT(20)
-+
- #endif
--- /dev/null
+From 845f786c561c0991d9b4088a2d77b8fd4831d487 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 22 Mar 2013 19:25:59 +0100
+Subject: [PATCH 103/137] MIPS: ralink: fix RT305x clock setup
+
+Add a few missing clocks.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5167/
+---
+ arch/mips/ralink/rt305x.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/arch/mips/ralink/rt305x.c
++++ b/arch/mips/ralink/rt305x.c
+@@ -124,6 +124,8 @@ struct ralink_pinmux gpio_pinmux = {
+ void __init ralink_clk_init(void)
+ {
+ unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate;
++ unsigned long wmac_rate = 40000000;
++
+ u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
+
+ if (soc_is_rt305x() || soc_is_rt3350()) {
+@@ -176,11 +178,21 @@ void __init ralink_clk_init(void)
+ BUG();
+ }
+
++ if (soc_is_rt3352() || soc_is_rt5350()) {
++ u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0);
++
++ if (!(val & RT3352_CLKCFG0_XTAL_SEL))
++ wmac_rate = 20000000;
++ }
++
+ ralink_clk_add("cpu", cpu_rate);
+ ralink_clk_add("10000b00.spi", sys_rate);
+ ralink_clk_add("10000100.timer", wdt_rate);
++ ralink_clk_add("10000120.watchdog", wdt_rate);
+ ralink_clk_add("10000500.uart", uart_rate);
+ ralink_clk_add("10000c00.uartlite", uart_rate);
++ ralink_clk_add("10100000.ethernet", sys_rate);
++ ralink_clk_add("10180000.wmac", wmac_rate);
+ }
+
+ void __init ralink_of_remap(void)
--- /dev/null
+From 2747613b1bba0d4497ed2c4a77e2011d02029153 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 16 Mar 2013 16:28:54 +0100
+Subject: [PATCH 104/137] MIPS: ralink: add missing comment in irq driver
+
+Trivial patch that adds a comment that makes the code more readable.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5168/
+---
+ arch/mips/ralink/irq.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/mips/ralink/irq.c
++++ b/arch/mips/ralink/irq.c
+@@ -166,6 +166,7 @@ static int __init intc_of_init(struct de
+ irq_set_chained_handler(irq, ralink_intc_irq_handler);
+ irq_set_handler_data(irq, domain);
+
++ /* tell the kernel which irq is used for performance monitoring */
+ cp0_perfcount_irq = irq_create_mapping(domain, 9);
+
+ return 0;
+++ /dev/null
-From 806a489c720767f63bf5046c2ccd87ded9549c1c Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 16 Mar 2013 00:50:57 +0100
-Subject: [PATCH 104/121] MIPS: ralink: add pinmux driver
-
-Add code to setup the pinmux on ralonk SoC. The SoC has a single 32 bit register
-for this functionality with simple on/off bits. Building a full featured pinctrl
-driver would be overkill.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Makefile | 2 +-
- arch/mips/ralink/common.h | 5 ++-
- arch/mips/ralink/of.c | 2 ++
- arch/mips/ralink/pinmux.c | 76 +++++++++++++++++++++++++++++++++++++++++++++
- arch/mips/ralink/rt305x.c | 6 ++--
- 5 files changed, 85 insertions(+), 6 deletions(-)
- create mode 100644 arch/mips/ralink/pinmux.c
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -6,7 +6,7 @@
- # 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 pinmux.o
-
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
-
---- a/arch/mips/ralink/common.h
-+++ b/arch/mips/ralink/common.h
-@@ -22,9 +22,10 @@ struct ralink_pinmux {
- struct ralink_pinmux_grp *mode;
- struct ralink_pinmux_grp *uart;
- int uart_shift;
-+ u32 uart_mask;
- void (*wdt_reset)(void);
- };
--extern struct ralink_pinmux gpio_pinmux;
-+extern struct ralink_pinmux rt_pinmux;
-
- struct ralink_soc_info {
- unsigned char sys_type[RAMIPS_SYS_TYPE_LEN];
-@@ -41,4 +42,6 @@ extern void prom_soc_init(struct ralink_
-
- __iomem void *plat_of_remap_node(const char *node);
-
-+void ralink_pinmux(void);
-+
- #endif /* _RALINK_COMMON_H__ */
---- a/arch/mips/ralink/of.c
-+++ b/arch/mips/ralink/of.c
-@@ -101,6 +101,8 @@ static int __init plat_of_setup(void)
- if (of_platform_populate(NULL, of_ids, NULL, NULL))
- panic("failed to populate DT\n");
-
-+ ralink_pinmux();
-+
- return 0;
- }
-
---- /dev/null
-+++ b/arch/mips/ralink/pinmux.c
-@@ -0,0 +1,76 @@
-+/*
-+ * 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/kernel.h>
-+#include <linux/of.h>
-+
-+#include <asm/mach-ralink/ralink_regs.h>
-+
-+#include "common.h"
-+
-+#define SYSC_REG_GPIO_MODE 0x60
-+
-+static u32 ralink_mux_mask(const char *name, struct ralink_pinmux_grp *grps)
-+{
-+ for (; grps->name; grps++)
-+ if (!strcmp(grps->name, name))
-+ return grps->mask;
-+
-+ return 0;
-+}
-+
-+void ralink_pinmux(void)
-+{
-+ const __be32 *wdt;
-+ struct device_node *np;
-+ struct property *prop;
-+ const char *uart, *pin;
-+ u32 mode = 0;
-+
-+ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-sysc");
-+ if (!np)
-+ return;
-+
-+ of_property_for_each_string(np, "ralink,gpiomux", prop, pin) {
-+ int m = ralink_mux_mask(pin, rt_pinmux.mode);
-+ if (m) {
-+ mode |= m;
-+ pr_debug("pinmux: registered gpiomux \"%s\"\n", pin);
-+ } else {
-+ pr_err("pinmux: failed to load \"%s\"\n", pin);
-+ }
-+ }
-+
-+ of_property_for_each_string(np, "ralink,pinmux", prop, pin) {
-+ int m = ralink_mux_mask(pin, rt_pinmux.mode);
-+ if (m) {
-+ mode &= ~m;
-+ pr_debug("pinmux: registered pinmux \"%s\"\n", pin);
-+ } else {
-+ pr_err("pinmux: failed to load group \"%s\"\n", pin);
-+ }
-+ }
-+
-+ of_property_read_string(np, "ralink,uartmux", &uart);
-+ if (uart) {
-+ int m = ralink_mux_mask(uart, rt_pinmux.uart);
-+ mode |= rt_pinmux.uart_mask << rt_pinmux.uart_shift;
-+ if (m) {
-+ mode &= ~(m << rt_pinmux.uart_shift);
-+ pr_debug("pinmux: registered uartmux \"%s\"\n", uart);
-+ } else {
-+ pr_debug("pinmux: registered uartmux \"gpio\"\n");
-+ }
-+ }
-+
-+ wdt = of_get_property(np, "ralink,wdtmux", NULL);
-+ if (wdt && *wdt && rt_pinmux.wdt_reset)
-+ rt_pinmux.wdt_reset();
-+
-+ rt_sysc_w32(mode, SYSC_REG_GPIO_MODE);
-+}
---- a/arch/mips/ralink/rt305x.c
-+++ b/arch/mips/ralink/rt305x.c
-@@ -97,9 +97,6 @@ struct ralink_pinmux_grp uart_mux[] = {
- .mask = RT305X_GPIO_MODE_GPIO_I2S,
- .gpio_first = RT305X_GPIO_7,
- .gpio_last = RT305X_GPIO_14,
-- }, {
-- .name = "gpio",
-- .mask = RT305X_GPIO_MODE_GPIO,
- }, {0}
- };
-
-@@ -114,10 +111,11 @@ void rt305x_wdt_reset(void)
- rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG);
- }
-
--struct ralink_pinmux gpio_pinmux = {
-+struct ralink_pinmux rt_pinmux = {
- .mode = mode_mux,
- .uart = uart_mux,
- .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT,
-+ .uart_mask = RT305X_GPIO_MODE_GPIO,
- .wdt_reset = rt305x_wdt_reset,
- };
-
+++ /dev/null
-From 45e797ec7555c50775d9ac7fc7a17a544344aa3f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 17:47:07 +0100
-Subject: [PATCH 105/121] MIPS: extend RT3050 dtsi file
-
-Add some additional properties to the dtsi file for ethernet and wifi.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/dts/rt3050.dtsi | 96 ++++++++++++++++++++++++++++++++------
- 1 file changed, 81 insertions(+), 15 deletions(-)
-
---- a/arch/mips/ralink/dts/rt3050.dtsi
-+++ b/arch/mips/ralink/dts/rt3050.dtsi
-@@ -1,7 +1,7 @@
- / {
- #address-cells = <1>;
- #size-cells = <1>;
-- compatible = "ralink,rt3050-soc", "ralink,rt3052-soc";
-+ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc";
-
- cpus {
- cpu@0 {
-@@ -23,7 +23,7 @@
- palmbus@10000000 {
- compatible = "palmbus";
- reg = <0x10000000 0x200000>;
-- ranges = <0x0 0x10000000 0x1FFFFF>;
-+ ranges = <0x0 0x10000000 0x1FFFFF>;
-
- #address-cells = <1>;
- #size-cells = <1>;
-@@ -34,8 +34,18 @@
- };
-
- timer@100 {
-+ compatible = "ralink,rt3052-timer", "ralink,rt2880-timer";
-+ reg = <0x100 0x20>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <1>;
-+
-+ status = "disabled";
-+ };
-+
-+ watchdog@120 {
- compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt";
-- reg = <0x100 0x100>;
-+ reg = <0x120 0x10>;
- };
-
- intc: intc@200 {
-@@ -61,10 +71,12 @@
- gpio-controller;
- #gpio-cells = <2>;
-
-- ralink,ngpio = <24>;
-- ralink,regs = [ 00 04 08 0c
-- 20 24 28 2c
-- 30 34 ];
-+ ralink,num-gpios = <24>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 20 24 28 2c
-+ 30 34 ];
-+
-+ status = "disabled";
- };
-
- gpio1: gpio@638 {
-@@ -74,10 +86,12 @@
- gpio-controller;
- #gpio-cells = <2>;
-
-- ralink,ngpio = <16>;
-- ralink,regs = [ 00 04 08 0c
-- 10 14 18 1c
-- 20 24 ];
-+ ralink,num-gpios = <16>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
- };
-
- gpio2: gpio@660 {
-@@ -87,10 +101,21 @@
- gpio-controller;
- #gpio-cells = <2>;
-
-- ralink,ngpio = <12>;
-- ralink,regs = [ 00 04 08 0c
-- 10 14 18 1c
-- 20 24 ];
-+ ralink,num-gpios = <12>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
-+ };
-+
-+ spi@b00 {
-+ compatible = "ralink,rt3050-spi", "ralink,rt2880-spi";
-+ reg = <0xb00 0x100>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "disabled";
- };
-
- uartlite@c00 {
-@@ -102,5 +127,46 @@
-
- reg-shift = <2>;
- };
-+
-+ };
-+
-+ ethernet@10100000 {
-+ compatible = "ralink,rt3050-eth";
-+ reg = <0x10100000 10000>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <5>;
-+
-+ status = "disabled";
-+ };
-+
-+ esw@10110000 {
-+ compatible = "ralink,rt3050-esw";
-+ reg = <0x10110000 8000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <17>;
-+
-+ status = "disabled";
-+ };
-+
-+ wmac@10180000 {
-+ compatible = "ralink,rt3050-wmac", "ralink,rt2880-wmac";
-+ reg = <0x10180000 40000>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <6>;
-+
-+ status = "disabled";
-+ };
-+
-+ otg@101c0000 {
-+ compatible = "ralink,rt3050-otg";
-+ reg = <0x101c0000 40000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <18>;
-+
-+ status = "disabled";
- };
- };
--- /dev/null
+From 31f4b3ca1c9bb4bcbbebbe5db5a33ac82f130d9c Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 25 Mar 2013 11:19:58 +0100
+Subject: [PATCH 105/137] MIPS: ralink: add RT5350 sdram register defines
+
+Add a few missing defines that are needed to make memory detection work on the
+RT5350.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5169/
+---
+ arch/mips/include/asm/mach-ralink/rt305x.h | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ralink/rt305x.h
++++ b/arch/mips/include/asm/mach-ralink/rt305x.h
+@@ -97,6 +97,14 @@ static inline int soc_is_rt5350(void)
+ #define RT5350_SYSCFG0_CPUCLK_320 0x2
+ #define RT5350_SYSCFG0_CPUCLK_300 0x3
+
++#define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12
++#define RT5350_SYSCFG0_DRAM_SIZE_MASK 7
++#define RT5350_SYSCFG0_DRAM_SIZE_2M 0
++#define RT5350_SYSCFG0_DRAM_SIZE_8M 1
++#define RT5350_SYSCFG0_DRAM_SIZE_16M 2
++#define RT5350_SYSCFG0_DRAM_SIZE_32M 3
++#define RT5350_SYSCFG0_DRAM_SIZE_64M 4
++
+ /* multi function gpio pins */
+ #define RT305X_GPIO_I2C_SD 1
+ #define RT305X_GPIO_I2C_SCLK 2
+++ /dev/null
-From 1238d973f3828a65ccf9aead437b4e04925b100e Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 17:47:24 +0100
-Subject: [PATCH 106/121] MIPS: add RT5350 dtsi file
-
-Add a dtsi file for RT5350 Soc. This SoC is almost the same as RT3050 but has
-OHCI/EHCI in favour of the Synopsis DWC2 core.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/dts/rt5350.dtsi | 181 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 181 insertions(+)
- create mode 100644 arch/mips/ralink/dts/rt5350.dtsi
-
---- /dev/null
-+++ b/arch/mips/ralink/dts/rt5350.dtsi
-@@ -0,0 +1,181 @@
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,rt5350-soc";
-+
-+ cpus {
-+ cpu@0 {
-+ compatible = "mips,mips24KEc";
-+ };
-+ };
-+
-+ chosen {
-+ bootargs = "console=ttyS0,57600 init=/init";
-+ };
-+
-+ cpuintc: cpuintc@0 {
-+ #address-cells = <0>;
-+ #interrupt-cells = <1>;
-+ interrupt-controller;
-+ compatible = "mti,cpu-interrupt-controller";
-+ };
-+
-+ palmbus@10000000 {
-+ compatible = "palmbus";
-+ reg = <0x10000000 0x200000>;
-+ ranges = <0x0 0x10000000 0x1FFFFF>;
-+
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ sysc@0 {
-+ compatible = "ralink,rt5350-sysc", "ralink,rt3050-sysc";
-+ reg = <0x0 0x100>;
-+ };
-+
-+ timer@100 {
-+ compatible = "ralink,rt5350-timer", "ralink,rt2880-timer";
-+ reg = <0x100 0x20>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <1>;
-+
-+ status = "disabled";
-+ };
-+
-+ watchdog@120 {
-+ compatible = "ralink,rt5350-wdt", "ralink,rt2880-wdt";
-+ reg = <0x120 0x10>;
-+ };
-+
-+ intc: intc@200 {
-+ compatible = "ralink,rt5350-intc", "ralink,rt2880-intc";
-+ reg = <0x200 0x100>;
-+
-+ interrupt-controller;
-+ #interrupt-cells = <1>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <2>;
-+ };
-+
-+ memc@300 {
-+ compatible = "ralink,rt5350-memc", "ralink,rt3050-memc";
-+ reg = <0x300 0x100>;
-+ };
-+
-+ gpio0: gpio@600 {
-+ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio";
-+ reg = <0x600 0x34>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <24>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 20 24 28 2c
-+ 30 34 ];
-+
-+ status = "disabled";
-+ };
-+
-+ gpio1: gpio@638 {
-+ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio";
-+ reg = <0x638 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <16>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
-+ };
-+
-+ gpio2: gpio@660 {
-+ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio";
-+ reg = <0x660 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <12>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
-+ };
-+
-+ spi@b00 {
-+ compatible = "ralink,rt5350-spi", "ralink,rt2880-spi";
-+ reg = <0xb00 0x100>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ status = "disabled";
-+ };
-+
-+ uartlite@c00 {
-+ compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a";
-+ reg = <0xc00 0x100>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <12>;
-+
-+ reg-shift = <2>;
-+ };
-+ };
-+
-+ ethernet@10100000 {
-+ compatible = "ralink,rt5350-eth", "ralink,rt3050-eth";
-+ reg = <0x10100000 10000>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <5>;
-+
-+ status = "disabled";
-+ };
-+
-+ esw@10110000 {
-+ compatible = "ralink,rt5350-esw", "ralink,rt3050-esw";
-+ reg = <0x10110000 8000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <17>;
-+
-+ status = "disabled";
-+ };
-+
-+ wmac@10180000 {
-+ compatible = "ralink,rt5350-wmac", "ralink,rt2880-wmac";
-+ reg = <0x10180000 40000>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <6>;
-+
-+ status = "disabled";
-+ };
-+
-+ ehci@101c0000 {
-+ compatible = "ralink,rt5350-ehci", "ehci-platform";
-+ reg = <0x101c0000 0x1000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <18>;
-+
-+ status = "disabled";
-+ };
-+
-+ ohci@101c1000 {
-+ compatible = "ralink,rt5350-ohci", "ohci-platform";
-+ reg = <0x101c1000 0x1000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <18>;
-+
-+ status = "disabled";
-+ };
-+};
--- /dev/null
+From d83e83a544258b68b4411232a31ccce134244a19 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 9 Apr 2013 18:31:15 +0200
+Subject: [PATCH 106/137] MIPS: ralink: make early_printk work on RT2880
+
+RT2880 has a different location for the early serial port.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5170/
+---
+ arch/mips/ralink/early_printk.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/mips/ralink/early_printk.c
++++ b/arch/mips/ralink/early_printk.c
+@@ -11,7 +11,11 @@
+
+ #include <asm/addrspace.h>
+
++#ifdef CONFIG_SOC_RT288X
++#define EARLY_UART_BASE 0x300c00
++#else
+ #define EARLY_UART_BASE 0x10000c00
++#endif
+
+ #define UART_REG_RX 0x00
+ #define UART_REG_TX 0x04
+++ /dev/null
-From c4429f19cc66951962c171dba90b8747f95a654e Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 27 Jan 2013 09:17:20 +0100
-Subject: [PATCH V2 09/16] MIPS: ralink: adds support for RT2880 SoC family
-
-Add support code for rt2880 SOC.
-
-The code detects the SoC and registers the clk / pinmux settings.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/Kconfig | 2 +-
- arch/mips/include/asm/mach-ralink/rt288x.h | 49 ++++++++++
- arch/mips/ralink/Kconfig | 3 +
- arch/mips/ralink/Makefile | 1 +
- arch/mips/ralink/Platform | 5 +
- arch/mips/ralink/rt288x.c | 143 ++++++++++++++++++++++++++++
- 6 files changed, 202 insertions(+), 1 deletion(-)
- create mode 100644 arch/mips/include/asm/mach-ralink/rt288x.h
- create mode 100644 arch/mips/ralink/rt288x.c
-
---- a/arch/mips/Kconfig
-+++ b/arch/mips/Kconfig
-@@ -1189,7 +1189,7 @@ config BOOT_ELF32
-
- config MIPS_L1_CACHE_SHIFT
- int
-- default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL
-+ default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X
- default "6" if MIPS_CPU_SCACHE
- default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
- default "5"
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/rt288x.h
-@@ -0,0 +1,49 @@
-+/*
-+ * 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.
-+ *
-+ * Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#ifndef _RT288X_REGS_H_
-+#define _RT288X_REGS_H_
-+
-+#define RT2880_SYSC_BASE 0x00300000
-+
-+#define SYSC_REG_CHIP_NAME0 0x00
-+#define SYSC_REG_CHIP_NAME1 0x04
-+#define SYSC_REG_CHIP_ID 0x0c
-+#define SYSC_REG_SYSTEM_CONFIG 0x10
-+#define SYSC_REG_CLKCFG 0x30
-+
-+#define RT2880_CHIP_NAME0 0x38325452
-+#define RT2880_CHIP_NAME1 0x20203038
-+
-+#define CHIP_ID_ID_MASK 0xff
-+#define CHIP_ID_ID_SHIFT 8
-+#define CHIP_ID_REV_MASK 0xff
-+
-+#define SYSTEM_CONFIG_CPUCLK_SHIFT 20
-+#define SYSTEM_CONFIG_CPUCLK_MASK 0x3
-+#define SYSTEM_CONFIG_CPUCLK_250 0x0
-+#define SYSTEM_CONFIG_CPUCLK_266 0x1
-+#define SYSTEM_CONFIG_CPUCLK_280 0x2
-+#define SYSTEM_CONFIG_CPUCLK_300 0x3
-+
-+#define RT2880_GPIO_MODE_I2C BIT(0)
-+#define RT2880_GPIO_MODE_UART0 BIT(1)
-+#define RT2880_GPIO_MODE_SPI BIT(2)
-+#define RT2880_GPIO_MODE_UART1 BIT(3)
-+#define RT2880_GPIO_MODE_JTAG BIT(4)
-+#define RT2880_GPIO_MODE_MDIO BIT(5)
-+#define RT2880_GPIO_MODE_SDRAM BIT(6)
-+#define RT2880_GPIO_MODE_PCI BIT(7)
-+
-+#define CLKCFG_SRAM_CS_N_WDT BIT(9)
-+
-+#endif
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -6,6 +6,9 @@ choice
- help
- Select Ralink MIPS SoC type.
-
-+ config SOC_RT288X
-+ bool "RT288x"
-+
- config SOC_RT305X
- bool "RT305x"
- select USB_ARCH_HAS_HCD
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -8,6 +8,7 @@
-
- obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o
-
-+obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
-
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
---- a/arch/mips/ralink/Platform
-+++ b/arch/mips/ralink/Platform
-@@ -5,6 +5,11 @@ core-$(CONFIG_RALINK) += arch/mips/rali
- cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink
-
- #
-+# Ralink RT288x
-+#
-+load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000
-+
-+#
- # Ralink RT305x
- #
- load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
---- /dev/null
-+++ b/arch/mips/ralink/rt288x.c
-@@ -0,0 +1,143 @@
-+/*
-+ * 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.
-+ *
-+ * Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+
-+#include <asm/mipsregs.h>
-+#include <asm/mach-ralink/ralink_regs.h>
-+#include <asm/mach-ralink/rt288x.h>
-+
-+#include "common.h"
-+
-+struct ralink_pinmux_grp mode_mux[] = {
-+ {
-+ .name = "i2c",
-+ .mask = RT2880_GPIO_MODE_I2C,
-+ .gpio_first = 1,
-+ .gpio_last = 2,
-+ }, {
-+ .name = "spi",
-+ .mask = RT2880_GPIO_MODE_SPI,
-+ .gpio_first = 3,
-+ .gpio_last = 6,
-+ }, {
-+ .name = "uartlite",
-+ .mask = RT2880_GPIO_MODE_UART0,
-+ .gpio_first = 7,
-+ .gpio_last = 14,
-+ }, {
-+ .name = "jtag",
-+ .mask = RT2880_GPIO_MODE_JTAG,
-+ .gpio_first = 17,
-+ .gpio_last = 21,
-+ }, {
-+ .name = "mdio",
-+ .mask = RT2880_GPIO_MODE_MDIO,
-+ .gpio_first = 22,
-+ .gpio_last = 23,
-+ }, {
-+ .name = "sdram",
-+ .mask = RT2880_GPIO_MODE_SDRAM,
-+ .gpio_first = 24,
-+ .gpio_last = 39,
-+ }, {
-+ .name = "pci",
-+ .mask = RT2880_GPIO_MODE_PCI,
-+ .gpio_first = 40,
-+ .gpio_last = 71,
-+ }, {0}
-+};
-+
-+void rt288x_wdt_reset(void)
-+{
-+ u32 t;
-+
-+ /* enable WDT reset output on pin SRAM_CS_N */
-+ t = rt_sysc_r32(SYSC_REG_CLKCFG);
-+ t |= CLKCFG_SRAM_CS_N_WDT;
-+ rt_sysc_w32(t, SYSC_REG_CLKCFG);
-+}
-+
-+struct ralink_pinmux rt_pinmux = {
-+ .mode = mode_mux,
-+ .wdt_reset = rt288x_wdt_reset,
-+};
-+
-+void ralink_usb_platform(void)
-+{
-+}
-+
-+void __init ralink_clk_init(void)
-+{
-+ unsigned long cpu_rate;
-+ u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
-+ t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK);
-+
-+ switch (t) {
-+ case SYSTEM_CONFIG_CPUCLK_250:
-+ cpu_rate = 250000000;
-+ break;
-+ case SYSTEM_CONFIG_CPUCLK_266:
-+ cpu_rate = 266666667;
-+ break;
-+ case SYSTEM_CONFIG_CPUCLK_280:
-+ cpu_rate = 280000000;
-+ break;
-+ case SYSTEM_CONFIG_CPUCLK_300:
-+ cpu_rate = 300000000;
-+ break;
-+ }
-+
-+ ralink_clk_add("cpu", cpu_rate);
-+ ralink_clk_add("300100.timer", cpu_rate / 2);
-+ ralink_clk_add("300120.watchdog", cpu_rate / 2);
-+ ralink_clk_add("300500.uart", cpu_rate / 2);
-+ ralink_clk_add("300c00.uartlite", cpu_rate / 2);
-+ ralink_clk_add("400000.ethernet", cpu_rate / 2);
-+}
-+
-+void __init ralink_of_remap(void)
-+{
-+ rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc");
-+ rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc");
-+
-+ if (!rt_sysc_membase || !rt_memc_membase)
-+ panic("Failed to remap core resources");
-+}
-+
-+void prom_soc_init(struct ralink_soc_info *soc_info)
-+{
-+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT2880_SYSC_BASE);
-+ const char *name;
-+ u32 n0;
-+ u32 n1;
-+ u32 id;
-+
-+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
-+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
-+ id = __raw_readl(sysc + SYSC_REG_CHIP_ID);
-+
-+ if (n0 == RT2880_CHIP_NAME0 && n1 == RT2880_CHIP_NAME1) {
-+ soc_info->compatible = "ralink,r2880-soc";
-+ name = "RT2880";
-+ } else {
-+ panic("rt288x: unknown SoC, n0:%08x n1:%08x", n0, n1);
-+ }
-+
-+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
-+ "Ralink %s id:%u rev:%u",
-+ name,
-+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
-+ (id & CHIP_ID_REV_MASK));
-+}
--- /dev/null
+From b4c597bd073d5e4c9cee800ac5a25fb9ff1c0ef7 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 12 Apr 2013 22:12:09 +0200
+Subject: [PATCH 107/137] MIPS: ralink: rename gpio_pinmux to rt_gpio_pinmux
+
+Add proper namespacing to the variable.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5171/
+---
+ arch/mips/ralink/common.h | 2 +-
+ arch/mips/ralink/rt305x.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/ralink/common.h
++++ b/arch/mips/ralink/common.h
+@@ -24,7 +24,7 @@ struct ralink_pinmux {
+ int uart_shift;
+ void (*wdt_reset)(void);
+ };
+-extern struct ralink_pinmux gpio_pinmux;
++extern struct ralink_pinmux rt_gpio_pinmux;
+
+ struct ralink_soc_info {
+ unsigned char sys_type[RAMIPS_SYS_TYPE_LEN];
+--- a/arch/mips/ralink/rt305x.c
++++ b/arch/mips/ralink/rt305x.c
+@@ -114,7 +114,7 @@ void rt305x_wdt_reset(void)
+ rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG);
+ }
+
+-struct ralink_pinmux gpio_pinmux = {
++struct ralink_pinmux rt_gpio_pinmux = {
+ .mode = mode_mux,
+ .uart = uart_mux,
+ .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT,
+++ /dev/null
-From b72ae753b73cbc4b488dcdbf997faec199c8bb3f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 18:29:02 +0100
-Subject: [PATCH 108/121] MIPS: add rt2880 dts files
-
-Add a dtsi file for RT2880 SoC and a sample dts file. This SoC is first one that
-was released in this SoC family.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Kconfig | 4 ++
- arch/mips/ralink/dts/Makefile | 1 +
- arch/mips/ralink/dts/rt2880.dtsi | 116 ++++++++++++++++++++++++++++++++++
- arch/mips/ralink/dts/rt2880_eval.dts | 52 +++++++++++++++
- 4 files changed, 173 insertions(+)
- create mode 100644 arch/mips/ralink/dts/rt2880.dtsi
- create mode 100644 arch/mips/ralink/dts/rt2880_eval.dts
-
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -26,6 +26,10 @@ choice
- config DTB_RT_NONE
- bool "None"
-
-+ config DTB_RT2880_EVAL
-+ bool "RT2880 eval kit"
-+ depends on SOC_RT288X
-+
- config DTB_RT305X_EVAL
- bool "RT305x eval kit"
- depends on SOC_RT305X
---- a/arch/mips/ralink/dts/Makefile
-+++ b/arch/mips/ralink/dts/Makefile
-@@ -1 +1,2 @@
-+obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
- obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
---- /dev/null
-+++ b/arch/mips/ralink/dts/rt2880.dtsi
-@@ -0,0 +1,116 @@
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,rt2880-soc";
-+
-+ cpus {
-+ cpu@0 {
-+ compatible = "mips,mips24KEc";
-+ };
-+ };
-+
-+ chosen {
-+ bootargs = "console=ttyS0,57600 init=/init";
-+ };
-+
-+ cpuintc: cpuintc@0 {
-+ #address-cells = <0>;
-+ #interrupt-cells = <1>;
-+ interrupt-controller;
-+ compatible = "mti,cpu-interrupt-controller";
-+ };
-+
-+ palmbus@10000000 {
-+ compatible = "palmbus";
-+ reg = <0x10000000 0x200000>;
-+ ranges = <0x0 0x10000000 0x1FFFFF>;
-+
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ sysc@300000 {
-+ compatible = "ralink,rt2880-sysc";
-+ reg = <0x300000 0x100>;
-+ };
-+
-+ timer@300100 {
-+ compatible = "ralink,rt2880-timer";
-+ reg = <0x300100 0x20>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <1>;
-+
-+ status = "disabled";
-+ };
-+
-+ watchdog@300120 {
-+ compatible = "ralink,rt2880-wdt";
-+ reg = <0x300120 0x10>;
-+ };
-+
-+ intc: intc@300200 {
-+ compatible = "ralink,rt2880-intc";
-+ reg = <0x300200 0x100>;
-+
-+ interrupt-controller;
-+ #interrupt-cells = <1>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <2>;
-+ };
-+
-+ memc@300300 {
-+ compatible = "ralink,rt2880-memc";
-+ reg = <0x300300 0x100>;
-+ };
-+
-+ gpio0: gpio@300600 {
-+ compatible = "ralink,rt2880-gpio";
-+ reg = <0x300600 0x34>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <24>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 20 24 28 2c
-+ 30 34 ];
-+ };
-+
-+ gpio1: gpio@300638 {
-+ compatible = "ralink,rt2880-gpio";
-+ reg = <0x300638 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <16>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+ };
-+
-+ gpio2: gpio@300660 {
-+ compatible = "ralink,rt2880-gpio";
-+ reg = <0x300660 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <32>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+ };
-+
-+ uartlite@300c00 {
-+ compatible = "ralink,rt2880-uart", "ns16550a";
-+ reg = <0x300c00 0x100>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <12>;
-+
-+ reg-shift = <2>;
-+ };
-+ };
-+};
---- /dev/null
-+++ b/arch/mips/ralink/dts/rt2880_eval.dts
-@@ -0,0 +1,52 @@
-+/dts-v1/;
-+
-+/include/ "rt2880.dtsi"
-+
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,rt2880-eval-board", "ralink,rt2880-soc";
-+ model = "Ralink RT2880 evaluation board";
-+
-+ memory@8000000 {
-+ reg = <0x0 0x2000000>;
-+ };
-+
-+ palmbus@10000000 {
-+ sysc@300000 {
-+ ralink,pinmux = "uartlite", "spi";
-+ ralink,uartmux = "gpio";
-+ ralink,wdtmux = <0>;
-+ };
-+ };
-+
-+ cfi@1f000000 {
-+ compatible = "cfi-flash";
-+ reg = <0x1f000000 0x800000>;
-+
-+ bank-width = <2>;
-+ device-width = <2>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ partition@0 {
-+ label = "uboot";
-+ reg = <0x0 0x30000>;
-+ read-only;
-+ };
-+ partition@30000 {
-+ label = "uboot-env";
-+ reg = <0x30000 0x10000>;
-+ read-only;
-+ };
-+ partition@40000 {
-+ label = "calibration";
-+ reg = <0x40000 0x10000>;
-+ read-only;
-+ };
-+ partition@50000 {
-+ label = "linux";
-+ reg = <0x50000 0x7b0000>;
-+ };
-+ };
-+};
--- /dev/null
+From 96eba63bf18cd3d96ded62fb809c8cf7e0f2e2c1 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 12 Apr 2013 22:16:12 +0200
+Subject: [PATCH 108/137] MIPS: ralink: make the RT305x pinmuxing structure
+ static
+
+These structures are exported via struct ralink_pinmux rt_gpio_pinmux and can
+hence be static.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5172/
+---
+ arch/mips/ralink/rt305x.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/ralink/rt305x.c
++++ b/arch/mips/ralink/rt305x.c
+@@ -22,7 +22,7 @@
+
+ enum rt305x_soc_type rt305x_soc;
+
+-struct ralink_pinmux_grp mode_mux[] = {
++static struct ralink_pinmux_grp mode_mux[] = {
+ {
+ .name = "i2c",
+ .mask = RT305X_GPIO_MODE_I2C,
+@@ -61,7 +61,7 @@ struct ralink_pinmux_grp mode_mux[] = {
+ }, {0}
+ };
+
+-struct ralink_pinmux_grp uart_mux[] = {
++static struct ralink_pinmux_grp uart_mux[] = {
+ {
+ .name = "uartf",
+ .mask = RT305X_GPIO_MODE_UARTF,
+@@ -103,7 +103,7 @@ struct ralink_pinmux_grp uart_mux[] = {
+ }, {0}
+ };
+
+-void rt305x_wdt_reset(void)
++static void rt305x_wdt_reset(void)
+ {
+ u32 t;
+
--- /dev/null
+From 61d50d9625dcb454759950ebd45a335c3aaacf84 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Fri, 12 Apr 2013 12:40:23 +0200
+Subject: [PATCH 109/137] MIPS: ralink: add pci group to struct ralink_pinmux
+
+This will be used for RT3662/RT3883.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+Acked-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5173/
+---
+ arch/mips/ralink/common.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/mips/ralink/common.h
++++ b/arch/mips/ralink/common.h
+@@ -23,6 +23,9 @@ struct ralink_pinmux {
+ struct ralink_pinmux_grp *uart;
+ int uart_shift;
+ void (*wdt_reset)(void);
++ struct ralink_pinmux_grp *pci;
++ int pci_shift;
++ u32 pci_mask;
+ };
+ extern struct ralink_pinmux rt_gpio_pinmux;
+
+++ /dev/null
-From 45a8644332a85e8b099df9d467a719ded741e749 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 27 Jan 2013 09:39:02 +0100
-Subject: [PATCH 109/121] MIPS: ralink: adds support for RT3883 SoC family
-
-Add support code for rt3883 SOC.
-
-The code detects the SoC and registers the clk / pinmux settings.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/include/asm/mach-ralink/rt3883.h | 247 ++++++++++++++++++++++++++++
- arch/mips/ralink/Kconfig | 5 +
- arch/mips/ralink/Makefile | 1 +
- arch/mips/ralink/Platform | 5 +
- arch/mips/ralink/rt3883.c | 207 +++++++++++++++++++++++
- 5 files changed, 465 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/rt3883.h
- create mode 100644 arch/mips/ralink/rt3883.c
-
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/rt3883.h
-@@ -0,0 +1,247 @@
-+/*
-+ * Ralink RT3662/RT3883 SoC register definitions
-+ *
-+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+
-+#ifndef _RT3883_REGS_H_
-+#define _RT3883_REGS_H_
-+
-+#include <linux/bitops.h>
-+
-+#define RT3883_SDRAM_BASE 0x00000000
-+#define RT3883_SYSC_BASE 0x10000000
-+#define RT3883_TIMER_BASE 0x10000100
-+#define RT3883_INTC_BASE 0x10000200
-+#define RT3883_MEMC_BASE 0x10000300
-+#define RT3883_UART0_BASE 0x10000500
-+#define RT3883_PIO_BASE 0x10000600
-+#define RT3883_FSCC_BASE 0x10000700
-+#define RT3883_NANDC_BASE 0x10000810
-+#define RT3883_I2C_BASE 0x10000900
-+#define RT3883_I2S_BASE 0x10000a00
-+#define RT3883_SPI_BASE 0x10000b00
-+#define RT3883_UART1_BASE 0x10000c00
-+#define RT3883_PCM_BASE 0x10002000
-+#define RT3883_GDMA_BASE 0x10002800
-+#define RT3883_CODEC1_BASE 0x10003000
-+#define RT3883_CODEC2_BASE 0x10003800
-+#define RT3883_FE_BASE 0x10100000
-+#define RT3883_ROM_BASE 0x10118000
-+#define RT3883_USBDEV_BASE 0x10112000
-+#define RT3883_PCI_BASE 0x10140000
-+#define RT3883_WLAN_BASE 0x10180000
-+#define RT3883_USBHOST_BASE 0x101c0000
-+#define RT3883_BOOT_BASE 0x1c000000
-+#define RT3883_SRAM_BASE 0x1e000000
-+#define RT3883_PCIMEM_BASE 0x20000000
-+
-+#define RT3883_EHCI_BASE (RT3883_USBHOST_BASE)
-+#define RT3883_OHCI_BASE (RT3883_USBHOST_BASE + 0x1000)
-+
-+#define RT3883_SYSC_SIZE 0x100
-+#define RT3883_TIMER_SIZE 0x100
-+#define RT3883_INTC_SIZE 0x100
-+#define RT3883_MEMC_SIZE 0x100
-+#define RT3883_UART0_SIZE 0x100
-+#define RT3883_UART1_SIZE 0x100
-+#define RT3883_PIO_SIZE 0x100
-+#define RT3883_FSCC_SIZE 0x100
-+#define RT3883_NANDC_SIZE 0x0f0
-+#define RT3883_I2C_SIZE 0x100
-+#define RT3883_I2S_SIZE 0x100
-+#define RT3883_SPI_SIZE 0x100
-+#define RT3883_PCM_SIZE 0x800
-+#define RT3883_GDMA_SIZE 0x800
-+#define RT3883_CODEC1_SIZE 0x800
-+#define RT3883_CODEC2_SIZE 0x800
-+#define RT3883_FE_SIZE 0x10000
-+#define RT3883_ROM_SIZE 0x4000
-+#define RT3883_USBDEV_SIZE 0x4000
-+#define RT3883_PCI_SIZE 0x40000
-+#define RT3883_WLAN_SIZE 0x40000
-+#define RT3883_USBHOST_SIZE 0x40000
-+#define RT3883_BOOT_SIZE (32 * 1024 * 1024)
-+#define RT3883_SRAM_SIZE (32 * 1024 * 1024)
-+
-+/* SYSC registers */
-+#define RT3883_SYSC_REG_CHIPID0_3 0x00 /* Chip ID 0 */
-+#define RT3883_SYSC_REG_CHIPID4_7 0x04 /* Chip ID 1 */
-+#define RT3883_SYSC_REG_REVID 0x0c /* Chip Revision Identification */
-+#define RT3883_SYSC_REG_SYSCFG0 0x10 /* System Configuration 0 */
-+#define RT3883_SYSC_REG_SYSCFG1 0x14 /* System Configuration 1 */
-+#define RT3883_SYSC_REG_CLKCFG0 0x2c /* Clock Configuration 0 */
-+#define RT3883_SYSC_REG_CLKCFG1 0x30 /* Clock Configuration 1 */
-+#define RT3883_SYSC_REG_RSTCTRL 0x34 /* Reset Control*/
-+#define RT3883_SYSC_REG_RSTSTAT 0x38 /* Reset Status*/
-+#define RT3883_SYSC_REG_USB_PS 0x5c /* USB Power saving control */
-+#define RT3883_SYSC_REG_GPIO_MODE 0x60 /* GPIO Purpose Select */
-+#define RT3883_SYSC_REG_PCIE_CLK_GEN0 0x7c
-+#define RT3883_SYSC_REG_PCIE_CLK_GEN1 0x80
-+#define RT3883_SYSC_REG_PCIE_CLK_GEN2 0x84
-+#define RT3883_SYSC_REG_PMU 0x88
-+#define RT3883_SYSC_REG_PMU1 0x8c
-+
-+#define RT3883_CHIP_NAME0 0x38335452
-+#define RT3883_CHIP_NAME1 0x20203338
-+
-+#define RT3883_REVID_VER_ID_MASK 0x0f
-+#define RT3883_REVID_VER_ID_SHIFT 8
-+#define RT3883_REVID_ECO_ID_MASK 0x0f
-+
-+#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17)
-+#define RT3883_SYSCFG0_CPUCLK_SHIFT 8
-+#define RT3883_SYSCFG0_CPUCLK_MASK 0x3
-+#define RT3883_SYSCFG0_CPUCLK_250 0x0
-+#define RT3883_SYSCFG0_CPUCLK_384 0x1
-+#define RT3883_SYSCFG0_CPUCLK_480 0x2
-+#define RT3883_SYSCFG0_CPUCLK_500 0x3
-+
-+#define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10)
-+#define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8)
-+#define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7)
-+#define RT3883_SYSCFG1_PCI_66M_MODE BIT(6)
-+#define RT3883_SYSCFG1_GPIO2_AS_WDT_OUT BIT(2)
-+
-+#define RT3883_CLKCFG1_PCIE_CLK_EN BIT(21)
-+#define RT3883_CLKCFG1_UPHY1_CLK_EN BIT(20)
-+#define RT3883_CLKCFG1_PCI_CLK_EN BIT(19)
-+#define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18)
-+
-+#define RT3883_GPIO_MODE_I2C BIT(0)
-+#define RT3883_GPIO_MODE_SPI BIT(1)
-+#define RT3883_GPIO_MODE_UART0_SHIFT 2
-+#define RT3883_GPIO_MODE_UART0_MASK 0x7
-+#define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT)
-+#define RT3883_GPIO_MODE_UARTF 0x0
-+#define RT3883_GPIO_MODE_PCM_UARTF 0x1
-+#define RT3883_GPIO_MODE_PCM_I2S 0x2
-+#define RT3883_GPIO_MODE_I2S_UARTF 0x3
-+#define RT3883_GPIO_MODE_PCM_GPIO 0x4
-+#define RT3883_GPIO_MODE_GPIO_UARTF 0x5
-+#define RT3883_GPIO_MODE_GPIO_I2S 0x6
-+#define RT3883_GPIO_MODE_GPIO 0x7
-+#define RT3883_GPIO_MODE_UART1 BIT(5)
-+#define RT3883_GPIO_MODE_JTAG BIT(6)
-+#define RT3883_GPIO_MODE_MDIO BIT(7)
-+#define RT3883_GPIO_MODE_GE1 BIT(9)
-+#define RT3883_GPIO_MODE_GE2 BIT(10)
-+#define RT3883_GPIO_MODE_PCI_SHIFT 11
-+#define RT3883_GPIO_MODE_PCI_MASK 0x7
-+#define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT)
-+#define RT3883_GPIO_MODE_LNA_A_SHIFT 16
-+#define RT3883_GPIO_MODE_LNA_A_MASK 0x3
-+#define _RT3883_GPIO_MODE_LNA_A(_x) ((_x) << RT3883_GPIO_MODE_LNA_A_SHIFT)
-+#define RT3883_GPIO_MODE_LNA_A_GPIO 0x3
-+#define RT3883_GPIO_MODE_LNA_A _RT3883_GPIO_MODE_LNA_A(RT3883_GPIO_MODE_LNA_A_MASK)
-+#define RT3883_GPIO_MODE_LNA_G_SHIFT 18
-+#define RT3883_GPIO_MODE_LNA_G_MASK 0x3
-+#define _RT3883_GPIO_MODE_LNA_G(_x) ((_x) << RT3883_GPIO_MODE_LNA_G_SHIFT)
-+#define RT3883_GPIO_MODE_LNA_G_GPIO 0x3
-+#define RT3883_GPIO_MODE_LNA_G _RT3883_GPIO_MODE_LNA_G(RT3883_GPIO_MODE_LNA_G_MASK)
-+
-+#define RT3883_GPIO_I2C_SD 1
-+#define RT3883_GPIO_I2C_SCLK 2
-+#define RT3883_GPIO_SPI_CS0 3
-+#define RT3883_GPIO_SPI_CLK 4
-+#define RT3883_GPIO_SPI_MOSI 5
-+#define RT3883_GPIO_SPI_MISO 6
-+#define RT3883_GPIO_7 7
-+#define RT3883_GPIO_10 10
-+#define RT3883_GPIO_14 14
-+#define RT3883_GPIO_UART1_TXD 15
-+#define RT3883_GPIO_UART1_RXD 16
-+#define RT3883_GPIO_JTAG_TDO 17
-+#define RT3883_GPIO_JTAG_TDI 18
-+#define RT3883_GPIO_JTAG_TMS 19
-+#define RT3883_GPIO_JTAG_TCLK 20
-+#define RT3883_GPIO_JTAG_TRST_N 21
-+#define RT3883_GPIO_MDIO_MDC 22
-+#define RT3883_GPIO_MDIO_MDIO 23
-+#define RT3883_GPIO_LNA_PE_A0 32
-+#define RT3883_GPIO_LNA_PE_A1 33
-+#define RT3883_GPIO_LNA_PE_A2 34
-+#define RT3883_GPIO_LNA_PE_G0 35
-+#define RT3883_GPIO_LNA_PE_G1 36
-+#define RT3883_GPIO_LNA_PE_G2 37
-+#define RT3883_GPIO_PCI_AD0 40
-+#define RT3883_GPIO_PCI_AD31 71
-+#define RT3883_GPIO_GE2_TXD0 72
-+#define RT3883_GPIO_GE2_TXD1 73
-+#define RT3883_GPIO_GE2_TXD2 74
-+#define RT3883_GPIO_GE2_TXD3 75
-+#define RT3883_GPIO_GE2_TXEN 76
-+#define RT3883_GPIO_GE2_TXCLK 77
-+#define RT3883_GPIO_GE2_RXD0 78
-+#define RT3883_GPIO_GE2_RXD1 79
-+#define RT3883_GPIO_GE2_RXD2 80
-+#define RT3883_GPIO_GE2_RXD3 81
-+#define RT3883_GPIO_GE2_RXDV 82
-+#define RT3883_GPIO_GE2_RXCLK 83
-+#define RT3883_GPIO_GE1_TXD0 84
-+#define RT3883_GPIO_GE1_TXD1 85
-+#define RT3883_GPIO_GE1_TXD2 86
-+#define RT3883_GPIO_GE1_TXD3 87
-+#define RT3883_GPIO_GE1_TXEN 88
-+#define RT3883_GPIO_GE1_TXCLK 89
-+#define RT3883_GPIO_GE1_RXD0 90
-+#define RT3883_GPIO_GE1_RXD1 91
-+#define RT3883_GPIO_GE1_RXD2 92
-+#define RT3883_GPIO_GE1_RXD3 93
-+#define RT3883_GPIO_GE1_RXDV 94
-+#define RT3883_GPIO_GE1_RXCLK 95
-+
-+#define RT3883_RSTCTRL_PCIE_PCI_PDM BIT(27)
-+#define RT3883_RSTCTRL_FLASH BIT(26)
-+#define RT3883_RSTCTRL_UDEV BIT(25)
-+#define RT3883_RSTCTRL_PCI BIT(24)
-+#define RT3883_RSTCTRL_PCIE BIT(23)
-+#define RT3883_RSTCTRL_UHST BIT(22)
-+#define RT3883_RSTCTRL_FE BIT(21)
-+#define RT3883_RSTCTRL_WLAN BIT(20)
-+#define RT3883_RSTCTRL_UART1 BIT(29)
-+#define RT3883_RSTCTRL_SPI BIT(18)
-+#define RT3883_RSTCTRL_I2S BIT(17)
-+#define RT3883_RSTCTRL_I2C BIT(16)
-+#define RT3883_RSTCTRL_NAND BIT(15)
-+#define RT3883_RSTCTRL_DMA BIT(14)
-+#define RT3883_RSTCTRL_PIO BIT(13)
-+#define RT3883_RSTCTRL_UART BIT(12)
-+#define RT3883_RSTCTRL_PCM BIT(11)
-+#define RT3883_RSTCTRL_MC BIT(10)
-+#define RT3883_RSTCTRL_INTC BIT(9)
-+#define RT3883_RSTCTRL_TIMER BIT(8)
-+#define RT3883_RSTCTRL_SYS BIT(0)
-+
-+#define RT3883_INTC_INT_SYSCTL BIT(0)
-+#define RT3883_INTC_INT_TIMER0 BIT(1)
-+#define RT3883_INTC_INT_TIMER1 BIT(2)
-+#define RT3883_INTC_INT_IA BIT(3)
-+#define RT3883_INTC_INT_PCM BIT(4)
-+#define RT3883_INTC_INT_UART0 BIT(5)
-+#define RT3883_INTC_INT_PIO BIT(6)
-+#define RT3883_INTC_INT_DMA BIT(7)
-+#define RT3883_INTC_INT_NAND BIT(8)
-+#define RT3883_INTC_INT_PERFC BIT(9)
-+#define RT3883_INTC_INT_I2S BIT(10)
-+#define RT3883_INTC_INT_UART1 BIT(12)
-+#define RT3883_INTC_INT_UHST BIT(18)
-+#define RT3883_INTC_INT_UDEV BIT(19)
-+
-+/* FLASH/SRAM/Codec Controller registers */
-+#define RT3883_FSCC_REG_FLASH_CFG0 0x00
-+#define RT3883_FSCC_REG_FLASH_CFG1 0x04
-+#define RT3883_FSCC_REG_CODEC_CFG0 0x40
-+#define RT3883_FSCC_REG_CODEC_CFG1 0x44
-+
-+#define RT3883_FLASH_CFG_WIDTH_SHIFT 26
-+#define RT3883_FLASH_CFG_WIDTH_MASK 0x3
-+#define RT3883_FLASH_CFG_WIDTH_8BIT 0x0
-+#define RT3883_FLASH_CFG_WIDTH_16BIT 0x1
-+#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2
-+
-+#endif /* _RT3883_REGS_H_ */
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -15,6 +15,11 @@ choice
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
-
-+ config SOC_RT3883
-+ bool "RT3883"
-+ select USB_ARCH_HAS_OHCI
-+ select USB_ARCH_HAS_EHCI
-+
- endchoice
-
- choice
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -10,6 +10,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o
-
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
-+obj-$(CONFIG_SOC_RT3883) += rt3883.o
-
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-
---- a/arch/mips/ralink/Platform
-+++ b/arch/mips/ralink/Platform
-@@ -13,3 +13,8 @@ load-$(CONFIG_SOC_RT288X) += 0xffffffff8
- # Ralink RT305x
- #
- load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
-+
-+#
-+# Ralink RT3883
-+#
-+load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
---- /dev/null
-+++ b/arch/mips/ralink/rt3883.c
-@@ -0,0 +1,207 @@
-+/*
-+ * 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.
-+ *
-+ * Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
-+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+
-+#include <asm/mipsregs.h>
-+#include <asm/mach-ralink/ralink_regs.h>
-+#include <asm/mach-ralink/rt3883.h>
-+
-+#include "common.h"
-+
-+struct ralink_pinmux_grp mode_mux[] = {
-+ {
-+ .name = "i2c",
-+ .mask = RT3883_GPIO_MODE_I2C,
-+ .gpio_first = RT3883_GPIO_I2C_SD,
-+ .gpio_last = RT3883_GPIO_I2C_SCLK,
-+ }, {
-+ .name = "spi",
-+ .mask = RT3883_GPIO_MODE_SPI,
-+ .gpio_first = RT3883_GPIO_SPI_CS0,
-+ .gpio_last = RT3883_GPIO_SPI_MISO,
-+ }, {
-+ .name = "uartlite",
-+ .mask = RT3883_GPIO_MODE_UART1,
-+ .gpio_first = RT3883_GPIO_UART1_TXD,
-+ .gpio_last = RT3883_GPIO_UART1_RXD,
-+ }, {
-+ .name = "jtag",
-+ .mask = RT3883_GPIO_MODE_JTAG,
-+ .gpio_first = RT3883_GPIO_JTAG_TDO,
-+ .gpio_last = RT3883_GPIO_JTAG_TCLK,
-+ }, {
-+ .name = "mdio",
-+ .mask = RT3883_GPIO_MODE_MDIO,
-+ .gpio_first = RT3883_GPIO_MDIO_MDC,
-+ .gpio_last = RT3883_GPIO_MDIO_MDIO,
-+ }, {
-+ .name = "ge1",
-+ .mask = RT3883_GPIO_MODE_GE1,
-+ .gpio_first = RT3883_GPIO_GE1_TXD0,
-+ .gpio_last = RT3883_GPIO_GE1_RXCLK,
-+ }, {
-+ .name = "ge2",
-+ .mask = RT3883_GPIO_MODE_GE2,
-+ .gpio_first = RT3883_GPIO_GE2_TXD0,
-+ .gpio_last = RT3883_GPIO_GE2_RXCLK,
-+ }, {
-+ .name = "pci",
-+ .mask = RT3883_GPIO_MODE_PCI,
-+ .gpio_first = RT3883_GPIO_PCI_AD0,
-+ .gpio_last = RT3883_GPIO_PCI_AD31,
-+ }, {
-+ .name = "lna a",
-+ .mask = RT3883_GPIO_MODE_LNA_A,
-+ .gpio_first = RT3883_GPIO_LNA_PE_A0,
-+ .gpio_last = RT3883_GPIO_LNA_PE_A2,
-+ }, {
-+ .name = "lna g",
-+ .mask = RT3883_GPIO_MODE_LNA_G,
-+ .gpio_first = RT3883_GPIO_LNA_PE_G0,
-+ .gpio_last = RT3883_GPIO_LNA_PE_G2,
-+ }, {0}
-+};
-+
-+struct ralink_pinmux_grp uart_mux[] = {
-+ {
-+ .name = "uartf",
-+ .mask = RT3883_GPIO_MODE_UARTF,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "pcm uartf",
-+ .mask = RT3883_GPIO_MODE_PCM_UARTF,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "pcm i2s",
-+ .mask = RT3883_GPIO_MODE_PCM_I2S,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "i2s uartf",
-+ .mask = RT3883_GPIO_MODE_I2S_UARTF,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "pcm gpio",
-+ .mask = RT3883_GPIO_MODE_PCM_GPIO,
-+ .gpio_first = RT3883_GPIO_10,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "gpio uartf",
-+ .mask = RT3883_GPIO_MODE_GPIO_UARTF,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "gpio i2s",
-+ .mask = RT3883_GPIO_MODE_GPIO_I2S,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
-+ }, {0}
-+};
-+
-+static void rt3883_wdt_reset(void)
-+{
-+ u32 t;
-+
-+ /* enable WDT reset output on GPIO 2 */
-+ t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1);
-+ t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT;
-+ rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1);
-+}
-+
-+struct ralink_pinmux rt_pinmux = {
-+ .mode = mode_mux,
-+ .uart = uart_mux,
-+ .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT,
-+ .uart_mask = RT3883_GPIO_MODE_GPIO,
-+ .wdt_reset = rt3883_wdt_reset,
-+};
-+
-+void __init ralink_clk_init(void)
-+{
-+ unsigned long cpu_rate, sys_rate;
-+ u32 syscfg0;
-+ u32 clksel;
-+ u32 ddr2;
-+
-+ syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0);
-+ clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) &
-+ RT3883_SYSCFG0_CPUCLK_MASK);
-+ ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
-+
-+ switch (clksel) {
-+ case RT3883_SYSCFG0_CPUCLK_250:
-+ cpu_rate = 250000000;
-+ sys_rate = (ddr2) ? 125000000 : 83000000;
-+ break;
-+ case RT3883_SYSCFG0_CPUCLK_384:
-+ cpu_rate = 384000000;
-+ sys_rate = (ddr2) ? 128000000 : 96000000;
-+ break;
-+ case RT3883_SYSCFG0_CPUCLK_480:
-+ cpu_rate = 480000000;
-+ sys_rate = (ddr2) ? 160000000 : 120000000;
-+ break;
-+ case RT3883_SYSCFG0_CPUCLK_500:
-+ cpu_rate = 500000000;
-+ sys_rate = (ddr2) ? 166000000 : 125000000;
-+ break;
-+ }
-+
-+ ralink_clk_add("cpu", cpu_rate);
-+ ralink_clk_add("10000100.timer", sys_rate);
-+ ralink_clk_add("10000120.watchdog", sys_rate);
-+ ralink_clk_add("10000500.uart", 40000000);
-+ ralink_clk_add("10000b00.spi", sys_rate);
-+ ralink_clk_add("10000c00.uartlite", 40000000);
-+ ralink_clk_add("10100000.ethernet", sys_rate);
-+}
-+
-+void __init ralink_of_remap(void)
-+{
-+ rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc");
-+ rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc");
-+
-+ if (!rt_sysc_membase || !rt_memc_membase)
-+ panic("Failed to remap core resources");
-+}
-+
-+void prom_soc_init(struct ralink_soc_info *soc_info)
-+{
-+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT3883_SYSC_BASE);
-+ const char *name;
-+ u32 n0;
-+ u32 n1;
-+ u32 id;
-+
-+ n0 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID0_3);
-+ n1 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID4_7);
-+ id = __raw_readl(sysc + RT3883_SYSC_REG_REVID);
-+
-+ if (n0 == RT3883_CHIP_NAME0 && n1 == RT3883_CHIP_NAME1) {
-+ soc_info->compatible = "ralink,rt3883-soc";
-+ name = "RT3883";
-+ } else {
-+ panic("rt3883: unknown SoC, n0:%08x n1:%08x", n0, n1);
-+ }
-+
-+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
-+ "Ralink %s ver:%u eco:%u",
-+ name,
-+ (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK,
-+ (id & RT3883_REVID_ECO_ID_MASK));
-+}
+++ /dev/null
-From 9d13fedc08f4e2cd9640983c2af8b9e9c64c094b Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 18:37:00 +0100
-Subject: [PATCH 110/121] MIPS: add rt3883 dts files
-
-Add a dtsi file for RT3883 SoC. This SoC is almost the same as RT3050 but has
-OHCI/EHCI in favour of the Synopsis DWC2 core. There is also a 3x3 802.11n
-wifi core.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Kconfig | 4 +
- arch/mips/ralink/dts/Makefile | 1 +
- arch/mips/ralink/dts/rt3883.dtsi | 186 ++++++++++++++++++++++++++++++++++
- arch/mips/ralink/dts/rt3883_eval.dts | 52 ++++++++++
- 4 files changed, 243 insertions(+)
- create mode 100644 arch/mips/ralink/dts/rt3883.dtsi
- create mode 100644 arch/mips/ralink/dts/rt3883_eval.dts
-
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -39,6 +39,10 @@ choice
- bool "RT305x eval kit"
- depends on SOC_RT305X
-
-+ config DTB_RT3883_EVAL
-+ bool "RT3883 eval kit"
-+ depends on SOC_RT3883
-+
- endchoice
-
- endif
---- a/arch/mips/ralink/dts/Makefile
-+++ b/arch/mips/ralink/dts/Makefile
-@@ -1,2 +1,3 @@
- obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
- obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
-+obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o
---- /dev/null
-+++ b/arch/mips/ralink/dts/rt3883.dtsi
-@@ -0,0 +1,186 @@
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,rt3883-soc";
-+
-+ cpus {
-+ cpu@0 {
-+ compatible = "mips,mips74Kc";
-+ };
-+ };
-+
-+ chosen {
-+ bootargs = "console=ttyS0,57600 init=/init";
-+ };
-+
-+ cpuintc: cpuintc@0 {
-+ #address-cells = <0>;
-+ #interrupt-cells = <1>;
-+ interrupt-controller;
-+ compatible = "mti,cpu-interrupt-controller";
-+ };
-+
-+ palmbus@10000000 {
-+ compatible = "palmbus";
-+ reg = <0x10000000 0x200000>;
-+ ranges = <0x0 0x10000000 0x1FFFFF>;
-+
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ sysc@0 {
-+ compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc";
-+ reg = <0x0 0x100>;
-+ };
-+
-+ timer@100 {
-+ compatible = "ralink,rt3883-timer", "ralink,rt2880-timer";
-+ reg = <0x100 0x20>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <1>;
-+
-+ status = "disabled";
-+ };
-+
-+ watchdog@120 {
-+ compatible = "ralink,rt3883-wdt", "ralink,rt2880-wdt";
-+ reg = <0x120 0x10>;
-+ };
-+
-+ intc: intc@200 {
-+ compatible = "ralink,rt3883-intc", "ralink,rt2880-intc";
-+ reg = <0x200 0x100>;
-+
-+ interrupt-controller;
-+ #interrupt-cells = <1>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <2>;
-+ };
-+
-+ memc@300 {
-+ compatible = "ralink,rt3883-memc", "ralink,rt3050-memc";
-+ reg = <0x300 0x100>;
-+ };
-+
-+ gpio0: gpio@600 {
-+ compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio";
-+ reg = <0x600 0x34>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <24>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 20 24 28 2c
-+ 30 34 ];
-+
-+ status = "disabled";
-+ };
-+
-+ gpio1: gpio@638 {
-+ compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio";
-+ reg = <0x638 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <16>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
-+ };
-+
-+ gpio2: gpio@660 {
-+ compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio";
-+ reg = <0x660 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <32>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
-+ };
-+
-+ gpio3: gpio@688 {
-+ compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio";
-+ reg = <0x688 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <24>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+
-+ status = "disabled";
-+ };
-+
-+ spi@b00 {
-+ compatible = "ralink,rt3883-spi", "ralink,rt2880-spi";
-+ reg = <0xb00 0x100>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "disabled";
-+ };
-+
-+ uartlite@c00 {
-+ compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a";
-+ reg = <0xc00 0x100>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <12>;
-+
-+ reg-shift = <2>;
-+ };
-+ };
-+
-+ ethernet@10100000 {
-+ compatible = "ralink,rt3883-eth";
-+ reg = <0x10100000 10000>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <5>;
-+
-+ status = "disabled";
-+ };
-+
-+ wmac@10180000 {
-+ compatible = "ralink,rt3883-wmac", "ralink,rt2880-wmac";
-+ reg = <0x10180000 40000>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <6>;
-+
-+ status = "disabled";
-+ };
-+
-+ ehci@101c0000 {
-+ compatible = "ralink,rt3883-ehci", "ehci-platform";
-+ reg = <0x101c0000 0x1000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <18>;
-+
-+ status = "disabled";
-+ };
-+
-+ ohci@101c1000 {
-+ compatible = "ralink,rt3883-ohci", "ohci-platform";
-+ reg = <0x101c1000 0x1000>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <18>;
-+
-+ status = "disabled";
-+ };
-+};
---- /dev/null
-+++ b/arch/mips/ralink/dts/rt3883_eval.dts
-@@ -0,0 +1,52 @@
-+/dts-v1/;
-+
-+/include/ "rt3883.dtsi"
-+
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,rt3883-eval-board", "ralink,rt3883-soc";
-+ model = "Ralink RT3883 evaluation board";
-+
-+ memory@0 {
-+ reg = <0x0 0x4000000>;
-+ };
-+
-+ palmbus@10000000 {
-+ sysc@0 {
-+ ralink,pinmux = "uartlite", "spi";
-+ ralink,uartmux = "gpio";
-+ ralink,wdtmux = <0>;
-+ };
-+ };
-+
-+ cfi@1f000000 {
-+ compatible = "cfi-flash";
-+ reg = <0x1f000000 0x800000>;
-+
-+ bank-width = <2>;
-+ device-width = <2>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ partition@0 {
-+ label = "uboot";
-+ reg = <0x0 0x30000>;
-+ read-only;
-+ };
-+ partition@30000 {
-+ label = "uboot-env";
-+ reg = <0x30000 0x10000>;
-+ read-only;
-+ };
-+ partition@40000 {
-+ label = "calibration";
-+ reg = <0x40000 0x10000>;
-+ read-only;
-+ };
-+ partition@50000 {
-+ label = "linux";
-+ reg = <0x50000 0x7b0000>;
-+ };
-+ };
-+};
--- /dev/null
+From faf5989efed503b2ee689dad82bb2d60da718d99 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 12 Apr 2013 12:45:27 +0200
+Subject: [PATCH 110/137] MIPS: ralink: add uart mask to struct ralink_pinmux
+
+Add a field for the uart muxing mask and set it inside the rt305x setup code.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5744/
+---
+ arch/mips/ralink/common.h | 1 +
+ arch/mips/ralink/rt305x.c | 5 +++--
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/ralink/common.h
++++ b/arch/mips/ralink/common.h
+@@ -22,6 +22,7 @@ struct ralink_pinmux {
+ struct ralink_pinmux_grp *mode;
+ struct ralink_pinmux_grp *uart;
+ int uart_shift;
++ u32 uart_mask;
+ void (*wdt_reset)(void);
+ struct ralink_pinmux_grp *pci;
+ int pci_shift;
+--- a/arch/mips/ralink/rt305x.c
++++ b/arch/mips/ralink/rt305x.c
+@@ -91,12 +91,12 @@ static struct ralink_pinmux_grp uart_mux
+ .name = "gpio uartf",
+ .mask = RT305X_GPIO_MODE_GPIO_UARTF,
+ .gpio_first = RT305X_GPIO_7,
+- .gpio_last = RT305X_GPIO_14,
++ .gpio_last = RT305X_GPIO_10,
+ }, {
+ .name = "gpio i2s",
+ .mask = RT305X_GPIO_MODE_GPIO_I2S,
+ .gpio_first = RT305X_GPIO_7,
+- .gpio_last = RT305X_GPIO_14,
++ .gpio_last = RT305X_GPIO_10,
+ }, {
+ .name = "gpio",
+ .mask = RT305X_GPIO_MODE_GPIO,
+@@ -118,6 +118,7 @@ struct ralink_pinmux rt_gpio_pinmux = {
+ .mode = mode_mux,
+ .uart = uart_mux,
+ .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT,
++ .uart_mask = RT305X_GPIO_MODE_UART0_MASK,
+ .wdt_reset = rt305x_wdt_reset,
+ };
+
+++ /dev/null
-From 8831277e0167cdcf3dc3ecc5d5a67d4fd9d0ed77 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 17:49:02 +0100
-Subject: [PATCH 111/121] MIPS: ralink: adds support for MT7620 SoC family
-
-Add support code for mt7620 SOC.
-
-The code detects the SoC and registers the clk / pinmux settings.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/include/asm/mach-ralink/mt7620.h | 66 +++++++++
- arch/mips/ralink/Kconfig | 3 +
- arch/mips/ralink/Makefile | 1 +
- arch/mips/ralink/Platform | 5 +
- arch/mips/ralink/mt7620.c | 215 ++++++++++++++++++++++++++++
- 5 files changed, 290 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/mt7620.h
- create mode 100644 arch/mips/ralink/mt7620.c
-
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
-@@ -0,0 +1,66 @@
-+/*
-+ * 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.
-+ *
-+ * Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#ifndef _MT7620_REGS_H_
-+#define _MT7620_REGS_H_
-+
-+#define MT7620_SYSC_BASE 0x10000000
-+
-+#define SYSC_REG_CHIP_NAME0 0x00
-+#define SYSC_REG_CHIP_NAME1 0x04
-+#define SYSC_REG_CHIP_REV 0x0c
-+#define SYSC_REG_SYSTEM_CONFIG0 0x10
-+#define SYSC_REG_SYSTEM_CONFIG1 0x14
-+#define SYSC_REG_CPLL_CONFIG0 0x54
-+#define SYSC_REG_CPLL_CONFIG1 0x58
-+
-+#define MT7620N_CHIP_NAME0 0x33365452
-+#define MT7620N_CHIP_NAME1 0x20203235
-+
-+#define MT7620A_CHIP_NAME0 0x3637544d
-+#define MT7620A_CHIP_NAME1 0x20203032
-+
-+#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 MT7620_CPLL_SW_CONFIG_SHIFT 31
-+#define MT7620_CPLL_SW_CONFIG_MASK 0x1
-+#define MT7620_CPLL_CPU_CLK_SHIFT 24
-+#define MT7620_CPLL_CPU_CLK_MASK 0x1
-+
-+#define MT7620_GPIO_MODE_I2C BIT(0)
-+#define MT7620_GPIO_MODE_UART0_SHIFT 2
-+#define MT7620_GPIO_MODE_UART0_MASK 0x7
-+#define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT)
-+#define MT7620_GPIO_MODE_UARTF 0x0
-+#define MT7620_GPIO_MODE_PCM_UARTF 0x1
-+#define MT7620_GPIO_MODE_PCM_I2S 0x2
-+#define MT7620_GPIO_MODE_I2S_UARTF 0x3
-+#define MT7620_GPIO_MODE_PCM_GPIO 0x4
-+#define MT7620_GPIO_MODE_GPIO_UARTF 0x5
-+#define MT7620_GPIO_MODE_GPIO_I2S 0x6
-+#define MT7620_GPIO_MODE_GPIO 0x7
-+#define MT7620_GPIO_MODE_UART1 BIT(5)
-+#define MT7620_GPIO_MODE_MDIO BIT(8)
-+#define MT7620_GPIO_MODE_RGMII1 BIT(9)
-+#define MT7620_GPIO_MODE_RGMII2 BIT(10)
-+#define MT7620_GPIO_MODE_SPI BIT(11)
-+#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12)
-+#define MT7620_GPIO_MODE_WLED BIT(13)
-+#define MT7620_GPIO_MODE_JTAG BIT(15)
-+#define MT7620_GPIO_MODE_EPHY BIT(15)
-+#define MT7620_GPIO_MODE_WDT BIT(22)
-+
-+#endif
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -20,6 +20,9 @@ choice
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
-
-+ config SOC_MT7620
-+ bool "MT7620"
-+
- endchoice
-
- choice
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -11,6 +11,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
- obj-$(CONFIG_SOC_RT3883) += rt3883.o
-+obj-$(CONFIG_SOC_MT7620) += mt7620.o
-
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-
---- a/arch/mips/ralink/Platform
-+++ b/arch/mips/ralink/Platform
-@@ -18,3 +18,8 @@ load-$(CONFIG_SOC_RT305X) += 0xffffffff8
- # Ralink RT3883
- #
- load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
-+
-+#
-+# Ralink MT7620
-+#
-+load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000
---- /dev/null
-+++ b/arch/mips/ralink/mt7620.c
-@@ -0,0 +1,215 @@
-+/*
-+ * 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.
-+ *
-+ * Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+
-+#include <asm/mipsregs.h>
-+#include <asm/mach-ralink/ralink_regs.h>
-+#include <asm/mach-ralink/mt7620.h>
-+
-+#include "common.h"
-+
-+
-+struct ralink_pinmux_grp mode_mux[] = {
-+ {
-+ .name = "i2c",
-+ .mask = MT7620_GPIO_MODE_I2C,
-+ .gpio_first = 1,
-+ .gpio_last = 2,
-+ }, {
-+ .name = "spi",
-+ .mask = MT7620_GPIO_MODE_SPI,
-+ .gpio_first = 3,
-+ .gpio_last = 6,
-+ }, {
-+ .name = "uartlite",
-+ .mask = MT7620_GPIO_MODE_UART1,
-+ .gpio_first = 15,
-+ .gpio_last = 16,
-+ }, {
-+ .name = "wdt",
-+ .mask = MT7620_GPIO_MODE_WDT,
-+ .gpio_first = 17,
-+ .gpio_last = 17,
-+ }, {
-+ .name = "mdio",
-+ .mask = MT7620_GPIO_MODE_MDIO,
-+ .gpio_first = 22,
-+ .gpio_last = 23,
-+ }, {
-+ .name = "rgmii1",
-+ .mask = MT7620_GPIO_MODE_RGMII1,
-+ .gpio_first = 24,
-+ .gpio_last = 35,
-+ }, {
-+ .name = "spi refclk",
-+ .mask = MT7620_GPIO_MODE_SPI_REF_CLK,
-+ .gpio_first = 37,
-+ .gpio_last = 39,
-+ }, {
-+ .name = "jtag",
-+ .mask = MT7620_GPIO_MODE_JTAG,
-+ .gpio_first = 40,
-+ .gpio_last = 44,
-+ }, {
-+ /* shared lines with jtag */
-+ .name = "ephy",
-+ .mask = MT7620_GPIO_MODE_EPHY,
-+ .gpio_first = 40,
-+ .gpio_last = 44,
-+ }, {
-+ .name = "nand",
-+ .mask = MT7620_GPIO_MODE_JTAG,
-+ .gpio_first = 45,
-+ .gpio_last = 59,
-+ }, {
-+ .name = "rgmii2",
-+ .mask = MT7620_GPIO_MODE_RGMII2,
-+ .gpio_first = 60,
-+ .gpio_last = 71,
-+ }, {
-+ .name = "wled",
-+ .mask = MT7620_GPIO_MODE_WLED,
-+ .gpio_first = 72,
-+ .gpio_last = 72,
-+ }, {0}
-+};
-+
-+
-+struct ralink_pinmux_grp uart_mux[] = {
-+ {
-+ .name = "uartf",
-+ .mask = MT7620_GPIO_MODE_UARTF,
-+ .gpio_first = 7,
-+ .gpio_last = 14,
-+ }, {
-+ .name = "pcm uartf",
-+ .mask = MT7620_GPIO_MODE_PCM_UARTF,
-+ .gpio_first = 7,
-+ .gpio_last = 14,
-+ }, {
-+ .name = "pcm i2s",
-+ .mask = MT7620_GPIO_MODE_PCM_I2S,
-+ .gpio_first = 7,
-+ .gpio_last = 14,
-+ }, {
-+ .name = "i2s uartf",
-+ .mask = MT7620_GPIO_MODE_I2S_UARTF,
-+ .gpio_first = 7,
-+ .gpio_last = 14,
-+ }, {
-+ .name = "pcm gpio",
-+ .mask = MT7620_GPIO_MODE_PCM_GPIO,
-+ .gpio_first = 11,
-+ .gpio_last = 14,
-+ }, {
-+ .name = "gpio uartf",
-+ .mask = MT7620_GPIO_MODE_GPIO_UARTF,
-+ .gpio_first = 7,
-+ .gpio_last = 10,
-+ }, {
-+ .name = "gpio i2s",
-+ .mask = MT7620_GPIO_MODE_GPIO_I2S,
-+ .gpio_first = 7,
-+ .gpio_last = 10,
-+ }, {
-+ .name = "gpio",
-+ .mask = MT7620_GPIO_MODE_GPIO,
-+ }, {0}
-+};
-+/*
-+void rt305x_wdt_reset(void)
-+{
-+ u32 t;
-+
-+ t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
-+ t |= RT305X_SYSCFG_SRAM_CS0_MODE_WDT <<
-+ RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT;
-+ rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG);
-+}
-+*/
-+struct ralink_pinmux rt_pinmux = {
-+ .mode = mode_mux,
-+ .uart = uart_mux,
-+ .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT,
-+// .wdt_reset = rt305x_wdt_reset,
-+};
-+
-+void __init ralink_clk_init(void)
-+{
-+ unsigned long cpu_rate, sys_rate;
-+ u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0);
-+ u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1);
-+
-+ c0 = (c0 >> MT7620_CPLL_SW_CONFIG_SHIFT) &
-+ MT7620_CPLL_SW_CONFIG_MASK;
-+ c1 = (c1 >> MT7620_CPLL_CPU_CLK_SHIFT) &
-+ MT7620_CPLL_CPU_CLK_MASK;
-+ if (c1 == 0x01) {
-+ cpu_rate = 480000000;
-+ } else {
-+ if (c1 == 0x0) {
-+ cpu_rate = 600000000;
-+ } else {
-+ /* TODO calculate custom clock from pll settings */
-+ BUG();
-+ }
-+ }
-+ /* FIXME SDR - 4, DDR - 3 */
-+ sys_rate = cpu_rate / 4;
-+
-+ ralink_clk_add("cpu", cpu_rate);
-+ ralink_clk_add("10000100.timer", 40000000);
-+ ralink_clk_add("10000500.uart", 40000000);
-+ ralink_clk_add("10000c00.uartlite", 40000000);
-+}
-+
-+void __init ralink_of_remap(void)
-+{
-+ rt_sysc_membase = plat_of_remap_node("ralink,mt7620-sysc");
-+ rt_memc_membase = plat_of_remap_node("ralink,mt7620-memc");
-+
-+ if (!rt_sysc_membase || !rt_memc_membase)
-+ panic("Failed to remap core resources");
-+}
-+
-+void prom_soc_init(struct ralink_soc_info *soc_info)
-+{
-+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE);
-+ unsigned char *name = NULL;
-+ u32 n0;
-+ u32 n1;
-+ u32 rev;
-+
-+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
-+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
-+
-+ if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) {
-+ name = "MT7620N";
-+ soc_info->compatible = "ralink,mt7620n-soc";
-+ } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) {
-+ name = "MT7620A";
-+ soc_info->compatible = "ralink,mt7620a-soc";
-+ } else {
-+ printk("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
-+ }
-+
-+ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
-+
-+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
-+ "Ralink %s ver:%u eco:%u",
-+ name,
-+ (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
-+ (rev & CHIP_REV_ECO_MASK));
-+}
--- /dev/null
+From cccb9a7b42227a442ca42d590c838c8b6fa0eba1 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 27 Jan 2013 09:17:20 +0100
+Subject: [PATCH 111/137] MIPS: ralink: adds support for RT2880 SoC family
+
+Add support code for rt2880 SOC.
+
+The code detects the SoC and registers the clk / pinmux settings.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5176/
+---
+ arch/mips/Kconfig | 2 +-
+ arch/mips/include/asm/mach-ralink/rt288x.h | 49 ++++++++++
+ arch/mips/ralink/Kconfig | 3 +
+ arch/mips/ralink/Makefile | 1 +
+ arch/mips/ralink/Platform | 5 +
+ arch/mips/ralink/rt288x.c | 139 ++++++++++++++++++++++++++++
+ 6 files changed, 198 insertions(+), 1 deletion(-)
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt288x.h
+ create mode 100644 arch/mips/ralink/rt288x.c
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -1189,7 +1189,7 @@ config BOOT_ELF32
+
+ config MIPS_L1_CACHE_SHIFT
+ int
+- default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL
++ default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X
+ default "6" if MIPS_CPU_SCACHE
+ default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
+ default "5"
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/rt288x.h
+@@ -0,0 +1,49 @@
++/*
++ * 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.
++ *
++ * Parts of this file are based on Ralink's 2.6.21 BSP
++ *
++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _RT288X_REGS_H_
++#define _RT288X_REGS_H_
++
++#define RT2880_SYSC_BASE 0x00300000
++
++#define SYSC_REG_CHIP_NAME0 0x00
++#define SYSC_REG_CHIP_NAME1 0x04
++#define SYSC_REG_CHIP_ID 0x0c
++#define SYSC_REG_SYSTEM_CONFIG 0x10
++#define SYSC_REG_CLKCFG 0x30
++
++#define RT2880_CHIP_NAME0 0x38325452
++#define RT2880_CHIP_NAME1 0x20203038
++
++#define CHIP_ID_ID_MASK 0xff
++#define CHIP_ID_ID_SHIFT 8
++#define CHIP_ID_REV_MASK 0xff
++
++#define SYSTEM_CONFIG_CPUCLK_SHIFT 20
++#define SYSTEM_CONFIG_CPUCLK_MASK 0x3
++#define SYSTEM_CONFIG_CPUCLK_250 0x0
++#define SYSTEM_CONFIG_CPUCLK_266 0x1
++#define SYSTEM_CONFIG_CPUCLK_280 0x2
++#define SYSTEM_CONFIG_CPUCLK_300 0x3
++
++#define RT2880_GPIO_MODE_I2C BIT(0)
++#define RT2880_GPIO_MODE_UART0 BIT(1)
++#define RT2880_GPIO_MODE_SPI BIT(2)
++#define RT2880_GPIO_MODE_UART1 BIT(3)
++#define RT2880_GPIO_MODE_JTAG BIT(4)
++#define RT2880_GPIO_MODE_MDIO BIT(5)
++#define RT2880_GPIO_MODE_SDRAM BIT(6)
++#define RT2880_GPIO_MODE_PCI BIT(7)
++
++#define CLKCFG_SRAM_CS_N_WDT BIT(9)
++
++#endif
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -6,6 +6,9 @@ choice
+ help
+ Select Ralink MIPS SoC type.
+
++ config SOC_RT288X
++ bool "RT288x"
++
+ config SOC_RT305X
+ bool "RT305x"
+ select USB_ARCH_HAS_HCD
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -8,6 +8,7 @@
+
+ obj-y := prom.o of.o reset.o clk.o irq.o
+
++obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+--- a/arch/mips/ralink/Platform
++++ b/arch/mips/ralink/Platform
+@@ -5,6 +5,11 @@ core-$(CONFIG_RALINK) += arch/mips/rali
+ cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink
+
+ #
++# Ralink RT288x
++#
++load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000
++
++#
+ # Ralink RT305x
+ #
+ load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
+--- /dev/null
++++ b/arch/mips/ralink/rt288x.c
+@@ -0,0 +1,139 @@
++/*
++ * 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.
++ *
++ * Parts of this file are based on Ralink's 2.6.21 BSP
++ *
++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/mipsregs.h>
++#include <asm/mach-ralink/ralink_regs.h>
++#include <asm/mach-ralink/rt288x.h>
++
++#include "common.h"
++
++static struct ralink_pinmux_grp mode_mux[] = {
++ {
++ .name = "i2c",
++ .mask = RT2880_GPIO_MODE_I2C,
++ .gpio_first = 1,
++ .gpio_last = 2,
++ }, {
++ .name = "spi",
++ .mask = RT2880_GPIO_MODE_SPI,
++ .gpio_first = 3,
++ .gpio_last = 6,
++ }, {
++ .name = "uartlite",
++ .mask = RT2880_GPIO_MODE_UART0,
++ .gpio_first = 7,
++ .gpio_last = 14,
++ }, {
++ .name = "jtag",
++ .mask = RT2880_GPIO_MODE_JTAG,
++ .gpio_first = 17,
++ .gpio_last = 21,
++ }, {
++ .name = "mdio",
++ .mask = RT2880_GPIO_MODE_MDIO,
++ .gpio_first = 22,
++ .gpio_last = 23,
++ }, {
++ .name = "sdram",
++ .mask = RT2880_GPIO_MODE_SDRAM,
++ .gpio_first = 24,
++ .gpio_last = 39,
++ }, {
++ .name = "pci",
++ .mask = RT2880_GPIO_MODE_PCI,
++ .gpio_first = 40,
++ .gpio_last = 71,
++ }, {0}
++};
++
++static void rt288x_wdt_reset(void)
++{
++ u32 t;
++
++ /* enable WDT reset output on pin SRAM_CS_N */
++ t = rt_sysc_r32(SYSC_REG_CLKCFG);
++ t |= CLKCFG_SRAM_CS_N_WDT;
++ rt_sysc_w32(t, SYSC_REG_CLKCFG);
++}
++
++struct ralink_pinmux rt_gpio_pinmux = {
++ .mode = mode_mux,
++ .wdt_reset = rt288x_wdt_reset,
++};
++
++void __init ralink_clk_init(void)
++{
++ unsigned long cpu_rate;
++ u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
++ t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK);
++
++ switch (t) {
++ case SYSTEM_CONFIG_CPUCLK_250:
++ cpu_rate = 250000000;
++ break;
++ case SYSTEM_CONFIG_CPUCLK_266:
++ cpu_rate = 266666667;
++ break;
++ case SYSTEM_CONFIG_CPUCLK_280:
++ cpu_rate = 280000000;
++ break;
++ case SYSTEM_CONFIG_CPUCLK_300:
++ cpu_rate = 300000000;
++ break;
++ }
++
++ ralink_clk_add("cpu", cpu_rate);
++ ralink_clk_add("300100.timer", cpu_rate / 2);
++ ralink_clk_add("300120.watchdog", cpu_rate / 2);
++ ralink_clk_add("300500.uart", cpu_rate / 2);
++ ralink_clk_add("300c00.uartlite", cpu_rate / 2);
++ ralink_clk_add("400000.ethernet", cpu_rate / 2);
++}
++
++void __init ralink_of_remap(void)
++{
++ rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc");
++ rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc");
++
++ if (!rt_sysc_membase || !rt_memc_membase)
++ panic("Failed to remap core resources");
++}
++
++void prom_soc_init(struct ralink_soc_info *soc_info)
++{
++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT2880_SYSC_BASE);
++ const char *name;
++ u32 n0;
++ u32 n1;
++ u32 id;
++
++ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
++ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
++ id = __raw_readl(sysc + SYSC_REG_CHIP_ID);
++
++ if (n0 == RT2880_CHIP_NAME0 && n1 == RT2880_CHIP_NAME1) {
++ soc_info->compatible = "ralink,r2880-soc";
++ name = "RT2880";
++ } else {
++ panic("rt288x: unknown SoC, n0:%08x n1:%08x", n0, n1);
++ }
++
++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
++ "Ralink %s id:%u rev:%u",
++ name,
++ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
++ (id & CHIP_ID_REV_MASK));
++}
+++ /dev/null
-From 9c83b58b49f88a48565fad6acea921a0ae222856 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 17:50:05 +0100
-Subject: [PATCH 112/121] MIPS: add MT7620 dts files
-
-Adds the dtsi file for MT7620 SoC. This is the latest and greatest SoC shipped
-by Mediatek.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Kconfig | 4 +
- arch/mips/ralink/dts/Makefile | 1 +
- arch/mips/ralink/dts/mt7620.dtsi | 138 ++++++++++++++++++++++++++++++++++
- arch/mips/ralink/dts/mt7620_eval.dts | 22 ++++++
- 4 files changed, 165 insertions(+)
- create mode 100644 arch/mips/ralink/dts/mt7620.dtsi
- create mode 100644 arch/mips/ralink/dts/mt7620_eval.dts
-
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -46,6 +46,10 @@ choice
- bool "RT3883 eval kit"
- depends on SOC_RT3883
-
-+ config DTB_MT7620_EVAL
-+ bool "MT7620 eval kit"
-+ depends on SOC_MT7620
-+
- endchoice
-
- endif
---- a/arch/mips/ralink/dts/Makefile
-+++ b/arch/mips/ralink/dts/Makefile
-@@ -1,3 +1,4 @@
- obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
- obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
- obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o
-+obj-$(CONFIG_DTB_MT7620_EVAL) := mt7620_eval.dtb.o
---- /dev/null
-+++ b/arch/mips/ralink/dts/mt7620.dtsi
-@@ -0,0 +1,138 @@
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,mtk7620n-soc", "ralink,mt7620-soc";
-+
-+ cpus {
-+ cpu@0 {
-+ compatible = "mips,mips24KEc";
-+ };
-+ };
-+
-+ chosen {
-+ bootargs = "console=ttyS0,57600 init=/init";
-+ };
-+
-+ cpuintc: cpuintc@0 {
-+ #address-cells = <0>;
-+ #interrupt-cells = <1>;
-+ interrupt-controller;
-+ compatible = "mti,cpu-interrupt-controller";
-+ };
-+
-+ palmbus@10000000 {
-+ compatible = "palmbus";
-+ reg = <0x10000000 0x200000>;
-+ ranges = <0x0 0x10000000 0x1FFFFF>;
-+
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ sysc@0 {
-+ compatible = "ralink,mt7620-sysc", "ralink,mt7620n-sysc";
-+ reg = <0x0 0x100>;
-+ };
-+
-+ timer@100 {
-+ compatible = "ralink,mt7620-timer", "ralink,rt2880-timer";
-+ reg = <0x100 0x20>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <1>;
-+
-+ status = "disabled";
-+ };
-+
-+ watchdog@120 {
-+ compatible = "ralink,mt7620-wdt", "ralink,rt2880-wdt";
-+ reg = <0x120 0x10>;
-+ };
-+
-+ intc: intc@200 {
-+ compatible = "ralink,mt7620-intc", "ralink,rt2880-intc";
-+ reg = <0x200 0x100>;
-+
-+ interrupt-controller;
-+ #interrupt-cells = <1>;
-+
-+ interrupt-parent = <&cpuintc>;
-+ interrupts = <2>;
-+ };
-+
-+ memc@300 {
-+ compatible = "ralink,mt7620-memc", "ralink,rt3050-memc";
-+ reg = <0x300 0x100>;
-+ };
-+
-+ gpio0: gpio@600 {
-+ compatible = "ralink,mt7620-gpio", "ralink,rt2880-gpio";
-+ reg = <0x600 0x34>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <24>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 20 24 28 2c
-+ 30 34 ];
-+ };
-+
-+ gpio1: gpio@638 {
-+ compatible = "ralink,mt7620-gpio", "ralink,rt2880-gpio";
-+ reg = <0x638 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <16>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+ };
-+
-+ gpio2: gpio@660 {
-+ compatible = "ralink,mt7620-gpio", "ralink,rt2880-gpio";
-+ reg = <0x660 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <32>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+ };
-+
-+ gpio3: gpio@688 {
-+ compatible = "ralink,mt7620-gpio", "ralink,rt2880-gpio";
-+ reg = <0x688 0x24>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ ralink,num-gpios = <1>;
-+ ralink,register-map = [ 00 04 08 0c
-+ 10 14 18 1c
-+ 20 24 ];
-+ };
-+
-+ spi@b00 {
-+ compatible = "ralink,rt3883-spi", "ralink,rt2880-spi";
-+ reg = <0xb00 0x100>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ status = "disabled";
-+ };
-+
-+ uartlite@c00 {
-+ compatible = "ralink,mt7620-uart", "ralink,rt2880-uart", "ns16550a";
-+ reg = <0xc00 0x100>;
-+
-+ interrupt-parent = <&intc>;
-+ interrupts = <12>;
-+
-+ reg-shift = <2>;
-+ };
-+ };
-+};
---- /dev/null
-+++ b/arch/mips/ralink/dts/mt7620_eval.dts
-@@ -0,0 +1,22 @@
-+/dts-v1/;
-+
-+/include/ "mt7620.dtsi"
-+
-+/ {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc";
-+ model = "Ralink MT7620 evaluation board";
-+
-+ memory@0 {
-+ reg = <0x0 0x4000000>;
-+ };
-+
-+ palmbus@10000000 {
-+ sysc@0 {
-+ ralink,pinmux = "uartlite", "spi";
-+ ralink,uartmux = "gpio";
-+ ralink,wdtmux = <0>;
-+ };
-+ };
-+};
--- /dev/null
+From 5eb4dfe5072595e0706de3364f2da45378dbaca6 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 27 Jan 2013 09:39:02 +0100
+Subject: [PATCH 112/137] MIPS: ralink: adds support for RT3883 SoC family
+
+Add support code for rt3883 SOC.
+
+The code detects the SoC and registers the clk / pinmux settings.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5185/
+---
+ arch/mips/include/asm/mach-ralink/rt3883.h | 247 ++++++++++++++++++++++++++++
+ arch/mips/ralink/Kconfig | 5 +
+ arch/mips/ralink/Makefile | 1 +
+ arch/mips/ralink/Platform | 5 +
+ arch/mips/ralink/rt3883.c | 242 +++++++++++++++++++++++++++
+ 5 files changed, 500 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt3883.h
+ create mode 100644 arch/mips/ralink/rt3883.c
+
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/rt3883.h
+@@ -0,0 +1,247 @@
++/*
++ * Ralink RT3662/RT3883 SoC register definitions
++ *
++ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#ifndef _RT3883_REGS_H_
++#define _RT3883_REGS_H_
++
++#include <linux/bitops.h>
++
++#define RT3883_SDRAM_BASE 0x00000000
++#define RT3883_SYSC_BASE 0x10000000
++#define RT3883_TIMER_BASE 0x10000100
++#define RT3883_INTC_BASE 0x10000200
++#define RT3883_MEMC_BASE 0x10000300
++#define RT3883_UART0_BASE 0x10000500
++#define RT3883_PIO_BASE 0x10000600
++#define RT3883_FSCC_BASE 0x10000700
++#define RT3883_NANDC_BASE 0x10000810
++#define RT3883_I2C_BASE 0x10000900
++#define RT3883_I2S_BASE 0x10000a00
++#define RT3883_SPI_BASE 0x10000b00
++#define RT3883_UART1_BASE 0x10000c00
++#define RT3883_PCM_BASE 0x10002000
++#define RT3883_GDMA_BASE 0x10002800
++#define RT3883_CODEC1_BASE 0x10003000
++#define RT3883_CODEC2_BASE 0x10003800
++#define RT3883_FE_BASE 0x10100000
++#define RT3883_ROM_BASE 0x10118000
++#define RT3883_USBDEV_BASE 0x10112000
++#define RT3883_PCI_BASE 0x10140000
++#define RT3883_WLAN_BASE 0x10180000
++#define RT3883_USBHOST_BASE 0x101c0000
++#define RT3883_BOOT_BASE 0x1c000000
++#define RT3883_SRAM_BASE 0x1e000000
++#define RT3883_PCIMEM_BASE 0x20000000
++
++#define RT3883_EHCI_BASE (RT3883_USBHOST_BASE)
++#define RT3883_OHCI_BASE (RT3883_USBHOST_BASE + 0x1000)
++
++#define RT3883_SYSC_SIZE 0x100
++#define RT3883_TIMER_SIZE 0x100
++#define RT3883_INTC_SIZE 0x100
++#define RT3883_MEMC_SIZE 0x100
++#define RT3883_UART0_SIZE 0x100
++#define RT3883_UART1_SIZE 0x100
++#define RT3883_PIO_SIZE 0x100
++#define RT3883_FSCC_SIZE 0x100
++#define RT3883_NANDC_SIZE 0x0f0
++#define RT3883_I2C_SIZE 0x100
++#define RT3883_I2S_SIZE 0x100
++#define RT3883_SPI_SIZE 0x100
++#define RT3883_PCM_SIZE 0x800
++#define RT3883_GDMA_SIZE 0x800
++#define RT3883_CODEC1_SIZE 0x800
++#define RT3883_CODEC2_SIZE 0x800
++#define RT3883_FE_SIZE 0x10000
++#define RT3883_ROM_SIZE 0x4000
++#define RT3883_USBDEV_SIZE 0x4000
++#define RT3883_PCI_SIZE 0x40000
++#define RT3883_WLAN_SIZE 0x40000
++#define RT3883_USBHOST_SIZE 0x40000
++#define RT3883_BOOT_SIZE (32 * 1024 * 1024)
++#define RT3883_SRAM_SIZE (32 * 1024 * 1024)
++
++/* SYSC registers */
++#define RT3883_SYSC_REG_CHIPID0_3 0x00 /* Chip ID 0 */
++#define RT3883_SYSC_REG_CHIPID4_7 0x04 /* Chip ID 1 */
++#define RT3883_SYSC_REG_REVID 0x0c /* Chip Revision Identification */
++#define RT3883_SYSC_REG_SYSCFG0 0x10 /* System Configuration 0 */
++#define RT3883_SYSC_REG_SYSCFG1 0x14 /* System Configuration 1 */
++#define RT3883_SYSC_REG_CLKCFG0 0x2c /* Clock Configuration 0 */
++#define RT3883_SYSC_REG_CLKCFG1 0x30 /* Clock Configuration 1 */
++#define RT3883_SYSC_REG_RSTCTRL 0x34 /* Reset Control*/
++#define RT3883_SYSC_REG_RSTSTAT 0x38 /* Reset Status*/
++#define RT3883_SYSC_REG_USB_PS 0x5c /* USB Power saving control */
++#define RT3883_SYSC_REG_GPIO_MODE 0x60 /* GPIO Purpose Select */
++#define RT3883_SYSC_REG_PCIE_CLK_GEN0 0x7c
++#define RT3883_SYSC_REG_PCIE_CLK_GEN1 0x80
++#define RT3883_SYSC_REG_PCIE_CLK_GEN2 0x84
++#define RT3883_SYSC_REG_PMU 0x88
++#define RT3883_SYSC_REG_PMU1 0x8c
++
++#define RT3883_CHIP_NAME0 0x38335452
++#define RT3883_CHIP_NAME1 0x20203338
++
++#define RT3883_REVID_VER_ID_MASK 0x0f
++#define RT3883_REVID_VER_ID_SHIFT 8
++#define RT3883_REVID_ECO_ID_MASK 0x0f
++
++#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17)
++#define RT3883_SYSCFG0_CPUCLK_SHIFT 8
++#define RT3883_SYSCFG0_CPUCLK_MASK 0x3
++#define RT3883_SYSCFG0_CPUCLK_250 0x0
++#define RT3883_SYSCFG0_CPUCLK_384 0x1
++#define RT3883_SYSCFG0_CPUCLK_480 0x2
++#define RT3883_SYSCFG0_CPUCLK_500 0x3
++
++#define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10)
++#define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8)
++#define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7)
++#define RT3883_SYSCFG1_PCI_66M_MODE BIT(6)
++#define RT3883_SYSCFG1_GPIO2_AS_WDT_OUT BIT(2)
++
++#define RT3883_CLKCFG1_PCIE_CLK_EN BIT(21)
++#define RT3883_CLKCFG1_UPHY1_CLK_EN BIT(20)
++#define RT3883_CLKCFG1_PCI_CLK_EN BIT(19)
++#define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18)
++
++#define RT3883_GPIO_MODE_I2C BIT(0)
++#define RT3883_GPIO_MODE_SPI BIT(1)
++#define RT3883_GPIO_MODE_UART0_SHIFT 2
++#define RT3883_GPIO_MODE_UART0_MASK 0x7
++#define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT)
++#define RT3883_GPIO_MODE_UARTF 0x0
++#define RT3883_GPIO_MODE_PCM_UARTF 0x1
++#define RT3883_GPIO_MODE_PCM_I2S 0x2
++#define RT3883_GPIO_MODE_I2S_UARTF 0x3
++#define RT3883_GPIO_MODE_PCM_GPIO 0x4
++#define RT3883_GPIO_MODE_GPIO_UARTF 0x5
++#define RT3883_GPIO_MODE_GPIO_I2S 0x6
++#define RT3883_GPIO_MODE_GPIO 0x7
++#define RT3883_GPIO_MODE_UART1 BIT(5)
++#define RT3883_GPIO_MODE_JTAG BIT(6)
++#define RT3883_GPIO_MODE_MDIO BIT(7)
++#define RT3883_GPIO_MODE_GE1 BIT(9)
++#define RT3883_GPIO_MODE_GE2 BIT(10)
++#define RT3883_GPIO_MODE_PCI_SHIFT 11
++#define RT3883_GPIO_MODE_PCI_MASK 0x7
++#define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT)
++#define RT3883_GPIO_MODE_LNA_A_SHIFT 16
++#define RT3883_GPIO_MODE_LNA_A_MASK 0x3
++#define _RT3883_GPIO_MODE_LNA_A(_x) ((_x) << RT3883_GPIO_MODE_LNA_A_SHIFT)
++#define RT3883_GPIO_MODE_LNA_A_GPIO 0x3
++#define RT3883_GPIO_MODE_LNA_A _RT3883_GPIO_MODE_LNA_A(RT3883_GPIO_MODE_LNA_A_MASK)
++#define RT3883_GPIO_MODE_LNA_G_SHIFT 18
++#define RT3883_GPIO_MODE_LNA_G_MASK 0x3
++#define _RT3883_GPIO_MODE_LNA_G(_x) ((_x) << RT3883_GPIO_MODE_LNA_G_SHIFT)
++#define RT3883_GPIO_MODE_LNA_G_GPIO 0x3
++#define RT3883_GPIO_MODE_LNA_G _RT3883_GPIO_MODE_LNA_G(RT3883_GPIO_MODE_LNA_G_MASK)
++
++#define RT3883_GPIO_I2C_SD 1
++#define RT3883_GPIO_I2C_SCLK 2
++#define RT3883_GPIO_SPI_CS0 3
++#define RT3883_GPIO_SPI_CLK 4
++#define RT3883_GPIO_SPI_MOSI 5
++#define RT3883_GPIO_SPI_MISO 6
++#define RT3883_GPIO_7 7
++#define RT3883_GPIO_10 10
++#define RT3883_GPIO_14 14
++#define RT3883_GPIO_UART1_TXD 15
++#define RT3883_GPIO_UART1_RXD 16
++#define RT3883_GPIO_JTAG_TDO 17
++#define RT3883_GPIO_JTAG_TDI 18
++#define RT3883_GPIO_JTAG_TMS 19
++#define RT3883_GPIO_JTAG_TCLK 20
++#define RT3883_GPIO_JTAG_TRST_N 21
++#define RT3883_GPIO_MDIO_MDC 22
++#define RT3883_GPIO_MDIO_MDIO 23
++#define RT3883_GPIO_LNA_PE_A0 32
++#define RT3883_GPIO_LNA_PE_A1 33
++#define RT3883_GPIO_LNA_PE_A2 34
++#define RT3883_GPIO_LNA_PE_G0 35
++#define RT3883_GPIO_LNA_PE_G1 36
++#define RT3883_GPIO_LNA_PE_G2 37
++#define RT3883_GPIO_PCI_AD0 40
++#define RT3883_GPIO_PCI_AD31 71
++#define RT3883_GPIO_GE2_TXD0 72
++#define RT3883_GPIO_GE2_TXD1 73
++#define RT3883_GPIO_GE2_TXD2 74
++#define RT3883_GPIO_GE2_TXD3 75
++#define RT3883_GPIO_GE2_TXEN 76
++#define RT3883_GPIO_GE2_TXCLK 77
++#define RT3883_GPIO_GE2_RXD0 78
++#define RT3883_GPIO_GE2_RXD1 79
++#define RT3883_GPIO_GE2_RXD2 80
++#define RT3883_GPIO_GE2_RXD3 81
++#define RT3883_GPIO_GE2_RXDV 82
++#define RT3883_GPIO_GE2_RXCLK 83
++#define RT3883_GPIO_GE1_TXD0 84
++#define RT3883_GPIO_GE1_TXD1 85
++#define RT3883_GPIO_GE1_TXD2 86
++#define RT3883_GPIO_GE1_TXD3 87
++#define RT3883_GPIO_GE1_TXEN 88
++#define RT3883_GPIO_GE1_TXCLK 89
++#define RT3883_GPIO_GE1_RXD0 90
++#define RT3883_GPIO_GE1_RXD1 91
++#define RT3883_GPIO_GE1_RXD2 92
++#define RT3883_GPIO_GE1_RXD3 93
++#define RT3883_GPIO_GE1_RXDV 94
++#define RT3883_GPIO_GE1_RXCLK 95
++
++#define RT3883_RSTCTRL_PCIE_PCI_PDM BIT(27)
++#define RT3883_RSTCTRL_FLASH BIT(26)
++#define RT3883_RSTCTRL_UDEV BIT(25)
++#define RT3883_RSTCTRL_PCI BIT(24)
++#define RT3883_RSTCTRL_PCIE BIT(23)
++#define RT3883_RSTCTRL_UHST BIT(22)
++#define RT3883_RSTCTRL_FE BIT(21)
++#define RT3883_RSTCTRL_WLAN BIT(20)
++#define RT3883_RSTCTRL_UART1 BIT(29)
++#define RT3883_RSTCTRL_SPI BIT(18)
++#define RT3883_RSTCTRL_I2S BIT(17)
++#define RT3883_RSTCTRL_I2C BIT(16)
++#define RT3883_RSTCTRL_NAND BIT(15)
++#define RT3883_RSTCTRL_DMA BIT(14)
++#define RT3883_RSTCTRL_PIO BIT(13)
++#define RT3883_RSTCTRL_UART BIT(12)
++#define RT3883_RSTCTRL_PCM BIT(11)
++#define RT3883_RSTCTRL_MC BIT(10)
++#define RT3883_RSTCTRL_INTC BIT(9)
++#define RT3883_RSTCTRL_TIMER BIT(8)
++#define RT3883_RSTCTRL_SYS BIT(0)
++
++#define RT3883_INTC_INT_SYSCTL BIT(0)
++#define RT3883_INTC_INT_TIMER0 BIT(1)
++#define RT3883_INTC_INT_TIMER1 BIT(2)
++#define RT3883_INTC_INT_IA BIT(3)
++#define RT3883_INTC_INT_PCM BIT(4)
++#define RT3883_INTC_INT_UART0 BIT(5)
++#define RT3883_INTC_INT_PIO BIT(6)
++#define RT3883_INTC_INT_DMA BIT(7)
++#define RT3883_INTC_INT_NAND BIT(8)
++#define RT3883_INTC_INT_PERFC BIT(9)
++#define RT3883_INTC_INT_I2S BIT(10)
++#define RT3883_INTC_INT_UART1 BIT(12)
++#define RT3883_INTC_INT_UHST BIT(18)
++#define RT3883_INTC_INT_UDEV BIT(19)
++
++/* FLASH/SRAM/Codec Controller registers */
++#define RT3883_FSCC_REG_FLASH_CFG0 0x00
++#define RT3883_FSCC_REG_FLASH_CFG1 0x04
++#define RT3883_FSCC_REG_CODEC_CFG0 0x40
++#define RT3883_FSCC_REG_CODEC_CFG1 0x44
++
++#define RT3883_FLASH_CFG_WIDTH_SHIFT 26
++#define RT3883_FLASH_CFG_WIDTH_MASK 0x3
++#define RT3883_FLASH_CFG_WIDTH_8BIT 0x0
++#define RT3883_FLASH_CFG_WIDTH_16BIT 0x1
++#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2
++
++#endif /* _RT3883_REGS_H_ */
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -15,6 +15,11 @@ choice
+ select USB_ARCH_HAS_OHCI
+ select USB_ARCH_HAS_EHCI
+
++ config SOC_RT3883
++ bool "RT3883"
++ select USB_ARCH_HAS_OHCI
++ select USB_ARCH_HAS_EHCI
++
+ endchoice
+
+ choice
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -10,6 +10,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o
+
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
++obj-$(CONFIG_SOC_RT3883) += rt3883.o
+
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+--- a/arch/mips/ralink/Platform
++++ b/arch/mips/ralink/Platform
+@@ -13,3 +13,8 @@ load-$(CONFIG_SOC_RT288X) += 0xffffffff8
+ # Ralink RT305x
+ #
+ load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
++
++#
++# Ralink RT3883
++#
++load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
+--- /dev/null
++++ b/arch/mips/ralink/rt3883.c
+@@ -0,0 +1,242 @@
++/*
++ * 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.
++ *
++ * Parts of this file are based on Ralink's 2.6.21 BSP
++ *
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/mipsregs.h>
++#include <asm/mach-ralink/ralink_regs.h>
++#include <asm/mach-ralink/rt3883.h>
++
++#include "common.h"
++
++static struct ralink_pinmux_grp mode_mux[] = {
++ {
++ .name = "i2c",
++ .mask = RT3883_GPIO_MODE_I2C,
++ .gpio_first = RT3883_GPIO_I2C_SD,
++ .gpio_last = RT3883_GPIO_I2C_SCLK,
++ }, {
++ .name = "spi",
++ .mask = RT3883_GPIO_MODE_SPI,
++ .gpio_first = RT3883_GPIO_SPI_CS0,
++ .gpio_last = RT3883_GPIO_SPI_MISO,
++ }, {
++ .name = "uartlite",
++ .mask = RT3883_GPIO_MODE_UART1,
++ .gpio_first = RT3883_GPIO_UART1_TXD,
++ .gpio_last = RT3883_GPIO_UART1_RXD,
++ }, {
++ .name = "jtag",
++ .mask = RT3883_GPIO_MODE_JTAG,
++ .gpio_first = RT3883_GPIO_JTAG_TDO,
++ .gpio_last = RT3883_GPIO_JTAG_TCLK,
++ }, {
++ .name = "mdio",
++ .mask = RT3883_GPIO_MODE_MDIO,
++ .gpio_first = RT3883_GPIO_MDIO_MDC,
++ .gpio_last = RT3883_GPIO_MDIO_MDIO,
++ }, {
++ .name = "ge1",
++ .mask = RT3883_GPIO_MODE_GE1,
++ .gpio_first = RT3883_GPIO_GE1_TXD0,
++ .gpio_last = RT3883_GPIO_GE1_RXCLK,
++ }, {
++ .name = "ge2",
++ .mask = RT3883_GPIO_MODE_GE2,
++ .gpio_first = RT3883_GPIO_GE2_TXD0,
++ .gpio_last = RT3883_GPIO_GE2_RXCLK,
++ }, {
++ .name = "pci",
++ .mask = RT3883_GPIO_MODE_PCI,
++ .gpio_first = RT3883_GPIO_PCI_AD0,
++ .gpio_last = RT3883_GPIO_PCI_AD31,
++ }, {
++ .name = "lna a",
++ .mask = RT3883_GPIO_MODE_LNA_A,
++ .gpio_first = RT3883_GPIO_LNA_PE_A0,
++ .gpio_last = RT3883_GPIO_LNA_PE_A2,
++ }, {
++ .name = "lna g",
++ .mask = RT3883_GPIO_MODE_LNA_G,
++ .gpio_first = RT3883_GPIO_LNA_PE_G0,
++ .gpio_last = RT3883_GPIO_LNA_PE_G2,
++ }, {0}
++};
++
++static struct ralink_pinmux_grp uart_mux[] = {
++ {
++ .name = "uartf",
++ .mask = RT3883_GPIO_MODE_UARTF,
++ .gpio_first = RT3883_GPIO_7,
++ .gpio_last = RT3883_GPIO_14,
++ }, {
++ .name = "pcm uartf",
++ .mask = RT3883_GPIO_MODE_PCM_UARTF,
++ .gpio_first = RT3883_GPIO_7,
++ .gpio_last = RT3883_GPIO_14,
++ }, {
++ .name = "pcm i2s",
++ .mask = RT3883_GPIO_MODE_PCM_I2S,
++ .gpio_first = RT3883_GPIO_7,
++ .gpio_last = RT3883_GPIO_14,
++ }, {
++ .name = "i2s uartf",
++ .mask = RT3883_GPIO_MODE_I2S_UARTF,
++ .gpio_first = RT3883_GPIO_7,
++ .gpio_last = RT3883_GPIO_14,
++ }, {
++ .name = "pcm gpio",
++ .mask = RT3883_GPIO_MODE_PCM_GPIO,
++ .gpio_first = RT3883_GPIO_11,
++ .gpio_last = RT3883_GPIO_14,
++ }, {
++ .name = "gpio uartf",
++ .mask = RT3883_GPIO_MODE_GPIO_UARTF,
++ .gpio_first = RT3883_GPIO_7,
++ .gpio_last = RT3883_GPIO_10,
++ }, {
++ .name = "gpio i2s",
++ .mask = RT3883_GPIO_MODE_GPIO_I2S,
++ .gpio_first = RT3883_GPIO_7,
++ .gpio_last = RT3883_GPIO_10,
++ }, {
++ .name = "gpio",
++ .mask = RT3883_GPIO_MODE_GPIO,
++ }, {0}
++};
++
++static struct ralink_pinmux_grp pci_mux[] = {
++ {
++ .name = "pci-dev",
++ .mask = 0,
++ .gpio_first = RT3883_GPIO_PCI_AD0,
++ .gpio_last = RT3883_GPIO_PCI_AD31,
++ }, {
++ .name = "pci-host2",
++ .mask = 1,
++ .gpio_first = RT3883_GPIO_PCI_AD0,
++ .gpio_last = RT3883_GPIO_PCI_AD31,
++ }, {
++ .name = "pci-host1",
++ .mask = 2,
++ .gpio_first = RT3883_GPIO_PCI_AD0,
++ .gpio_last = RT3883_GPIO_PCI_AD31,
++ }, {
++ .name = "pci-fnc",
++ .mask = 3,
++ .gpio_first = RT3883_GPIO_PCI_AD0,
++ .gpio_last = RT3883_GPIO_PCI_AD31,
++ }, {
++ .name = "pci-gpio",
++ .mask = 7,
++ .gpio_first = RT3883_GPIO_PCI_AD0,
++ .gpio_last = RT3883_GPIO_PCI_AD31,
++ }, {0}
++};
++
++static void rt3883_wdt_reset(void)
++{
++ u32 t;
++
++ /* enable WDT reset output on GPIO 2 */
++ t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1);
++ t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT;
++ rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1);
++}
++
++struct ralink_pinmux rt_gpio_pinmux = {
++ .mode = mode_mux,
++ .uart = uart_mux,
++ .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT,
++ .uart_mask = RT3883_GPIO_MODE_GPIO,
++ .wdt_reset = rt3883_wdt_reset,
++ .pci = pci_mux,
++ .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT,
++ .pci_mask = RT3883_GPIO_MODE_PCI_MASK,
++};
++
++void __init ralink_clk_init(void)
++{
++ unsigned long cpu_rate, sys_rate;
++ u32 syscfg0;
++ u32 clksel;
++ u32 ddr2;
++
++ syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0);
++ clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) &
++ RT3883_SYSCFG0_CPUCLK_MASK);
++ ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
++
++ switch (clksel) {
++ case RT3883_SYSCFG0_CPUCLK_250:
++ cpu_rate = 250000000;
++ sys_rate = (ddr2) ? 125000000 : 83000000;
++ break;
++ case RT3883_SYSCFG0_CPUCLK_384:
++ cpu_rate = 384000000;
++ sys_rate = (ddr2) ? 128000000 : 96000000;
++ break;
++ case RT3883_SYSCFG0_CPUCLK_480:
++ cpu_rate = 480000000;
++ sys_rate = (ddr2) ? 160000000 : 120000000;
++ break;
++ case RT3883_SYSCFG0_CPUCLK_500:
++ cpu_rate = 500000000;
++ sys_rate = (ddr2) ? 166000000 : 125000000;
++ break;
++ }
++
++ ralink_clk_add("cpu", cpu_rate);
++ ralink_clk_add("10000100.timer", sys_rate);
++ ralink_clk_add("10000120.watchdog", sys_rate);
++ ralink_clk_add("10000500.uart", 40000000);
++ ralink_clk_add("10000b00.spi", sys_rate);
++ ralink_clk_add("10000c00.uartlite", 40000000);
++ ralink_clk_add("10100000.ethernet", sys_rate);
++}
++
++void __init ralink_of_remap(void)
++{
++ rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc");
++ rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc");
++
++ if (!rt_sysc_membase || !rt_memc_membase)
++ panic("Failed to remap core resources");
++}
++
++void prom_soc_init(struct ralink_soc_info *soc_info)
++{
++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT3883_SYSC_BASE);
++ const char *name;
++ u32 n0;
++ u32 n1;
++ u32 id;
++
++ n0 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID0_3);
++ n1 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID4_7);
++ id = __raw_readl(sysc + RT3883_SYSC_REG_REVID);
++
++ if (n0 == RT3883_CHIP_NAME0 && n1 == RT3883_CHIP_NAME1) {
++ soc_info->compatible = "ralink,rt3883-soc";
++ name = "RT3883";
++ } else {
++ panic("rt3883: unknown SoC, n0:%08x n1:%08x", n0, n1);
++ }
++
++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
++ "Ralink %s ver:%u eco:%u",
++ name,
++ (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK,
++ (id & RT3883_REVID_ECO_ID_MASK));
++}
+++ /dev/null
-From cdbc5a9dbd78a771edb6c211edbc677596cbd17f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 23 Mar 2013 19:44:41 +0100
-Subject: [PATCH 113/121] MIPS: ralink: add support for periodic timer irq
-
-Adds a driver for the periodic timer found on Ralink SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Makefile | 2 +-
- arch/mips/ralink/timer.c | 192 +++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 193 insertions(+), 1 deletion(-)
- create mode 100644 arch/mips/ralink/timer.c
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -6,7 +6,7 @@
- # 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 pinmux.o
-+obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o
-
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
---- /dev/null
-+++ b/arch/mips/ralink/timer.c
-@@ -0,0 +1,192 @@
-+/*
-+ * 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;
-+
-+ if (!res) {
-+ dev_err(&pdev->dev, "no memory resource found\n");
-+ return -EINVAL;
-+ }
-+
-+ 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 (!rt->membase) {
-+ dev_err(&pdev->dev, "failed to ioremap\n");
-+ return -ENOMEM;
-+ }
-+
-+ 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");
--- /dev/null
+From a8d7045a9530d0a9e0c65c0f81852bd57ebde53c Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 21 Mar 2013 17:49:02 +0100
+Subject: [PATCH 113/137] MIPS: ralink: adds support for MT7620 SoC family
+
+Add support code for mt7620 SOC.
+
+The code detects the SoC and registers the clk / pinmux settings.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Gabor Juhos <juhosg@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5177/
+---
+ arch/mips/include/asm/mach-ralink/mt7620.h | 76 ++++++++++
+ arch/mips/ralink/Kconfig | 3 +
+ arch/mips/ralink/Makefile | 1 +
+ arch/mips/ralink/Platform | 5 +
+ arch/mips/ralink/mt7620.c | 214 ++++++++++++++++++++++++++++
+ 5 files changed, 299 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/mt7620.h
+ create mode 100644 arch/mips/ralink/mt7620.c
+
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/mt7620.h
+@@ -0,0 +1,76 @@
++/*
++ * 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.
++ *
++ * Parts of this file are based on Ralink's 2.6.21 BSP
++ *
++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _MT7620_REGS_H_
++#define _MT7620_REGS_H_
++
++#define MT7620_SYSC_BASE 0x10000000
++
++#define SYSC_REG_CHIP_NAME0 0x00
++#define SYSC_REG_CHIP_NAME1 0x04
++#define SYSC_REG_CHIP_REV 0x0c
++#define SYSC_REG_SYSTEM_CONFIG0 0x10
++#define SYSC_REG_SYSTEM_CONFIG1 0x14
++#define SYSC_REG_CPLL_CONFIG0 0x54
++#define SYSC_REG_CPLL_CONFIG1 0x58
++
++#define MT7620N_CHIP_NAME0 0x33365452
++#define MT7620N_CHIP_NAME1 0x20203235
++
++#define MT7620A_CHIP_NAME0 0x3637544d
++#define MT7620A_CHIP_NAME1 0x20203032
++
++#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 SYSCFG0_DRAM_TYPE_MASK 0x3
++#define SYSCFG0_DRAM_TYPE_SHIFT 4
++#define SYSCFG0_DRAM_TYPE_SDRAM 0
++#define SYSCFG0_DRAM_TYPE_DDR1 1
++#define SYSCFG0_DRAM_TYPE_DDR2 2
++
++#define MT7620_GPIO_MODE_I2C BIT(0)
++#define MT7620_GPIO_MODE_UART0_SHIFT 2
++#define MT7620_GPIO_MODE_UART0_MASK 0x7
++#define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT)
++#define MT7620_GPIO_MODE_UARTF 0x0
++#define MT7620_GPIO_MODE_PCM_UARTF 0x1
++#define MT7620_GPIO_MODE_PCM_I2S 0x2
++#define MT7620_GPIO_MODE_I2S_UARTF 0x3
++#define MT7620_GPIO_MODE_PCM_GPIO 0x4
++#define MT7620_GPIO_MODE_GPIO_UARTF 0x5
++#define MT7620_GPIO_MODE_GPIO_I2S 0x6
++#define MT7620_GPIO_MODE_GPIO 0x7
++#define MT7620_GPIO_MODE_UART1 BIT(5)
++#define MT7620_GPIO_MODE_MDIO BIT(8)
++#define MT7620_GPIO_MODE_RGMII1 BIT(9)
++#define MT7620_GPIO_MODE_RGMII2 BIT(10)
++#define MT7620_GPIO_MODE_SPI BIT(11)
++#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12)
++#define MT7620_GPIO_MODE_WLED BIT(13)
++#define MT7620_GPIO_MODE_JTAG BIT(15)
++#define MT7620_GPIO_MODE_EPHY BIT(15)
++#define MT7620_GPIO_MODE_WDT BIT(22)
++
++#endif
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -20,6 +20,9 @@ choice
+ select USB_ARCH_HAS_OHCI
+ select USB_ARCH_HAS_EHCI
+
++ config SOC_MT7620
++ bool "MT7620"
++
+ endchoice
+
+ choice
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -11,6 +11,7 @@ obj-y := prom.o of.o reset.o clk.o irq.o
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+ obj-$(CONFIG_SOC_RT3883) += rt3883.o
++obj-$(CONFIG_SOC_MT7620) += mt7620.o
+
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+--- a/arch/mips/ralink/Platform
++++ b/arch/mips/ralink/Platform
+@@ -18,3 +18,8 @@ load-$(CONFIG_SOC_RT305X) += 0xffffffff8
+ # Ralink RT3883
+ #
+ load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
++
++#
++# Ralink MT7620
++#
++load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000
+--- /dev/null
++++ b/arch/mips/ralink/mt7620.c
+@@ -0,0 +1,214 @@
++/*
++ * 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.
++ *
++ * Parts of this file are based on Ralink's 2.6.21 BSP
++ *
++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++
++#include <asm/mipsregs.h>
++#include <asm/mach-ralink/ralink_regs.h>
++#include <asm/mach-ralink/mt7620.h>
++
++#include "common.h"
++
++/* 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",
++ .mask = MT7620_GPIO_MODE_I2C,
++ .gpio_first = 1,
++ .gpio_last = 2,
++ }, {
++ .name = "spi",
++ .mask = MT7620_GPIO_MODE_SPI,
++ .gpio_first = 3,
++ .gpio_last = 6,
++ }, {
++ .name = "uartlite",
++ .mask = MT7620_GPIO_MODE_UART1,
++ .gpio_first = 15,
++ .gpio_last = 16,
++ }, {
++ .name = "wdt",
++ .mask = MT7620_GPIO_MODE_WDT,
++ .gpio_first = 17,
++ .gpio_last = 17,
++ }, {
++ .name = "mdio",
++ .mask = MT7620_GPIO_MODE_MDIO,
++ .gpio_first = 22,
++ .gpio_last = 23,
++ }, {
++ .name = "rgmii1",
++ .mask = MT7620_GPIO_MODE_RGMII1,
++ .gpio_first = 24,
++ .gpio_last = 35,
++ }, {
++ .name = "spi refclk",
++ .mask = MT7620_GPIO_MODE_SPI_REF_CLK,
++ .gpio_first = 37,
++ .gpio_last = 39,
++ }, {
++ .name = "jtag",
++ .mask = MT7620_GPIO_MODE_JTAG,
++ .gpio_first = 40,
++ .gpio_last = 44,
++ }, {
++ /* shared lines with jtag */
++ .name = "ephy",
++ .mask = MT7620_GPIO_MODE_EPHY,
++ .gpio_first = 40,
++ .gpio_last = 44,
++ }, {
++ .name = "nand",
++ .mask = MT7620_GPIO_MODE_JTAG,
++ .gpio_first = 45,
++ .gpio_last = 59,
++ }, {
++ .name = "rgmii2",
++ .mask = MT7620_GPIO_MODE_RGMII2,
++ .gpio_first = 60,
++ .gpio_last = 71,
++ }, {
++ .name = "wled",
++ .mask = MT7620_GPIO_MODE_WLED,
++ .gpio_first = 72,
++ .gpio_last = 72,
++ }, {0}
++};
++
++static struct ralink_pinmux_grp uart_mux[] = {
++ {
++ .name = "uartf",
++ .mask = MT7620_GPIO_MODE_UARTF,
++ .gpio_first = 7,
++ .gpio_last = 14,
++ }, {
++ .name = "pcm uartf",
++ .mask = MT7620_GPIO_MODE_PCM_UARTF,
++ .gpio_first = 7,
++ .gpio_last = 14,
++ }, {
++ .name = "pcm i2s",
++ .mask = MT7620_GPIO_MODE_PCM_I2S,
++ .gpio_first = 7,
++ .gpio_last = 14,
++ }, {
++ .name = "i2s uartf",
++ .mask = MT7620_GPIO_MODE_I2S_UARTF,
++ .gpio_first = 7,
++ .gpio_last = 14,
++ }, {
++ .name = "pcm gpio",
++ .mask = MT7620_GPIO_MODE_PCM_GPIO,
++ .gpio_first = 11,
++ .gpio_last = 14,
++ }, {
++ .name = "gpio uartf",
++ .mask = MT7620_GPIO_MODE_GPIO_UARTF,
++ .gpio_first = 7,
++ .gpio_last = 10,
++ }, {
++ .name = "gpio i2s",
++ .mask = MT7620_GPIO_MODE_GPIO_I2S,
++ .gpio_first = 7,
++ .gpio_last = 10,
++ }, {
++ .name = "gpio",
++ .mask = MT7620_GPIO_MODE_GPIO,
++ }, {0}
++};
++
++struct ralink_pinmux rt_gpio_pinmux = {
++ .mode = mode_mux,
++ .uart = uart_mux,
++ .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT,
++ .uart_mask = MT7620_GPIO_MODE_GPIO,
++};
++
++void __init ralink_clk_init(void)
++{
++ 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;
++
++ cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000;
++ }
++
++ if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM)
++ sys_rate = cpu_rate / 4;
++ else
++ sys_rate = cpu_rate / 3;
++
++ ralink_clk_add("cpu", cpu_rate);
++ ralink_clk_add("10000100.timer", 40000000);
++ ralink_clk_add("10000500.uart", 40000000);
++ ralink_clk_add("10000c00.uartlite", 40000000);
++}
++
++void __init ralink_of_remap(void)
++{
++ rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc");
++ rt_memc_membase = plat_of_remap_node("ralink,mt7620a-memc");
++
++ if (!rt_sysc_membase || !rt_memc_membase)
++ panic("Failed to remap core resources");
++}
++
++void prom_soc_init(struct ralink_soc_info *soc_info)
++{
++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE);
++ unsigned char *name = NULL;
++ u32 n0;
++ u32 n1;
++ u32 rev;
++ u32 cfg0;
++
++ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
++ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
++
++ if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) {
++ name = "MT7620N";
++ soc_info->compatible = "ralink,mt7620n-soc";
++ } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) {
++ name = "MT7620A";
++ soc_info->compatible = "ralink,mt7620a-soc";
++ } else {
++ panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
++ }
++
++ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
++
++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
++ "Ralink %s ver:%u eco:%u",
++ name,
++ (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
++ (rev & CHIP_REV_ECO_MASK));
++
++ cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
++ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
++}
+++ /dev/null
-From f22c157f44c93d61058d2e2aa5626ee2899fde5a Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 22 Jan 2013 18:24:34 +0100
-Subject: [PATCH 114/121] GPIO: MIPS: ralink: adds ralink gpio support
-
-Add gpio driver for Ralink SoC. This driver makes the gpio core on
-RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/Kconfig | 1 +
- arch/mips/include/asm/mach-ralink/gpio.h | 24 ++++
- drivers/gpio/Kconfig | 6 +
- drivers/gpio/Makefile | 1 +
- drivers/gpio/gpio-ralink.c | 176 ++++++++++++++++++++++++++++++
- 5 files changed, 208 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h
- create mode 100644 drivers/gpio/gpio-ralink.c
-
---- a/arch/mips/Kconfig
-+++ b/arch/mips/Kconfig
-@@ -449,6 +449,7 @@ config RALINK
- select SYS_HAS_EARLY_PRINTK
- select HAVE_MACH_CLKDEV
- select CLKDEV_LOOKUP
-+ select ARCH_REQUIRE_GPIOLIB
-
- config SGI_IP22
- bool "SGI IP22 (Indy/Indigo2)"
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/gpio.h
-@@ -0,0 +1,24 @@
-+/*
-+ * Ralink SoC GPIO API support
-+ *
-+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ *
-+ */
-+
-+#ifndef __ASM_MACH_RALINK_GPIO_H
-+#define __ASM_MACH_RALINK_GPIO_H
-+
-+#define ARCH_NR_GPIOS 128
-+#include <asm-generic/gpio.h>
-+
-+#define gpio_get_value __gpio_get_value
-+#define gpio_set_value __gpio_set_value
-+#define gpio_cansleep __gpio_cansleep
-+#define gpio_to_irq __gpio_to_irq
-+
-+#endif /* __ASM_MACH_RALINK_GPIO_H */
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -201,6 +201,12 @@ config GPIO_PXA
- help
- Say yes here to support the PXA GPIO device
-
-+config GPIO_RALINK
-+ bool "Ralink GPIO Support"
-+ depends on RALINK
-+ help
-+ Say yes here to support the Ralink SoC GPIO device
-+
- config GPIO_SPEAR_SPICS
- bool "ST SPEAr13xx SPI Chip Select as GPIO support"
- depends on PLAT_SPEAR
---- a/drivers/gpio/Makefile
-+++ b/drivers/gpio/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf85
- obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
- obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
- obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
-+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o
- obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
- obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
- obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
---- /dev/null
-+++ b/drivers/gpio/gpio-ralink.c
-@@ -0,0 +1,176 @@
-+/*
-+ * 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) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/io.h>
-+#include <linux/gpio.h>
-+#include <linux/spinlock.h>
-+#include <linux/platform_device.h>
-+
-+enum ralink_gpio_reg {
-+ GPIO_REG_INT = 0,
-+ GPIO_REG_EDGE,
-+ GPIO_REG_RENA,
-+ GPIO_REG_FENA,
-+ GPIO_REG_DATA,
-+ GPIO_REG_DIR,
-+ GPIO_REG_POL,
-+ GPIO_REG_SET,
-+ GPIO_REG_RESET,
-+ GPIO_REG_TOGGLE,
-+ GPIO_REG_MAX
-+};
-+
-+struct ralink_gpio_chip {
-+ struct gpio_chip chip;
-+ u8 regs[GPIO_REG_MAX];
-+
-+ spinlock_t lock;
-+ void __iomem *membase;
-+};
-+
-+static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip)
-+{
-+ struct ralink_gpio_chip *rg;
-+
-+ rg = container_of(chip, struct ralink_gpio_chip, chip);
-+ return rg;
-+}
-+
-+static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val)
-+{
-+ iowrite32(val, rg->membase + rg->regs[reg]);
-+}
-+
-+static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg)
-+{
-+ return ioread32(rg->membase + rg->regs[reg]);
-+}
-+
-+static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-+{
-+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
-+
-+ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset));
-+}
-+
-+static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
-+
-+ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset));
-+}
-+
-+static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
-+ unsigned long flags;
-+ u32 t;
-+
-+ spin_lock_irqsave(&rg->lock, flags);
-+ t = rt_gpio_r32(rg, GPIO_REG_DIR);
-+ t &= ~BIT(offset);
-+ rt_gpio_w32(rg, GPIO_REG_DIR, t);
-+ spin_unlock_irqrestore(&rg->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int ralink_gpio_direction_output(struct gpio_chip *chip,
-+ unsigned offset, int value)
-+{
-+ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
-+ unsigned long flags;
-+ u32 t;
-+
-+ spin_lock_irqsave(&rg->lock, flags);
-+ ralink_gpio_set(chip, offset, value);
-+ t = rt_gpio_r32(rg, GPIO_REG_DIR);
-+ t |= BIT(offset);
-+ rt_gpio_w32(rg, GPIO_REG_DIR, t);
-+ spin_unlock_irqrestore(&rg->lock, flags);
-+
-+ return 0;
-+}
-+
-+static int ralink_gpio_probe(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ struct ralink_gpio_chip *gc;
-+ const __be32 *ngpio;
-+
-+ if (!res) {
-+ dev_err(&pdev->dev, "failed to find resource\n");
-+ return -ENOMEM;
-+ }
-+
-+ gc = devm_kzalloc(&pdev->dev,
-+ sizeof(struct ralink_gpio_chip), GFP_KERNEL);
-+ if (!gc)
-+ return -ENOMEM;
-+
-+ gc->membase = devm_request_and_ioremap(&pdev->dev, res);
-+ if (!gc->membase) {
-+ dev_err(&pdev->dev, "cannot remap I/O memory region\n");
-+ return -ENOMEM;
-+ }
-+
-+ if (of_property_read_u8_array(np, "ralink,register-map",
-+ gc->regs, GPIO_REG_MAX)) {
-+ dev_err(&pdev->dev, "failed to read register definition\n");
-+ return -EINVAL;
-+ }
-+
-+ ngpio = of_get_property(np, "ralink,num-gpios", NULL);
-+ if (!ngpio) {
-+ dev_err(&pdev->dev, "failed to read number of pins\n");
-+ return -EINVAL;
-+ }
-+
-+ spin_lock_init(&gc->lock);
-+
-+ gc->chip.label = dev_name(&pdev->dev);
-+ gc->chip.of_node = np;
-+ gc->chip.base = -1;
-+ gc->chip.ngpio = be32_to_cpu(*ngpio);
-+ gc->chip.direction_input = ralink_gpio_direction_input;
-+ gc->chip.direction_output = ralink_gpio_direction_output;
-+ gc->chip.get = ralink_gpio_get;
-+ gc->chip.set = ralink_gpio_set;
-+
-+ /* set polarity to low for all lines */
-+ rt_gpio_w32(gc, GPIO_REG_POL, 0);
-+
-+ dev_info(&pdev->dev, "registering %d gpios\n", gc->chip.ngpio);
-+
-+ return gpiochip_add(&gc->chip);
-+}
-+
-+static const struct of_device_id ralink_gpio_match[] = {
-+ { .compatible = "ralink,rt2880-gpio" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ralink_gpio_match);
-+
-+static struct platform_driver ralink_gpio_driver = {
-+ .probe = ralink_gpio_probe,
-+ .driver = {
-+ .name = "rt2880_gpio",
-+ .owner = THIS_MODULE,
-+ .of_match_table = ralink_gpio_match,
-+ },
-+};
-+
-+static int __init ralink_gpio_init(void)
-+{
-+ return platform_driver_register(&ralink_gpio_driver);
-+}
-+
-+subsys_initcall(ralink_gpio_init);
--- /dev/null
+From 33c525913af22d1b799a7218ee48579c22a50cf8 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 10 Apr 2013 09:19:07 +0200
+Subject: [PATCH 114/137] MIPS: ralink: add cpu-feature-overrides.h
+
+Add cpu-feature-overrides.h for RT288x, RT305x and RT3883.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5175/
+---
+ .../asm/mach-ralink/rt288x/cpu-feature-overrides.h | 56 ++++++++++++++++++++
+ .../asm/mach-ralink/rt305x/cpu-feature-overrides.h | 56 ++++++++++++++++++++
+ .../asm/mach-ralink/rt3883/cpu-feature-overrides.h | 55 +++++++++++++++++++
+ arch/mips/ralink/Platform | 3 ++
+ 4 files changed, 170 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h
+
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h
+@@ -0,0 +1,56 @@
++/*
++ * Ralink RT288x 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 _RT288X_CPU_FEATURE_OVERRIDES_H
++#define _RT288X_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 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() 16
++#define cpu_icache_line_size() 16
++
++#endif /* _RT288X_CPU_FEATURE_OVERRIDES_H */
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h
+@@ -0,0 +1,56 @@
++/*
++ * Ralink RT305x 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 _RT305X_CPU_FEATURE_OVERRIDES_H
++#define _RT305X_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 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 /* _RT305X_CPU_FEATURE_OVERRIDES_H */
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h
+@@ -0,0 +1,55 @@
++/*
++ * Ralink RT3662/RT3883 specific CPU feature overrides
++ *
++ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@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 _RT3883_CPU_FEATURE_OVERRIDES_H
++#define _RT3883_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 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 /* _RT3883_CPU_FEATURE_OVERRIDES_H */
+--- a/arch/mips/ralink/Platform
++++ b/arch/mips/ralink/Platform
+@@ -8,16 +8,19 @@ cflags-$(CONFIG_RALINK) += -I$(srctree)
+ # Ralink RT288x
+ #
+ load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000
++cflags-$(CONFIG_SOC_RT288X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt288x
+
+ #
+ # Ralink RT305x
+ #
+ load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
++cflags-$(CONFIG_SOC_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt305x
+
+ #
+ # Ralink RT3883
+ #
+ load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
++cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883
+
+ #
+ # Ralink MT7620
--- /dev/null
+From 9377ecb9f1fb5da25a0fbd324e7add7644b1d43d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 10:11:51 +0200
+Subject: [PATCH 115/137] DT: add vendor prefixes for Ralink
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -40,6 +40,7 @@ onnn ON Semiconductor Corp.
+ picochip Picochip Ltd
+ powervr PowerVR (deprecated, use img)
+ qcom Qualcomm, Inc.
++ralink Mediatek/Ralink Technology Corp.
+ ramtron Ramtron International
+ realtek Realtek Semiconductor Corp.
+ samsung Samsung Semiconductor
+++ /dev/null
-e8c5ebbd743dac63178807c0f68fe1b75680474a3 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Wed, 30 Jan 2013 17:58:15 +0100
-Subject: [PATCH 115/121] SPI: ralink: add Ralink SoC spi driver
-
-Add the driver needed to make SPI work on Ralink SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/spi/Kconfig | 6 +
- drivers/spi/Makefile | 1 +
- drivers/spi/spi-ralink.c | 472 ++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 479 insertions(+)
- create mode 100644 drivers/spi/spi-ralink.c
-
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -324,6 +324,12 @@ config SPI_RSPI
- help
- SPI driver for Renesas RSPI blocks.
-
-+config SPI_RALINK
-+ tristate "Ralink RT288x/RT305x/RT3662 SPI Controller"
-+ depends on (SOC_RT288X || SOC_RT305X || SOC_RT3883)
-+ help
-+ This selects a driver for the Ralink RT288x/RT305x SPI Controller.
-+
- config SPI_S3C24XX
- tristate "Samsung S3C24XX series SPI"
- depends on ARCH_S3C24XX && EXPERIMENTAL
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -51,6 +51,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.
- obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o
- obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
- obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
-+obj-$(CONFIG_SPI_RALINK) += spi-ralink.o
- obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
- spi-s3c24xx-hw-y := spi-s3c24xx.o
- spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
---- /dev/null
-+++ b/drivers/spi/spi-ralink.c
-@@ -0,0 +1,472 @@
-+/*
-+ * spi-ralink.c -- Ralink RT288x/RT305x SPI controller driver
-+ *
-+ * Copyright (C) 2011 Sergiy <piratfm@gmail.com>
-+ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * Some parts are based on spi-orion.c:
-+ * Author: Shadi Ammouri <shadi@marvell.com>
-+ * Copyright (C) 2007-2008 Marvell Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/io.h>
-+#include <linux/spi/spi.h>
-+
-+#define DRIVER_NAME "spi-ralink"
-+#define RALINK_NUM_CHIPSELECTS 1 /* only one slave is supported*/
-+#define RALINK_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
-+
-+#define RAMIPS_SPI_STAT 0x00
-+#define RAMIPS_SPI_CFG 0x10
-+#define RAMIPS_SPI_CTL 0x14
-+#define RAMIPS_SPI_DATA 0x20
-+
-+/* SPISTAT register bit field */
-+#define SPISTAT_BUSY BIT(0)
-+
-+/* SPICFG register bit field */
-+#define SPICFG_LSBFIRST 0
-+#define SPICFG_MSBFIRST BIT(8)
-+#define SPICFG_SPICLKPOL BIT(6)
-+#define SPICFG_RXCLKEDGE_FALLING BIT(5)
-+#define SPICFG_TXCLKEDGE_FALLING BIT(4)
-+#define SPICFG_SPICLK_PRESCALE_MASK 0x7
-+#define SPICFG_SPICLK_DIV2 0
-+#define SPICFG_SPICLK_DIV4 1
-+#define SPICFG_SPICLK_DIV8 2
-+#define SPICFG_SPICLK_DIV16 3
-+#define SPICFG_SPICLK_DIV32 4
-+#define SPICFG_SPICLK_DIV64 5
-+#define SPICFG_SPICLK_DIV128 6
-+#define SPICFG_SPICLK_DISABLE 7
-+
-+/* SPICTL register bit field */
-+#define SPICTL_HIZSDO BIT(3)
-+#define SPICTL_STARTWR BIT(2)
-+#define SPICTL_STARTRD BIT(1)
-+#define SPICTL_SPIENA BIT(0)
-+
-+#ifdef DEBUG
-+#define spi_debug(args...) printk(args)
-+#else
-+#define spi_debug(args...)
-+#endif
-+
-+struct ralink_spi {
-+ struct spi_master *master;
-+ void __iomem *base;
-+ unsigned int sys_freq;
-+ unsigned int speed;
-+ struct clk *clk;
-+};
-+
-+static inline struct ralink_spi *spidev_to_ralink_spi(struct spi_device *spi)
-+{
-+ return spi_master_get_devdata(spi->master);
-+}
-+
-+static inline u32 ralink_spi_read(struct ralink_spi *rs, u32 reg)
-+{
-+ return ioread32(rs->base + reg);
-+}
-+
-+static inline void ralink_spi_write(struct ralink_spi *rs, u32 reg, u32 val)
-+{
-+ iowrite32(val, rs->base + reg);
-+}
-+
-+static inline void ralink_spi_setbits(struct ralink_spi *rs, u32 reg, u32 mask)
-+{
-+ void __iomem *addr = rs->base + reg;
-+ u32 val;
-+
-+ val = ioread32(addr);
-+ val |= mask;
-+ iowrite32(val, addr);
-+}
-+
-+static inline void ralink_spi_clrbits(struct ralink_spi *rs, u32 reg, u32 mask)
-+{
-+ void __iomem *addr = rs->base + reg;
-+ u32 val;
-+
-+ val = ioread32(addr);
-+ val &= ~mask;
-+ iowrite32(val, addr);
-+}
-+
-+static int ralink_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
-+{
-+ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
-+ u32 rate;
-+ u32 prescale;
-+ u32 reg;
-+
-+ spi_debug("%s: speed:%u\n", __func__, speed);
-+
-+ /*
-+ * the supported rates are: 2, 4, 8, ... 128
-+ * round up as we look for equal or less speed
-+ */
-+ rate = DIV_ROUND_UP(rs->sys_freq, speed);
-+ spi_debug("%s: rate-1:%u\n", __func__, rate);
-+ rate = roundup_pow_of_two(rate);
-+ spi_debug("%s: rate-2:%u\n", __func__, rate);
-+
-+ /* check if requested speed is too small */
-+ if (rate > 128)
-+ return -EINVAL;
-+
-+ if (rate < 2)
-+ rate = 2;
-+
-+ /* Convert the rate to SPI clock divisor value. */
-+ prescale = ilog2(rate/2);
-+ spi_debug("%s: prescale:%u\n", __func__, prescale);
-+
-+ reg = ralink_spi_read(rs, RAMIPS_SPI_CFG);
-+ reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale);
-+ ralink_spi_write(rs, RAMIPS_SPI_CFG, reg);
-+ rs->speed = speed;
-+ return 0;
-+}
-+
-+/*
-+ * called only when no transfer is active on the bus
-+ */
-+static int
-+ralink_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-+{
-+ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
-+ unsigned int speed = spi->max_speed_hz;
-+ int rc;
-+ unsigned int bits_per_word = 8;
-+
-+ if ((t != NULL) && t->speed_hz)
-+ speed = t->speed_hz;
-+
-+ if ((t != NULL) && t->bits_per_word)
-+ bits_per_word = t->bits_per_word;
-+
-+ if (rs->speed != speed) {
-+ spi_debug("%s: speed_hz:%u\n", __func__, speed);
-+ rc = ralink_spi_baudrate_set(spi, speed);
-+ if (rc)
-+ return rc;
-+ }
-+
-+ if (bits_per_word != 8) {
-+ spi_debug("%s: bad bits_per_word: %u\n", __func__,
-+ bits_per_word);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static void ralink_spi_set_cs(struct ralink_spi *rs, int enable)
-+{
-+ if (enable)
-+ ralink_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
-+ else
-+ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
-+}
-+
-+static inline int ralink_spi_wait_till_ready(struct ralink_spi *rs)
-+{
-+ int i;
-+
-+ for (i = 0; i < RALINK_SPI_WAIT_RDY_MAX_LOOP; i++) {
-+ u32 status;
-+
-+ status = ralink_spi_read(rs, RAMIPS_SPI_STAT);
-+ if ((status & SPISTAT_BUSY) == 0)
-+ return 0;
-+
-+ udelay(1);
-+ }
-+
-+ return -ETIMEDOUT;
-+}
-+
-+static unsigned int
-+ralink_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
-+{
-+ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
-+ unsigned count = 0;
-+ u8 *rx = xfer->rx_buf;
-+ const u8 *tx = xfer->tx_buf;
-+ int err;
-+
-+ spi_debug("%s(%d): %s %s\n", __func__, xfer->len,
-+ (tx != NULL) ? "tx" : " ",
-+ (rx != NULL) ? "rx" : " ");
-+
-+ if (tx) {
-+ for (count = 0; count < xfer->len; count++) {
-+ ralink_spi_write(rs, RAMIPS_SPI_DATA, tx[count]);
-+ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR);
-+ err = ralink_spi_wait_till_ready(rs);
-+ if (err) {
-+ dev_err(&spi->dev, "TX failed, err=%d\n", err);
-+ goto out;
-+ }
-+ }
-+ }
-+
-+ if (rx) {
-+ for (count = 0; count < xfer->len; count++) {
-+ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD);
-+ err = ralink_spi_wait_till_ready(rs);
-+ if (err) {
-+ dev_err(&spi->dev, "RX failed, err=%d\n", err);
-+ goto out;
-+ }
-+ rx[count] = (u8) ralink_spi_read(rs, RAMIPS_SPI_DATA);
-+ }
-+ }
-+
-+out:
-+ return count;
-+}
-+
-+static int ralink_spi_transfer_one_message(struct spi_master *master,
-+ struct spi_message *m)
-+{
-+ struct ralink_spi *rs = spi_master_get_devdata(master);
-+ struct spi_device *spi = m->spi;
-+ struct spi_transfer *t = NULL;
-+ int par_override = 0;
-+ int status = 0;
-+ int cs_active = 0;
-+
-+ /* Load defaults */
-+ status = ralink_spi_setup_transfer(spi, NULL);
-+ if (status < 0)
-+ goto msg_done;
-+
-+ list_for_each_entry(t, &m->transfers, transfer_list) {
-+ unsigned int bits_per_word = spi->bits_per_word;
-+
-+ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
-+ dev_err(&spi->dev,
-+ "message rejected: invalid transfer data buffers\n");
-+ status = -EIO;
-+ goto msg_done;
-+ }
-+
-+ if (t->bits_per_word)
-+ bits_per_word = t->bits_per_word;
-+
-+ if (bits_per_word != 8) {
-+ dev_err(&spi->dev,
-+ "message rejected: invalid transfer bits_per_word (%d bits)\n",
-+ bits_per_word);
-+ status = -EIO;
-+ goto msg_done;
-+ }
-+
-+ if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) {
-+ dev_err(&spi->dev,
-+ "message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n",
-+ (rs->sys_freq / 128), t->speed_hz);
-+ status = -EIO;
-+ goto msg_done;
-+ }
-+
-+ if (par_override || t->speed_hz || t->bits_per_word) {
-+ par_override = 1;
-+ status = ralink_spi_setup_transfer(spi, t);
-+ if (status < 0)
-+ goto msg_done;
-+ if (!t->speed_hz && !t->bits_per_word)
-+ par_override = 0;
-+ }
-+
-+ if (!cs_active) {
-+ ralink_spi_set_cs(rs, 1);
-+ cs_active = 1;
-+ }
-+
-+ if (t->len)
-+ m->actual_length += ralink_spi_write_read(spi, t);
-+
-+ if (t->delay_usecs)
-+ udelay(t->delay_usecs);
-+
-+ if (t->cs_change) {
-+ ralink_spi_set_cs(rs, 0);
-+ cs_active = 0;
-+ }
-+ }
-+
-+msg_done:
-+ if (cs_active)
-+ ralink_spi_set_cs(rs, 0);
-+
-+ m->status = status;
-+ spi_finalize_current_message(master);
-+
-+ return 0;
-+}
-+
-+static int ralink_spi_setup(struct spi_device *spi)
-+{
-+ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
-+
-+ if ((spi->max_speed_hz == 0) ||
-+ (spi->max_speed_hz > (rs->sys_freq / 2)))
-+ spi->max_speed_hz = (rs->sys_freq / 2);
-+
-+ if (spi->max_speed_hz < (rs->sys_freq / 128)) {
-+ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n",
-+ spi->max_speed_hz);
-+ return -EINVAL;
-+ }
-+
-+ if (spi->bits_per_word != 0 && spi->bits_per_word != 8) {
-+ dev_err(&spi->dev,
-+ "setup: requested bits per words - os wrong %d bpw\n",
-+ spi->bits_per_word);
-+ return -EINVAL;
-+ }
-+
-+ if (spi->bits_per_word == 0)
-+ spi->bits_per_word = 8;
-+
-+ /*
-+ * baudrate & width will be set ralink_spi_setup_transfer
-+ */
-+ return 0;
-+}
-+
-+static void ralink_spi_reset(struct ralink_spi *rs)
-+{
-+ ralink_spi_write(rs, RAMIPS_SPI_CFG,
-+ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING |
-+ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL);
-+ ralink_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA);
-+}
-+
-+static int ralink_spi_probe(struct platform_device *pdev)
-+{
-+ struct spi_master *master;
-+ struct ralink_spi *rs;
-+ struct resource *r;
-+ int status = 0;
-+
-+ master = spi_alloc_master(&pdev->dev, sizeof(*rs));
-+ if (master == NULL) {
-+ dev_dbg(&pdev->dev, "master allocation failed\n");
-+ return -ENOMEM;
-+ }
-+
-+ //if (pdev->id != -1)
-+ master->bus_num = 0;
-+
-+ /* we support only mode 0, and no options */
-+ master->mode_bits = 0;
-+
-+ master->setup = ralink_spi_setup;
-+ master->transfer_one_message = ralink_spi_transfer_one_message;
-+ master->num_chipselect = RALINK_NUM_CHIPSELECTS;
-+ master->dev.of_node = pdev->dev.of_node;
-+
-+ dev_set_drvdata(&pdev->dev, master);
-+
-+ rs = spi_master_get_devdata(master);
-+ rs->master = master;
-+
-+ rs->clk = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(rs->clk)) {
-+ status = PTR_ERR(rs->clk);
-+ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n",
-+ status);
-+ goto out_put_master;
-+ }
-+
-+ status = clk_enable(rs->clk);
-+ if (status)
-+ goto out_put_clk;
-+
-+ rs->sys_freq = clk_get_rate(rs->clk);
-+ spi_debug("%s: sys_freq: %u\n", __func__, rs->sys_freq);
-+
-+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (r == NULL) {
-+ status = -ENODEV;
-+ goto out_disable_clk;
-+ }
-+
-+ rs->base = devm_request_and_ioremap(&pdev->dev, r);
-+ if (!rs->base) {
-+ status = -EADDRNOTAVAIL;
-+ goto out_disable_clk;
-+ }
-+
-+ ralink_spi_reset(rs);
-+
-+ status = spi_register_master(master);
-+ if (status)
-+ goto out_disable_clk;
-+
-+ return 0;
-+
-+out_disable_clk:
-+ clk_disable(rs->clk);
-+out_put_clk:
-+ clk_put(rs->clk);
-+out_put_master:
-+ spi_master_put(master);
-+ return status;
-+}
-+
-+static int ralink_spi_remove(struct platform_device *pdev)
-+{
-+ struct spi_master *master;
-+ struct ralink_spi *rs;
-+
-+ master = dev_get_drvdata(&pdev->dev);
-+ rs = spi_master_get_devdata(master);
-+
-+ clk_disable(rs->clk);
-+ clk_put(rs->clk);
-+ spi_unregister_master(master);
-+
-+ return 0;
-+}
-+
-+MODULE_ALIAS("platform:" DRIVER_NAME);
-+
-+static const struct of_device_id ralink_spi_match[] = {
-+ { .compatible = "ralink,rt2880-spi" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ralink_spi_match);
-+
-+static struct platform_driver ralink_spi_driver = {
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ .of_match_table = ralink_spi_match,
-+ },
-+ .probe = ralink_spi_probe,
-+ .remove = ralink_spi_remove,
-+};
-+
-+module_platform_driver(ralink_spi_driver);
-+
-+MODULE_DESCRIPTION("Ralink SPI driver");
-+MODULE_AUTHOR("Sergiy <piratfm@gmail.com>");
-+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
-+MODULE_LICENSE("GPL");
--- /dev/null
+From fed1ff0d85b481bb3dbebf31e0720d65ce4170c9 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 13 Apr 2013 09:02:40 +0200
+Subject: [PATCH 116/137] DT: add documentation for the Ralink MIPS SoCs
+
+This patch adds binding documentation for the
+compatible values of the Ralink MIPS SoCs.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Patchwork: http://patchwork.linux-mips.org/patch/5187/
+---
+ Documentation/devicetree/bindings/mips/ralink.txt | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mips/ralink.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mips/ralink.txt
+@@ -0,0 +1,18 @@
++Ralink MIPS SoC device tree bindings
++
++1. SoCs
++
++Each device tree must specify a compatible value for the Ralink SoC
++it uses in the compatible property of the root node. The compatible
++value must be one of the following values:
++
++ ralink,rt2880-soc
++ ralink,rt3050-soc
++ ralink,rt3052-soc
++ ralink,rt3350-soc
++ ralink,rt3352-soc
++ ralink,rt3883-soc
++ ralink,rt5350-soc
++ ralink,mt7620a-soc
++ ralink,mt7620n-soc
++
+++ /dev/null
-From 6ffb42870411ca082e8e46d96d72bc5d8881ce8d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 22 Jan 2013 16:01:07 +0100
-Subject: [PATCH 116/121] serial: of: allow au1x00 and rt288x to load from OF
-
-In order to make serial_8250 loadable via OF on Au1x00 and Ralink WiSoC we need
-to default the iotype to UPIO_AU.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/tty/serial/of_serial.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/serial/of_serial.c
-+++ b/drivers/tty/serial/of_serial.c
-@@ -97,7 +97,10 @@ static int of_platform_serial_setup(stru
- port->regshift = prop;
-
- port->irq = irq_of_parse_and_map(np, 0);
-- port->iotype = UPIO_MEM;
-+ if (of_device_is_compatible(np, "ralink,rt2880-uart"))
-+ port->iotype = UPIO_AU;
-+ else
-+ port->iotype = UPIO_MEM;
- if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
- switch (prop) {
- case 1:
--- /dev/null
+From 7a30e00a278fe94ac8e42d0967ffde99d1ab74ee Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 21 Mar 2013 17:47:07 +0100
+Subject: [PATCH 117/137] DT: MIPS: ralink: clean up RT3050 dtsi and dts file
+
+* remove nodes for cores whose drivers are not upstream yet
+* add compat string for an additional soc
+* fix a whitespace error
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Patchwork: http://patchwork.linux-mips.org/patch/5186/
+---
+ arch/mips/ralink/dts/rt3050.dtsi | 52 ++--------------------------------
+ arch/mips/ralink/dts/rt3052_eval.dts | 10 ++-----
+ 2 files changed, 4 insertions(+), 58 deletions(-)
+
+--- a/arch/mips/ralink/dts/rt3050.dtsi
++++ b/arch/mips/ralink/dts/rt3050.dtsi
+@@ -1,7 +1,7 @@
+ / {
+ #address-cells = <1>;
+ #size-cells = <1>;
+- compatible = "ralink,rt3050-soc", "ralink,rt3052-soc";
++ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc";
+
+ cpus {
+ cpu@0 {
+@@ -9,10 +9,6 @@
+ };
+ };
+
+- chosen {
+- bootargs = "console=ttyS0,57600 init=/init";
+- };
+-
+ cpuintc: cpuintc@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+@@ -23,7 +19,7 @@
+ palmbus@10000000 {
+ compatible = "palmbus";
+ reg = <0x10000000 0x200000>;
+- ranges = <0x0 0x10000000 0x1FFFFF>;
++ ranges = <0x0 0x10000000 0x1FFFFF>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+@@ -33,11 +29,6 @@
+ reg = <0x0 0x100>;
+ };
+
+- timer@100 {
+- compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt";
+- reg = <0x100 0x100>;
+- };
+-
+ intc: intc@200 {
+ compatible = "ralink,rt3052-intc", "ralink,rt2880-intc";
+ reg = <0x200 0x100>;
+@@ -54,45 +45,6 @@
+ reg = <0x300 0x100>;
+ };
+
+- gpio0: gpio@600 {
+- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
+- reg = <0x600 0x34>;
+-
+- gpio-controller;
+- #gpio-cells = <2>;
+-
+- ralink,ngpio = <24>;
+- ralink,regs = [ 00 04 08 0c
+- 20 24 28 2c
+- 30 34 ];
+- };
+-
+- gpio1: gpio@638 {
+- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
+- reg = <0x638 0x24>;
+-
+- gpio-controller;
+- #gpio-cells = <2>;
+-
+- ralink,ngpio = <16>;
+- ralink,regs = [ 00 04 08 0c
+- 10 14 18 1c
+- 20 24 ];
+- };
+-
+- gpio2: gpio@660 {
+- compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
+- reg = <0x660 0x24>;
+-
+- gpio-controller;
+- #gpio-cells = <2>;
+-
+- ralink,ngpio = <12>;
+- ralink,regs = [ 00 04 08 0c
+- 10 14 18 1c
+- 20 24 ];
+- };
+-
+ uartlite@c00 {
+ compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a";
+ reg = <0xc00 0x100>;
+--- a/arch/mips/ralink/dts/rt3052_eval.dts
++++ b/arch/mips/ralink/dts/rt3052_eval.dts
+@@ -3,8 +3,6 @@
+ /include/ "rt3050.dtsi"
+
+ / {
+- #address-cells = <1>;
+- #size-cells = <1>;
+ compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc";
+ model = "Ralink RT3052 evaluation board";
+
+++ /dev/null
-From c1e24bf32404bec0032221b9ea37d6fd8c45dbdd Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 15 Mar 2013 18:16:01 +0100
-Subject: [PATCH 117/121] serial: ralink: adds mt7620 serial
-
-Add the config symbol for Mediatek7620 SoC to SERIAL_8250_RT288X
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/tty/serial/8250/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/tty/serial/8250/Kconfig
-+++ b/drivers/tty/serial/8250/Kconfig
-@@ -280,7 +280,7 @@ config SERIAL_8250_EM
-
- config SERIAL_8250_RT288X
- bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support"
-- depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883)
-+ depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620)
- help
- If you have a Ralink RT288x/RT305x SoC based board and want to use the
- serial port, say Y to this option. The driver can handle up to 2 serial
--- /dev/null
+From b39e659770cb71939765de8c9e73c0a0cfa832db Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 12 Apr 2013 06:27:37 +0000
+Subject: [PATCH 118/137] DT: MIPS: ralink: add RT2880 dts files
+
+Add a dtsi file for RT2880 SoC and a sample dts file.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Patchwork: http://patchwork.linux-mips.org/patch/5188/
+---
+ arch/mips/ralink/Kconfig | 4 +++
+ arch/mips/ralink/dts/Makefile | 1 +
+ arch/mips/ralink/dts/rt2880.dtsi | 58 ++++++++++++++++++++++++++++++++++
+ arch/mips/ralink/dts/rt2880_eval.dts | 46 +++++++++++++++++++++++++++
+ 4 files changed, 109 insertions(+)
+ create mode 100644 arch/mips/ralink/dts/rt2880.dtsi
+ create mode 100644 arch/mips/ralink/dts/rt2880_eval.dts
+
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -34,6 +34,10 @@ choice
+ config DTB_RT_NONE
+ bool "None"
+
++ config DTB_RT2880_EVAL
++ bool "RT2880 eval kit"
++ depends on SOC_RT288X
++
+ config DTB_RT305X_EVAL
+ bool "RT305x eval kit"
+ depends on SOC_RT305X
+--- a/arch/mips/ralink/dts/Makefile
++++ b/arch/mips/ralink/dts/Makefile
+@@ -1 +1,2 @@
++obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
+ obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
+--- /dev/null
++++ b/arch/mips/ralink/dts/rt2880.dtsi
+@@ -0,0 +1,58 @@
++/ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "ralink,rt2880-soc";
++
++ cpus {
++ cpu@0 {
++ compatible = "mips,mips4KEc";
++ };
++ };
++
++ cpuintc: cpuintc@0 {
++ #address-cells = <0>;
++ #interrupt-cells = <1>;
++ interrupt-controller;
++ compatible = "mti,cpu-interrupt-controller";
++ };
++
++ palmbus@300000 {
++ compatible = "palmbus";
++ reg = <0x300000 0x200000>;
++ ranges = <0x0 0x300000 0x1FFFFF>;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ sysc@0 {
++ compatible = "ralink,rt2880-sysc";
++ reg = <0x0 0x100>;
++ };
++
++ intc: intc@200 {
++ compatible = "ralink,rt2880-intc";
++ reg = <0x200 0x100>;
++
++ interrupt-controller;
++ #interrupt-cells = <1>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <2>;
++ };
++
++ memc@300 {
++ compatible = "ralink,rt2880-memc";
++ reg = <0x300 0x100>;
++ };
++
++ uartlite@c00 {
++ compatible = "ralink,rt2880-uart", "ns16550a";
++ reg = <0xc00 0x100>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <8>;
++
++ reg-shift = <2>;
++ };
++ };
++};
+--- /dev/null
++++ b/arch/mips/ralink/dts/rt2880_eval.dts
+@@ -0,0 +1,46 @@
++/dts-v1/;
++
++/include/ "rt2880.dtsi"
++
++/ {
++ compatible = "ralink,rt2880-eval-board", "ralink,rt2880-soc";
++ model = "Ralink RT2880 evaluation board";
++
++ memory@0 {
++ reg = <0x8000000 0x2000000>;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,57600";
++ };
++
++ cfi@1f000000 {
++ compatible = "cfi-flash";
++ reg = <0x1f000000 0x400000>;
++
++ bank-width = <2>;
++ device-width = <2>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "uboot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++ partition@30000 {
++ label = "uboot-env";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++ partition@40000 {
++ label = "calibration";
++ reg = <0x40000 0x10000>;
++ read-only;
++ };
++ partition@50000 {
++ label = "linux";
++ reg = <0x50000 0x3b0000>;
++ };
++ };
++};
+++ /dev/null
-From 028f340b63bf722e8807b31ef955484acf2cce47 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 18:27:29 +0100
-Subject: [PATCH 118/121] PCI: MIPS: adds rt2880 pci support
-
-Add support for the pci found on the rt2880 SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/pci/Makefile | 1 +
- arch/mips/pci/pci-rt2880.c | 281 ++++++++++++++++++++++++++++++++++++++++++++
- arch/mips/ralink/Kconfig | 1 +
- 3 files changed, 283 insertions(+)
- create mode 100644 arch/mips/pci/pci-rt2880.c
-
---- a/arch/mips/pci/Makefile
-+++ b/arch/mips/pci/Makefile
-@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1
- 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_RT2880) += pci-rt2880.o
- obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
- obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
- obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
---- /dev/null
-+++ b/arch/mips/pci/pci-rt2880.c
-@@ -0,0 +1,281 @@
-+/*
-+ * Ralink RT288x SoC PCI register definitions
-+ *
-+ * Copyright (C) 2009 John Crispin <blogic@openwrt.org>
-+ * Copyright (C) 2009 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/module.h>
-+#include <linux/of_platform.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+
-+#include <asm/mach-ralink/rt288x.h>
-+
-+#define RT2880_PCI_BASE 0x00440000
-+#define RT288X_CPU_IRQ_PCI 4
-+
-+#define RT2880_PCI_MEM_BASE 0x20000000
-+#define RT2880_PCI_MEM_SIZE 0x10000000
-+#define RT2880_PCI_IO_BASE 0x00460000
-+#define RT2880_PCI_IO_SIZE 0x00010000
-+
-+#define RT2880_PCI_REG_PCICFG_ADDR 0x00
-+#define RT2880_PCI_REG_PCIMSK_ADDR 0x0c
-+#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10
-+#define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18
-+#define RT2880_PCI_REG_CONFIG_ADDR 0x20
-+#define RT2880_PCI_REG_CONFIG_DATA 0x24
-+#define RT2880_PCI_REG_MEMBASE 0x28
-+#define RT2880_PCI_REG_IOBASE 0x2c
-+#define RT2880_PCI_REG_ID 0x30
-+#define RT2880_PCI_REG_CLASS 0x34
-+#define RT2880_PCI_REG_SUBID 0x38
-+#define RT2880_PCI_REG_ARBCTL 0x80
-+
-+static void __iomem *rt2880_pci_base;
-+static DEFINE_SPINLOCK(rt2880_pci_lock);
-+
-+static u32 rt2880_pci_reg_read(u32 reg)
-+{
-+ return readl(rt2880_pci_base + reg);
-+}
-+
-+static void rt2880_pci_reg_write(u32 val, u32 reg)
-+{
-+ writel(val, rt2880_pci_base + reg);
-+}
-+
-+static inline u32 rt2880_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 int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 *val)
-+{
-+ unsigned long flags;
-+ u32 address;
-+ u32 data;
-+
-+ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+ PCI_FUNC(devfn), where);
-+
-+ spin_lock_irqsave(&rt2880_pci_lock, flags);
-+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt2880_pci_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 rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 val)
-+{
-+ unsigned long flags;
-+ u32 address;
-+ u32 data;
-+
-+ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+ PCI_FUNC(devfn), where);
-+
-+ spin_lock_irqsave(&rt2880_pci_lock, flags);
-+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
-+
-+ 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;
-+ }
-+
-+ rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static struct pci_ops rt2880_pci_ops = {
-+ .read = rt2880_pci_config_read,
-+ .write = rt2880_pci_config_write,
-+};
-+
-+static struct resource rt2880_pci_mem_resource = {
-+ .name = "PCI MEM space",
-+ .start = RT2880_PCI_MEM_BASE,
-+ .end = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1,
-+ .flags = IORESOURCE_MEM,
-+};
-+
-+static struct resource rt2880_pci_io_resource = {
-+ .name = "PCI IO space",
-+ .start = RT2880_PCI_IO_BASE,
-+ .end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1,
-+ .flags = IORESOURCE_IO,
-+};
-+
-+static struct pci_controller rt2880_pci_controller = {
-+ .pci_ops = &rt2880_pci_ops,
-+ .mem_resource = &rt2880_pci_mem_resource,
-+ .io_resource = &rt2880_pci_io_resource,
-+};
-+
-+static inline u32 rt2880_pci_read_u32(unsigned long reg)
-+{
-+ unsigned long flags;
-+ u32 address;
-+ u32 ret;
-+
-+ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg);
-+
-+ spin_lock_irqsave(&rt2880_pci_lock, flags);
-+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+ ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+
-+ return ret;
-+}
-+
-+static inline void rt2880_pci_write_u32(unsigned long reg, u32 val)
-+{
-+ unsigned long flags;
-+ u32 address;
-+
-+ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg);
-+
-+ spin_lock_irqsave(&rt2880_pci_lock, flags);
-+ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+ rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+}
-+
-+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ u16 cmd;
-+ int irq = -1;
-+
-+ if (dev->bus->number != 0)
-+ return irq;
-+
-+ switch (PCI_SLOT(dev->devfn)) {
-+ case 0x00:
-+ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
-+ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
-+ break;
-+ case 0x11:
-+ irq = RT288X_CPU_IRQ_PCI;
-+ break;
-+ default:
-+ printk("%s:%s[%d] trying to alloc unknown pci irq\n",
-+ __FILE__, __func__, __LINE__);
-+ BUG();
-+ break;
-+ }
-+
-+ pci_write_config_byte((struct pci_dev*)dev, PCI_CACHE_LINE_SIZE, 0x14);
-+ pci_write_config_byte((struct pci_dev*)dev, PCI_LATENCY_TIMER, 0xFF);
-+ pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd);
-+ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK |
-+ PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY;
-+ pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd);
-+ pci_write_config_byte((struct pci_dev*)dev, PCI_INTERRUPT_LINE,
-+ dev->irq);
-+ return irq;
-+}
-+
-+static int rt288x_pci_probe(struct platform_device *pdev)
-+{
-+ void __iomem *io_map_base;
-+ int i;
-+
-+ rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE);
-+
-+ io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE);
-+ rt2880_pci_controller.io_map_base = (unsigned long) io_map_base;
-+ set_io_port_base((unsigned long) io_map_base);
-+
-+ ioport_resource.start = RT2880_PCI_IO_BASE;
-+ ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1;
-+
-+ rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR);
-+ for(i = 0; i < 0xfffff; i++) {}
-+
-+ rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL);
-+ rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR);
-+ rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE);
-+ rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE);
-+ rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR);
-+ rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID);
-+ rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS);
-+ rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID);
-+ rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR);
-+
-+ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
-+ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
-+
-+ register_pci_controller(&rt2880_pci_controller);
-+ return 0;
-+}
-+
-+int pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+ return 0;
-+}
-+
-+static const struct of_device_id rt288x_pci_match[] = {
-+ { .compatible = "ralink,rt288x-pci" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, rt288x_pci_match);
-+
-+static struct platform_driver rt288x_pci_driver = {
-+ .probe = rt288x_pci_probe,
-+ .driver = {
-+ .name = "rt288x-pci",
-+ .owner = THIS_MODULE,
-+ .of_match_table = rt288x_pci_match,
-+ },
-+};
-+
-+int __init pcibios_init(void)
-+{
-+ int ret = platform_driver_register(&rt288x_pci_driver);
-+ if (ret)
-+ pr_info("rt288x-pci: Error registering platform driver!");
-+ return ret;
-+}
-+
-+arch_initcall(pcibios_init);
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -8,6 +8,7 @@ choice
-
- config SOC_RT288X
- bool "RT288x"
-+ select HW_HAS_PCI
-
- config SOC_RT305X
- bool "RT305x"
--- /dev/null
+From 8b02459b5aa171dc8726698c4b19341a4e441bb8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 12 Apr 2013 06:27:39 +0000
+Subject: [PATCH 119/137] DT: MIPS: ralink: add RT3883 dts files
+
+Add a dtsi file for RT3883 SoC and a sample dts file.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Patchwork: http://patchwork.linux-mips.org/patch/5189/
+---
+ arch/mips/ralink/Kconfig | 4 +++
+ arch/mips/ralink/dts/Makefile | 1 +
+ arch/mips/ralink/dts/rt3883.dtsi | 58 ++++++++++++++++++++++++++++++++++
+ arch/mips/ralink/dts/rt3883_eval.dts | 16 ++++++++++
+ 4 files changed, 79 insertions(+)
+ create mode 100644 arch/mips/ralink/dts/rt3883.dtsi
+ create mode 100644 arch/mips/ralink/dts/rt3883_eval.dts
+
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -42,6 +42,10 @@ choice
+ bool "RT305x eval kit"
+ depends on SOC_RT305X
+
++ config DTB_RT3883_EVAL
++ bool "RT3883 eval kit"
++ depends on SOC_RT3883
++
+ endchoice
+
+ endif
+--- a/arch/mips/ralink/dts/Makefile
++++ b/arch/mips/ralink/dts/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
+ obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
++obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o
+--- /dev/null
++++ b/arch/mips/ralink/dts/rt3883.dtsi
+@@ -0,0 +1,58 @@
++/ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "ralink,rt3883-soc";
++
++ cpus {
++ cpu@0 {
++ compatible = "mips,mips74Kc";
++ };
++ };
++
++ cpuintc: cpuintc@0 {
++ #address-cells = <0>;
++ #interrupt-cells = <1>;
++ interrupt-controller;
++ compatible = "mti,cpu-interrupt-controller";
++ };
++
++ palmbus@10000000 {
++ compatible = "palmbus";
++ reg = <0x10000000 0x200000>;
++ ranges = <0x0 0x10000000 0x1FFFFF>;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ sysc@0 {
++ compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc";
++ reg = <0x0 0x100>;
++ };
++
++ intc: intc@200 {
++ compatible = "ralink,rt3883-intc", "ralink,rt2880-intc";
++ reg = <0x200 0x100>;
++
++ interrupt-controller;
++ #interrupt-cells = <1>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <2>;
++ };
++
++ memc@300 {
++ compatible = "ralink,rt3883-memc", "ralink,rt3050-memc";
++ reg = <0x300 0x100>;
++ };
++
++ uartlite@c00 {
++ compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a";
++ reg = <0xc00 0x100>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <12>;
++
++ reg-shift = <2>;
++ };
++ };
++};
+--- /dev/null
++++ b/arch/mips/ralink/dts/rt3883_eval.dts
+@@ -0,0 +1,16 @@
++/dts-v1/;
++
++/include/ "rt3883.dtsi"
++
++/ {
++ compatible = "ralink,rt3883-eval-board", "ralink,rt3883-soc";
++ model = "Ralink RT3883 evaluation board";
++
++ memory@0 {
++ reg = <0x0 0x2000000>;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,57600";
++ };
++};
+++ /dev/null
-From f01830fcc57273bd9ec5f6733ab3d28adeb71955 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 17:34:08 +0100
-Subject: [PATCH 119/121] PCI: MIPS: adds rt3883 pci support
-
-Add support for the pcie found on the rt3883 SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/pci/Makefile | 1 +
- arch/mips/pci/pci-rt3883.c | 487 ++++++++++++++++++++++++++++++++++++++++++++
- arch/mips/ralink/Kconfig | 1 +
- 3 files changed, 489 insertions(+)
- create mode 100644 arch/mips/pci/pci-rt3883.c
-
---- a/arch/mips/pci/Makefile
-+++ b/arch/mips/pci/Makefile
-@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops
- obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
- obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
- obj-$(CONFIG_SOC_RT2880) += pci-rt2880.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
---- /dev/null
-+++ b/arch/mips/pci/pci-rt3883.c
-@@ -0,0 +1,487 @@
-+/*
-+ * Ralink RT3883 SoC PCI support
-+ *
-+ * Copyright (C) 2011-2012 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 <asm/mach-ralink/rt3883.h>
-+#include <asm/mach-ralink/rt3883_regs.h>
-+
-+#define RT3883_MEMORY_BASE 0x00000000
-+#define RT3883_MEMORY_SIZE 0x02000000
-+
-+#define RT3883_PCI_MEM_BASE 0x20000000
-+#define RT3883_PCI_MEM_SIZE 0x10000000
-+#define RT3883_PCI_IO_BASE 0x10160000
-+#define RT3883_PCI_IO_SIZE 0x00010000
-+
-+#define RT3883_PCI_REG_PCICFG_ADDR 0x00
-+#define RT3883_PCI_REG_PCIRAW_ADDR 0x04
-+#define RT3883_PCI_REG_PCIINT_ADDR 0x08
-+#define RT3883_PCI_REG_PCIMSK_ADDR 0x0c
-+#define RT3833_PCI_PCIINT_PCIE BIT(20)
-+#define RT3833_PCI_PCIINT_PCI1 BIT(19)
-+#define RT3833_PCI_PCIINT_PCI0 BIT(18)
-+
-+#define RT3883_PCI_REG_CONFIG_ADDR 0x20
-+#define RT3883_PCI_REG_CONFIG_DATA 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_ADDR(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10)
-+#define RT3883_PCI_REG_IMBASEBAR0_ADDR(_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)
-+
-+static int (*rt3883_pci_plat_dev_init)(struct pci_dev *dev);
-+static void __iomem *rt3883_pci_base;
-+static DEFINE_SPINLOCK(rt3883_pci_lock);
-+
-+static inline u32 rt3883_pci_rr(unsigned reg)
-+{
-+ return readl(rt3883_pci_base + reg);
-+}
-+
-+static inline void rt3883_pci_wr(u32 val, unsigned reg)
-+{
-+ writel(val, rt3883_pci_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_u32(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(&rt3883_pci_lock, flags);
-+ rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-+ ret = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+
-+ return ret;
-+}
-+
-+static void rt3883_pci_write_u32(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(&rt3883_pci_lock, flags);
-+ rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-+ rt3883_pci_wr(val, RT3883_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+}
-+
-+static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
-+{
-+ u32 pending;
-+
-+ pending = rt3883_pci_rr(RT3883_PCI_REG_PCIINT_ADDR) &
-+ rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+
-+ if (!pending) {
-+ spurious_interrupt();
-+ return;
-+ }
-+
-+ if (pending & RT3833_PCI_PCIINT_PCI0)
-+ generic_handle_irq(RT3883_PCI_IRQ_PCI0);
-+
-+ if (pending & RT3833_PCI_PCIINT_PCI1)
-+ generic_handle_irq(RT3883_PCI_IRQ_PCI1);
-+
-+ if (pending & RT3833_PCI_PCIINT_PCIE)
-+ generic_handle_irq(RT3883_PCI_IRQ_PCIE);
-+}
-+
-+static void rt3883_pci_irq_unmask(struct irq_data *d)
-+{
-+ int irq = d->irq;
-+ u32 mask;
-+ u32 t;
-+
-+ switch (irq) {
-+ case RT3883_PCI_IRQ_PCI0:
-+ mask = RT3833_PCI_PCIINT_PCI0;
-+ break;
-+ case RT3883_PCI_IRQ_PCI1:
-+ mask = RT3833_PCI_PCIINT_PCI1;
-+ break;
-+ case RT3883_PCI_IRQ_PCIE:
-+ mask = RT3833_PCI_PCIINT_PCIE;
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ t = rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+ rt3883_pci_wr(t | mask, RT3883_PCI_REG_PCIMSK_ADDR);
-+ /* flush write */
-+ rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+}
-+
-+static void rt3883_pci_irq_mask(struct irq_data *d)
-+{
-+ int irq = d->irq;
-+ u32 mask;
-+ u32 t;
-+
-+ switch (irq) {
-+ case RT3883_PCI_IRQ_PCI0:
-+ mask = RT3833_PCI_PCIINT_PCI0;
-+ break;
-+ case RT3883_PCI_IRQ_PCI1:
-+ mask = RT3833_PCI_PCIINT_PCI1;
-+ break;
-+ case RT3883_PCI_IRQ_PCIE:
-+ mask = RT3833_PCI_PCIINT_PCIE;
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ t = rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+ rt3883_pci_wr(t & ~mask, RT3883_PCI_REG_PCIMSK_ADDR);
-+ /* flush write */
-+ rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+}
-+
-+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 void __init rt3883_pci_irq_init(void)
-+{
-+ int i;
-+
-+ /* disable all interrupts */
-+ rt3883_pci_wr(0, RT3883_PCI_REG_PCIMSK_ADDR);
-+
-+ for (i = RT3883_PCI_IRQ_BASE;
-+ i < RT3883_PCI_IRQ_BASE + RT3883_PCI_IRQ_COUNT; i++) {
-+ irq_set_chip_and_handler(i, &rt3883_pci_irq_chip,
-+ handle_level_irq);
-+ }
-+
-+ irq_set_chained_handler(RT3883_CPU_IRQ_PCI, rt3883_pci_irq_handler);
-+}
-+
-+static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn,
-+ int where, int size, u32 *val)
-+{
-+ unsigned long flags;
-+ u32 address;
-+ u32 data;
-+
-+ address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+ PCI_FUNC(devfn), where);
-+
-+ spin_lock_irqsave(&rt3883_pci_lock, flags);
-+ rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-+ data = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt3883_pci_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)
-+{
-+ unsigned long flags;
-+ u32 address;
-+ u32 data;
-+
-+ address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+ PCI_FUNC(devfn), where);
-+
-+ spin_lock_irqsave(&rt3883_pci_lock, flags);
-+ rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-+ data = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA);
-+
-+ 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_wr(data, RT3883_PCI_REG_CONFIG_DATA);
-+ spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static struct pci_ops rt3883_pci_ops = {
-+ .read = rt3883_pci_config_read,
-+ .write = rt3883_pci_config_write,
-+};
-+
-+static struct resource rt3883_pci_mem_resource = {
-+ .name = "PCI MEM space",
-+ .start = RT3883_PCI_MEM_BASE,
-+ .end = RT3883_PCI_MEM_BASE + RT3883_PCI_MEM_SIZE - 1,
-+ .flags = IORESOURCE_MEM,
-+};
-+
-+static struct resource rt3883_pci_io_resource = {
-+ .name = "PCI IO space",
-+ .start = RT3883_PCI_IO_BASE,
-+ .end = RT3883_PCI_IO_BASE + RT3883_PCI_IO_SIZE - 1,
-+ .flags = IORESOURCE_IO,
-+};
-+
-+static struct pci_controller rt3883_pci_controller = {
-+ .pci_ops = &rt3883_pci_ops,
-+ .mem_resource = &rt3883_pci_mem_resource,
-+ .io_resource = &rt3883_pci_io_resource,
-+};
-+
-+static void rt3883_pci_preinit(unsigned mode)
-+{
-+ u32 syscfg1;
-+ u32 rstctrl;
-+ u32 clkcfg1;
-+
-+ if (mode & RT3883_PCI_MODE_PCIE) {
-+ u32 val;
-+
-+ val = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1);
-+ val &= ~(0x30);
-+ val |= (2 << 4);
-+ rt3883_sysc_wr(val, RT3883_SYSC_REG_SYSCFG1);
-+
-+ val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+ val &= ~BIT(31);
-+ rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+
-+ val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+ val &= 0x80ffffff;
-+ rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+
-+ val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+ val |= 0xa << 24;
-+ rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+
-+ val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+ val |= BIT(31);
-+ rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+
-+ msleep(50);
-+ }
-+
-+ syscfg1 = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1);
-+ syscfg1 &= ~(RT3883_SYSCFG1_PCIE_RC_MODE |
-+ RT3883_SYSCFG1_PCI_HOST_MODE);
-+
-+ rstctrl = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL);
-+ rstctrl |= (RT3883_RSTCTRL_PCI | RT3883_RSTCTRL_PCIE);
-+
-+ clkcfg1 = rt3883_sysc_rr(RT3883_SYSC_REG_CLKCFG1);
-+ clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN |
-+ RT3883_CLKCFG1_PCIE_CLK_EN);
-+
-+ if (mode & RT3883_PCI_MODE_PCI) {
-+ syscfg1 |= RT3883_SYSCFG1_PCI_HOST_MODE;
-+ clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN;
-+ rstctrl &= ~RT3883_RSTCTRL_PCI;
-+ }
-+ if (mode & RT3883_PCI_MODE_PCIE) {
-+ syscfg1 |= RT3883_SYSCFG1_PCI_HOST_MODE |
-+ RT3883_SYSCFG1_PCIE_RC_MODE;
-+ clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN;
-+ rstctrl &= ~RT3883_RSTCTRL_PCIE;
-+ }
-+
-+ rt3883_sysc_wr(syscfg1, RT3883_SYSC_REG_SYSCFG1);
-+ rt3883_sysc_wr(rstctrl, RT3883_SYSC_REG_RSTCTRL);
-+ rt3883_sysc_wr(clkcfg1, RT3883_SYSC_REG_CLKCFG1);
-+
-+ msleep(500);
-+}
-+
-+static int rt3883_pcie_ready(void)
-+{
-+ u32 status;
-+
-+ msleep(500);
-+
-+ status = rt3883_pci_rr(RT3883_PCI_REG_STATUS(1));
-+ if (status & BIT(0))
-+ return 0;
-+
-+ /* TODO: reset PCIe and turn off PCIe clock */
-+
-+ return -ENODEV;
-+}
-+
-+void __init rt3883_pci_init(unsigned mode)
-+{
-+ u32 val;
-+ int err;
-+
-+ rt3883_pci_preinit(mode);
-+
-+ rt3883_pci_base = ioremap(RT3883_PCI_BASE, PAGE_SIZE);
-+ if (rt3883_pci_base == NULL) {
-+ pr_err("failed to ioremap PCI registers\n");
-+ return;
-+ }
-+
-+ rt3883_pci_wr(0, RT3883_PCI_REG_PCICFG_ADDR);
-+ if (mode & RT3883_PCI_MODE_PCI)
-+ rt3883_pci_wr(BIT(16), RT3883_PCI_REG_PCICFG_ADDR);
-+
-+ msleep(500);
-+
-+ if (mode & RT3883_PCI_MODE_PCIE) {
-+ err = rt3883_pcie_ready();
-+ if (err)
-+ return;
-+ }
-+
-+ if (mode & RT3883_PCI_MODE_PCI)
-+ rt3883_pci_wr(0x79, RT3883_PCI_REG_ARBCTL);
-+
-+ rt3883_pci_wr(RT3883_PCI_MEM_BASE, RT3883_PCI_REG_MEMBASE);
-+ rt3883_pci_wr(RT3883_PCI_IO_BASE, RT3883_PCI_REG_IOBASE);
-+
-+ /* PCI */
-+ rt3883_pci_wr(0x03ff0000, RT3883_PCI_REG_BAR0SETUP_ADDR(0));
-+ rt3883_pci_wr(RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0_ADDR(0));
-+ rt3883_pci_wr(0x08021814, RT3883_PCI_REG_ID(0));
-+ rt3883_pci_wr(0x00800001, RT3883_PCI_REG_CLASS(0));
-+ rt3883_pci_wr(0x28801814, RT3883_PCI_REG_SUBID(0));
-+
-+ /* PCIe */
-+ rt3883_pci_wr(0x01ff0000, RT3883_PCI_REG_BAR0SETUP_ADDR(1));
-+ rt3883_pci_wr(RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0_ADDR(1));
-+ rt3883_pci_wr(0x08021814, RT3883_PCI_REG_ID(1));
-+ rt3883_pci_wr(0x06040001, RT3883_PCI_REG_CLASS(1));
-+ rt3883_pci_wr(0x28801814, RT3883_PCI_REG_SUBID(1));
-+
-+ rt3883_pci_irq_init();
-+
-+ /* PCIe */
-+ val = rt3883_pci_read_u32(0, 0x01, 0, PCI_COMMAND);
-+ val |= 0x7;
-+ rt3883_pci_write_u32(0, 0x01, 0, PCI_COMMAND, val);
-+
-+ /* PCI */
-+ val = rt3883_pci_read_u32(0, 0x00, 0, PCI_COMMAND);
-+ val |= 0x7;
-+ rt3883_pci_write_u32(0, 0x00, 0, PCI_COMMAND, val);
-+
-+ ioport_resource.start = rt3883_pci_io_resource.start;
-+ ioport_resource.end = rt3883_pci_io_resource.end;
-+
-+ register_pci_controller(&rt3883_pci_controller);
-+}
-+
-+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ int irq = -1;
-+
-+ switch (dev->bus->number) {
-+ case 0:
-+ switch (PCI_SLOT(dev->devfn)) {
-+ case 0x00:
-+ rt3883_pci_wr(0x03ff0001,
-+ RT3883_PCI_REG_BAR0SETUP_ADDR(0));
-+ rt3883_pci_wr(0x03ff0001,
-+ RT3883_PCI_REG_BAR0SETUP_ADDR(1));
-+
-+ rt3883_pci_write_u32(0, 0x00, 0, PCI_BASE_ADDRESS_0,
-+ RT3883_MEMORY_BASE);
-+ rt3883_pci_read_u32(0, 0x00, 0, PCI_BASE_ADDRESS_0);
-+
-+ irq = RT3883_CPU_IRQ_PCI;
-+ break;
-+ case 0x01:
-+ rt3883_pci_write_u32(0, 0x01, 0, PCI_IO_BASE,
-+ 0x00000101);
-+ break;
-+ case 0x11:
-+ irq = RT3883_PCI_IRQ_PCI0;
-+ break;
-+ case 0x12:
-+ irq = RT3883_PCI_IRQ_PCI1;
-+ break;
-+ }
-+ break;
-+
-+ case 1:
-+ irq = RT3883_PCI_IRQ_PCIE;
-+ break;
-+
-+ default:
-+ dev_err(&dev->dev, "no IRQ specified\n");
-+ return irq;
-+ }
-+
-+ return irq;
-+}
-+
-+void __init rt3883_pci_set_plat_dev_init(int (*f)(struct pci_dev *dev))
-+{
-+ rt3883_pci_plat_dev_init = f;
-+}
-+
-+int pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+ if (rt3883_pci_plat_dev_init)
-+ return rt3883_pci_plat_dev_init(dev);
-+
-+ return 0;
-+}
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -20,6 +20,7 @@ choice
- bool "RT3883"
- select USB_ARCH_HAS_OHCI
- select USB_ARCH_HAS_EHCI
-+ select HW_HAS_PCI
-
- config SOC_MT7620
- bool "MT7620"
--- /dev/null
+From 07741f61fc94fad3c3d21fa1a2ad6f01455cc1dd Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 12 Apr 2013 06:27:41 +0000
+Subject: [PATCH 120/137] DT: MIPS: ralink: add MT7620A dts files
+
+Add a dtsi file for MT7620A SoC and a sample dts file.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Patchwork: http://patchwork.linux-mips.org/patch/5190/
+---
+ arch/mips/ralink/Kconfig | 4 +++
+ arch/mips/ralink/dts/Makefile | 1 +
+ arch/mips/ralink/dts/mt7620a.dtsi | 58 +++++++++++++++++++++++++++++++++
+ arch/mips/ralink/dts/mt7620a_eval.dts | 16 +++++++++
+ 4 files changed, 79 insertions(+)
+ create mode 100644 arch/mips/ralink/dts/mt7620a.dtsi
+ create mode 100644 arch/mips/ralink/dts/mt7620a_eval.dts
+
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -46,6 +46,10 @@ choice
+ bool "RT3883 eval kit"
+ depends on SOC_RT3883
+
++ config DTB_MT7620A_EVAL
++ bool "MT7620A eval kit"
++ depends on SOC_MT7620
++
+ endchoice
+
+ endif
+--- a/arch/mips/ralink/dts/Makefile
++++ b/arch/mips/ralink/dts/Makefile
+@@ -1,3 +1,4 @@
+ obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
+ obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
+ obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o
++obj-$(CONFIG_DTB_MT7620A_EVAL) := mt7620a_eval.dtb.o
+--- /dev/null
++++ b/arch/mips/ralink/dts/mt7620a.dtsi
+@@ -0,0 +1,58 @@
++/ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "ralink,mtk7620a-soc";
++
++ cpus {
++ cpu@0 {
++ compatible = "mips,mips24KEc";
++ };
++ };
++
++ cpuintc: cpuintc@0 {
++ #address-cells = <0>;
++ #interrupt-cells = <1>;
++ interrupt-controller;
++ compatible = "mti,cpu-interrupt-controller";
++ };
++
++ palmbus@10000000 {
++ compatible = "palmbus";
++ reg = <0x10000000 0x200000>;
++ ranges = <0x0 0x10000000 0x1FFFFF>;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ sysc@0 {
++ compatible = "ralink,mt7620a-sysc";
++ reg = <0x0 0x100>;
++ };
++
++ intc: intc@200 {
++ compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc";
++ reg = <0x200 0x100>;
++
++ interrupt-controller;
++ #interrupt-cells = <1>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <2>;
++ };
++
++ memc@300 {
++ compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc";
++ reg = <0x300 0x100>;
++ };
++
++ uartlite@c00 {
++ compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
++ reg = <0xc00 0x100>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <12>;
++
++ reg-shift = <2>;
++ };
++ };
++};
+--- /dev/null
++++ b/arch/mips/ralink/dts/mt7620a_eval.dts
+@@ -0,0 +1,16 @@
++/dts-v1/;
++
++/include/ "mt7620a.dtsi"
++
++/ {
++ compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc";
++ model = "Ralink MT7620A evaluation board";
++
++ memory@0 {
++ reg = <0x0 0x2000000>;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,57600";
++ };
++};
+++ /dev/null
-From 1c31c288bc1e853e3226ba593a13a0492b39c9e8 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 15 Mar 2013 19:07:05 +0100
-Subject: [PATCH 120/121] NET: MIPS: add ralink SoC ethernet driver
-
-Add support for Ralink FE and ESW.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- .../include/asm/mach-ralink/rt305x_esw_platform.h | 27 +
- arch/mips/ralink/rt305x.c | 1 +
- drivers/net/ethernet/Kconfig | 1 +
- drivers/net/ethernet/Makefile | 1 +
- drivers/net/ethernet/ramips/Kconfig | 18 +
- drivers/net/ethernet/ramips/Makefile | 9 +
- drivers/net/ethernet/ramips/ramips_debugfs.c | 127 ++
- drivers/net/ethernet/ramips/ramips_esw.c | 1220 +++++++++++++++++++
- drivers/net/ethernet/ramips/ramips_eth.h | 375 ++++++
- drivers/net/ethernet/ramips/ramips_main.c | 1285 ++++++++++++++++++++
- 10 files changed, 3064 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
- create mode 100644 drivers/net/ethernet/ramips/Kconfig
- create mode 100644 drivers/net/ethernet/ramips/Makefile
- create mode 100644 drivers/net/ethernet/ramips/ramips_debugfs.c
- create mode 100644 drivers/net/ethernet/ramips/ramips_esw.c
- create mode 100644 drivers/net/ethernet/ramips/ramips_eth.h
- create mode 100644 drivers/net/ethernet/ramips/ramips_main.c
-
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
-@@ -0,0 +1,27 @@
-+/*
-+ * Ralink RT305x SoC platform device registration
-+ *
-+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+
-+#ifndef _RT305X_ESW_PLATFORM_H
-+#define _RT305X_ESW_PLATFORM_H
-+
-+enum {
-+ RT305X_ESW_VLAN_CONFIG_NONE = 0,
-+ RT305X_ESW_VLAN_CONFIG_LLLLW,
-+ RT305X_ESW_VLAN_CONFIG_WLLLL,
-+};
-+
-+struct rt305x_esw_platform_data
-+{
-+ u8 vlan_config;
-+ u32 reg_initval_fct2;
-+ u32 reg_initval_fpa2;
-+};
-+
-+#endif /* _RT305X_ESW_PLATFORM_H */
---- a/arch/mips/ralink/rt305x.c
-+++ b/arch/mips/ralink/rt305x.c
-@@ -182,6 +182,7 @@ void __init ralink_clk_init(void)
- }
-
- ralink_clk_add("cpu", cpu_rate);
-+ ralink_clk_add("sys", sys_rate);
- ralink_clk_add("10000b00.spi", sys_rate);
- ralink_clk_add("10000100.timer", wdt_rate);
- ralink_clk_add("10000120.watchdog", wdt_rate);
---- a/drivers/net/ethernet/Kconfig
-+++ b/drivers/net/ethernet/Kconfig
-@@ -136,6 +136,7 @@ source "drivers/net/ethernet/packetengin
- source "drivers/net/ethernet/pasemi/Kconfig"
- source "drivers/net/ethernet/qlogic/Kconfig"
- source "drivers/net/ethernet/racal/Kconfig"
-+source "drivers/net/ethernet/ramips/Kconfig"
- source "drivers/net/ethernet/realtek/Kconfig"
- source "drivers/net/ethernet/renesas/Kconfig"
- source "drivers/net/ethernet/rdc/Kconfig"
---- a/drivers/net/ethernet/Makefile
-+++ b/drivers/net/ethernet/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_NET_PACKET_ENGINE) += packe
- obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
- obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
- obj-$(CONFIG_NET_VENDOR_RACAL) += racal/
-+obj-$(CONFIG_NET_RAMIPS) += ramips/
- obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
- obj-$(CONFIG_SH_ETH) += renesas/
- obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
---- /dev/null
-+++ b/drivers/net/ethernet/ramips/Kconfig
-@@ -0,0 +1,18 @@
-+config NET_RAMIPS
-+ tristate "Ralink RT288X/RT3X5X/RT3662/RT3883 ethernet driver"
-+ depends on RALINK
-+ select PHYLIB if (SOC_RT288X || SOC_RT3883)
-+ select SWCONFIG if SOC_RT305X
-+ help
-+ This driver supports the etehrnet mac inside the ralink wisocs
-+
-+if NET_RAMIPS
-+
-+config NET_RAMIPS_DEBUG
-+ bool "Enable debug messages in the Ralink ethernet driver"
-+
-+config NET_RAMIPS_DEBUG_FS
-+ bool "Enable debugfs support for the Ralink ethernet driver"
-+ depends on DEBUG_FS
-+
-+endif
---- /dev/null
-+++ b/drivers/net/ethernet/ramips/Makefile
-@@ -0,0 +1,9 @@
-+#
-+# Makefile for the Ramips SoCs built-in ethernet macs
-+#
-+
-+ramips-y += ramips_main.o
-+
-+ramips-$(CONFIG_NET_RAMIPS_DEBUG_FS) += ramips_debugfs.o
-+
-+obj-$(CONFIG_NET_RAMIPS) += ramips.o
---- /dev/null
-+++ b/drivers/net/ethernet/ramips/ramips_debugfs.c
-@@ -0,0 +1,127 @@
-+/*
-+ * Ralink SoC ethernet driver debugfs code
-+ *
-+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+
-+#include <linux/debugfs.h>
-+#include <linux/module.h>
-+#include <linux/phy.h>
-+
-+#include "ramips_eth.h"
-+
-+static struct dentry *raeth_debugfs_root;
-+
-+static int raeth_debugfs_generic_open(struct inode *inode, struct file *file)
-+{
-+ file->private_data = inode->i_private;
-+ return 0;
-+}
-+
-+void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status)
-+{
-+ re->debug.int_stats.total += !!status;
-+
-+ re->debug.int_stats.rx_delayed += !!(status & RAMIPS_RX_DLY_INT);
-+ re->debug.int_stats.rx_done0 += !!(status & RAMIPS_RX_DONE_INT0);
-+ re->debug.int_stats.rx_coherent += !!(status & RAMIPS_RX_COHERENT);
-+
-+ re->debug.int_stats.tx_delayed += !!(status & RAMIPS_TX_DLY_INT);
-+ re->debug.int_stats.tx_done0 += !!(status & RAMIPS_TX_DONE_INT0);
-+ re->debug.int_stats.tx_done1 += !!(status & RAMIPS_TX_DONE_INT1);
-+ re->debug.int_stats.tx_done2 += !!(status & RAMIPS_TX_DONE_INT2);
-+ re->debug.int_stats.tx_done3 += !!(status & RAMIPS_TX_DONE_INT3);
-+ re->debug.int_stats.tx_coherent += !!(status & RAMIPS_TX_COHERENT);
-+
-+ re->debug.int_stats.pse_fq_empty += !!(status & RAMIPS_PSE_FQ_EMPTY);
-+ re->debug.int_stats.pse_p0_fc += !!(status & RAMIPS_PSE_P0_FC);
-+ re->debug.int_stats.pse_p1_fc += !!(status & RAMIPS_PSE_P1_FC);
-+ re->debug.int_stats.pse_p2_fc += !!(status & RAMIPS_PSE_P2_FC);
-+ re->debug.int_stats.pse_buf_drop += !!(status & RAMIPS_PSE_BUF_DROP);
-+}
-+
-+static ssize_t read_file_int_stats(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+#define PR_INT_STAT(_label, _field) \
-+ len += snprintf(buf + len, sizeof(buf) - len, \
-+ "%-18s: %10lu\n", _label, re->debug.int_stats._field);
-+
-+ struct raeth_priv *re = file->private_data;
-+ char buf[512];
-+ unsigned int len = 0;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&re->page_lock, flags);
-+
-+ PR_INT_STAT("RX Delayed", rx_delayed);
-+ PR_INT_STAT("RX Done 0", rx_done0);
-+ PR_INT_STAT("RX Coherent", rx_coherent);
-+
-+ PR_INT_STAT("TX Delayed", tx_delayed);
-+ PR_INT_STAT("TX Done 0", tx_done0);
-+ PR_INT_STAT("TX Done 1", tx_done1);
-+ PR_INT_STAT("TX Done 2", tx_done2);
-+ PR_INT_STAT("TX Done 3", tx_done3);
-+ PR_INT_STAT("TX Coherent", tx_coherent);
-+
-+ PR_INT_STAT("PSE FQ empty", pse_fq_empty);
-+ PR_INT_STAT("CDMA Flow control", pse_p0_fc);
-+ PR_INT_STAT("GDMA1 Flow control", pse_p1_fc);
-+ PR_INT_STAT("GDMA2 Flow control", pse_p2_fc);
-+ PR_INT_STAT("PSE discard", pse_buf_drop);
-+
-+ len += snprintf(buf + len, sizeof(buf) - len, "\n");
-+ PR_INT_STAT("Total", total);
-+
-+ spin_unlock_irqrestore(&re->page_lock, flags);
-+
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+#undef PR_INT_STAT
-+}
-+
-+static const struct file_operations raeth_fops_int_stats = {
-+ .open = raeth_debugfs_generic_open,
-+ .read = read_file_int_stats,
-+ .owner = THIS_MODULE
-+};
-+
-+void raeth_debugfs_exit(struct raeth_priv *re)
-+{
-+ debugfs_remove_recursive(re->debug.debugfs_dir);
-+}
-+
-+int raeth_debugfs_init(struct raeth_priv *re)
-+{
-+ re->debug.debugfs_dir = debugfs_create_dir(re->netdev->name,
-+ raeth_debugfs_root);
-+ if (!re->debug.debugfs_dir)
-+ return -ENOMEM;
-+
-+ debugfs_create_file("int_stats", S_IRUGO, re->debug.debugfs_dir,
-+ re, &raeth_fops_int_stats);
-+
-+ return 0;
-+}
-+
-+int raeth_debugfs_root_init(void)
-+{
-+ if (raeth_debugfs_root)
-+ return -EBUSY;
-+
-+ raeth_debugfs_root = debugfs_create_dir("raeth", NULL);
-+ if (!raeth_debugfs_root)
-+ return -ENOENT;
-+
-+ return 0;
-+}
-+
-+void raeth_debugfs_root_exit(void)
-+{
-+ debugfs_remove(raeth_debugfs_root);
-+ raeth_debugfs_root = NULL;
-+}
---- /dev/null
-+++ b/drivers/net/ethernet/ramips/ramips_esw.c
-@@ -0,0 +1,1221 @@
-+#include <linux/ioport.h>
-+#include <linux/switch.h>
-+#include <linux/mii.h>
-+
-+#include <ralink_regs.h>
-+#include <rt305x.h>
-+#include <rt305x_esw_platform.h>
-+
-+/*
-+ * HW limitations for this switch:
-+ * - No large frame support (PKT_MAX_LEN at most 1536)
-+ * - Can't have untagged vlan and tagged vlan on one port at the same time,
-+ * though this might be possible using the undocumented PPE.
-+ */
-+
-+#define RT305X_ESW_REG_ISR 0x00
-+#define RT305X_ESW_REG_IMR 0x04
-+#define RT305X_ESW_REG_FCT0 0x08
-+#define RT305X_ESW_REG_PFC1 0x14
-+#define RT305X_ESW_REG_ATS 0x24
-+#define RT305X_ESW_REG_ATS0 0x28
-+#define RT305X_ESW_REG_ATS1 0x2c
-+#define RT305X_ESW_REG_ATS2 0x30
-+#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
-+#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
-+#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
-+#define RT305X_ESW_REG_POA 0x80
-+#define RT305X_ESW_REG_FPA 0x84
-+#define RT305X_ESW_REG_SOCPC 0x8c
-+#define RT305X_ESW_REG_POC0 0x90
-+#define RT305X_ESW_REG_POC1 0x94
-+#define RT305X_ESW_REG_POC2 0x98
-+#define RT305X_ESW_REG_SGC 0x9c
-+#define RT305X_ESW_REG_STRT 0xa0
-+#define RT305X_ESW_REG_PCR0 0xc0
-+#define RT305X_ESW_REG_PCR1 0xc4
-+#define RT305X_ESW_REG_FPA2 0xc8
-+#define RT305X_ESW_REG_FCT2 0xcc
-+#define RT305X_ESW_REG_SGC2 0xe4
-+#define RT305X_ESW_REG_P0LED 0xa4
-+#define RT305X_ESW_REG_P1LED 0xa8
-+#define RT305X_ESW_REG_P2LED 0xac
-+#define RT305X_ESW_REG_P3LED 0xb0
-+#define RT305X_ESW_REG_P4LED 0xb4
-+#define RT305X_ESW_REG_P0PC 0xe8
-+#define RT305X_ESW_REG_P1PC 0xec
-+#define RT305X_ESW_REG_P2PC 0xf0
-+#define RT305X_ESW_REG_P3PC 0xf4
-+#define RT305X_ESW_REG_P4PC 0xf8
-+#define RT305X_ESW_REG_P5PC 0xfc
-+
-+#define RT305X_ESW_LED_LINK 0
-+#define RT305X_ESW_LED_100M 1
-+#define RT305X_ESW_LED_DUPLEX 2
-+#define RT305X_ESW_LED_ACTIVITY 3
-+#define RT305X_ESW_LED_COLLISION 4
-+#define RT305X_ESW_LED_LINKACT 5
-+#define RT305X_ESW_LED_DUPLCOLL 6
-+#define RT305X_ESW_LED_10MACT 7
-+#define RT305X_ESW_LED_100MACT 8
-+/* Additional led states not in datasheet: */
-+#define RT305X_ESW_LED_BLINK 10
-+#define RT305X_ESW_LED_ON 12
-+
-+#define RT305X_ESW_LINK_S 25
-+#define RT305X_ESW_DUPLEX_S 9
-+#define RT305X_ESW_SPD_S 0
-+
-+#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
-+#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
-+#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
-+
-+#define RT305X_ESW_PCR1_WT_DONE BIT(0)
-+
-+#define RT305X_ESW_ATS_TIMEOUT (5 * HZ)
-+#define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
-+
-+#define RT305X_ESW_PVIDC_PVID_M 0xfff
-+#define RT305X_ESW_PVIDC_PVID_S 12
-+
-+#define RT305X_ESW_VLANI_VID_M 0xfff
-+#define RT305X_ESW_VLANI_VID_S 12
-+
-+#define RT305X_ESW_VMSC_MSC_M 0xff
-+#define RT305X_ESW_VMSC_MSC_S 8
-+
-+#define RT305X_ESW_SOCPC_DISUN2CPU_S 0
-+#define RT305X_ESW_SOCPC_DISMC2CPU_S 8
-+#define RT305X_ESW_SOCPC_DISBC2CPU_S 16
-+#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
-+
-+#define RT305X_ESW_POC0_EN_BP_S 0
-+#define RT305X_ESW_POC0_EN_FC_S 8
-+#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16
-+#define RT305X_ESW_POC0_DIS_PORT_M 0x7f
-+#define RT305X_ESW_POC0_DIS_PORT_S 23
-+
-+#define RT305X_ESW_POC2_UNTAG_EN_M 0xff
-+#define RT305X_ESW_POC2_UNTAG_EN_S 0
-+#define RT305X_ESW_POC2_ENAGING_S 8
-+#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
-+
-+#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f
-+#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0
-+#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f
-+#define RT305X_ESW_SGC2_LAN_PMAP_S 24
-+
-+#define RT305X_ESW_PFC1_EN_VLAN_M 0xff
-+#define RT305X_ESW_PFC1_EN_VLAN_S 16
-+#define RT305X_ESW_PFC1_EN_TOS_S 24
-+
-+#define RT305X_ESW_VLAN_NONE 0xfff
-+
-+#define RT305X_ESW_POA_LINK_MASK 0x1f
-+#define RT305X_ESW_POA_LINK_SHIFT 25
-+
-+#define RT305X_ESW_PORT_ST_CHG BIT(26)
-+#define RT305X_ESW_PORT0 0
-+#define RT305X_ESW_PORT1 1
-+#define RT305X_ESW_PORT2 2
-+#define RT305X_ESW_PORT3 3
-+#define RT305X_ESW_PORT4 4
-+#define RT305X_ESW_PORT5 5
-+#define RT305X_ESW_PORT6 6
-+
-+#define RT305X_ESW_PORTS_NONE 0
-+
-+#define RT305X_ESW_PMAP_LLLLLL 0x3f
-+#define RT305X_ESW_PMAP_LLLLWL 0x2f
-+#define RT305X_ESW_PMAP_WLLLLL 0x3e
-+
-+#define RT305X_ESW_PORTS_INTERNAL \
-+ (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
-+ BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
-+ BIT(RT305X_ESW_PORT4))
-+
-+#define RT305X_ESW_PORTS_NOCPU \
-+ (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
-+
-+#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
-+
-+#define RT305X_ESW_PORTS_ALL \
-+ (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
-+
-+#define RT305X_ESW_NUM_VLANS 16
-+#define RT305X_ESW_NUM_VIDS 4096
-+#define RT305X_ESW_NUM_PORTS 7
-+#define RT305X_ESW_NUM_LANWAN 6
-+#define RT305X_ESW_NUM_LEDS 5
-+
-+enum {
-+ /* Global attributes. */
-+ RT305X_ESW_ATTR_ENABLE_VLAN,
-+ RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
-+ /* Port attributes. */
-+ RT305X_ESW_ATTR_PORT_DISABLE,
-+ RT305X_ESW_ATTR_PORT_DOUBLETAG,
-+ RT305X_ESW_ATTR_PORT_UNTAG,
-+ RT305X_ESW_ATTR_PORT_LED,
-+ RT305X_ESW_ATTR_PORT_LAN,
-+ RT305X_ESW_ATTR_PORT_RECV_BAD,
-+ RT305X_ESW_ATTR_PORT_RECV_GOOD,
-+};
-+
-+struct rt305x_esw_port {
-+ bool disable;
-+ bool doubletag;
-+ bool untag;
-+ u8 led;
-+ u16 pvid;
-+};
-+
-+struct rt305x_esw_vlan {
-+ u8 ports;
-+ u16 vid;
-+};
-+
-+struct rt305x_esw {
-+ struct device *dev;
-+ void __iomem *base;
-+ int irq;
-+ const struct rt305x_esw_platform_data *pdata;
-+ /* Protects against concurrent register rmw operations. */
-+ spinlock_t reg_rw_lock;
-+
-+ unsigned char port_map;
-+ unsigned int reg_initval_fct2;
-+ unsigned int reg_initval_fpa2;
-+
-+
-+ struct switch_dev swdev;
-+ bool global_vlan_enable;
-+ bool alt_vlan_disable;
-+ struct rt305x_esw_vlan vlans[RT305X_ESW_NUM_VLANS];
-+ struct rt305x_esw_port ports[RT305X_ESW_NUM_PORTS];
-+
-+};
-+
-+static inline void
-+rt305x_esw_wr(struct rt305x_esw *esw, u32 val, unsigned reg)
-+{
-+ __raw_writel(val, esw->base + reg);
-+}
-+
-+static inline u32
-+rt305x_esw_rr(struct rt305x_esw *esw, unsigned reg)
-+{
-+ return __raw_readl(esw->base + reg);
-+}
-+
-+static inline void
-+rt305x_esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, unsigned long mask,
-+ unsigned long val)
-+{
-+ unsigned long t;
-+
-+ t = __raw_readl(esw->base + reg) & ~mask;
-+ __raw_writel(t | val, esw->base + reg);
-+}
-+
-+static void
-+rt305x_esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask,
-+ unsigned long val)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&esw->reg_rw_lock, flags);
-+ rt305x_esw_rmw_raw(esw, reg, mask, val);
-+ spin_unlock_irqrestore(&esw->reg_rw_lock, flags);
-+}
-+
-+static u32
-+rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register,
-+ u32 write_data)
-+{
-+ unsigned long t_start = jiffies;
-+ int ret = 0;
-+
-+ while (1) {
-+ if (!(rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) &
-+ RT305X_ESW_PCR1_WT_DONE))
-+ break;
-+ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
-+ ret = 1;
-+ goto out;
-+ }
-+ }
-+
-+ write_data &= 0xffff;
-+ rt305x_esw_wr(esw,
-+ (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) |
-+ (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) |
-+ (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD,
-+ RT305X_ESW_REG_PCR0);
-+
-+ t_start = jiffies;
-+ while (1) {
-+ if (rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) &
-+ RT305X_ESW_PCR1_WT_DONE)
-+ break;
-+
-+ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
-+ ret = 1;
-+ break;
-+ }
-+ }
-+out:
-+ if (ret)
-+ printk(KERN_ERR "ramips_eth: MDIO timeout\n");
-+ return ret;
-+}
-+
-+static unsigned
-+rt305x_esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan)
-+{
-+ unsigned s;
-+ unsigned val;
-+
-+ s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
-+ val = rt305x_esw_rr(esw, RT305X_ESW_REG_VLANI(vlan / 2));
-+ val = (val >> s) & RT305X_ESW_VLANI_VID_M;
-+
-+ return val;
-+}
-+
-+static void
-+rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid)
-+{
-+ unsigned s;
-+
-+ s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
-+ rt305x_esw_rmw(esw,
-+ RT305X_ESW_REG_VLANI(vlan / 2),
-+ RT305X_ESW_VLANI_VID_M << s,
-+ (vid & RT305X_ESW_VLANI_VID_M) << s);
-+}
-+
-+static unsigned
-+rt305x_esw_get_pvid(struct rt305x_esw *esw, unsigned port)
-+{
-+ unsigned s, val;
-+
-+ s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
-+ val = rt305x_esw_rr(esw, RT305X_ESW_REG_PVIDC(port / 2));
-+ return (val >> s) & RT305X_ESW_PVIDC_PVID_M;
-+}
-+
-+static void
-+rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid)
-+{
-+ unsigned s;
-+
-+ s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
-+ rt305x_esw_rmw(esw,
-+ RT305X_ESW_REG_PVIDC(port / 2),
-+ RT305X_ESW_PVIDC_PVID_M << s,
-+ (pvid & RT305X_ESW_PVIDC_PVID_M) << s);
-+}
-+
-+static unsigned
-+rt305x_esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan)
-+{
-+ unsigned s, val;
-+
-+ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
-+ val = rt305x_esw_rr(esw, RT305X_ESW_REG_VMSC(vlan / 4));
-+ val = (val >> s) & RT305X_ESW_VMSC_MSC_M;
-+
-+ return val;
-+}
-+
-+static void
-+rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
-+{
-+ unsigned s;
-+
-+ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
-+ rt305x_esw_rmw(esw,
-+ RT305X_ESW_REG_VMSC(vlan / 4),
-+ RT305X_ESW_VMSC_MSC_M << s,
-+ (msc & RT305X_ESW_VMSC_MSC_M) << s);
-+}
-+
-+static unsigned
-+rt305x_esw_get_port_disable(struct rt305x_esw *esw)
-+{
-+ unsigned reg;
-+ reg = rt305x_esw_rr(esw, RT305X_ESW_REG_POC0);
-+ return (reg >> RT305X_ESW_POC0_DIS_PORT_S) &
-+ RT305X_ESW_POC0_DIS_PORT_M;
-+}
-+
-+static void
-+rt305x_esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask)
-+{
-+ unsigned old_mask;
-+ unsigned enable_mask;
-+ unsigned changed;
-+ int i;
-+
-+ old_mask = rt305x_esw_get_port_disable(esw);
-+ changed = old_mask ^ disable_mask;
-+ enable_mask = old_mask & disable_mask;
-+
-+ /* enable before writing to MII */
-+ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
-+ (RT305X_ESW_POC0_DIS_PORT_M <<
-+ RT305X_ESW_POC0_DIS_PORT_S),
-+ enable_mask << RT305X_ESW_POC0_DIS_PORT_S);
-+
-+ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) {
-+ if (!(changed & (1 << i)))
-+ continue;
-+ if (disable_mask & (1 << i)) {
-+ /* disable */
-+ rt305x_mii_write(esw, i, MII_BMCR,
-+ BMCR_PDOWN);
-+ } else {
-+ /* enable */
-+ rt305x_mii_write(esw, i, MII_BMCR,
-+ BMCR_FULLDPLX |
-+ BMCR_ANENABLE |
-+ BMCR_ANRESTART |
-+ BMCR_SPEED100);
-+ }
-+ }
-+
-+ /* disable after writing to MII */
-+ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
-+ (RT305X_ESW_POC0_DIS_PORT_M <<
-+ RT305X_ESW_POC0_DIS_PORT_S),
-+ disable_mask << RT305X_ESW_POC0_DIS_PORT_S);
-+}
-+
-+static int
-+rt305x_esw_apply_config(struct switch_dev *dev);
-+
-+static void
-+rt305x_esw_hw_init(struct rt305x_esw *esw)
-+{
-+ int i;
-+ u8 port_disable = 0;
-+ u8 port_map = RT305X_ESW_PMAP_LLLLLL;
-+
-+ /* vodoo from original driver */
-+ rt305x_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
-+ rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2);
-+ /* Port priority 1 for all ports, vlan enabled. */
-+ rt305x_esw_wr(esw, 0x00005555 |
-+ (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S),
-+ RT305X_ESW_REG_PFC1);
-+
-+ /* Enable Back Pressure, and Flow Control */
-+ rt305x_esw_wr(esw,
-+ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) |
-+ (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)),
-+ RT305X_ESW_REG_POC0);
-+
-+ /* Enable Aging, and VLAN TAG removal */
-+ rt305x_esw_wr(esw,
-+ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) |
-+ (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)),
-+ RT305X_ESW_REG_POC2);
-+
-+ if (esw->reg_initval_fct2)
-+ rt305x_esw_wr(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2);
-+ else
-+ rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2);
-+
-+ /*
-+ * 300s aging timer, max packet len 1536, broadcast storm prevention
-+ * disabled, disable collision abort, mac xor48 hash, 10 packet back
-+ * pressure jam, GMII disable was_transmit, back pressure disabled,
-+ * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all
-+ * ports.
-+ */
-+ rt305x_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC);
-+
-+ /* Setup SoC Port control register */
-+ rt305x_esw_wr(esw,
-+ (RT305X_ESW_SOCPC_CRC_PADDING |
-+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) |
-+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) |
-+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)),
-+ RT305X_ESW_REG_SOCPC);
-+
-+ if (esw->reg_initval_fpa2)
-+ rt305x_esw_wr(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
-+ else
-+ rt305x_esw_wr(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
-+ rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_FPA);
-+
-+ /* Force Link/Activity on ports */
-+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P0LED);
-+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P1LED);
-+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P2LED);
-+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P3LED);
-+ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P4LED);
-+
-+ /* Copy disabled port configuration from bootloader setup */
-+ port_disable = rt305x_esw_get_port_disable(esw);
-+ for (i = 0; i < 6; i++)
-+ esw->ports[i].disable = (port_disable & (1 << i)) != 0;
-+
-+ rt305x_mii_write(esw, 0, 31, 0x8000);
-+ for (i = 0; i < 5; i++) {
-+ if (esw->ports[i].disable) {
-+ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
-+ } else {
-+ rt305x_mii_write(esw, i, MII_BMCR,
-+ BMCR_FULLDPLX |
-+ BMCR_ANENABLE |
-+ BMCR_SPEED100);
-+ }
-+ /* TX10 waveform coefficient */
-+ rt305x_mii_write(esw, i, 26, 0x1601);
-+ /* TX100/TX10 AD/DA current bias */
-+ rt305x_mii_write(esw, i, 29, 0x7058);
-+ /* TX100 slew rate control */
-+ rt305x_mii_write(esw, i, 30, 0x0018);
-+ }
-+
-+ /* PHY IOT */
-+ /* select global register */
-+ rt305x_mii_write(esw, 0, 31, 0x0);
-+ /* tune TP_IDL tail and head waveform */
-+ rt305x_mii_write(esw, 0, 22, 0x052f);
-+ /* set TX10 signal amplitude threshold to minimum */
-+ rt305x_mii_write(esw, 0, 17, 0x0fe0);
-+ /* set squelch amplitude to higher threshold */
-+ rt305x_mii_write(esw, 0, 18, 0x40ba);
-+ /* longer TP_IDL tail length */
-+ rt305x_mii_write(esw, 0, 14, 0x65);
-+ /* select local register */
-+ rt305x_mii_write(esw, 0, 31, 0x8000);
-+
-+ if (esw->port_map)
-+ port_map = esw->port_map;
-+ else
-+ port_map = RT305X_ESW_PMAP_LLLLLL;
-+
-+ /*
-+ * Unused HW feature, but still nice to be consistent here...
-+ * This is also exported to userspace ('lan' attribute) so it's
-+ * conveniently usable to decide which ports go into the wan vlan by
-+ * default.
-+ */
-+ rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
-+ RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S,
-+ port_map << RT305X_ESW_SGC2_LAN_PMAP_S);
-+
-+ /* make the switch leds blink */
-+ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++)
-+ esw->ports[i].led = 0x05;
-+
-+ /* Apply the empty config. */
-+ rt305x_esw_apply_config(&esw->swdev);
-+}
-+
-+static irqreturn_t
-+rt305x_esw_interrupt(int irq, void *_esw)
-+{
-+ struct rt305x_esw *esw = (struct rt305x_esw *) _esw;
-+ u32 status;
-+
-+ status = rt305x_esw_rr(esw, RT305X_ESW_REG_ISR);
-+ if (status & RT305X_ESW_PORT_ST_CHG) {
-+ u32 link = rt305x_esw_rr(esw, RT305X_ESW_REG_POA);
-+ link >>= RT305X_ESW_POA_LINK_SHIFT;
-+ link &= RT305X_ESW_POA_LINK_MASK;
-+ dev_info(esw->dev, "link changed 0x%02X\n", link);
-+ }
-+ rt305x_esw_wr(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static void
-+rt305x_esw_request_irq(struct rt305x_esw *esw)
-+{
-+ /* Only unmask the port change interrupt */
-+ rt305x_esw_wr(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
-+
-+ /* request the irq handler */
-+ request_irq(esw->irq, rt305x_esw_interrupt, 0, "esw", esw);
-+}
-+
-+static int
-+rt305x_esw_apply_config(struct switch_dev *dev)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int i;
-+ u8 disable = 0;
-+ u8 doubletag = 0;
-+ u8 en_vlan = 0;
-+ u8 untag = 0;
-+
-+ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
-+ u32 vid, vmsc;
-+ if (esw->global_vlan_enable) {
-+ vid = esw->vlans[i].vid;
-+ vmsc = esw->vlans[i].ports;
-+ } else {
-+ vid = RT305X_ESW_VLAN_NONE;
-+ vmsc = RT305X_ESW_PORTS_NONE;
-+ }
-+ rt305x_esw_set_vlan_id(esw, i, vid);
-+ rt305x_esw_set_vmsc(esw, i, vmsc);
-+ }
-+
-+ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
-+ u32 pvid;
-+ disable |= esw->ports[i].disable << i;
-+ if (esw->global_vlan_enable) {
-+ doubletag |= esw->ports[i].doubletag << i;
-+ en_vlan |= 1 << i;
-+ untag |= esw->ports[i].untag << i;
-+ pvid = esw->ports[i].pvid;
-+ } else {
-+ int x = esw->alt_vlan_disable ? 0 : 1;
-+ doubletag |= x << i;
-+ en_vlan |= x << i;
-+ untag |= x << i;
-+ pvid = 0;
-+ }
-+ rt305x_esw_set_pvid(esw, i, pvid);
-+ if (i < RT305X_ESW_NUM_LEDS)
-+ rt305x_esw_wr(esw, esw->ports[i].led,
-+ RT305X_ESW_REG_P0LED + 4*i);
-+ }
-+
-+ rt305x_esw_set_port_disable(esw, disable);
-+ rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
-+ (RT305X_ESW_SGC2_DOUBLE_TAG_M <<
-+ RT305X_ESW_SGC2_DOUBLE_TAG_S),
-+ doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S);
-+ rt305x_esw_rmw(esw, RT305X_ESW_REG_PFC1,
-+ RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S,
-+ en_vlan << RT305X_ESW_PFC1_EN_VLAN_S);
-+ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC2,
-+ RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S,
-+ untag << RT305X_ESW_POC2_UNTAG_EN_S);
-+
-+ if (!esw->global_vlan_enable) {
-+ /*
-+ * Still need to put all ports into vlan 0 or they'll be
-+ * isolated.
-+ * NOTE: vlan 0 is special, no vlan tag is prepended
-+ */
-+ rt305x_esw_set_vlan_id(esw, 0, 0);
-+ rt305x_esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL);
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_reset_switch(struct switch_dev *dev)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ esw->global_vlan_enable = 0;
-+ memset(esw->ports, 0, sizeof(esw->ports));
-+ memset(esw->vlans, 0, sizeof(esw->vlans));
-+ rt305x_esw_hw_init(esw);
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_vlan_enable(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+
-+ val->value.i = esw->global_vlan_enable;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_set_vlan_enable(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+
-+ esw->global_vlan_enable = val->value.i != 0;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_alt_vlan_disable(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+
-+ val->value.i = esw->alt_vlan_disable;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_set_alt_vlan_disable(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+
-+ esw->alt_vlan_disable = val->value.i != 0;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_port_link(struct switch_dev *dev,
-+ int port,
-+ struct switch_port_link *link)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ u32 speed, poa;
-+
-+ if (port < 0 || port >= RT305X_ESW_NUM_PORTS)
-+ return -EINVAL;
-+
-+ poa = rt305x_esw_rr(esw, RT305X_ESW_REG_POA) >> port;
-+
-+ link->link = (poa >> RT305X_ESW_LINK_S) & 1;
-+ link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1;
-+ if (port < RT305X_ESW_NUM_LEDS) {
-+ speed = (poa >> RT305X_ESW_SPD_S) & 1;
-+ } else {
-+ if (port == RT305X_ESW_NUM_PORTS - 1)
-+ poa >>= 1;
-+ speed = (poa >> RT305X_ESW_SPD_S) & 3;
-+ }
-+ switch (speed) {
-+ case 0:
-+ link->speed = SWITCH_PORT_SPEED_10;
-+ break;
-+ case 1:
-+ link->speed = SWITCH_PORT_SPEED_100;
-+ break;
-+ case 2:
-+ case 3: /* forced gige speed can be 2 or 3 */
-+ link->speed = SWITCH_PORT_SPEED_1000;
-+ break;
-+ default:
-+ link->speed = SWITCH_PORT_SPEED_UNKNOWN;
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_port_bool(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int idx = val->port_vlan;
-+ u32 x, reg, shift;
-+
-+ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS)
-+ return -EINVAL;
-+
-+ switch (attr->id) {
-+ case RT305X_ESW_ATTR_PORT_DISABLE:
-+ reg = RT305X_ESW_REG_POC0;
-+ shift = RT305X_ESW_POC0_DIS_PORT_S;
-+ break;
-+ case RT305X_ESW_ATTR_PORT_DOUBLETAG:
-+ reg = RT305X_ESW_REG_SGC2;
-+ shift = RT305X_ESW_SGC2_DOUBLE_TAG_S;
-+ break;
-+ case RT305X_ESW_ATTR_PORT_UNTAG:
-+ reg = RT305X_ESW_REG_POC2;
-+ shift = RT305X_ESW_POC2_UNTAG_EN_S;
-+ break;
-+ case RT305X_ESW_ATTR_PORT_LAN:
-+ reg = RT305X_ESW_REG_SGC2;
-+ shift = RT305X_ESW_SGC2_LAN_PMAP_S;
-+ if (idx >= RT305X_ESW_NUM_LANWAN)
-+ return -EINVAL;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ x = rt305x_esw_rr(esw, reg);
-+ val->value.i = (x >> (idx + shift)) & 1;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_set_port_bool(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int idx = val->port_vlan;
-+
-+ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
-+ val->value.i < 0 || val->value.i > 1)
-+ return -EINVAL;
-+
-+ switch (attr->id) {
-+ case RT305X_ESW_ATTR_PORT_DISABLE:
-+ esw->ports[idx].disable = val->value.i;
-+ break;
-+ case RT305X_ESW_ATTR_PORT_DOUBLETAG:
-+ esw->ports[idx].doubletag = val->value.i;
-+ break;
-+ case RT305X_ESW_ATTR_PORT_UNTAG:
-+ esw->ports[idx].untag = val->value.i;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_port_recv_badgood(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int idx = val->port_vlan;
-+ int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16;
-+ u32 reg;
-+
-+ if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN)
-+ return -EINVAL;
-+
-+ reg = rt305x_esw_rr(esw, RT305X_ESW_REG_P0PC + 4*idx);
-+ val->value.i = (reg >> shift) & 0xffff;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_port_led(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int idx = val->port_vlan;
-+
-+ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
-+ idx >= RT305X_ESW_NUM_LEDS)
-+ return -EINVAL;
-+
-+ val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0LED + 4*idx);
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_set_port_led(struct switch_dev *dev,
-+ const struct switch_attr *attr,
-+ struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int idx = val->port_vlan;
-+
-+ if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS)
-+ return -EINVAL;
-+
-+ esw->ports[idx].led = val->value.i;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_port_pvid(struct switch_dev *dev, int port, int *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+
-+ if (port >= RT305X_ESW_NUM_PORTS)
-+ return -EINVAL;
-+
-+ *val = rt305x_esw_get_pvid(esw, port);
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_set_port_pvid(struct switch_dev *dev, int port, int val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+
-+ if (port >= RT305X_ESW_NUM_PORTS)
-+ return -EINVAL;
-+
-+ esw->ports[port].pvid = val;
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ u32 vmsc, poc2;
-+ int vlan_idx = -1;
-+ int i;
-+
-+ val->len = 0;
-+
-+ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS)
-+ return -EINVAL;
-+
-+ /* valid vlan? */
-+ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
-+ if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan &&
-+ rt305x_esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) {
-+ vlan_idx = i;
-+ break;
-+ }
-+ }
-+
-+ if (vlan_idx == -1)
-+ return -EINVAL;
-+
-+ vmsc = rt305x_esw_get_vmsc(esw, vlan_idx);
-+ poc2 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC2);
-+
-+ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
-+ struct switch_port *p;
-+ int port_mask = 1 << i;
-+
-+ if (!(vmsc & port_mask))
-+ continue;
-+
-+ p = &val->value.ports[val->len++];
-+ p->id = i;
-+ if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S))
-+ p->flags = 0;
-+ else
-+ p->flags = 1 << SWITCH_PORT_FLAG_TAGGED;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+rt305x_esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
-+{
-+ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
-+ int ports;
-+ int vlan_idx = -1;
-+ int i;
-+
-+ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS ||
-+ val->len > RT305X_ESW_NUM_PORTS)
-+ return -EINVAL;
-+
-+ /* one of the already defined vlans? */
-+ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
-+ if (esw->vlans[i].vid == val->port_vlan &&
-+ esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) {
-+ vlan_idx = i;
-+ break;
-+ }
-+ }
-+
-+ /* select a free slot */
-+ for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) {
-+ if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE)
-+ vlan_idx = i;
-+ }
-+
-+ /* bail if all slots are in use */
-+ if (vlan_idx == -1)
-+ return -EINVAL;
-+
-+ ports = RT305X_ESW_PORTS_NONE;
-+ for (i = 0; i < val->len; i++) {
-+ struct switch_port *p = &val->value.ports[i];
-+ int port_mask = 1 << p->id;
-+ bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED));
-+
-+ if (p->id >= RT305X_ESW_NUM_PORTS)
-+ return -EINVAL;
-+
-+ ports |= port_mask;
-+ esw->ports[p->id].untag = untagged;
-+ }
-+ esw->vlans[vlan_idx].ports = ports;
-+ if (ports == RT305X_ESW_PORTS_NONE)
-+ esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE;
-+ else
-+ esw->vlans[vlan_idx].vid = val->port_vlan;
-+
-+ return 0;
-+}
-+
-+static const struct switch_attr rt305x_esw_global[] = {
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "enable_vlan",
-+ .description = "VLAN mode (1:enabled)",
-+ .max = 1,
-+ .id = RT305X_ESW_ATTR_ENABLE_VLAN,
-+ .get = rt305x_esw_get_vlan_enable,
-+ .set = rt305x_esw_set_vlan_enable,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "alternate_vlan_disable",
-+ .description = "Use en_vlan instead of doubletag to disable"
-+ " VLAN mode",
-+ .max = 1,
-+ .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
-+ .get = rt305x_esw_get_alt_vlan_disable,
-+ .set = rt305x_esw_set_alt_vlan_disable,
-+ },
-+};
-+
-+static const struct switch_attr rt305x_esw_port[] = {
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "disable",
-+ .description = "Port state (1:disabled)",
-+ .max = 1,
-+ .id = RT305X_ESW_ATTR_PORT_DISABLE,
-+ .get = rt305x_esw_get_port_bool,
-+ .set = rt305x_esw_set_port_bool,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "doubletag",
-+ .description = "Double tagging for incoming vlan packets "
-+ "(1:enabled)",
-+ .max = 1,
-+ .id = RT305X_ESW_ATTR_PORT_DOUBLETAG,
-+ .get = rt305x_esw_get_port_bool,
-+ .set = rt305x_esw_set_port_bool,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "untag",
-+ .description = "Untag (1:strip outgoing vlan tag)",
-+ .max = 1,
-+ .id = RT305X_ESW_ATTR_PORT_UNTAG,
-+ .get = rt305x_esw_get_port_bool,
-+ .set = rt305x_esw_set_port_bool,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "led",
-+ .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity,"
-+ " 4:collision, 5:linkact, 6:duplcoll, 7:10mact,"
-+ " 8:100mact, 10:blink, 12:on)",
-+ .max = 15,
-+ .id = RT305X_ESW_ATTR_PORT_LED,
-+ .get = rt305x_esw_get_port_led,
-+ .set = rt305x_esw_set_port_led,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "lan",
-+ .description = "HW port group (0:wan, 1:lan)",
-+ .max = 1,
-+ .id = RT305X_ESW_ATTR_PORT_LAN,
-+ .get = rt305x_esw_get_port_bool,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "recv_bad",
-+ .description = "Receive bad packet counter",
-+ .id = RT305X_ESW_ATTR_PORT_RECV_BAD,
-+ .get = rt305x_esw_get_port_recv_badgood,
-+ },
-+ {
-+ .type = SWITCH_TYPE_INT,
-+ .name = "recv_good",
-+ .description = "Receive good packet counter",
-+ .id = RT305X_ESW_ATTR_PORT_RECV_GOOD,
-+ .get = rt305x_esw_get_port_recv_badgood,
-+ },
-+};
-+
-+static const struct switch_attr rt305x_esw_vlan[] = {
-+};
-+
-+static const struct switch_dev_ops rt305x_esw_ops = {
-+ .attr_global = {
-+ .attr = rt305x_esw_global,
-+ .n_attr = ARRAY_SIZE(rt305x_esw_global),
-+ },
-+ .attr_port = {
-+ .attr = rt305x_esw_port,
-+ .n_attr = ARRAY_SIZE(rt305x_esw_port),
-+ },
-+ .attr_vlan = {
-+ .attr = rt305x_esw_vlan,
-+ .n_attr = ARRAY_SIZE(rt305x_esw_vlan),
-+ },
-+ .get_vlan_ports = rt305x_esw_get_vlan_ports,
-+ .set_vlan_ports = rt305x_esw_set_vlan_ports,
-+ .get_port_pvid = rt305x_esw_get_port_pvid,
-+ .set_port_pvid = rt305x_esw_set_port_pvid,
-+ .get_port_link = rt305x_esw_get_port_link,
-+ .apply_config = rt305x_esw_apply_config,
-+ .reset_switch = rt305x_esw_reset_switch,
-+};
-+
-+static struct rt305x_esw_platform_data rt3050_esw_data = {
-+ /* All ports are LAN ports. */
-+ .vlan_config = RT305X_ESW_VLAN_CONFIG_NONE,
-+ .reg_initval_fct2 = 0x00d6500c,
-+ /*
-+ * ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1,
-+ * turbo mii off, rgmi 3.3v off
-+ * port5: disabled
-+ * port6: enabled, gige, full-duplex, rx/tx-flow-control
-+ */
-+ .reg_initval_fpa2 = 0x3f502b28,
-+};
-+
-+static const struct of_device_id ralink_esw_match[] = {
-+ { .compatible = "ralink,rt3050-esw", .data = &rt3050_esw_data },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ralink_esw_match);
-+
-+static int
-+rt305x_esw_probe(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ const struct rt305x_esw_platform_data *pdata;
-+ const __be32 *port_map, *reg_init;
-+ struct rt305x_esw *esw;
-+ struct switch_dev *swdev;
-+ struct resource *res, *irq;
-+ int err;
-+
-+ pdata = pdev->dev.platform_data;
-+ if (!pdata) {
-+ const struct of_device_id *match;
-+ match = of_match_device(ralink_esw_match, &pdev->dev);
-+ if (match)
-+ pdata = (struct rt305x_esw_platform_data *) match->data;
-+ }
-+ if (!pdata)
-+ return -EINVAL;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "no memory resource found\n");
-+ return -ENOMEM;
-+ }
-+
-+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+ if (!irq) {
-+ dev_err(&pdev->dev, "no irq resource found\n");
-+ return -ENOMEM;
-+ }
-+
-+ esw = kzalloc(sizeof(struct rt305x_esw), GFP_KERNEL);
-+ if (!esw) {
-+ dev_err(&pdev->dev, "no memory for private data\n");
-+ return -ENOMEM;
-+ }
-+
-+ esw->dev = &pdev->dev;
-+ esw->irq = irq->start;
-+ esw->base = ioremap(res->start, resource_size(res));
-+ if (!esw->base) {
-+ dev_err(&pdev->dev, "ioremap failed\n");
-+ err = -ENOMEM;
-+ goto free_esw;
-+ }
-+
-+ port_map = of_get_property(np, "ralink,portmap", NULL);
-+ if (port_map)
-+ esw->port_map = be32_to_cpu(*port_map);
-+
-+ reg_init = of_get_property(np, "ralink,fct2", NULL);
-+ if (reg_init)
-+ esw->reg_initval_fct2 = be32_to_cpu(*reg_init);
-+
-+ reg_init = of_get_property(np, "ralink,fpa2", NULL);
-+ if (reg_init)
-+ esw->reg_initval_fpa2 = be32_to_cpu(*reg_init);
-+
-+ swdev = &esw->swdev;
-+ swdev->of_node = pdev->dev.of_node;
-+ swdev->name = "rt305x-esw";
-+ swdev->alias = "rt305x";
-+ swdev->cpu_port = RT305X_ESW_PORT6;
-+ swdev->ports = RT305X_ESW_NUM_PORTS;
-+ swdev->vlans = RT305X_ESW_NUM_VIDS;
-+ swdev->ops = &rt305x_esw_ops;
-+
-+ err = register_switch(swdev, NULL);
-+ if (err < 0) {
-+ dev_err(&pdev->dev, "register_switch failed\n");
-+ goto unmap_base;
-+ }
-+
-+ platform_set_drvdata(pdev, esw);
-+
-+ esw->pdata = pdata;
-+ spin_lock_init(&esw->reg_rw_lock);
-+ rt305x_esw_hw_init(esw);
-+ rt305x_esw_request_irq(esw);
-+
-+ return 0;
-+
-+unmap_base:
-+ iounmap(esw->base);
-+free_esw:
-+ kfree(esw);
-+ return err;
-+}
-+
-+static int
-+rt305x_esw_remove(struct platform_device *pdev)
-+{
-+ struct rt305x_esw *esw;
-+
-+ esw = platform_get_drvdata(pdev);
-+ if (esw) {
-+ unregister_switch(&esw->swdev);
-+ platform_set_drvdata(pdev, NULL);
-+ iounmap(esw->base);
-+ kfree(esw);
-+ }
-+
-+ return 0;
-+}
-+
-+static struct platform_driver rt305x_esw_driver = {
-+ .probe = rt305x_esw_probe,
-+ .remove = rt305x_esw_remove,
-+ .driver = {
-+ .name = "rt305x-esw",
-+ .owner = THIS_MODULE,
-+ .of_match_table = ralink_esw_match,
-+ },
-+};
-+
-+static int __init
-+rt305x_esw_init(void)
-+{
-+ return platform_driver_register(&rt305x_esw_driver);
-+}
-+
-+static void
-+rt305x_esw_exit(void)
-+{
-+ platform_driver_unregister(&rt305x_esw_driver);
-+}
---- /dev/null
-+++ b/drivers/net/ethernet/ramips/ramips_eth.h
-@@ -0,0 +1,375 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * based on Ralink SDK3.3
-+ * Copyright (C) 2009 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#ifndef RAMIPS_ETH_H
-+#define RAMIPS_ETH_H
-+
-+#include <linux/mii.h>
-+#include <linux/interrupt.h>
-+#include <linux/netdevice.h>
-+#include <linux/dma-mapping.h>
-+
-+#define NUM_RX_DESC 256
-+#define NUM_TX_DESC 256
-+
-+#define RAMIPS_DELAY_EN_INT 0x80
-+#define RAMIPS_DELAY_MAX_INT 0x04
-+#define RAMIPS_DELAY_MAX_TOUT 0x04
-+#define RAMIPS_DELAY_CHAN (((RAMIPS_DELAY_EN_INT | RAMIPS_DELAY_MAX_INT) << 8) | RAMIPS_DELAY_MAX_TOUT)
-+#define RAMIPS_DELAY_INIT ((RAMIPS_DELAY_CHAN << 16) | RAMIPS_DELAY_CHAN)
-+#define RAMIPS_PSE_FQFC_CFG_INIT 0x80504000
-+
-+/* interrupt bits */
-+#define RAMIPS_CNT_PPE_AF BIT(31)
-+#define RAMIPS_CNT_GDM_AF BIT(29)
-+#define RAMIPS_PSE_P2_FC BIT(26)
-+#define RAMIPS_PSE_BUF_DROP BIT(24)
-+#define RAMIPS_GDM_OTHER_DROP BIT(23)
-+#define RAMIPS_PSE_P1_FC BIT(22)
-+#define RAMIPS_PSE_P0_FC BIT(21)
-+#define RAMIPS_PSE_FQ_EMPTY BIT(20)
-+#define RAMIPS_GE1_STA_CHG BIT(18)
-+#define RAMIPS_TX_COHERENT BIT(17)
-+#define RAMIPS_RX_COHERENT BIT(16)
-+#define RAMIPS_TX_DONE_INT3 BIT(11)
-+#define RAMIPS_TX_DONE_INT2 BIT(10)
-+#define RAMIPS_TX_DONE_INT1 BIT(9)
-+#define RAMIPS_TX_DONE_INT0 BIT(8)
-+#define RAMIPS_RX_DONE_INT0 BIT(2)
-+#define RAMIPS_TX_DLY_INT BIT(1)
-+#define RAMIPS_RX_DLY_INT BIT(0)
-+
-+#define RT5350_RX_DLY_INT BIT(30)
-+#define RT5350_TX_DLY_INT BIT(28)
-+
-+/* registers */
-+#define RAMIPS_FE_OFFSET 0x0000
-+#define RAMIPS_GDMA_OFFSET 0x0020
-+#define RAMIPS_PSE_OFFSET 0x0040
-+#define RAMIPS_GDMA2_OFFSET 0x0060
-+#define RAMIPS_CDMA_OFFSET 0x0080
-+#define RAMIPS_PDMA_OFFSET 0x0100
-+#define RAMIPS_PPE_OFFSET 0x0200
-+#define RAMIPS_CMTABLE_OFFSET 0x0400
-+#define RAMIPS_POLICYTABLE_OFFSET 0x1000
-+
-+#define RT5350_PDMA_OFFSET 0x0800
-+#define RT5350_SDM_OFFSET 0x0c00
-+
-+#define RAMIPS_MDIO_ACCESS (RAMIPS_FE_OFFSET + 0x00)
-+#define RAMIPS_MDIO_CFG (RAMIPS_FE_OFFSET + 0x04)
-+#define RAMIPS_FE_GLO_CFG (RAMIPS_FE_OFFSET + 0x08)
-+#define RAMIPS_FE_RST_GL (RAMIPS_FE_OFFSET + 0x0C)
-+#define RAMIPS_FE_INT_STATUS (RAMIPS_FE_OFFSET + 0x10)
-+#define RAMIPS_FE_INT_ENABLE (RAMIPS_FE_OFFSET + 0x14)
-+#define RAMIPS_MDIO_CFG2 (RAMIPS_FE_OFFSET + 0x18)
-+#define RAMIPS_FOC_TS_T (RAMIPS_FE_OFFSET + 0x1C)
-+
-+#define RAMIPS_GDMA1_FWD_CFG (RAMIPS_GDMA_OFFSET + 0x00)
-+#define RAMIPS_GDMA1_SCH_CFG (RAMIPS_GDMA_OFFSET + 0x04)
-+#define RAMIPS_GDMA1_SHPR_CFG (RAMIPS_GDMA_OFFSET + 0x08)
-+#define RAMIPS_GDMA1_MAC_ADRL (RAMIPS_GDMA_OFFSET + 0x0C)
-+#define RAMIPS_GDMA1_MAC_ADRH (RAMIPS_GDMA_OFFSET + 0x10)
-+
-+#define RAMIPS_GDMA2_FWD_CFG (RAMIPS_GDMA2_OFFSET + 0x00)
-+#define RAMIPS_GDMA2_SCH_CFG (RAMIPS_GDMA2_OFFSET + 0x04)
-+#define RAMIPS_GDMA2_SHPR_CFG (RAMIPS_GDMA2_OFFSET + 0x08)
-+#define RAMIPS_GDMA2_MAC_ADRL (RAMIPS_GDMA2_OFFSET + 0x0C)
-+#define RAMIPS_GDMA2_MAC_ADRH (RAMIPS_GDMA2_OFFSET + 0x10)
-+
-+#define RAMIPS_PSE_FQ_CFG (RAMIPS_PSE_OFFSET + 0x00)
-+#define RAMIPS_CDMA_FC_CFG (RAMIPS_PSE_OFFSET + 0x04)
-+#define RAMIPS_GDMA1_FC_CFG (RAMIPS_PSE_OFFSET + 0x08)
-+#define RAMIPS_GDMA2_FC_CFG (RAMIPS_PSE_OFFSET + 0x0C)
-+
-+#define RAMIPS_CDMA_CSG_CFG (RAMIPS_CDMA_OFFSET + 0x00)
-+#define RAMIPS_CDMA_SCH_CFG (RAMIPS_CDMA_OFFSET + 0x04)
-+
-+#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00)
-+#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04)
-+#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08)
-+#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C)
-+#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10)
-+#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14)
-+#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18)
-+#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C)
-+#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20)
-+#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24)
-+#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28)
-+#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C)
-+#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30)
-+#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34)
-+#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38)
-+#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C)
-+#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100)
-+#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104)
-+#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108)
-+#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C)
-+#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110)
-+#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114)
-+#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118)
-+#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C)
-+#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204)
-+#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208)
-+#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c)
-+#define RT5350_FE_INT_STATUS (RT5350_PDMA_OFFSET + 0x220)
-+#define RT5350_FE_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228)
-+#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280)
-+
-+
-+#define RAMIPS_PDMA_GLO_CFG (RAMIPS_PDMA_OFFSET + 0x00)
-+#define RAMIPS_PDMA_RST_CFG (RAMIPS_PDMA_OFFSET + 0x04)
-+#define RAMIPS_PDMA_SCH_CFG (RAMIPS_PDMA_OFFSET + 0x08)
-+#define RAMIPS_DLY_INT_CFG (RAMIPS_PDMA_OFFSET + 0x0C)
-+#define RAMIPS_TX_BASE_PTR0 (RAMIPS_PDMA_OFFSET + 0x10)
-+#define RAMIPS_TX_MAX_CNT0 (RAMIPS_PDMA_OFFSET + 0x14)
-+#define RAMIPS_TX_CTX_IDX0 (RAMIPS_PDMA_OFFSET + 0x18)
-+#define RAMIPS_TX_DTX_IDX0 (RAMIPS_PDMA_OFFSET + 0x1C)
-+#define RAMIPS_TX_BASE_PTR1 (RAMIPS_PDMA_OFFSET + 0x20)
-+#define RAMIPS_TX_MAX_CNT1 (RAMIPS_PDMA_OFFSET + 0x24)
-+#define RAMIPS_TX_CTX_IDX1 (RAMIPS_PDMA_OFFSET + 0x28)
-+#define RAMIPS_TX_DTX_IDX1 (RAMIPS_PDMA_OFFSET + 0x2C)
-+#define RAMIPS_RX_BASE_PTR0 (RAMIPS_PDMA_OFFSET + 0x30)
-+#define RAMIPS_RX_MAX_CNT0 (RAMIPS_PDMA_OFFSET + 0x34)
-+#define RAMIPS_RX_CALC_IDX0 (RAMIPS_PDMA_OFFSET + 0x38)
-+#define RAMIPS_RX_DRX_IDX0 (RAMIPS_PDMA_OFFSET + 0x3C)
-+#define RAMIPS_TX_BASE_PTR2 (RAMIPS_PDMA_OFFSET + 0x40)
-+#define RAMIPS_TX_MAX_CNT2 (RAMIPS_PDMA_OFFSET + 0x44)
-+#define RAMIPS_TX_CTX_IDX2 (RAMIPS_PDMA_OFFSET + 0x48)
-+#define RAMIPS_TX_DTX_IDX2 (RAMIPS_PDMA_OFFSET + 0x4C)
-+#define RAMIPS_TX_BASE_PTR3 (RAMIPS_PDMA_OFFSET + 0x50)
-+#define RAMIPS_TX_MAX_CNT3 (RAMIPS_PDMA_OFFSET + 0x54)
-+#define RAMIPS_TX_CTX_IDX3 (RAMIPS_PDMA_OFFSET + 0x58)
-+#define RAMIPS_TX_DTX_IDX3 (RAMIPS_PDMA_OFFSET + 0x5C)
-+#define RAMIPS_RX_BASE_PTR1 (RAMIPS_PDMA_OFFSET + 0x60)
-+#define RAMIPS_RX_MAX_CNT1 (RAMIPS_PDMA_OFFSET + 0x64)
-+#define RAMIPS_RX_CALC_IDX1 (RAMIPS_PDMA_OFFSET + 0x68)
-+#define RAMIPS_RX_DRX_IDX1 (RAMIPS_PDMA_OFFSET + 0x6C)
-+
-+#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00) //Switch DMA configuration
-+#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04) //Switch DMA Rx Ring
-+#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08) //Switch DMA Tx Ring
-+#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C) //Switch MAC address LSB
-+#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10) //Switch MAC Address MSB
-+#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100) //Switch DMA Tx packet count
-+#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104) //Switch DMA Tx byte count
-+#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108) //Switch DMA rx packet count
-+#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C) //Switch DMA rx byte count
-+#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110) //Switch DMA rx checksum error count
-+
-+#define RT5350_SDM_ICS_EN BIT(16)
-+#define RT5350_SDM_TCS_EN BIT(17)
-+#define RT5350_SDM_UCS_EN BIT(18)
-+
-+
-+/* MDIO_CFG register bits */
-+#define RAMIPS_MDIO_CFG_AUTO_POLL_EN BIT(29)
-+#define RAMIPS_MDIO_CFG_GP1_BP_EN BIT(16)
-+#define RAMIPS_MDIO_CFG_GP1_FRC_EN BIT(15)
-+#define RAMIPS_MDIO_CFG_GP1_SPEED_10 (0 << 13)
-+#define RAMIPS_MDIO_CFG_GP1_SPEED_100 (1 << 13)
-+#define RAMIPS_MDIO_CFG_GP1_SPEED_1000 (2 << 13)
-+#define RAMIPS_MDIO_CFG_GP1_DUPLEX BIT(12)
-+#define RAMIPS_MDIO_CFG_GP1_FC_TX BIT(11)
-+#define RAMIPS_MDIO_CFG_GP1_FC_RX BIT(10)
-+#define RAMIPS_MDIO_CFG_GP1_LNK_DWN BIT(9)
-+#define RAMIPS_MDIO_CFG_GP1_AN_FAIL BIT(8)
-+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6)
-+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6)
-+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6)
-+#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6)
-+#define RAMIPS_MDIO_CFG_TURBO_MII_FREQ BIT(5)
-+#define RAMIPS_MDIO_CFG_TURBO_MII_MODE BIT(4)
-+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2)
-+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2)
-+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2)
-+#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2)
-+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_0 0
-+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 1
-+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_400 2
-+#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_INV 3
-+
-+/* uni-cast port */
-+#define RAMIPS_GDM1_ICS_EN BIT(22)
-+#define RAMIPS_GDM1_TCS_EN BIT(21)
-+#define RAMIPS_GDM1_UCS_EN BIT(20)
-+#define RAMIPS_GDM1_JMB_EN BIT(19)
-+#define RAMIPS_GDM1_STRPCRC BIT(16)
-+#define RAMIPS_GDM1_UFRC_P_CPU (0 << 12)
-+#define RAMIPS_GDM1_UFRC_P_GDMA1 (1 << 12)
-+#define RAMIPS_GDM1_UFRC_P_PPE (6 << 12)
-+
-+/* checksums */
-+#define RAMIPS_ICS_GEN_EN BIT(2)
-+#define RAMIPS_UCS_GEN_EN BIT(1)
-+#define RAMIPS_TCS_GEN_EN BIT(0)
-+
-+/* dma ring */
-+#define RAMIPS_PST_DRX_IDX0 BIT(16)
-+#define RAMIPS_PST_DTX_IDX3 BIT(3)
-+#define RAMIPS_PST_DTX_IDX2 BIT(2)
-+#define RAMIPS_PST_DTX_IDX1 BIT(1)
-+#define RAMIPS_PST_DTX_IDX0 BIT(0)
-+
-+#define RAMIPS_TX_WB_DDONE BIT(6)
-+#define RAMIPS_RX_DMA_BUSY BIT(3)
-+#define RAMIPS_TX_DMA_BUSY BIT(1)
-+#define RAMIPS_RX_DMA_EN BIT(2)
-+#define RAMIPS_TX_DMA_EN BIT(0)
-+
-+#define RAMIPS_PDMA_SIZE_4DWORDS (0 << 4)
-+#define RAMIPS_PDMA_SIZE_8DWORDS (1 << 4)
-+#define RAMIPS_PDMA_SIZE_16DWORDS (2 << 4)
-+
-+#define RAMIPS_US_CYC_CNT_MASK 0xff
-+#define RAMIPS_US_CYC_CNT_SHIFT 0x8
-+#define RAMIPS_US_CYC_CNT_DIVISOR 1000000
-+
-+#define RX_DMA_PLEN0(_x) (((_x) >> 16) & 0x3fff)
-+#define RX_DMA_LSO BIT(30)
-+#define RX_DMA_DONE BIT(31)
-+
-+struct ramips_rx_dma {
-+ unsigned int rxd1;
-+ unsigned int rxd2;
-+ unsigned int rxd3;
-+ unsigned int rxd4;
-+} __packed __aligned(4);
-+
-+#define TX_DMA_PLEN0_MASK ((0x3fff) << 16)
-+#define TX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16)
-+#define TX_DMA_LSO BIT(30)
-+#define TX_DMA_DONE BIT(31)
-+#define TX_DMA_QN(_x) ((_x) << 16)
-+#define TX_DMA_PN(_x) ((_x) << 24)
-+#define TX_DMA_QN_MASK TX_DMA_QN(0x7)
-+#define TX_DMA_PN_MASK TX_DMA_PN(0x7)
-+
-+struct ramips_tx_dma {
-+ unsigned int txd1;
-+ unsigned int txd2;
-+ unsigned int txd3;
-+ unsigned int txd4;
-+} __packed __aligned(4);
-+
-+struct raeth_tx_info {
-+ struct ramips_tx_dma *tx_desc;
-+ struct sk_buff *tx_skb;
-+};
-+
-+struct raeth_rx_info {
-+ struct ramips_rx_dma *rx_desc;
-+ struct sk_buff *rx_skb;
-+ dma_addr_t rx_dma;
-+ unsigned int pad;
-+};
-+
-+struct raeth_int_stats {
-+ unsigned long rx_delayed;
-+ unsigned long tx_delayed;
-+ unsigned long rx_done0;
-+ unsigned long tx_done0;
-+ unsigned long tx_done1;
-+ unsigned long tx_done2;
-+ unsigned long tx_done3;
-+ unsigned long rx_coherent;
-+ unsigned long tx_coherent;
-+
-+ unsigned long pse_fq_empty;
-+ unsigned long pse_p0_fc;
-+ unsigned long pse_p1_fc;
-+ unsigned long pse_p2_fc;
-+ unsigned long pse_buf_drop;
-+
-+ unsigned long total;
-+};
-+
-+struct raeth_debug {
-+ struct dentry *debugfs_dir;
-+
-+ struct raeth_int_stats int_stats;
-+};
-+
-+struct raeth_priv
-+{
-+ struct device_node *of_node;
-+
-+ struct raeth_rx_info *rx_info;
-+ dma_addr_t rx_desc_dma;
-+ struct tasklet_struct rx_tasklet;
-+ struct ramips_rx_dma *rx;
-+
-+ struct raeth_tx_info *tx_info;
-+ dma_addr_t tx_desc_dma;
-+ struct tasklet_struct tx_housekeeping_tasklet;
-+ struct ramips_tx_dma *tx;
-+
-+ unsigned int skb_free_idx;
-+
-+ spinlock_t page_lock;
-+ struct net_device *netdev;
-+ struct device *parent;
-+
-+ int link;
-+ int speed;
-+ int duplex;
-+ int tx_fc;
-+ int rx_fc;
-+
-+ struct mii_bus *mii_bus;
-+ int mii_irq[PHY_MAX_ADDR];
-+ struct phy_device *phy_dev;
-+ spinlock_t phy_lock;
-+ unsigned long sys_freq;
-+
-+ unsigned char mac[6];
-+ void (*reset_fe)(void);
-+ int min_pkt_len;
-+
-+ u32 phy_mask;
-+ phy_interface_t phy_if_mode;
-+
-+#ifdef CONFIG_NET_RAMIPS_DEBUG_FS
-+ struct raeth_debug debug;
-+#endif
-+};
-+
-+struct ramips_soc_data
-+{
-+ unsigned char mac[6];
-+ void (*reset_fe)(void);
-+ int min_pkt_len;
-+};
-+
-+
-+#ifdef CONFIG_NET_RAMIPS_DEBUG_FS
-+int raeth_debugfs_root_init(void);
-+void raeth_debugfs_root_exit(void);
-+int raeth_debugfs_init(struct raeth_priv *re);
-+void raeth_debugfs_exit(struct raeth_priv *re);
-+void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status);
-+#else
-+static inline int raeth_debugfs_root_init(void) { return 0; }
-+static inline void raeth_debugfs_root_exit(void) {}
-+static inline int raeth_debugfs_init(struct raeth_priv *re) { return 0; }
-+static inline void raeth_debugfs_exit(struct raeth_priv *re) {}
-+static inline void raeth_debugfs_update_int_stats(struct raeth_priv *re,
-+ u32 status) {}
-+#endif /* CONFIG_NET_RAMIPS_DEBUG_FS */
-+
-+#endif /* RAMIPS_ETH_H */
---- /dev/null
-+++ b/drivers/net/ethernet/ramips/ramips_main.c
-@@ -0,0 +1,1285 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; version 2 of the License
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * Copyright (C) 2009 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/init.h>
-+#include <linux/skbuff.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/platform_device.h>
-+#include <linux/phy.h>
-+#include <linux/of_device.h>
-+#include <linux/clk.h>
-+#include <linux/of_net.h>
-+
-+#include "ramips_eth.h"
-+
-+#define TX_TIMEOUT (20 * HZ / 100)
-+#define MAX_RX_LENGTH 1600
-+
-+#ifdef CONFIG_SOC_RT305X
-+#include <rt305x.h>
-+#include "ramips_esw.c"
-+#else
-+#include <asm/mach-ralink/ralink_regs.h>
-+static inline int rt305x_esw_init(void) { return 0; }
-+static inline void rt305x_esw_exit(void) { }
-+static inline int soc_is_rt5350(void) { return 0; }
-+#endif
-+
-+#define phys_to_bus(a) (a & 0x1FFFFFFF)
-+
-+#ifdef CONFIG_NET_RAMIPS_DEBUG
-+#define RADEBUG(fmt, args...) printk(KERN_DEBUG fmt, ## args)
-+#else
-+#define RADEBUG(fmt, args...) do {} while (0)
-+#endif
-+
-+#define RX_DLY_INT ((soc_is_rt5350())?(RT5350_RX_DLY_INT):(RAMIPS_RX_DLY_INT))
-+#define TX_DLY_INT ((soc_is_rt5350())?(RT5350_TX_DLY_INT):(RAMIPS_TX_DLY_INT))
-+
-+enum raeth_reg {
-+ RAETH_REG_PDMA_GLO_CFG = 0,
-+ RAETH_REG_PDMA_RST_CFG,
-+ RAETH_REG_DLY_INT_CFG,
-+ RAETH_REG_TX_BASE_PTR0,
-+ RAETH_REG_TX_MAX_CNT0,
-+ RAETH_REG_TX_CTX_IDX0,
-+ RAETH_REG_RX_BASE_PTR0,
-+ RAETH_REG_RX_MAX_CNT0,
-+ RAETH_REG_RX_CALC_IDX0,
-+ RAETH_REG_FE_INT_ENABLE,
-+ RAETH_REG_FE_INT_STATUS,
-+ RAETH_REG_COUNT
-+};
-+
-+static const u32 ramips_reg_table[RAETH_REG_COUNT] = {
-+ [RAETH_REG_PDMA_GLO_CFG] = RAMIPS_PDMA_GLO_CFG,
-+ [RAETH_REG_PDMA_RST_CFG] = RAMIPS_PDMA_RST_CFG,
-+ [RAETH_REG_DLY_INT_CFG] = RAMIPS_DLY_INT_CFG,
-+ [RAETH_REG_TX_BASE_PTR0] = RAMIPS_TX_BASE_PTR0,
-+ [RAETH_REG_TX_MAX_CNT0] = RAMIPS_TX_MAX_CNT0,
-+ [RAETH_REG_TX_CTX_IDX0] = RAMIPS_TX_CTX_IDX0,
-+ [RAETH_REG_RX_BASE_PTR0] = RAMIPS_RX_BASE_PTR0,
-+ [RAETH_REG_RX_MAX_CNT0] = RAMIPS_RX_MAX_CNT0,
-+ [RAETH_REG_RX_CALC_IDX0] = RAMIPS_RX_CALC_IDX0,
-+ [RAETH_REG_FE_INT_ENABLE] = RAMIPS_FE_INT_ENABLE,
-+ [RAETH_REG_FE_INT_STATUS] = RAMIPS_FE_INT_STATUS,
-+};
-+
-+static const u32 rt5350_reg_table[RAETH_REG_COUNT] = {
-+ [RAETH_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG,
-+ [RAETH_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG,
-+ [RAETH_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG,
-+ [RAETH_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0,
-+ [RAETH_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0,
-+ [RAETH_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0,
-+ [RAETH_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0,
-+ [RAETH_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0,
-+ [RAETH_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0,
-+ [RAETH_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE,
-+ [RAETH_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS,
-+};
-+
-+static struct net_device * ramips_dev;
-+static void __iomem *ramips_fe_base = 0;
-+
-+static inline u32 get_reg_offset(enum raeth_reg reg)
-+{
-+ const u32 *table;
-+
-+ if (soc_is_rt5350())
-+ table = rt5350_reg_table;
-+ else
-+ table = ramips_reg_table;
-+
-+ return table[reg];
-+}
-+
-+static inline void
-+ramips_fe_wr(u32 val, unsigned reg)
-+{
-+ __raw_writel(val, ramips_fe_base + reg);
-+}
-+
-+static inline u32
-+ramips_fe_rr(unsigned reg)
-+{
-+ return __raw_readl(ramips_fe_base + reg);
-+}
-+
-+static inline void
-+ramips_fe_twr(u32 val, enum raeth_reg reg)
-+{
-+ ramips_fe_wr(val, get_reg_offset(reg));
-+}
-+
-+static inline u32
-+ramips_fe_trr(enum raeth_reg reg)
-+{
-+ return ramips_fe_rr(get_reg_offset(reg));
-+}
-+
-+static inline void
-+ramips_fe_int_disable(u32 mask)
-+{
-+ ramips_fe_twr(ramips_fe_trr(RAETH_REG_FE_INT_ENABLE) & ~mask,
-+ RAETH_REG_FE_INT_ENABLE);
-+ /* flush write */
-+ ramips_fe_trr(RAETH_REG_FE_INT_ENABLE);
-+}
-+
-+static inline void
-+ramips_fe_int_enable(u32 mask)
-+{
-+ ramips_fe_twr(ramips_fe_trr(RAETH_REG_FE_INT_ENABLE) | mask,
-+ RAETH_REG_FE_INT_ENABLE);
-+ /* flush write */
-+ ramips_fe_trr(RAETH_REG_FE_INT_ENABLE);
-+}
-+
-+static inline void
-+ramips_hw_set_macaddr(unsigned char *mac)
-+{
-+ if (soc_is_rt5350()) {
-+ ramips_fe_wr((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH);
-+ ramips_fe_wr((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
-+ RT5350_SDM_MAC_ADRL);
-+ } else {
-+ ramips_fe_wr((mac[0] << 8) | mac[1], RAMIPS_GDMA1_MAC_ADRH);
-+ ramips_fe_wr((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
-+ RAMIPS_GDMA1_MAC_ADRL);
-+ }
-+}
-+
-+static struct sk_buff *
-+ramips_alloc_skb(struct raeth_priv *re)
-+{
-+ struct sk_buff *skb;
-+
-+ skb = netdev_alloc_skb(re->netdev, MAX_RX_LENGTH + NET_IP_ALIGN);
-+ if (!skb)
-+ return NULL;
-+
-+ skb_reserve(skb, NET_IP_ALIGN);
-+
-+ return skb;
-+}
-+
-+static void
-+ramips_ring_setup(struct raeth_priv *re)
-+{
-+ int len;
-+ int i;
-+
-+ memset(re->tx_info, 0, NUM_TX_DESC * sizeof(struct raeth_tx_info));
-+
-+ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma);
-+ memset(re->tx, 0, len);
-+
-+ for (i = 0; i < NUM_TX_DESC; i++) {
-+ struct raeth_tx_info *txi;
-+ struct ramips_tx_dma *txd;
-+
-+ txd = &re->tx[i];
-+ txd->txd4 = TX_DMA_QN(3) | TX_DMA_PN(1);
-+ txd->txd2 = TX_DMA_LSO | TX_DMA_DONE;
-+
-+ txi = &re->tx_info[i];
-+ txi->tx_desc = txd;
-+ if (txi->tx_skb != NULL) {
-+ netdev_warn(re->netdev,
-+ "dirty skb for TX desc %d\n", i);
-+ txi->tx_skb = NULL;
-+ }
-+ }
-+
-+ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma);
-+ memset(re->rx, 0, len);
-+
-+ for (i = 0; i < NUM_RX_DESC; i++) {
-+ struct raeth_rx_info *rxi;
-+ struct ramips_rx_dma *rxd;
-+ dma_addr_t dma_addr;
-+
-+ rxd = &re->rx[i];
-+ rxi = &re->rx_info[i];
-+ BUG_ON(rxi->rx_skb == NULL);
-+ dma_addr = dma_map_single(&re->netdev->dev, rxi->rx_skb->data,
-+ MAX_RX_LENGTH, DMA_FROM_DEVICE);
-+ rxi->rx_dma = dma_addr;
-+ rxi->rx_desc = rxd;
-+
-+ rxd->rxd1 = (unsigned int) dma_addr;
-+ rxd->rxd2 = RX_DMA_LSO;
-+ }
-+
-+ /* flush descriptors */
-+ wmb();
-+}
-+
-+static void
-+ramips_ring_cleanup(struct raeth_priv *re)
-+{
-+ int i;
-+
-+ for (i = 0; i < NUM_RX_DESC; i++) {
-+ struct raeth_rx_info *rxi;
-+
-+ rxi = &re->rx_info[i];
-+ if (rxi->rx_skb)
-+ dma_unmap_single(&re->netdev->dev, rxi->rx_dma,
-+ MAX_RX_LENGTH, DMA_FROM_DEVICE);
-+ }
-+
-+ for (i = 0; i < NUM_TX_DESC; i++) {
-+ struct raeth_tx_info *txi;
-+
-+ txi = &re->tx_info[i];
-+ if (txi->tx_skb) {
-+ dev_kfree_skb_any(txi->tx_skb);
-+ txi->tx_skb = NULL;
-+ }
-+ }
-+
-+ netdev_reset_queue(re->netdev);
-+}
-+
-+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT3883)
-+
-+#define RAMIPS_MDIO_RETRY 1000
-+
-+static unsigned char *ramips_speed_str(struct raeth_priv *re)
-+{
-+ switch (re->speed) {
-+ case SPEED_1000:
-+ return "1000";
-+ case SPEED_100:
-+ return "100";
-+ case SPEED_10:
-+ return "10";
-+ }
-+
-+ return "?";
-+}
-+
-+static void ramips_link_adjust(struct raeth_priv *re)
-+{
-+ u32 mdio_cfg;
-+
-+ if (!re->link) {
-+ netif_carrier_off(re->netdev);
-+ netdev_info(re->netdev, "link down\n");
-+ return;
-+ }
-+
-+ mdio_cfg = RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 |
-+ RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 |
-+ RAMIPS_MDIO_CFG_GP1_FRC_EN;
-+
-+ if (re->duplex == DUPLEX_FULL)
-+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_DUPLEX;
-+
-+ if (re->tx_fc)
-+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_FC_TX;
-+
-+ if (re->rx_fc)
-+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_FC_RX;
-+
-+ switch (re->speed) {
-+ case SPEED_10:
-+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_10;
-+ break;
-+ case SPEED_100:
-+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_100;
-+ break;
-+ case SPEED_1000:
-+ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_1000;
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ ramips_fe_wr(mdio_cfg, RAMIPS_MDIO_CFG);
-+
-+ netif_carrier_on(re->netdev);
-+ netdev_info(re->netdev, "link up (%sMbps/%s duplex)\n",
-+ ramips_speed_str(re),
-+ (DUPLEX_FULL == re->duplex) ? "Full" : "Half");
-+}
-+
-+static int
-+ramips_mdio_wait_ready(struct raeth_priv *re)
-+{
-+ int retries;
-+
-+ retries = RAMIPS_MDIO_RETRY;
-+ while (1) {
-+ u32 t;
-+
-+ t = ramips_fe_rr(RAMIPS_MDIO_ACCESS);
-+ if ((t & (0x1 << 31)) == 0)
-+ return 0;
-+
-+ if (retries-- == 0)
-+ break;
-+
-+ udelay(1);
-+ }
-+
-+ dev_err(re->parent, "MDIO operation timed out\n");
-+ return -ETIMEDOUT;
-+}
-+
-+static int
-+ramips_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
-+{
-+ struct raeth_priv *re = bus->priv;
-+ int err;
-+ u32 t;
-+
-+ err = ramips_mdio_wait_ready(re);
-+ if (err)
-+ return 0xffff;
-+
-+ t = (phy_addr << 24) | (phy_reg << 16);
-+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
-+ t |= (1 << 31);
-+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
-+
-+ err = ramips_mdio_wait_ready(re);
-+ if (err)
-+ return 0xffff;
-+
-+ RADEBUG("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
-+ phy_addr, phy_reg, ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff);
-+
-+ return ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff;
-+}
-+
-+static int
-+ramips_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
-+{
-+ struct raeth_priv *re = bus->priv;
-+ int err;
-+ u32 t;
-+
-+ RADEBUG("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
-+ phy_addr, phy_reg, ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff);
-+
-+ err = ramips_mdio_wait_ready(re);
-+ if (err)
-+ return err;
-+
-+ t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val;
-+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
-+ t |= (1 << 31);
-+ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
-+
-+ return ramips_mdio_wait_ready(re);
-+}
-+
-+static int
-+ramips_mdio_reset(struct mii_bus *bus)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+static int
-+ramips_mdio_init(struct raeth_priv *re)
-+{
-+ int err;
-+ int i;
-+
-+ re->mii_bus = mdiobus_alloc();
-+ if (re->mii_bus == NULL)
-+ return -ENOMEM;
-+
-+ re->mii_bus->name = "ramips_mdio";
-+ re->mii_bus->read = ramips_mdio_read;
-+ re->mii_bus->write = ramips_mdio_write;
-+ re->mii_bus->reset = ramips_mdio_reset;
-+ re->mii_bus->irq = re->mii_irq;
-+ re->mii_bus->priv = re;
-+ re->mii_bus->parent = re->parent;
-+
-+ snprintf(re->mii_bus->id, MII_BUS_ID_SIZE, "%s", "ramips_mdio");
-+ re->mii_bus->phy_mask = 0;
-+
-+ for (i = 0; i < PHY_MAX_ADDR; i++)
-+ re->mii_irq[i] = PHY_POLL;
-+
-+ err = mdiobus_register(re->mii_bus);
-+ if (err)
-+ goto err_free_bus;
-+
-+ return 0;
-+
-+err_free_bus:
-+ kfree(re->mii_bus);
-+ return err;
-+}
-+
-+static void
-+ramips_mdio_cleanup(struct raeth_priv *re)
-+{
-+ mdiobus_unregister(re->mii_bus);
-+ kfree(re->mii_bus);
-+}
-+
-+static void
-+ramips_phy_link_adjust(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+ struct phy_device *phydev = re->phy_dev;
-+ unsigned long flags;
-+ int status_change = 0;
-+
-+ spin_lock_irqsave(&re->phy_lock, flags);
-+
-+ if (phydev->link)
-+ if (re->duplex != phydev->duplex ||
-+ re->speed != phydev->speed)
-+ status_change = 1;
-+
-+ if (phydev->link != re->link)
-+ status_change = 1;
-+
-+ re->link = phydev->link;
-+ re->duplex = phydev->duplex;
-+ re->speed = phydev->speed;
-+
-+ if (status_change)
-+ ramips_link_adjust(re);
-+
-+ spin_unlock_irqrestore(&re->phy_lock, flags);
-+}
-+
-+static int
-+ramips_phy_connect_multi(struct raeth_priv *re)
-+{
-+ struct net_device *netdev = re->netdev;
-+ struct phy_device *phydev = NULL;
-+ int phy_addr;
-+ int ret = 0;
-+
-+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-+ if (!(re->phy_mask & (1 << phy_addr)))
-+ continue;
-+
-+ if (re->mii_bus->phy_map[phy_addr] == NULL)
-+ continue;
-+
-+ RADEBUG("%s: PHY found at %s, uid=%08x\n",
-+ netdev->name,
-+ dev_name(&re->mii_bus->phy_map[phy_addr]->dev),
-+ re->mii_bus->phy_map[phy_addr]->phy_id);
-+
-+ if (phydev == NULL)
-+ phydev = re->mii_bus->phy_map[phy_addr];
-+ }
-+
-+ if (!phydev) {
-+ netdev_err(netdev, "no PHY found with phy_mask=%08x\n",
-+ re->phy_mask);
-+ return -ENODEV;
-+ }
-+
-+ re->phy_dev = phy_connect(netdev, dev_name(&phydev->dev),
-+ ramips_phy_link_adjust, 0, re->phy_if_mode);
-+
-+ if (IS_ERR(re->phy_dev)) {
-+ netdev_err(netdev, "could not connect to PHY at %s\n",
-+ dev_name(&phydev->dev));
-+ return PTR_ERR(re->phy_dev);
-+ }
-+
-+ phydev->supported &= PHY_GBIT_FEATURES;
-+ phydev->advertising = phydev->supported;
-+
-+ RADEBUG("%s: connected to PHY at %s [uid=%08x, driver=%s]\n",
-+ netdev->name, dev_name(&phydev->dev),
-+ phydev->phy_id, phydev->drv->name);
-+
-+ re->link = 0;
-+ re->speed = 0;
-+ re->duplex = -1;
-+ re->rx_fc = 0;
-+ re->tx_fc = 0;
-+
-+ return ret;
-+}
-+
-+static int
-+ramips_phy_connect_fixed(struct raeth_priv *re)
-+{
-+ if (!re->speed) {
-+ const __be32 *link;
-+ int size;
-+
-+ link = of_get_property(re->of_node,
-+ "ralink,fixed-link", &size);
-+ if (!link || size != (4 * sizeof(*link)))
-+ return -ENOENT;
-+
-+ re->speed = be32_to_cpup(link++);
-+ re->duplex = be32_to_cpup(link++);
-+ re->tx_fc = be32_to_cpup(link++);
-+ re->rx_fc = be32_to_cpup(link++);
-+ }
-+
-+ switch (re->speed) {
-+ case SPEED_10:
-+ case SPEED_100:
-+ case SPEED_1000:
-+ break;
-+ default:
-+ netdev_err(re->netdev, "invalid speed specified\n");
-+ return -EINVAL;
-+ }
-+
-+ pr_info("%s: using fixed link parameters\n", re->netdev->name);
-+ return 0;
-+}
-+
-+static int
-+ramips_phy_connect(struct raeth_priv *re)
-+{
-+ const __be32 *mask;
-+
-+ mask = of_get_property(re->of_node, "ralink,phy-mask", NULL);
-+ re->phy_if_mode = of_get_phy_mode(re->of_node);
-+
-+ if (!re->phy_if_mode || !mask)
-+ return ramips_phy_connect_fixed(re);
-+
-+ re->phy_mask = be32_to_cpup(mask);
-+ return ramips_phy_connect_multi(re);
-+
-+}
-+
-+static void
-+ramips_phy_disconnect(struct raeth_priv *re)
-+{
-+ if (re->phy_dev)
-+ phy_disconnect(re->phy_dev);
-+}
-+
-+static void
-+ramips_phy_start(struct raeth_priv *re)
-+{
-+ unsigned long flags;
-+
-+ if (re->phy_dev) {
-+ phy_start(re->phy_dev);
-+ } else {
-+ spin_lock_irqsave(&re->phy_lock, flags);
-+ re->link = 1;
-+ ramips_link_adjust(re);
-+ spin_unlock_irqrestore(&re->phy_lock, flags);
-+ }
-+}
-+
-+static void
-+ramips_phy_stop(struct raeth_priv *re)
-+{
-+ unsigned long flags;
-+
-+ if (re->phy_dev)
-+ phy_stop(re->phy_dev);
-+
-+ spin_lock_irqsave(&re->phy_lock, flags);
-+ re->link = 0;
-+ ramips_link_adjust(re);
-+ spin_unlock_irqrestore(&re->phy_lock, flags);
-+}
-+#else
-+static inline int
-+ramips_mdio_init(struct raeth_priv *re)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+ramips_mdio_cleanup(struct raeth_priv *re)
-+{
-+}
-+
-+static inline int
-+ramips_phy_connect(struct raeth_priv *re)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+ramips_phy_disconnect(struct raeth_priv *re)
-+{
-+}
-+
-+static inline void
-+ramips_phy_start(struct raeth_priv *re)
-+{
-+}
-+
-+static inline void
-+ramips_phy_stop(struct raeth_priv *re)
-+{
-+}
-+#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT3883 */
-+
-+static void
-+ramips_ring_free(struct raeth_priv *re)
-+{
-+ int len;
-+ int i;
-+
-+ if (re->rx_info) {
-+ for (i = 0; i < NUM_RX_DESC; i++) {
-+ struct raeth_rx_info *rxi;
-+
-+ rxi = &re->rx_info[i];
-+ if (rxi->rx_skb)
-+ dev_kfree_skb_any(rxi->rx_skb);
-+ }
-+ kfree(re->rx_info);
-+ }
-+
-+ if (re->rx) {
-+ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma);
-+ dma_free_coherent(&re->netdev->dev, len, re->rx,
-+ re->rx_desc_dma);
-+ }
-+
-+ if (re->tx) {
-+ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma);
-+ dma_free_coherent(&re->netdev->dev, len, re->tx,
-+ re->tx_desc_dma);
-+ }
-+
-+ kfree(re->tx_info);
-+}
-+
-+static int
-+ramips_ring_alloc(struct raeth_priv *re)
-+{
-+ int len;
-+ int err = -ENOMEM;
-+ int i;
-+
-+ re->tx_info = kzalloc(NUM_TX_DESC * sizeof(struct raeth_tx_info),
-+ GFP_ATOMIC);
-+ if (!re->tx_info)
-+ goto err_cleanup;
-+
-+ re->rx_info = kzalloc(NUM_RX_DESC * sizeof(struct raeth_rx_info),
-+ GFP_ATOMIC);
-+ if (!re->rx_info)
-+ goto err_cleanup;
-+
-+ /* allocate tx ring */
-+ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma);
-+ re->tx = dma_alloc_coherent(&re->netdev->dev, len,
-+ &re->tx_desc_dma, GFP_ATOMIC);
-+ if (!re->tx)
-+ goto err_cleanup;
-+
-+ /* allocate rx ring */
-+ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma);
-+ re->rx = dma_alloc_coherent(&re->netdev->dev, len,
-+ &re->rx_desc_dma, GFP_ATOMIC);
-+ if (!re->rx)
-+ goto err_cleanup;
-+
-+ for (i = 0; i < NUM_RX_DESC; i++) {
-+ struct sk_buff *skb;
-+
-+ skb = ramips_alloc_skb(re);
-+ if (!skb)
-+ goto err_cleanup;
-+
-+ re->rx_info[i].rx_skb = skb;
-+ }
-+
-+ return 0;
-+
-+err_cleanup:
-+ ramips_ring_free(re);
-+ return err;
-+}
-+
-+static void
-+ramips_setup_dma(struct raeth_priv *re)
-+{
-+ ramips_fe_twr(re->tx_desc_dma, RAETH_REG_TX_BASE_PTR0);
-+ ramips_fe_twr(NUM_TX_DESC, RAETH_REG_TX_MAX_CNT0);
-+ ramips_fe_twr(0, RAETH_REG_TX_CTX_IDX0);
-+ ramips_fe_twr(RAMIPS_PST_DTX_IDX0, RAETH_REG_PDMA_RST_CFG);
-+
-+ ramips_fe_twr(re->rx_desc_dma, RAETH_REG_RX_BASE_PTR0);
-+ ramips_fe_twr(NUM_RX_DESC, RAETH_REG_RX_MAX_CNT0);
-+ ramips_fe_twr((NUM_RX_DESC - 1), RAETH_REG_RX_CALC_IDX0);
-+ ramips_fe_twr(RAMIPS_PST_DRX_IDX0, RAETH_REG_PDMA_RST_CFG);
-+}
-+
-+static int
-+ramips_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+ struct raeth_tx_info *txi, *txi_next;
-+ struct ramips_tx_dma *txd, *txd_next;
-+ unsigned long tx;
-+ unsigned int tx_next;
-+ dma_addr_t mapped_addr;
-+
-+ if (re->min_pkt_len) {
-+ if (skb->len < re->min_pkt_len) {
-+ if (skb_padto(skb, re->min_pkt_len)) {
-+ printk(KERN_ERR
-+ "ramips_eth: skb_padto failed\n");
-+ kfree_skb(skb);
-+ return 0;
-+ }
-+ skb_put(skb, re->min_pkt_len - skb->len);
-+ }
-+ }
-+
-+ dev->trans_start = jiffies;
-+ mapped_addr = dma_map_single(&re->netdev->dev, skb->data, skb->len,
-+ DMA_TO_DEVICE);
-+
-+ spin_lock(&re->page_lock);
-+ tx = ramips_fe_trr(RAETH_REG_TX_CTX_IDX0);
-+ tx_next = (tx + 1) % NUM_TX_DESC;
-+
-+ txi = &re->tx_info[tx];
-+ txd = txi->tx_desc;
-+ txi_next = &re->tx_info[tx_next];
-+ txd_next = txi_next->tx_desc;
-+
-+ if ((txi->tx_skb) || (txi_next->tx_skb) ||
-+ !(txd->txd2 & TX_DMA_DONE) ||
-+ !(txd_next->txd2 & TX_DMA_DONE))
-+ goto out;
-+
-+ txi->tx_skb = skb;
-+
-+ txd->txd1 = (unsigned int) mapped_addr;
-+ wmb();
-+ txd->txd2 = TX_DMA_LSO | TX_DMA_PLEN0(skb->len);
-+ dev->stats.tx_packets++;
-+ dev->stats.tx_bytes += skb->len;
-+ ramips_fe_twr(tx_next, RAETH_REG_TX_CTX_IDX0);
-+ netdev_sent_queue(dev, skb->len);
-+ spin_unlock(&re->page_lock);
-+ return NETDEV_TX_OK;
-+
-+ out:
-+ spin_unlock(&re->page_lock);
-+ dev->stats.tx_dropped++;
-+ kfree_skb(skb);
-+ return NETDEV_TX_OK;
-+}
-+
-+static void
-+ramips_eth_rx_hw(unsigned long ptr)
-+{
-+ struct net_device *dev = (struct net_device *) ptr;
-+ struct raeth_priv *re = netdev_priv(dev);
-+ int rx;
-+ int max_rx = 16;
-+
-+ rx = ramips_fe_trr(RAETH_REG_RX_CALC_IDX0);
-+
-+ while (max_rx) {
-+ struct raeth_rx_info *rxi;
-+ struct ramips_rx_dma *rxd;
-+ struct sk_buff *rx_skb, *new_skb;
-+ int pktlen;
-+
-+ rx = (rx + 1) % NUM_RX_DESC;
-+
-+ rxi = &re->rx_info[rx];
-+ rxd = rxi->rx_desc;
-+ if (!(rxd->rxd2 & RX_DMA_DONE))
-+ break;
-+
-+ rx_skb = rxi->rx_skb;
-+ pktlen = RX_DMA_PLEN0(rxd->rxd2);
-+
-+ new_skb = ramips_alloc_skb(re);
-+ /* Reuse the buffer on allocation failures */
-+ if (new_skb) {
-+ dma_addr_t dma_addr;
-+
-+ dma_unmap_single(&re->netdev->dev, rxi->rx_dma,
-+ MAX_RX_LENGTH, DMA_FROM_DEVICE);
-+
-+ skb_put(rx_skb, pktlen);
-+ rx_skb->dev = dev;
-+ rx_skb->protocol = eth_type_trans(rx_skb, dev);
-+ rx_skb->ip_summed = CHECKSUM_NONE;
-+ dev->stats.rx_packets++;
-+ dev->stats.rx_bytes += pktlen;
-+ netif_rx(rx_skb);
-+
-+ rxi->rx_skb = new_skb;
-+
-+ dma_addr = dma_map_single(&re->netdev->dev,
-+ new_skb->data,
-+ MAX_RX_LENGTH,
-+ DMA_FROM_DEVICE);
-+ rxi->rx_dma = dma_addr;
-+ rxd->rxd1 = (unsigned int) dma_addr;
-+ wmb();
-+ } else {
-+ dev->stats.rx_dropped++;
-+ }
-+
-+ rxd->rxd2 = RX_DMA_LSO;
-+ ramips_fe_twr(rx, RAETH_REG_RX_CALC_IDX0);
-+ max_rx--;
-+ }
-+
-+ if (max_rx == 0)
-+ tasklet_schedule(&re->rx_tasklet);
-+ else
-+ ramips_fe_int_enable(RX_DLY_INT);
-+}
-+
-+static void
-+ramips_eth_tx_housekeeping(unsigned long ptr)
-+{
-+ struct net_device *dev = (struct net_device*)ptr;
-+ struct raeth_priv *re = netdev_priv(dev);
-+ unsigned int bytes_compl = 0, pkts_compl = 0;
-+
-+ spin_lock(&re->page_lock);
-+ while (1) {
-+ struct raeth_tx_info *txi;
-+ struct ramips_tx_dma *txd;
-+
-+ txi = &re->tx_info[re->skb_free_idx];
-+ txd = txi->tx_desc;
-+
-+ if (!(txd->txd2 & TX_DMA_DONE) || !(txi->tx_skb))
-+ break;
-+
-+ pkts_compl++;
-+ bytes_compl += txi->tx_skb->len;
-+
-+ dev_kfree_skb_irq(txi->tx_skb);
-+ txi->tx_skb = NULL;
-+ re->skb_free_idx++;
-+ if (re->skb_free_idx >= NUM_TX_DESC)
-+ re->skb_free_idx = 0;
-+ }
-+ netdev_completed_queue(dev, pkts_compl, bytes_compl);
-+ spin_unlock(&re->page_lock);
-+
-+ ramips_fe_int_enable(TX_DLY_INT);
-+}
-+
-+static void
-+ramips_eth_timeout(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+
-+ tasklet_schedule(&re->tx_housekeeping_tasklet);
-+}
-+
-+static irqreturn_t
-+ramips_eth_irq(int irq, void *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+ unsigned int status;
-+
-+ status = ramips_fe_trr(RAETH_REG_FE_INT_STATUS);
-+ status &= ramips_fe_trr(RAETH_REG_FE_INT_ENABLE);
-+
-+ if (!status)
-+ return IRQ_NONE;
-+
-+ ramips_fe_twr(status, RAETH_REG_FE_INT_STATUS);
-+
-+ if (status & RX_DLY_INT) {
-+ ramips_fe_int_disable(RX_DLY_INT);
-+ tasklet_schedule(&re->rx_tasklet);
-+ }
-+
-+ if (status & TX_DLY_INT) {
-+ ramips_fe_int_disable(TX_DLY_INT);
-+ tasklet_schedule(&re->tx_housekeeping_tasklet);
-+ }
-+
-+ raeth_debugfs_update_int_stats(re, status);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int
-+ramips_eth_hw_init(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+ int err;
-+
-+ err = request_irq(dev->irq, ramips_eth_irq, IRQF_DISABLED,
-+ dev_name(re->parent), dev);
-+ if (err)
-+ return err;
-+
-+ err = ramips_ring_alloc(re);
-+ if (err)
-+ goto err_free_irq;
-+
-+ ramips_ring_setup(re);
-+ ramips_hw_set_macaddr(dev->dev_addr);
-+
-+ ramips_setup_dma(re);
-+ ramips_fe_wr((ramips_fe_rr(RAMIPS_FE_GLO_CFG) &
-+ ~(RAMIPS_US_CYC_CNT_MASK << RAMIPS_US_CYC_CNT_SHIFT)) |
-+ ((re->sys_freq / RAMIPS_US_CYC_CNT_DIVISOR) << RAMIPS_US_CYC_CNT_SHIFT),
-+ RAMIPS_FE_GLO_CFG);
-+
-+ tasklet_init(&re->tx_housekeeping_tasklet, ramips_eth_tx_housekeeping,
-+ (unsigned long)dev);
-+ tasklet_init(&re->rx_tasklet, ramips_eth_rx_hw, (unsigned long)dev);
-+
-+
-+ ramips_fe_twr(RAMIPS_DELAY_INIT, RAETH_REG_DLY_INT_CFG);
-+ ramips_fe_twr(TX_DLY_INT | RX_DLY_INT, RAETH_REG_FE_INT_ENABLE);
-+ if (soc_is_rt5350()) {
-+ ramips_fe_wr(ramips_fe_rr(RT5350_SDM_CFG) &
-+ ~(RT5350_SDM_ICS_EN | RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN | 0xffff),
-+ RT5350_SDM_CFG);
-+ } else {
-+ ramips_fe_wr(ramips_fe_rr(RAMIPS_GDMA1_FWD_CFG) &
-+ ~(RAMIPS_GDM1_ICS_EN | RAMIPS_GDM1_TCS_EN | RAMIPS_GDM1_UCS_EN | 0xffff),
-+ RAMIPS_GDMA1_FWD_CFG);
-+ ramips_fe_wr(ramips_fe_rr(RAMIPS_CDMA_CSG_CFG) &
-+ ~(RAMIPS_ICS_GEN_EN | RAMIPS_TCS_GEN_EN | RAMIPS_UCS_GEN_EN),
-+ RAMIPS_CDMA_CSG_CFG);
-+ ramips_fe_wr(RAMIPS_PSE_FQFC_CFG_INIT, RAMIPS_PSE_FQ_CFG);
-+ }
-+ ramips_fe_wr(1, RAMIPS_FE_RST_GL);
-+ ramips_fe_wr(0, RAMIPS_FE_RST_GL);
-+
-+ return 0;
-+
-+err_free_irq:
-+ free_irq(dev->irq, dev);
-+ return err;
-+}
-+
-+static int
-+ramips_eth_open(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+
-+ ramips_fe_twr((ramips_fe_trr(RAETH_REG_PDMA_GLO_CFG) & 0xff) |
-+ (RAMIPS_TX_WB_DDONE | RAMIPS_RX_DMA_EN |
-+ RAMIPS_TX_DMA_EN | RAMIPS_PDMA_SIZE_4DWORDS),
-+ RAETH_REG_PDMA_GLO_CFG);
-+ ramips_phy_start(re);
-+ netif_start_queue(dev);
-+ return 0;
-+}
-+
-+static int
-+ramips_eth_stop(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+
-+ ramips_fe_twr(ramips_fe_trr(RAETH_REG_PDMA_GLO_CFG) &
-+ ~(RAMIPS_TX_WB_DDONE | RAMIPS_RX_DMA_EN | RAMIPS_TX_DMA_EN),
-+ RAETH_REG_PDMA_GLO_CFG);
-+
-+ netif_stop_queue(dev);
-+ ramips_phy_stop(re);
-+ RADEBUG("ramips_eth: stopped\n");
-+ return 0;
-+}
-+
-+static int __init
-+ramips_eth_probe(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+ int err;
-+
-+ BUG_ON(!re->reset_fe);
-+ re->reset_fe();
-+ net_srandom(jiffies);
-+ memcpy(dev->dev_addr, re->mac, ETH_ALEN);
-+ of_get_mac_address_mtd(re->of_node, dev->dev_addr);
-+ ether_setup(dev);
-+ dev->mtu = 1500;
-+ dev->watchdog_timeo = TX_TIMEOUT;
-+ spin_lock_init(&re->page_lock);
-+ spin_lock_init(&re->phy_lock);
-+
-+ err = ramips_mdio_init(re);
-+ if (err)
-+ return err;
-+
-+ err = ramips_phy_connect(re);
-+ if (err)
-+ goto err_mdio_cleanup;
-+
-+ err = raeth_debugfs_init(re);
-+ if (err)
-+ goto err_phy_disconnect;
-+
-+ err = ramips_eth_hw_init(dev);
-+ if (err)
-+ goto err_debugfs;
-+
-+ return 0;
-+
-+err_debugfs:
-+ raeth_debugfs_exit(re);
-+err_phy_disconnect:
-+ ramips_phy_disconnect(re);
-+err_mdio_cleanup:
-+ ramips_mdio_cleanup(re);
-+ return err;
-+}
-+
-+static void
-+ramips_eth_uninit(struct net_device *dev)
-+{
-+ struct raeth_priv *re = netdev_priv(dev);
-+
-+ raeth_debugfs_exit(re);
-+ ramips_phy_disconnect(re);
-+ ramips_mdio_cleanup(re);
-+ ramips_fe_twr(0, RAETH_REG_FE_INT_ENABLE);
-+ free_irq(dev->irq, dev);
-+ tasklet_kill(&re->tx_housekeeping_tasklet);
-+ tasklet_kill(&re->rx_tasklet);
-+ ramips_ring_cleanup(re);
-+ ramips_ring_free(re);
-+}
-+
-+static const struct net_device_ops ramips_eth_netdev_ops = {
-+ .ndo_init = ramips_eth_probe,
-+ .ndo_uninit = ramips_eth_uninit,
-+ .ndo_open = ramips_eth_open,
-+ .ndo_stop = ramips_eth_stop,
-+ .ndo_start_xmit = ramips_eth_hard_start_xmit,
-+ .ndo_tx_timeout = ramips_eth_timeout,
-+ .ndo_change_mtu = eth_change_mtu,
-+ .ndo_set_mac_address = eth_mac_addr,
-+ .ndo_validate_addr = eth_validate_addr,
-+};
-+
-+#ifdef CONFIG_SOC_RT305X
-+static void rt305x_fe_reset(void)
-+{
-+#define RT305X_RESET_FE BIT(21)
-+#define RT305X_RESET_ESW BIT(23)
-+#define SYSC_REG_RESET_CTRL 0x034
-+ u32 reset_bits = RT305X_RESET_FE;
-+
-+ if (soc_is_rt5350())
-+ reset_bits |= RT305X_RESET_ESW;
-+ rt_sysc_w32(reset_bits, SYSC_REG_RESET_CTRL);
-+ rt_sysc_w32(0, SYSC_REG_RESET_CTRL);
-+}
-+
-+struct ramips_soc_data rt3050_data = {
-+ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
-+ .reset_fe = rt305x_fe_reset,
-+ .min_pkt_len = 64,
-+};
-+
-+static const struct of_device_id ralink_eth_match[] = {
-+ { .compatible = "ralink,rt3050-eth", .data = &rt3050_data },
-+ {},
-+};
-+#else
-+static void rt3883_fe_reset(void)
-+{
-+#define RT3883_SYSC_REG_RSTCTRL 0x34
-+#define RT3883_RSTCTRL_FE BIT(21)
-+ u32 t;
-+
-+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
-+ t |= RT3883_RSTCTRL_FE;
-+ rt_sysc_w32(t , RT3883_SYSC_REG_RSTCTRL);
-+
-+ t &= ~RT3883_RSTCTRL_FE;
-+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
-+}
-+
-+struct ramips_soc_data rt3883_data = {
-+ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
-+ .reset_fe = rt3883_fe_reset,
-+ .min_pkt_len = 64,
-+};
-+
-+static const struct of_device_id ralink_eth_match[] = {
-+ { .compatible = "ralink,rt3883-eth", .data = &rt3883_data },
-+ {},
-+};
-+#endif
-+MODULE_DEVICE_TABLE(of, ralink_eth_match);
-+
-+static int
-+ramips_eth_plat_probe(struct platform_device *plat)
-+{
-+ struct raeth_priv *re;
-+ struct resource *res;
-+ struct clk *clk;
-+ int err;
-+ const struct of_device_id *match;
-+ const struct ramips_soc_data *soc = NULL;
-+
-+ match = of_match_device(ralink_eth_match, &plat->dev);
-+ if (match)
-+ soc = (const struct ramips_soc_data *) match->data;
-+
-+ if (!soc) {
-+ dev_err(&plat->dev, "no platform data specified\n");
-+ return -EINVAL;
-+ }
-+
-+ res = platform_get_resource(plat, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&plat->dev, "no memory resource found\n");
-+ return -ENXIO;
-+ }
-+
-+ ramips_fe_base = ioremap_nocache(res->start, res->end - res->start + 1);
-+ if (!ramips_fe_base)
-+ return -ENOMEM;
-+
-+ ramips_dev = alloc_etherdev(sizeof(struct raeth_priv));
-+ if (!ramips_dev) {
-+ dev_err(&plat->dev, "alloc_etherdev failed\n");
-+ err = -ENOMEM;
-+ goto err_unmap;
-+ }
-+
-+ strcpy(ramips_dev->name, "eth%d");
-+ ramips_dev->irq = platform_get_irq(plat, 0);
-+ if (ramips_dev->irq < 0) {
-+ dev_err(&plat->dev, "no IRQ resource found\n");
-+ err = -ENXIO;
-+ goto err_free_dev;
-+ }
-+ ramips_dev->addr_len = ETH_ALEN;
-+ ramips_dev->base_addr = (unsigned long)ramips_fe_base;
-+ ramips_dev->netdev_ops = &ramips_eth_netdev_ops;
-+
-+ re = netdev_priv(ramips_dev);
-+
-+ clk = clk_get(&plat->dev, NULL);
-+ if (IS_ERR(clk))
-+ panic("unable to get SYS clock, err=%ld", PTR_ERR(clk));
-+ re->sys_freq = clk_get_rate(clk);
-+
-+ re->netdev = ramips_dev;
-+ re->of_node = plat->dev.of_node;
-+ re->parent = &plat->dev;
-+ memcpy(re->mac, soc->mac, 6);
-+ re->reset_fe = soc->reset_fe;
-+ re->min_pkt_len = soc->min_pkt_len;
-+
-+ err = register_netdev(ramips_dev);
-+ if (err) {
-+ dev_err(&plat->dev, "error bringing up device\n");
-+ goto err_free_dev;
-+ }
-+
-+ netdev_info(ramips_dev, "done loading\n");
-+ return 0;
-+
-+ err_free_dev:
-+ kfree(ramips_dev);
-+ err_unmap:
-+ iounmap(ramips_fe_base);
-+ return err;
-+}
-+
-+static int
-+ramips_eth_plat_remove(struct platform_device *plat)
-+{
-+ unregister_netdev(ramips_dev);
-+ free_netdev(ramips_dev);
-+ RADEBUG("ramips_eth: unloaded\n");
-+ return 0;
-+}
-+
-+
-+
-+static struct platform_driver ramips_eth_driver = {
-+ .probe = ramips_eth_plat_probe,
-+ .remove = ramips_eth_plat_remove,
-+ .driver = {
-+ .name = "ramips_eth",
-+ .owner = THIS_MODULE,
-+ .of_match_table = ralink_eth_match
-+ },
-+};
-+
-+static int __init
-+ramips_eth_init(void)
-+{
-+ int ret;
-+
-+ ret = raeth_debugfs_root_init();
-+ if (ret)
-+ goto err_out;
-+
-+ ret = rt305x_esw_init();
-+ if (ret)
-+ goto err_debugfs_exit;
-+
-+ ret = platform_driver_register(&ramips_eth_driver);
-+ if (ret) {
-+ printk(KERN_ERR
-+ "ramips_eth: Error registering platfom driver!\n");
-+ goto esw_cleanup;
-+ }
-+
-+ return 0;
-+
-+esw_cleanup:
-+ rt305x_esw_exit();
-+err_debugfs_exit:
-+ raeth_debugfs_root_exit();
-+err_out:
-+ return ret;
-+}
-+
-+static void __exit
-+ramips_eth_cleanup(void)
-+{
-+ platform_driver_unregister(&ramips_eth_driver);
-+ rt305x_esw_exit();
-+ raeth_debugfs_root_exit();
-+}
-+
-+module_init(ramips_eth_init);
-+module_exit(ramips_eth_cleanup);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-+MODULE_DESCRIPTION("ethernet driver for ramips boards");
--- /dev/null
+From 9041c96ab5bd29d85ca95cffa44c755f68ae6bb1 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 13:15:47 +0200
+Subject: [PATCH 121/137] MIPS: add detect_memory_region()
+
+Add a generic way of detecting the available RAM. This function is based on the
+implementation already used by ath79.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5178/
+---
+ arch/mips/include/asm/bootinfo.h | 1 +
+ arch/mips/kernel/setup.c | 20 ++++++++++++++++++++
+ 2 files changed, 21 insertions(+)
+
+--- a/arch/mips/include/asm/bootinfo.h
++++ b/arch/mips/include/asm/bootinfo.h
+@@ -104,6 +104,7 @@ struct boot_mem_map {
+ extern struct boot_mem_map boot_mem_map;
+
+ extern void add_memory_region(phys_t start, phys_t size, long type);
++extern void detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max);
+
+ extern void prom_init(void);
+ extern void prom_free_prom_memory(void);
+--- a/arch/mips/kernel/setup.c
++++ b/arch/mips/kernel/setup.c
+@@ -23,6 +23,7 @@
+ #include <linux/pfn.h>
+ #include <linux/debugfs.h>
+ #include <linux/kexec.h>
++#include <linux/sizes.h>
+
+ #include <asm/addrspace.h>
+ #include <asm/bootinfo.h>
+@@ -122,6 +123,25 @@ void __init add_memory_region(phys_t sta
+ boot_mem_map.nr_map++;
+ }
+
++void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max)
++{
++ phys_t size;
++
++ for (size = sz_min; size < sz_max; size <<= 1) {
++ if (!memcmp(detect_memory_region,
++ detect_memory_region + size, 1024))
++ break;
++ }
++
++ pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n",
++ ((unsigned long long) size) / SZ_1M,
++ (unsigned long long) start,
++ ((unsigned long long) sz_min) / SZ_1M,
++ ((unsigned long long) sz_max) / SZ_1M);
++
++ add_memory_region(start, size, BOOT_MEM_RAM);
++}
++
+ static void __init print_memory_map(void)
+ {
+ int i;
+++ /dev/null
-From 8dd2c6ae6d9c858d9c4c4d55aa4bf180669ddfe9 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 22 Jan 2013 18:23:50 +0100
-Subject: [PATCH 121/121] watchdog: adds ralink wdt
-
-Adds the watchdog driver for ralink SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/watchdog/Kconfig | 6 +
- drivers/watchdog/Makefile | 1 +
- drivers/watchdog/ralink_wdt.c | 352 +++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 359 insertions(+)
- create mode 100644 drivers/watchdog/ralink_wdt.c
-
---- a/drivers/watchdog/Kconfig
-+++ b/drivers/watchdog/Kconfig
-@@ -1077,6 +1077,12 @@ config LANTIQ_WDT
- help
- Hardware driver for the Lantiq SoC Watchdog Timer.
-
-+config RALINK_WDT
-+ tristate "Ralink SoC watchdog"
-+ depends on RALINK
-+ help
-+ Hardware driver for the Ralink SoC Watchdog Timer.
-+
- # PARISC Architecture
-
- # POWERPC Architecture
---- a/drivers/watchdog/Makefile
-+++ b/drivers/watchdog/Makefile
-@@ -132,6 +132,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
- obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
- octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
- obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
-+obj-$(CONFIG_RALINK_WDT) += ralink_wdt.o
-
- # PARISC Architecture
-
---- /dev/null
-+++ b/drivers/watchdog/ralink_wdt.c
-@@ -0,0 +1,352 @@
-+/*
-+ * Ralink RT288X/RT305X built-in hardware watchdog timer
-+ *
-+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * This driver was based on: drivers/watchdog/ixp4xx_wdt.c
-+ * Author: Deepak Saxena <dsaxena@plexity.net>
-+ * Copyright 2004 (c) MontaVista, Software, Inc.
-+ *
-+ * which again was based on sa1100 driver,
-+ * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
-+ *
-+ * parts of the driver 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/bitops.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/miscdevice.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/platform_device.h>
-+#include <linux/types.h>
-+#include <linux/watchdog.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+
-+#define DRIVER_NAME "ralink-wdt"
-+
-+#define RALINK_WDT_TIMEOUT 30 /* seconds */
-+#define RALINK_WDT_PRESCALE 65536
-+
-+#define TIMER_REG_TMR1LOAD 0x00
-+#define TIMER_REG_TMR1CTL 0x08
-+
-+#define TMRSTAT_TMR1RST BIT(5)
-+
-+#define TMR1CTL_ENABLE BIT(7)
-+#define TMR1CTL_MODE_SHIFT 4
-+#define TMR1CTL_MODE_MASK 0x3
-+#define TMR1CTL_MODE_FREE_RUNNING 0x0
-+#define TMR1CTL_MODE_PERIODIC 0x1
-+#define TMR1CTL_MODE_TIMEOUT 0x2
-+#define TMR1CTL_MODE_WDT 0x3
-+#define TMR1CTL_PRESCALE_MASK 0xf
-+#define TMR1CTL_PRESCALE_65536 0xf
-+
-+static int nowayout = WATCHDOG_NOWAYOUT;
-+module_param(nowayout, int, 0);
-+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
-+ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-+
-+static int ralink_wdt_timeout = RALINK_WDT_TIMEOUT;
-+module_param_named(timeout, ralink_wdt_timeout, int, 0);
-+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 means use maximum "
-+ "(default=" __MODULE_STRING(RALINK_WDT_TIMEOUT) "s)");
-+
-+static unsigned long ralink_wdt_flags;
-+
-+#define WDT_FLAGS_BUSY 0
-+#define WDT_FLAGS_EXPECT_CLOSE 1
-+
-+static struct clk *ralink_wdt_clk;
-+static unsigned long ralink_wdt_freq;
-+static int ralink_wdt_max_timeout;
-+static void __iomem *ralink_wdt_base;
-+
-+static inline void rt_wdt_w32(unsigned reg, u32 val)
-+{
-+ __raw_writel(val, ralink_wdt_base + reg);
-+}
-+
-+static inline u32 rt_wdt_r32(unsigned reg)
-+{
-+ return __raw_readl(ralink_wdt_base + reg);
-+}
-+
-+static inline void ralink_wdt_keepalive(void)
-+{
-+ rt_wdt_w32(TIMER_REG_TMR1LOAD, ralink_wdt_timeout * ralink_wdt_freq);
-+}
-+
-+static inline void ralink_wdt_enable(void)
-+{
-+ u32 t;
-+
-+ ralink_wdt_keepalive();
-+
-+ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
-+ t |= TMR1CTL_ENABLE;
-+ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
-+}
-+
-+static inline void ralink_wdt_disable(void)
-+{
-+ u32 t;
-+
-+ ralink_wdt_keepalive();
-+
-+ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
-+ t &= ~TMR1CTL_ENABLE;
-+ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
-+}
-+
-+static int ralink_wdt_set_timeout(int val)
-+{
-+ if (val < 1 || val > ralink_wdt_max_timeout) {
-+ pr_warn(DRIVER_NAME
-+ ": timeout value %d must be 0 < timeout <= %d, using %d\n",
-+ val, ralink_wdt_max_timeout, ralink_wdt_timeout);
-+ return -EINVAL;
-+ }
-+
-+ ralink_wdt_timeout = val;
-+ ralink_wdt_keepalive();
-+
-+ return 0;
-+}
-+
-+static int ralink_wdt_open(struct inode *inode, struct file *file)
-+{
-+ u32 t;
-+
-+ if (test_and_set_bit(WDT_FLAGS_BUSY, &ralink_wdt_flags))
-+ return -EBUSY;
-+
-+ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags);
-+
-+ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
-+ t &= ~(TMR1CTL_MODE_MASK << TMR1CTL_MODE_SHIFT |
-+ TMR1CTL_PRESCALE_MASK);
-+ t |= (TMR1CTL_MODE_WDT << TMR1CTL_MODE_SHIFT |
-+ TMR1CTL_PRESCALE_65536);
-+ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
-+
-+ ralink_wdt_enable();
-+
-+ return nonseekable_open(inode, file);
-+}
-+
-+static int ralink_wdt_release(struct inode *inode, struct file *file)
-+{
-+ if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags))
-+ ralink_wdt_disable();
-+ else {
-+ pr_crit(DRIVER_NAME ": device closed unexpectedly, "
-+ "watchdog timer will not stop!\n");
-+ ralink_wdt_keepalive();
-+ }
-+
-+ clear_bit(WDT_FLAGS_BUSY, &ralink_wdt_flags);
-+ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags);
-+
-+ return 0;
-+}
-+
-+static ssize_t rt_wdt_w32ite(struct file *file, const char *data,
-+ size_t len, loff_t *ppos)
-+{
-+ if (len) {
-+ if (!nowayout) {
-+ size_t i;
-+
-+ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags);
-+
-+ for (i = 0; i != len; i++) {
-+ char c;
-+
-+ if (get_user(c, data + i))
-+ return -EFAULT;
-+
-+ if (c == 'V')
-+ set_bit(WDT_FLAGS_EXPECT_CLOSE,
-+ &ralink_wdt_flags);
-+ }
-+ }
-+
-+ ralink_wdt_keepalive();
-+ }
-+
-+ return len;
-+}
-+
-+static const struct watchdog_info ralink_wdt_info = {
-+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-+ WDIOF_MAGICCLOSE,
-+ .firmware_version = 0,
-+ .identity = "RALINK watchdog",
-+};
-+
-+static long ralink_wdt_ioctl(struct file *file, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ void __user *argp = (void __user *)arg;
-+ int __user *p = argp;
-+ int err;
-+ int t;
-+
-+ switch (cmd) {
-+ case WDIOC_GETSUPPORT:
-+ err = copy_to_user(argp, &ralink_wdt_info,
-+ sizeof(ralink_wdt_info)) ? -EFAULT : 0;
-+ break;
-+
-+ case WDIOC_GETSTATUS:
-+ err = put_user(0, p);
-+ break;
-+
-+ case WDIOC_KEEPALIVE:
-+ ralink_wdt_keepalive();
-+ err = 0;
-+ break;
-+
-+ case WDIOC_SETTIMEOUT:
-+ err = get_user(t, p);
-+ if (err)
-+ break;
-+
-+ err = ralink_wdt_set_timeout(t);
-+ if (err)
-+ break;
-+
-+ /* fallthrough */
-+ case WDIOC_GETTIMEOUT:
-+ err = put_user(ralink_wdt_timeout, p);
-+ break;
-+
-+ default:
-+ err = -ENOTTY;
-+ break;
-+ }
-+
-+ return err;
-+}
-+
-+static const struct file_operations ralink_wdt_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = no_llseek,
-+ .write = rt_wdt_w32ite,
-+ .unlocked_ioctl = ralink_wdt_ioctl,
-+ .open = ralink_wdt_open,
-+ .release = ralink_wdt_release,
-+};
-+
-+static struct miscdevice ralink_wdt_miscdev = {
-+ .minor = WATCHDOG_MINOR,
-+ .name = "watchdog",
-+ .fops = &ralink_wdt_fops,
-+};
-+
-+static int ralink_wdt_probe(struct platform_device *pdev)
-+{
-+ struct resource *res;
-+ int err;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ if (!res) {
-+ dev_err(&pdev->dev, "no memory resource found\n");
-+ return -EINVAL;
-+ }
-+
-+ ralink_wdt_base = ioremap(res->start, resource_size(res));
-+ if (!ralink_wdt_base)
-+ return -ENOMEM;
-+
-+ ralink_wdt_clk = clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(ralink_wdt_clk)) {
-+ err = PTR_ERR(ralink_wdt_clk);
-+ goto err_unmap;
-+ }
-+
-+ err = clk_enable(ralink_wdt_clk);
-+ if (err)
-+ goto err_clk_put;
-+
-+ ralink_wdt_freq = clk_get_rate(ralink_wdt_clk) / RALINK_WDT_PRESCALE;
-+ if (!ralink_wdt_freq) {
-+ err = -EINVAL;
-+ goto err_clk_disable;
-+ }
-+
-+ ralink_wdt_max_timeout = (0xfffful / ralink_wdt_freq);
-+ if (ralink_wdt_timeout < 1 ||
-+ ralink_wdt_timeout > ralink_wdt_max_timeout) {
-+ ralink_wdt_timeout = ralink_wdt_max_timeout;
-+ dev_info(&pdev->dev,
-+ "timeout value must be 0 < timeout <= %d, using %d\n",
-+ ralink_wdt_max_timeout, ralink_wdt_timeout);
-+ }
-+
-+ err = misc_register(&ralink_wdt_miscdev);
-+ if (err) {
-+ dev_err(&pdev->dev,
-+ "unable to register misc device, err=%d\n", err);
-+ goto err_clk_disable;
-+ }
-+
-+ return 0;
-+
-+err_clk_disable:
-+ clk_disable(ralink_wdt_clk);
-+err_clk_put:
-+ clk_put(ralink_wdt_clk);
-+err_unmap:
-+ iounmap(ralink_wdt_base);
-+ return err;
-+}
-+
-+static int ralink_wdt_remove(struct platform_device *pdev)
-+{
-+ misc_deregister(&ralink_wdt_miscdev);
-+ clk_disable(ralink_wdt_clk);
-+ clk_put(ralink_wdt_clk);
-+ iounmap(ralink_wdt_base);
-+ return 0;
-+}
-+
-+static void ralink_wdt_shutdown(struct platform_device *pdev)
-+{
-+ ralink_wdt_disable();
-+}
-+
-+static const struct of_device_id ralink_wdt_match[] = {
-+ { .compatible = "ralink,rt2880-wdt" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ralink_wdt_match);
-+
-+static struct platform_driver ralink_wdt_driver = {
-+ .probe = ralink_wdt_probe,
-+ .remove = ralink_wdt_remove,
-+ .shutdown = ralink_wdt_shutdown,
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ .of_match_table = ralink_wdt_match,
-+ },
-+};
-+
-+module_platform_driver(ralink_wdt_driver);
-+
-+MODULE_DESCRIPTION("MediaTek/Ralink RT288X/RT305X hardware watchdog driver");
-+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:" DRIVER_NAME);
-+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
--- /dev/null
+From 5155790ed1f270379ea98325f01e1c72a36a37d0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 15:10:14 +0200
+Subject: [PATCH 122/137] MIPS: ralink: add memory definition to struct
+ ralink_soc_info
+
+Depending on the actual SoC we have a different base address as well as minimum
+and maximum size for RAM. Add these fields to the per SoC structure.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5179/
+---
+ arch/mips/ralink/common.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/mips/ralink/common.h
++++ b/arch/mips/ralink/common.h
+@@ -33,6 +33,11 @@ extern struct ralink_pinmux rt_gpio_pinm
+ struct ralink_soc_info {
+ unsigned char sys_type[RAMIPS_SYS_TYPE_LEN];
+ unsigned char *compatible;
++
++ unsigned long mem_base;
++ unsigned long mem_size;
++ unsigned long mem_size_min;
++ unsigned long mem_size_max;
+ };
+ extern struct ralink_soc_info soc_info;
+
+++ /dev/null
-From e0fbc01d33265d32fe7f5f34269cb88be2a13c24 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 31 Mar 2013 10:17:26 +0200
-Subject: [PATCH] MIPS: ralink: handle PCI interrupts as well
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- arch/mips/ralink/irq.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/mips/ralink/irq.c
-+++ b/arch/mips/ralink/irq.c
-@@ -31,6 +31,7 @@
- #define INTC_INT_GLOBAL BIT(31)
-
- #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2)
-+#define RALINK_CPU_IRQ_PCI (MIPS_CPU_IRQ_BASE + 4)
- #define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5)
- #define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6)
- #define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7)
-@@ -104,6 +105,9 @@ asmlinkage void plat_irq_dispatch(void)
- else if (pending & STATUSF_IP6)
- do_IRQ(RALINK_CPU_IRQ_WIFI);
-
-+ else if (pending & STATUSF_IP4)
-+ do_IRQ(RALINK_CPU_IRQ_PCI);
-+
- else if (pending & STATUSF_IP2)
- do_IRQ(RALINK_CPU_IRQ_INTC);
-
--- /dev/null
+From 016f1f659cf70cc78e72e12a2130d8f3e1a6e0d3 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 15:13:40 +0200
+Subject: [PATCH 123/137] MIPS: ralink: add memory definition for RT305x
+
+Populate struct soc_info with the data that describes our RAM window.
+
+As memory detection fails on RT5350 we read the amount of available memory
+from the system controller.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5180/
+---
+ arch/mips/include/asm/mach-ralink/rt305x.h | 6 ++++
+ arch/mips/ralink/rt305x.c | 45 ++++++++++++++++++++++++++++
+ 2 files changed, 51 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ralink/rt305x.h
++++ b/arch/mips/include/asm/mach-ralink/rt305x.h
+@@ -157,4 +157,10 @@ static inline int soc_is_rt5350(void)
+ #define RT3352_RSTCTRL_UDEV BIT(25)
+ #define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10)
+
++#define RT305X_SDRAM_BASE 0x00000000
++#define RT305X_MEM_SIZE_MIN 2
++#define RT305X_MEM_SIZE_MAX 64
++#define RT3352_MEM_SIZE_MIN 2
++#define RT3352_MEM_SIZE_MAX 256
++
+ #endif
+--- a/arch/mips/ralink/rt305x.c
++++ b/arch/mips/ralink/rt305x.c
+@@ -122,6 +122,40 @@ struct ralink_pinmux rt_gpio_pinmux = {
+ .wdt_reset = rt305x_wdt_reset,
+ };
+
++static unsigned long rt5350_get_mem_size(void)
++{
++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE);
++ unsigned long ret;
++ u32 t;
++
++ t = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG);
++ t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) &
++ RT5350_SYSCFG0_DRAM_SIZE_MASK;
++
++ switch (t) {
++ case RT5350_SYSCFG0_DRAM_SIZE_2M:
++ ret = 2;
++ break;
++ case RT5350_SYSCFG0_DRAM_SIZE_8M:
++ ret = 8;
++ break;
++ case RT5350_SYSCFG0_DRAM_SIZE_16M:
++ ret = 16;
++ break;
++ case RT5350_SYSCFG0_DRAM_SIZE_32M:
++ ret = 32;
++ break;
++ case RT5350_SYSCFG0_DRAM_SIZE_64M:
++ ret = 64;
++ break;
++ default:
++ panic("rt5350: invalid DRAM size: %u", t);
++ break;
++ }
++
++ return ret;
++}
++
+ void __init ralink_clk_init(void)
+ {
+ unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate;
+@@ -252,4 +286,15 @@ void prom_soc_init(struct ralink_soc_inf
+ name,
+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
+ (id & CHIP_ID_REV_MASK));
++
++ soc_info->mem_base = RT305X_SDRAM_BASE;
++ if (soc_is_rt5350()) {
++ soc_info->mem_size = rt5350_get_mem_size();
++ } else if (soc_is_rt305x() || soc_is_rt3350()) {
++ soc_info->mem_size_min = RT305X_MEM_SIZE_MIN;
++ soc_info->mem_size_max = RT305X_MEM_SIZE_MAX;
++ } else if (soc_is_rt3352()) {
++ soc_info->mem_size_min = RT3352_MEM_SIZE_MIN;
++ soc_info->mem_size_max = RT3352_MEM_SIZE_MAX;
++ }
+ }
+++ /dev/null
-From 34a9a634432a95d8ae9af86d41fdaf32fb039c2c Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 27 Mar 2013 21:10:14 +0100
-Subject: [PATCH 1/5] MIPS: ralink: fix uartmux group handling
-
- * don't try get 'ralink,uartmux' porperty if the pinmux.uart is
- not initialized,
- * don't touch 'mode' value if mux mask is zero
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- arch/mips/ralink/pinmux.c | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
---- a/arch/mips/ralink/pinmux.c
-+++ b/arch/mips/ralink/pinmux.c
-@@ -56,15 +56,19 @@ void ralink_pinmux(void)
- }
- }
-
-- of_property_read_string(np, "ralink,uartmux", &uart);
-+ uart = NULL;
-+ if (rt_pinmux.uart)
-+ of_property_read_string(np, "ralink,uartmux", &uart);
-+
- if (uart) {
- int m = ralink_mux_mask(uart, rt_pinmux.uart);
-- mode |= rt_pinmux.uart_mask << rt_pinmux.uart_shift;
-+
- if (m) {
-- mode &= ~(m << rt_pinmux.uart_shift);
-+ mode &= ~(rt_pinmux.uart_mask << rt_pinmux.uart_shift);
-+ mode |= m << rt_pinmux.uart_shift;
- pr_debug("pinmux: registered uartmux \"%s\"\n", uart);
- } else {
-- pr_debug("pinmux: registered uartmux \"gpio\"\n");
-+ pr_debug("pinmux: unknown uartmux \"%s\"\n", uart);
- }
- }
-
--- /dev/null
+From 0151f5f0dbf43b6b3718b0d1d403c87429ac0313 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 15:37:37 +0200
+Subject: [PATCH 124/137] MIPS: ralink: add memory definition for RT2880
+
+Populate struct soc_info with the data that describes our RAM window.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5181/
+---
+ arch/mips/include/asm/mach-ralink/rt288x.h | 4 ++++
+ arch/mips/ralink/rt288x.c | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ralink/rt288x.h
++++ b/arch/mips/include/asm/mach-ralink/rt288x.h
+@@ -46,4 +46,8 @@
+
+ #define CLKCFG_SRAM_CS_N_WDT BIT(9)
+
++#define RT2880_SDRAM_BASE 0x08000000
++#define RT2880_MEM_SIZE_MIN 2
++#define RT2880_MEM_SIZE_MAX 128
++
+ #endif
+--- a/arch/mips/ralink/rt288x.c
++++ b/arch/mips/ralink/rt288x.c
+@@ -136,4 +136,8 @@ void prom_soc_init(struct ralink_soc_inf
+ name,
+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
+ (id & CHIP_ID_REV_MASK));
++
++ soc_info->mem_base = RT2880_SDRAM_BASE;
++ soc_info->mem_size_min = RT2880_MEM_SIZE_MIN;
++ soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
+ }
+++ /dev/null
-From 8818e2d260e7f98fd5388f9ba56f54b788e175f0 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 27 Mar 2013 20:42:18 +0100
-Subject: [PATCH 2/5] MIPS: ralink: add pci group to struct ralink_pinmux
-
-This will be used for RT3662/RT3883.
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- arch/mips/ralink/common.h | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/arch/mips/ralink/common.h
-+++ b/arch/mips/ralink/common.h
-@@ -24,6 +24,9 @@ struct ralink_pinmux {
- int uart_shift;
- u32 uart_mask;
- void (*wdt_reset)(void);
-+ struct ralink_pinmux_grp *pci;
-+ int pci_shift;
-+ u32 pci_mask;
- };
- extern struct ralink_pinmux rt_pinmux;
-
--- /dev/null
+From de85c6c3e2d5ed9c721a282d91af504a845e1fad Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 20:23:19 +0200
+Subject: [PATCH 125/137] MIPS: ralink: add memory definition for RT3883
+
+Populate struct soc_info with the data that describes our RAM window.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5182/
+---
+ arch/mips/include/asm/mach-ralink/rt3883.h | 4 ++++
+ arch/mips/ralink/rt3883.c | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ralink/rt3883.h
++++ b/arch/mips/include/asm/mach-ralink/rt3883.h
+@@ -244,4 +244,8 @@
+ #define RT3883_FLASH_CFG_WIDTH_16BIT 0x1
+ #define RT3883_FLASH_CFG_WIDTH_32BIT 0x2
+
++#define RT3883_SDRAM_BASE 0x00000000
++#define RT3883_MEM_SIZE_MIN 2
++#define RT3883_MEM_SIZE_MAX 256
++
+ #endif /* _RT3883_REGS_H_ */
+--- a/arch/mips/ralink/rt3883.c
++++ b/arch/mips/ralink/rt3883.c
+@@ -239,4 +239,8 @@ void prom_soc_init(struct ralink_soc_inf
+ name,
+ (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK,
+ (id & RT3883_REVID_ECO_ID_MASK));
++
++ soc_info->mem_base = RT3883_SDRAM_BASE;
++ soc_info->mem_size_min = RT3883_MEM_SIZE_MIN;
++ soc_info->mem_size_max = RT3883_MEM_SIZE_MAX;
+ }
+++ /dev/null
-From fe26f3e7d1329fc2a5ac14808dbecb7d324d0a41 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 27 Mar 2013 20:56:22 +0100
-Subject: [PATCH 3/5] MIPS: ralink: process PCI pinmux group
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- arch/mips/ralink/pinmux.c | 14 +++++++++++++-
- 1 file changed, 13 insertions(+), 1 deletion(-)
-
---- a/arch/mips/ralink/pinmux.c
-+++ b/arch/mips/ralink/pinmux.c
-@@ -29,7 +29,7 @@ void ralink_pinmux(void)
- const __be32 *wdt;
- struct device_node *np;
- struct property *prop;
-- const char *uart, *pin;
-+ const char *uart, *pci, *pin;
- u32 mode = 0;
-
- np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-sysc");
-@@ -76,5 +76,20 @@ void ralink_pinmux(void)
- if (wdt && *wdt && rt_pinmux.wdt_reset)
- rt_pinmux.wdt_reset();
-
-+ pci = NULL;
-+ if (rt_pinmux.pci)
-+ of_property_read_string(np, "ralink,pcimux", &pci);
-+
-+ if (pci) {
-+ int m = ralink_mux_mask(pci, rt_pinmux.pci);
-+ mode &= ~(rt_pinmux.pci_mask << rt_pinmux.pci_shift);
-+ if (m) {
-+ mode |= (m << rt_pinmux.pci_shift);
-+ pr_debug("pinmux: registered pcimux \"%s\"\n", pci);
-+ } else {
-+ pr_debug("pinmux: registered pcimux \"gpio\"\n");
-+ }
-+ }
-+
- rt_sysc_w32(mode, SYSC_REG_GPIO_MODE);
- }
+++ /dev/null
-From 2c868d77c161ce7dea8facf203c155924d776c33 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 27 Mar 2013 20:50:40 +0100
-Subject: [PATCH 4/5] MIPS: ralink: add PCI pinmux group for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- arch/mips/ralink/rt3883.c | 32 ++++++++++++++++++++++++++++++++
- 1 file changed, 32 insertions(+)
-
---- a/arch/mips/ralink/rt3883.c
-+++ b/arch/mips/ralink/rt3883.c
-@@ -113,6 +113,35 @@ struct ralink_pinmux_grp uart_mux[] = {
- }, {0}
- };
-
-+struct ralink_pinmux_grp pci_mux[] = {
-+ {
-+ .name = "pci-dev",
-+ .mask = 0,
-+ .gpio_first = RT3883_GPIO_PCI_AD0,
-+ .gpio_last = RT3883_GPIO_PCI_AD31,
-+ }, {
-+ .name = "pci-host2",
-+ .mask = 1,
-+ .gpio_first = RT3883_GPIO_PCI_AD0,
-+ .gpio_last = RT3883_GPIO_PCI_AD31,
-+ }, {
-+ .name = "pci-host1",
-+ .mask = 2,
-+ .gpio_first = RT3883_GPIO_PCI_AD0,
-+ .gpio_last = RT3883_GPIO_PCI_AD31,
-+ }, {
-+ .name = "pci-fnc",
-+ .mask = 3,
-+ .gpio_first = RT3883_GPIO_PCI_AD0,
-+ .gpio_last = RT3883_GPIO_PCI_AD31,
-+ }, {
-+ .name = "pci-gpio",
-+ .mask = 7,
-+ .gpio_first = RT3883_GPIO_PCI_AD0,
-+ .gpio_last = RT3883_GPIO_PCI_AD31,
-+ }, {0}
-+};
-+
- static void rt3883_wdt_reset(void)
- {
- u32 t;
-@@ -129,6 +158,9 @@ struct ralink_pinmux rt_pinmux = {
- .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT,
- .uart_mask = RT3883_GPIO_MODE_GPIO,
- .wdt_reset = rt3883_wdt_reset,
-+ .pci = pci_mux,
-+ .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT,
-+ .pci_mask = RT3883_GPIO_MODE_PCI_MASK,
- };
-
- void __init ralink_clk_init(void)
--- /dev/null
+From c1d35c42d697e9c28c817921a79c5f814529a4c6 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 14 Apr 2013 09:55:29 +0200
+Subject: [PATCH 126/137] MIPS: ralink: add memory definition for MT7620
+
+Populate struct soc_info with the data that describes our RAM window.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5183/
+---
+ arch/mips/include/asm/mach-ralink/mt7620.h | 8 ++++++++
+ arch/mips/ralink/mt7620.c | 20 ++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ralink/mt7620.h
++++ b/arch/mips/include/asm/mach-ralink/mt7620.h
+@@ -50,6 +50,14 @@
+ #define SYSCFG0_DRAM_TYPE_DDR1 1
+ #define SYSCFG0_DRAM_TYPE_DDR2 2
+
++#define MT7620_DRAM_BASE 0x0
++#define MT7620_SDRAM_SIZE_MIN 2
++#define MT7620_SDRAM_SIZE_MAX 64
++#define MT7620_DDR1_SIZE_MIN 32
++#define MT7620_DDR1_SIZE_MAX 128
++#define MT7620_DDR2_SIZE_MIN 32
++#define MT7620_DDR2_SIZE_MAX 256
++
+ #define MT7620_GPIO_MODE_I2C BIT(0)
+ #define MT7620_GPIO_MODE_UART0_SHIFT 2
+ #define MT7620_GPIO_MODE_UART0_MASK 0x7
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -211,4 +211,24 @@ void prom_soc_init(struct ralink_soc_inf
+
+ cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
+ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
++
++ switch (dram_type) {
++ case SYSCFG0_DRAM_TYPE_SDRAM:
++ soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN;
++ soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX;
++ break;
++
++ case SYSCFG0_DRAM_TYPE_DDR1:
++ soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN;
++ soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX;
++ break;
++
++ case SYSCFG0_DRAM_TYPE_DDR2:
++ soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN;
++ soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX;
++ break;
++ default:
++ BUG();
++ }
++ soc_info->mem_base = MT7620_DRAM_BASE;
+ }
+++ /dev/null
-From 79a01992e15216544dcfdc0be9f2f7695952d047 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 27 Mar 2013 20:59:26 +0100
-Subject: [PATCH 5/5] MIPS: ralink: add GPIO mode to RT3883 UART pinmux group
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- arch/mips/ralink/rt3883.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/arch/mips/ralink/rt3883.c
-+++ b/arch/mips/ralink/rt3883.c
-@@ -110,6 +110,11 @@ struct ralink_pinmux_grp uart_mux[] = {
- .mask = RT3883_GPIO_MODE_GPIO_I2S,
- .gpio_first = RT3883_GPIO_7,
- .gpio_last = RT3883_GPIO_14,
-+ }, {
-+ .name = "gpio",
-+ .mask = RT3883_GPIO_MODE_GPIO,
-+ .gpio_first = RT3883_GPIO_7,
-+ .gpio_last = RT3883_GPIO_14,
- }, {0}
- };
-
--- /dev/null
+From 1618a00f709817cbcdebf038d0b5e251c8d67237 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 13 Apr 2013 15:15:51 +0200
+Subject: [PATCH 127/137] MIPS: ralink: make use of the new memory detection
+ code
+
+Call detect_memory_region() from plat_mem_setup() unless the size was already
+read from the system controller.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Patchwork: http://patchwork.linux-mips.org/patch/5184/
+---
+ arch/mips/ralink/of.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/arch/mips/ralink/of.c
++++ b/arch/mips/ralink/of.c
+@@ -11,6 +11,7 @@
+ #include <linux/io.h>
+ #include <linux/clk.h>
+ #include <linux/init.h>
++#include <linux/sizes.h>
+ #include <linux/of_fdt.h>
+ #include <linux/kernel.h>
+ #include <linux/bootmem.h>
+@@ -85,6 +86,14 @@ void __init plat_mem_setup(void)
+ * parsed resulting in our memory appearing
+ */
+ __dt_setup_arch(&__dtb_start);
++
++ if (soc_info.mem_size)
++ add_memory_region(soc_info.mem_base, soc_info.mem_size,
++ BOOT_MEM_RAM);
++ else
++ detect_memory_region(soc_info.mem_base,
++ soc_info.mem_size_min * SZ_1M,
++ soc_info.mem_size_max * SZ_1M);
+ }
+
+ static int __init plat_of_setup(void)
+++ /dev/null
-From 9830273b0c7f2e58a9226cc38bb0c4363e1fd8a2 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 7 Apr 2013 17:00:40 +0200
-Subject: [PATCH 1/3] MIPS: ralink: add cpu-feature-overrides.h for RT288x
- SoCs
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- .../asm/mach-ralink/rt288x/cpu-feature-overrides.h | 56 ++++++++++++++++++++
- arch/mips/ralink/Platform | 1 +
- 2 files changed, 57 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h
-
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h
-@@ -0,0 +1,56 @@
-+/*
-+ * Ralink RT288x 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 _RT288X_CPU_FEATURE_OVERRIDES_H
-+#define _RT288X_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 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() 16
-+#define cpu_icache_line_size() 16
-+
-+#endif /* _RT288X_CPU_FEATURE_OVERRIDES_H */
---- a/arch/mips/ralink/Platform
-+++ b/arch/mips/ralink/Platform
-@@ -8,6 +8,7 @@ cflags-$(CONFIG_RALINK) += -I$(srctree)
- # Ralink RT288x
- #
- load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000
-+cflags-$(CONFIG_SOC_RT288X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt288x
-
- #
- # Ralink RT305x
--- /dev/null
+From 5a2079532dfaf5762f658370ee7a0afb686f066e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Apr 2013 23:11:42 +0200
+Subject: [PATCH 128/137] MIPS: ralink: add pinmux driver
+
+Add code to setup the pinmux on ralonk SoC. The SoC has a single 32 bit register
+for this functionality with simple on/off bits. Building a full featured pinctrl
+driver would be overkill.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Makefile | 2 +-
+ arch/mips/ralink/common.h | 2 ++
+ arch/mips/ralink/of.c | 2 ++
+ arch/mips/ralink/pinmux.c | 76 +++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 81 insertions(+), 1 deletion(-)
+ create mode 100644 arch/mips/ralink/pinmux.c
+
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -6,7 +6,7 @@
+ # 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 pinmux.o
+
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+--- a/arch/mips/ralink/common.h
++++ b/arch/mips/ralink/common.h
+@@ -50,4 +50,6 @@ extern void prom_soc_init(struct ralink_
+
+ __iomem void *plat_of_remap_node(const char *node);
+
++void ralink_pinmux(void);
++
+ #endif /* _RALINK_COMMON_H__ */
+--- a/arch/mips/ralink/of.c
++++ b/arch/mips/ralink/of.c
+@@ -110,6 +110,8 @@ static int __init plat_of_setup(void)
+ if (of_platform_populate(NULL, of_ids, NULL, NULL))
+ panic("failed to populate DT\n");
+
++ ralink_pinmux();
++
+ return 0;
+ }
+
+--- /dev/null
++++ b/arch/mips/ralink/pinmux.c
+@@ -0,0 +1,76 @@
++/*
++ * 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/kernel.h>
++#include <linux/of.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "common.h"
++
++#define SYSC_REG_GPIO_MODE 0x60
++
++static u32 ralink_mux_mask(const char *name, struct ralink_pinmux_grp *grps)
++{
++ for (; grps->name; grps++)
++ if (!strcmp(grps->name, name))
++ return grps->mask;
++
++ return 0;
++}
++
++void ralink_pinmux(void)
++{
++ const __be32 *wdt;
++ struct device_node *np;
++ struct property *prop;
++ const char *uart, *pin;
++ u32 mode = 0;
++
++ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-sysc");
++ if (!np)
++ return;
++
++ of_property_for_each_string(np, "ralink,gpiomux", prop, pin) {
++ int m = ralink_mux_mask(pin, rt_gpio_pinmux.mode);
++ if (m) {
++ mode |= m;
++ pr_debug("pinmux: registered gpiomux \"%s\"\n", pin);
++ } else {
++ pr_err("pinmux: failed to load \"%s\"\n", pin);
++ }
++ }
++
++ of_property_for_each_string(np, "ralink,pinmux", prop, pin) {
++ int m = ralink_mux_mask(pin, rt_gpio_pinmux.mode);
++ if (m) {
++ mode &= ~m;
++ pr_debug("pinmux: registered pinmux \"%s\"\n", pin);
++ } else {
++ pr_err("pinmux: failed to load group \"%s\"\n", pin);
++ }
++ }
++
++ of_property_read_string(np, "ralink,uartmux", &uart);
++ if (uart) {
++ int m = ralink_mux_mask(uart, rt_gpio_pinmux.uart);
++ mode |= rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift;
++ if (m) {
++ mode &= ~(m << rt_gpio_pinmux.uart_shift);
++ pr_debug("pinmux: registered uartmux \"%s\"\n", uart);
++ } else {
++ pr_debug("pinmux: registered uartmux \"gpio\"\n");
++ }
++ }
++
++ wdt = of_get_property(np, "ralink,wdtmux", NULL);
++ if (wdt && *wdt && rt_gpio_pinmux.wdt_reset)
++ rt_gpio_pinmux.wdt_reset();
++
++ rt_sysc_w32(mode, SYSC_REG_GPIO_MODE);
++}
+++ /dev/null
-From 0eccf6e501337213d1de75dcf8f158d194ae0f77 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 7 Apr 2013 17:02:27 +0200
-Subject: [PATCH 2/3] MIPS: ralink: add cpu-feature-overrides.h for
- RT3x5x/RT5350 SoCs
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- .../asm/mach-ralink/rt305x/cpu-feature-overrides.h | 56 ++++++++++++++++++++
- arch/mips/ralink/Platform | 1 +
- 2 files changed, 57 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h
-
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h
-@@ -0,0 +1,56 @@
-+/*
-+ * Ralink RT305x 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 _RT305X_CPU_FEATURE_OVERRIDES_H
-+#define _RT305X_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 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 /* _RT305X_CPU_FEATURE_OVERRIDES_H */
---- a/arch/mips/ralink/Platform
-+++ b/arch/mips/ralink/Platform
-@@ -14,6 +14,7 @@ cflags-$(CONFIG_SOC_RT288X) += -I$(srctr
- # Ralink RT305x
- #
- load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
-+cflags-$(CONFIG_SOC_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt305x
-
- #
- # Ralink RT3883
--- /dev/null
+From 1f307fd0fdca585d5c7c32963e8a8a6f38d8a78c Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 23 Mar 2013 19:44:41 +0100
+Subject: [PATCH 129/137] MIPS: ralink: add support for periodic timer irq
+
+Adds a driver for the periodic timer found on Ralink SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Makefile | 2 +-
+ arch/mips/ralink/timer.c | 192 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 193 insertions(+), 1 deletion(-)
+ create mode 100644 arch/mips/ralink/timer.c
+
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -6,7 +6,7 @@
+ # 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 pinmux.o
++obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o
+
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+--- /dev/null
++++ b/arch/mips/ralink/timer.c
+@@ -0,0 +1,192 @@
++/*
++ * 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;
++
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource found\n");
++ return -EINVAL;
++ }
++
++ 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 (!rt->membase) {
++ dev_err(&pdev->dev, "failed to ioremap\n");
++ return -ENOMEM;
++ }
++
++ 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");
--- /dev/null
+From 007ab7fe49bfcaa220372260eedeb4eed51f1631 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 22 Jan 2013 18:24:34 +0100
+Subject: [PATCH 130/137] GPIO: MIPS: ralink: adds ralink gpio support
+
+Add gpio driver for Ralink SoC. This driver makes the gpio core on
+RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/Kconfig | 1 +
+ arch/mips/include/asm/mach-ralink/gpio.h | 24 ++++
+ drivers/gpio/Kconfig | 6 +
+ drivers/gpio/Makefile | 1 +
+ drivers/gpio/gpio-ralink.c | 176 ++++++++++++++++++++++++++++++
+ 5 files changed, 208 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h
+ create mode 100644 drivers/gpio/gpio-ralink.c
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -449,6 +449,7 @@ config RALINK
+ select SYS_HAS_EARLY_PRINTK
+ select HAVE_MACH_CLKDEV
+ select CLKDEV_LOOKUP
++ select ARCH_REQUIRE_GPIOLIB
+
+ config SGI_IP22
+ bool "SGI IP22 (Indy/Indigo2)"
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/gpio.h
+@@ -0,0 +1,24 @@
++/*
++ * Ralink SoC GPIO API support
++ *
++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ */
++
++#ifndef __ASM_MACH_RALINK_GPIO_H
++#define __ASM_MACH_RALINK_GPIO_H
++
++#define ARCH_NR_GPIOS 128
++#include <asm-generic/gpio.h>
++
++#define gpio_get_value __gpio_get_value
++#define gpio_set_value __gpio_set_value
++#define gpio_cansleep __gpio_cansleep
++#define gpio_to_irq __gpio_to_irq
++
++#endif /* __ASM_MACH_RALINK_GPIO_H */
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -201,6 +201,12 @@ config GPIO_PXA
+ help
+ Say yes here to support the PXA GPIO device
+
++config GPIO_RALINK
++ bool "Ralink GPIO Support"
++ depends on RALINK
++ help
++ Say yes here to support the Ralink SoC GPIO device
++
+ config GPIO_SPEAR_SPICS
+ bool "ST SPEAr13xx SPI Chip Select as GPIO support"
+ depends on PLAT_SPEAR
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf85
+ obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
+ obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
+ obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
++obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o
+ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
+ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
+ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
+--- /dev/null
++++ b/drivers/gpio/gpio-ralink.c
+@@ -0,0 +1,176 @@
++/*
++ * 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) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++#include <linux/spinlock.h>
++#include <linux/platform_device.h>
++
++enum ralink_gpio_reg {
++ GPIO_REG_INT = 0,
++ GPIO_REG_EDGE,
++ GPIO_REG_RENA,
++ GPIO_REG_FENA,
++ GPIO_REG_DATA,
++ GPIO_REG_DIR,
++ GPIO_REG_POL,
++ GPIO_REG_SET,
++ GPIO_REG_RESET,
++ GPIO_REG_TOGGLE,
++ GPIO_REG_MAX
++};
++
++struct ralink_gpio_chip {
++ struct gpio_chip chip;
++ u8 regs[GPIO_REG_MAX];
++
++ spinlock_t lock;
++ void __iomem *membase;
++};
++
++static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip)
++{
++ struct ralink_gpio_chip *rg;
++
++ rg = container_of(chip, struct ralink_gpio_chip, chip);
++ return rg;
++}
++
++static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val)
++{
++ iowrite32(val, rg->membase + rg->regs[reg]);
++}
++
++static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg)
++{
++ return ioread32(rg->membase + rg->regs[reg]);
++}
++
++static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++
++ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset));
++}
++
++static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++
++ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset));
++}
++
++static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++ unsigned long flags;
++ u32 t;
++
++ spin_lock_irqsave(&rg->lock, flags);
++ t = rt_gpio_r32(rg, GPIO_REG_DIR);
++ t &= ~BIT(offset);
++ rt_gpio_w32(rg, GPIO_REG_DIR, t);
++ spin_unlock_irqrestore(&rg->lock, flags);
++
++ return 0;
++}
++
++static int ralink_gpio_direction_output(struct gpio_chip *chip,
++ unsigned offset, int value)
++{
++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++ unsigned long flags;
++ u32 t;
++
++ spin_lock_irqsave(&rg->lock, flags);
++ ralink_gpio_set(chip, offset, value);
++ t = rt_gpio_r32(rg, GPIO_REG_DIR);
++ t |= BIT(offset);
++ rt_gpio_w32(rg, GPIO_REG_DIR, t);
++ spin_unlock_irqrestore(&rg->lock, flags);
++
++ return 0;
++}
++
++static int ralink_gpio_probe(struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ struct ralink_gpio_chip *gc;
++ const __be32 *ngpio;
++
++ if (!res) {
++ dev_err(&pdev->dev, "failed to find resource\n");
++ return -ENOMEM;
++ }
++
++ gc = devm_kzalloc(&pdev->dev,
++ sizeof(struct ralink_gpio_chip), GFP_KERNEL);
++ if (!gc)
++ return -ENOMEM;
++
++ gc->membase = devm_request_and_ioremap(&pdev->dev, res);
++ if (!gc->membase) {
++ dev_err(&pdev->dev, "cannot remap I/O memory region\n");
++ return -ENOMEM;
++ }
++
++ if (of_property_read_u8_array(np, "ralink,register-map",
++ gc->regs, GPIO_REG_MAX)) {
++ dev_err(&pdev->dev, "failed to read register definition\n");
++ return -EINVAL;
++ }
++
++ ngpio = of_get_property(np, "ralink,num-gpios", NULL);
++ if (!ngpio) {
++ dev_err(&pdev->dev, "failed to read number of pins\n");
++ return -EINVAL;
++ }
++
++ spin_lock_init(&gc->lock);
++
++ gc->chip.label = dev_name(&pdev->dev);
++ gc->chip.of_node = np;
++ gc->chip.base = -1;
++ gc->chip.ngpio = be32_to_cpu(*ngpio);
++ gc->chip.direction_input = ralink_gpio_direction_input;
++ gc->chip.direction_output = ralink_gpio_direction_output;
++ gc->chip.get = ralink_gpio_get;
++ gc->chip.set = ralink_gpio_set;
++
++ /* set polarity to low for all lines */
++ rt_gpio_w32(gc, GPIO_REG_POL, 0);
++
++ dev_info(&pdev->dev, "registering %d gpios\n", gc->chip.ngpio);
++
++ return gpiochip_add(&gc->chip);
++}
++
++static const struct of_device_id ralink_gpio_match[] = {
++ { .compatible = "ralink,rt2880-gpio" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ralink_gpio_match);
++
++static struct platform_driver ralink_gpio_driver = {
++ .probe = ralink_gpio_probe,
++ .driver = {
++ .name = "rt2880_gpio",
++ .owner = THIS_MODULE,
++ .of_match_table = ralink_gpio_match,
++ },
++};
++
++static int __init ralink_gpio_init(void)
++{
++ return platform_driver_register(&ralink_gpio_driver);
++}
++
++subsys_initcall(ralink_gpio_init);
+++ /dev/null
-From 4cca623b74420aacf656b968fde29aace96ae3db Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 7 Apr 2013 16:57:30 +0200
-Subject: [PATCH 3/3] MIPS: ralink: add cpu-feature-overrides.h for
- RT3662/3883 SoCs
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- .../asm/mach-ralink/rt3883/cpu-feature-overrides.h | 55 ++++++++++++++++++++
- arch/mips/ralink/Platform | 1 +
- 2 files changed, 56 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h
-
---- /dev/null
-+++ b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h
-@@ -0,0 +1,55 @@
-+/*
-+ * Ralink RT3662/RT3883 specific CPU feature overrides
-+ *
-+ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@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 _RT3883_CPU_FEATURE_OVERRIDES_H
-+#define _RT3883_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 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 /* _RT3883_CPU_FEATURE_OVERRIDES_H */
---- a/arch/mips/ralink/Platform
-+++ b/arch/mips/ralink/Platform
-@@ -20,6 +20,7 @@ cflags-$(CONFIG_SOC_RT305X) += -I$(srctr
- # Ralink RT3883
- #
- load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
-+cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883
-
- #
- # Ralink MT7620
+++ /dev/null
---- a/arch/mips/pci/pci-rt3883.c
-+++ b/arch/mips/pci/pci-rt3883.c
-@@ -1,7 +1,7 @@
- /*
-- * Ralink RT3883 SoC PCI support
-+ * Ralink RT3662/RT3883 SoC PCI support
- *
-- * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
- *
- * Parts of this file are based on Ralink's 2.6.21 BSP
- *
-@@ -16,52 +16,82 @@
- #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/rt3883_regs.h>
-+#include <asm/mach-ralink/ralink_regs.h>
-
- #define RT3883_MEMORY_BASE 0x00000000
- #define RT3883_MEMORY_SIZE 0x02000000
-
--#define RT3883_PCI_MEM_BASE 0x20000000
--#define RT3883_PCI_MEM_SIZE 0x10000000
--#define RT3883_PCI_IO_BASE 0x10160000
--#define RT3883_PCI_IO_SIZE 0x00010000
--
--#define RT3883_PCI_REG_PCICFG_ADDR 0x00
--#define RT3883_PCI_REG_PCIRAW_ADDR 0x04
--#define RT3883_PCI_REG_PCIINT_ADDR 0x08
--#define RT3883_PCI_REG_PCIMSK_ADDR 0x0c
--#define RT3833_PCI_PCIINT_PCIE BIT(20)
--#define RT3833_PCI_PCIINT_PCI1 BIT(19)
--#define RT3833_PCI_PCIINT_PCI0 BIT(18)
-+#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_CONFIG_ADDR 0x20
--#define RT3883_PCI_REG_CONFIG_DATA 0x24
-+#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_ADDR(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10)
--#define RT3883_PCI_REG_IMBASEBAR0_ADDR(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18)
-+#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)
-
--static int (*rt3883_pci_plat_dev_init)(struct pci_dev *dev);
--static void __iomem *rt3883_pci_base;
--static DEFINE_SPINLOCK(rt3883_pci_lock);
-+#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)
-
--static inline u32 rt3883_pci_rr(unsigned reg)
-+#define RT3883_PCI_IRQ_COUNT 32
-+
-+#define RT3883_P2P_BR_DEVNUM 1
-+
-+struct rt3883_pci_controller {
-+ void __iomem *base;
-+ spinlock_t lock;
-+
-+ struct irq_domain *irq_domain;
-+
-+ struct pci_controller pci_controller;
-+ struct resource io_res;
-+ struct resource mem_res;
-+
-+ bool pcie_ready;
-+ unsigned char p2p_devnum;
-+};
-+
-+static inline struct rt3883_pci_controller *
-+pci_bus_to_rt3883_controller(struct pci_bus *bus)
- {
-- return readl(rt3883_pci_base + reg);
-+ 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_wr(u32 val, unsigned reg)
-+static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc,
-+ u32 val, unsigned reg)
- {
-- writel(val, rt3883_pci_base + reg);
-+ iowrite32(val, rpc->base + reg);
- }
-
- static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot,
-@@ -71,7 +101,8 @@ static inline u32 rt3883_pci_get_cfgaddr
- 0x80000000);
- }
-
--static u32 rt3883_pci_read_u32(unsigned bus, unsigned slot,
-+static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc,
-+ unsigned bus, unsigned slot,
- unsigned func, unsigned reg)
- {
- unsigned long flags;
-@@ -80,15 +111,16 @@ static u32 rt3883_pci_read_u32(unsigned
-
- address = rt3883_pci_get_cfgaddr(bus, slot, func, reg);
-
-- spin_lock_irqsave(&rt3883_pci_lock, flags);
-- rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-- ret = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA);
-- spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+ 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_u32(unsigned bus, unsigned slot,
-+static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc,
-+ unsigned bus, unsigned slot,
- unsigned func, unsigned reg, u32 val)
- {
- unsigned long flags;
-@@ -96,84 +128,61 @@ static void rt3883_pci_write_u32(unsigne
-
- address = rt3883_pci_get_cfgaddr(bus, slot, func, reg);
-
-- spin_lock_irqsave(&rt3883_pci_lock, flags);
-- rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-- rt3883_pci_wr(val, RT3883_PCI_REG_CONFIG_DATA);
-- spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+ 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;
-
-- pending = rt3883_pci_rr(RT3883_PCI_REG_PCIINT_ADDR) &
-- rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+ 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;
- }
-
-- if (pending & RT3833_PCI_PCIINT_PCI0)
-- generic_handle_irq(RT3883_PCI_IRQ_PCI0);
-+ while (pending) {
-+ unsigned bit = __ffs(pending);
-
-- if (pending & RT3833_PCI_PCIINT_PCI1)
-- generic_handle_irq(RT3883_PCI_IRQ_PCI1);
-+ irq = irq_find_mapping(rpc->irq_domain, bit);
-+ generic_handle_irq(irq);
-
-- if (pending & RT3833_PCI_PCIINT_PCIE)
-- generic_handle_irq(RT3883_PCI_IRQ_PCIE);
-+ pending &= ~BIT(bit);
-+ }
- }
-
- static void rt3883_pci_irq_unmask(struct irq_data *d)
- {
-- int irq = d->irq;
-- u32 mask;
-+ struct rt3883_pci_controller *rpc;
- u32 t;
-
-- switch (irq) {
-- case RT3883_PCI_IRQ_PCI0:
-- mask = RT3833_PCI_PCIINT_PCI0;
-- break;
-- case RT3883_PCI_IRQ_PCI1:
-- mask = RT3833_PCI_PCIINT_PCI1;
-- break;
-- case RT3883_PCI_IRQ_PCIE:
-- mask = RT3833_PCI_PCIINT_PCIE;
-- break;
-- default:
-- BUG();
-- }
-+ rpc = irq_data_get_irq_chip_data(d);
-
-- t = rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-- rt3883_pci_wr(t | mask, RT3883_PCI_REG_PCIMSK_ADDR);
-+ 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_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
- }
-
- static void rt3883_pci_irq_mask(struct irq_data *d)
- {
-- int irq = d->irq;
-- u32 mask;
-+ struct rt3883_pci_controller *rpc;
- u32 t;
-
-- switch (irq) {
-- case RT3883_PCI_IRQ_PCI0:
-- mask = RT3833_PCI_PCIINT_PCI0;
-- break;
-- case RT3883_PCI_IRQ_PCI1:
-- mask = RT3833_PCI_PCIINT_PCI1;
-- break;
-- case RT3883_PCI_IRQ_PCIE:
-- mask = RT3833_PCI_PCIINT_PCIE;
-- break;
-- default:
-- BUG();
-- }
-+ rpc = irq_data_get_irq_chip_data(d);
-
-- t = rt3883_pci_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-- rt3883_pci_wr(t & ~mask, RT3883_PCI_REG_PCIMSK_ADDR);
-+ 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_rr(RT3883_PCI_REG_PCIMSK_ADDR);
-+ rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
- }
-
- static struct irq_chip rt3883_pci_irq_chip = {
-@@ -183,36 +192,84 @@ static struct irq_chip rt3883_pci_irq_ch
- .irq_mask_ack = rt3883_pci_irq_mask,
- };
-
--static void __init rt3883_pci_irq_init(void)
-+static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq,
-+ irq_hw_number_t hw)
- {
-- int i;
-+ 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)
-+{
-+ struct device_node *np = dev->of_node;
-+ struct device_node *intc_np;
-+ int irq;
-+ int err;
-+
-+ intc_np = of_get_child_by_name(np, "interrupt-controller");
-+ if (!intc_np) {
-+ dev_err(dev, "no %s child node found", "interrupt-controller");
-+ return -ENODEV;
-+ }
-+
-+ irq = irq_of_parse_and_map(intc_np, 0);
-+ if (irq == 0) {
-+ dev_err(dev, "%s has no IRQ", of_node_full_name(intc_np));
-+ err = -EINVAL;
-+ goto err_put_intc;
-+ }
-
- /* disable all interrupts */
-- rt3883_pci_wr(0, RT3883_PCI_REG_PCIMSK_ADDR);
-+ rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA);
-
-- for (i = RT3883_PCI_IRQ_BASE;
-- i < RT3883_PCI_IRQ_BASE + RT3883_PCI_IRQ_COUNT; i++) {
-- irq_set_chip_and_handler(i, &rt3883_pci_irq_chip,
-- handle_level_irq);
-+ rpc->irq_domain =
-+ irq_domain_add_linear(intc_np, RT3883_PCI_IRQ_COUNT,
-+ &rt3883_pci_irq_domain_ops,
-+ rpc);
-+ if (!rpc->irq_domain) {
-+ dev_err(dev, "unable to add IRQ domain\n");
-+ err = -ENODEV;
-+ goto err_put_intc;
- }
-
-- irq_set_chained_handler(RT3883_CPU_IRQ_PCI, rt3883_pci_irq_handler);
-+ irq_set_handler_data(irq, rpc);
-+ irq_set_chained_handler(irq, rt3883_pci_irq_handler);
-+
-+ return 0;
-+
-+err_put_intc:
-+ of_node_put(intc_np);
-+ return err;
- }
-
- 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(&rt3883_pci_lock, flags);
-- rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-- data = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA);
-- spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+ 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:
-@@ -232,16 +289,22 @@ static int rt3883_pci_config_read(struct
- 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(&rt3883_pci_lock, flags);
-- rt3883_pci_wr(address, RT3883_PCI_REG_CONFIG_ADDR);
-- data = rt3883_pci_rr(RT3883_PCI_REG_CONFIG_DATA);
-+ 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:
-@@ -257,8 +320,8 @@ static int rt3883_pci_config_write(struc
- break;
- }
-
-- rt3883_pci_wr(data, RT3883_PCI_REG_CONFIG_DATA);
-- spin_unlock_irqrestore(&rt3883_pci_lock, flags);
-+ rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA);
-+ spin_unlock_irqrestore(&rpc->lock, flags);
-
- return PCIBIOS_SUCCESSFUL;
- }
-@@ -268,220 +331,310 @@ static struct pci_ops rt3883_pci_ops = {
- .write = rt3883_pci_config_write,
- };
-
--static struct resource rt3883_pci_mem_resource = {
-- .name = "PCI MEM space",
-- .start = RT3883_PCI_MEM_BASE,
-- .end = RT3883_PCI_MEM_BASE + RT3883_PCI_MEM_SIZE - 1,
-- .flags = IORESOURCE_MEM,
--};
--
--static struct resource rt3883_pci_io_resource = {
-- .name = "PCI IO space",
-- .start = RT3883_PCI_IO_BASE,
-- .end = RT3883_PCI_IO_BASE + RT3883_PCI_IO_SIZE - 1,
-- .flags = IORESOURCE_IO,
--};
--
--static struct pci_controller rt3883_pci_controller = {
-- .pci_ops = &rt3883_pci_ops,
-- .mem_resource = &rt3883_pci_mem_resource,
-- .io_resource = &rt3883_pci_io_resource,
--};
--
--static void rt3883_pci_preinit(unsigned mode)
-+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) {
-- u32 val;
-+ rstctrl |= RT3883_RSTCTRL_PCIE;
-+ rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
-
-- val = rt3883_sysc_rr(RT3883_SYSC_REG_SYSCFG1);
-- val &= ~(0x30);
-- val |= (2 << 4);
-- rt3883_sysc_wr(val, RT3883_SYSC_REG_SYSCFG1);
--
-- val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-- val &= ~BIT(31);
-- rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN0);
--
-- val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN1);
-- val &= 0x80ffffff;
-- rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN1);
--
-- val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN1);
-- val |= 0xa << 24;
-- rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN1);
--
-- val = rt3883_sysc_rr(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-- val |= BIT(31);
-- rt3883_sysc_wr(val, RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+ /* 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_sysc_rr(RT3883_SYSC_REG_SYSCFG1);
-- syscfg1 &= ~(RT3883_SYSCFG1_PCIE_RC_MODE |
-- RT3883_SYSCFG1_PCI_HOST_MODE);
--
-- rstctrl = rt3883_sysc_rr(RT3883_SYSC_REG_RSTCTRL);
-- rstctrl |= (RT3883_RSTCTRL_PCI | RT3883_RSTCTRL_PCIE);
--
-- clkcfg1 = rt3883_sysc_rr(RT3883_SYSC_REG_CLKCFG1);
-- clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN |
-- RT3883_CLKCFG1_PCIE_CLK_EN);
-+ 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) {
-- syscfg1 |= RT3883_SYSCFG1_PCI_HOST_MODE;
- clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN;
- rstctrl &= ~RT3883_RSTCTRL_PCI;
- }
-+
- if (mode & RT3883_PCI_MODE_PCIE) {
-- syscfg1 |= RT3883_SYSCFG1_PCI_HOST_MODE |
-- RT3883_SYSCFG1_PCIE_RC_MODE;
- clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN;
- rstctrl &= ~RT3883_RSTCTRL_PCIE;
- }
-
-- rt3883_sysc_wr(syscfg1, RT3883_SYSC_REG_SYSCFG1);
-- rt3883_sysc_wr(rstctrl, RT3883_SYSC_REG_RSTCTRL);
-- rt3883_sysc_wr(clkcfg1, RT3883_SYSC_REG_CLKCFG1);
-+ 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);
--}
-
--static int rt3883_pcie_ready(void)
--{
-- u32 status;
-+ /*
-+ * 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);
-
-- status = rt3883_pci_rr(RT3883_PCI_REG_STATUS(1));
-- if (status & BIT(0))
-- return 0;
-+ 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);
-+}
-
-- /* TODO: reset PCIe and turn off PCIe clock */
-+static inline void
-+rt3883_dump_pci_config(struct rt3883_pci_controller *rpc,
-+ int bus, int slot)
-+{
-+ int i;
-+
-+ for (i = 0; i < 16; i++) {
-+ u32 val;
-
-- return -ENODEV;
-+ val = rt3883_pci_read_cfg32(rpc, bus, slot, 0, i << 2);
-+ pr_info("pci %02x:%02x.0 0x%02x = %08x\n",
-+ bus, slot, i << 2, val);
-+ }
- }
-
--void __init rt3883_pci_init(unsigned mode)
-+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;
-
-- rt3883_pci_preinit(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);
-+
-+ rpc->pci_controller.of_node = of_get_child_by_name(np, "host-bridge");
-+ if (!rpc->pci_controller.of_node) {
-+ dev_err(dev, "no %s child node found", "host-bridge");
-+ return -ENODEV;
-+ }
-+
-+ mode = RT3883_PCI_MODE_NONE;
-+ for_each_child_of_node(rpc->pci_controller.of_node, child) {
-+ u32 slot;
-+
-+ if (!of_device_is_available(child))
-+ continue;
-+
-+ if (of_property_read_u32(child, "ralink,pci-slot",
-+ &slot)) {
-+ dev_err(dev, "no '%s' property found for %s\n",
-+ "ralink,pci-slot",
-+ of_node_full_name(child));
-+ continue;
-+ }
-
-- rt3883_pci_base = ioremap(RT3883_PCI_BASE, PAGE_SIZE);
-- if (rt3883_pci_base == NULL) {
-- pr_err("failed to ioremap PCI registers\n");
-- return;
-+ switch (slot) {
-+ case 1:
-+ mode |= RT3883_PCI_MODE_PCIE;
-+ break;
-+
-+ case 17:
-+ case 18:
-+ mode |= RT3883_PCI_MODE_PCI;
-+ break;
-+ }
- }
-
-- rt3883_pci_wr(0, RT3883_PCI_REG_PCICFG_ADDR);
-- if (mode & RT3883_PCI_MODE_PCI)
-- rt3883_pci_wr(BIT(16), RT3883_PCI_REG_PCICFG_ADDR);
-+ if (mode == RT3883_PCI_MODE_NONE) {
-+ dev_err(dev, "unable to determine PCI mode\n");
-+ err = -EINVAL;
-+ goto err_put_hb_node;
-+ }
-
-- msleep(500);
-+ dev_info(dev, "mode:%s%s\n",
-+ (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "",
-+ (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : "");
-
-- if (mode & RT3883_PCI_MODE_PCIE) {
-- err = rt3883_pcie_ready();
-- if (err)
-- return;
-- }
-+ rt3883_pci_preinit(rpc, mode);
-
-- if (mode & RT3883_PCI_MODE_PCI)
-- rt3883_pci_wr(0x79, RT3883_PCI_REG_ARBCTL);
-+ rpc->pci_controller.pci_ops = &rt3883_pci_ops;
-+ rpc->pci_controller.io_resource = &rpc->io_res;
-+ rpc->pci_controller.mem_resource = &rpc->mem_res;
-
-- rt3883_pci_wr(RT3883_PCI_MEM_BASE, RT3883_PCI_REG_MEMBASE);
-- rt3883_pci_wr(RT3883_PCI_IO_BASE, RT3883_PCI_REG_IOBASE);
-+ /* 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_wr(0x03ff0000, RT3883_PCI_REG_BAR0SETUP_ADDR(0));
-- rt3883_pci_wr(RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0_ADDR(0));
-- rt3883_pci_wr(0x08021814, RT3883_PCI_REG_ID(0));
-- rt3883_pci_wr(0x00800001, RT3883_PCI_REG_CLASS(0));
-- rt3883_pci_wr(0x28801814, RT3883_PCI_REG_SUBID(0));
-+ 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_wr(0x01ff0000, RT3883_PCI_REG_BAR0SETUP_ADDR(1));
-- rt3883_pci_wr(RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0_ADDR(1));
-- rt3883_pci_wr(0x08021814, RT3883_PCI_REG_ID(1));
-- rt3883_pci_wr(0x06040001, RT3883_PCI_REG_CLASS(1));
-- rt3883_pci_wr(0x28801814, RT3883_PCI_REG_SUBID(1));
--
-- rt3883_pci_irq_init();
-+ 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_u32(0, 0x01, 0, PCI_COMMAND);
-- val |= 0x7;
-- rt3883_pci_write_u32(0, 0x01, 0, PCI_COMMAND, val);
-+ 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_u32(0, 0x00, 0, PCI_COMMAND);
-- val |= 0x7;
-- rt3883_pci_write_u32(0, 0x00, 0, PCI_COMMAND, val);
-+ 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);
-
-- ioport_resource.start = rt3883_pci_io_resource.start;
-- ioport_resource.end = rt3883_pci_io_resource.end;
-+ return 0;
-
-- register_pci_controller(&rt3883_pci_controller);
-+err_put_hb_node:
-+ of_node_put(rpc->pci_controller.of_node);
-+ return err;
- }
-
- int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
- {
-- int irq = -1;
--
-- switch (dev->bus->number) {
-- case 0:
-- switch (PCI_SLOT(dev->devfn)) {
-- case 0x00:
-- rt3883_pci_wr(0x03ff0001,
-- RT3883_PCI_REG_BAR0SETUP_ADDR(0));
-- rt3883_pci_wr(0x03ff0001,
-- RT3883_PCI_REG_BAR0SETUP_ADDR(1));
--
-- rt3883_pci_write_u32(0, 0x00, 0, PCI_BASE_ADDRESS_0,
-- RT3883_MEMORY_BASE);
-- rt3883_pci_read_u32(0, 0x00, 0, PCI_BASE_ADDRESS_0);
--
-- irq = RT3883_CPU_IRQ_PCI;
-- break;
-- case 0x01:
-- rt3883_pci_write_u32(0, 0x01, 0, PCI_IO_BASE,
-- 0x00000101);
-- break;
-- case 0x11:
-- irq = RT3883_PCI_IRQ_PCI0;
-- break;
-- case 0x12:
-- irq = RT3883_PCI_IRQ_PCI1;
-- break;
-- }
-- break;
--
-- case 1:
-- irq = RT3883_PCI_IRQ_PCIE;
-- break;
-+ struct rt3883_pci_controller *rpc;
-+ struct of_irq dev_irq;
-+ int err;
-+ int irq;
-
-- default:
-- dev_err(&dev->dev, "no IRQ specified\n");
-- return irq;
-+ rpc = pci_bus_to_rt3883_controller(dev->bus);
-+ 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;
- }
-
--void __init rt3883_pci_set_plat_dev_init(int (*f)(struct pci_dev *dev))
-+int pcibios_plat_dev_init(struct pci_dev *dev)
- {
-- rt3883_pci_plat_dev_init = f;
-+ return 0;
- }
-
--int pcibios_plat_dev_init(struct pci_dev *dev)
--{
-- if (rt3883_pci_plat_dev_init)
-- return rt3883_pci_plat_dev_init(dev);
-+static const struct of_device_id rt3883_pci_ids[] = {
-+ { .compatible = "ralink,rt3883-pci" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, rt3883_pci_ids);
-
-- return 0;
-+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);
--- /dev/null
+From 32c1cff4c75925a0bbd305e85ed4adb30140cd42 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Apr 2013 23:16:18 +0200
+Subject: [PATCH 131/137] SPI: ralink: add Ralink SoC spi driver
+
+Add the driver needed to make SPI work on Ralink SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/spi/Kconfig | 6 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-ralink.c | 472 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 479 insertions(+)
+ create mode 100644 drivers/spi/spi-ralink.c
+
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -324,6 +324,12 @@ config SPI_RSPI
+ help
+ SPI driver for Renesas RSPI blocks.
+
++config SPI_RALINK
++ tristate "Ralink RT288x/RT305x/RT3662 SPI Controller"
++ depends on (SOC_RT288X || SOC_RT305X || SOC_RT3883)
++ help
++ This selects a driver for the Ralink RT288x/RT305x SPI Controller.
++
+ config SPI_S3C24XX
+ tristate "Samsung S3C24XX series SPI"
+ depends on ARCH_S3C24XX && EXPERIMENTAL
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.
+ obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o
+ obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
+ obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
++obj-$(CONFIG_SPI_RALINK) += spi-ralink.o
+ obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
+ spi-s3c24xx-hw-y := spi-s3c24xx.o
+ spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
+--- /dev/null
++++ b/drivers/spi/spi-ralink.c
+@@ -0,0 +1,472 @@
++/*
++ * spi-ralink.c -- Ralink RT288x/RT305x SPI controller driver
++ *
++ * Copyright (C) 2011 Sergiy <piratfm@gmail.com>
++ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * Some parts are based on spi-orion.c:
++ * Author: Shadi Ammouri <shadi@marvell.com>
++ * Copyright (C) 2007-2008 Marvell Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/spi/spi.h>
++
++#define DRIVER_NAME "spi-ralink"
++#define RALINK_NUM_CHIPSELECTS 1 /* only one slave is supported*/
++#define RALINK_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
++
++#define RAMIPS_SPI_STAT 0x00
++#define RAMIPS_SPI_CFG 0x10
++#define RAMIPS_SPI_CTL 0x14
++#define RAMIPS_SPI_DATA 0x20
++
++/* SPISTAT register bit field */
++#define SPISTAT_BUSY BIT(0)
++
++/* SPICFG register bit field */
++#define SPICFG_LSBFIRST 0
++#define SPICFG_MSBFIRST BIT(8)
++#define SPICFG_SPICLKPOL BIT(6)
++#define SPICFG_RXCLKEDGE_FALLING BIT(5)
++#define SPICFG_TXCLKEDGE_FALLING BIT(4)
++#define SPICFG_SPICLK_PRESCALE_MASK 0x7
++#define SPICFG_SPICLK_DIV2 0
++#define SPICFG_SPICLK_DIV4 1
++#define SPICFG_SPICLK_DIV8 2
++#define SPICFG_SPICLK_DIV16 3
++#define SPICFG_SPICLK_DIV32 4
++#define SPICFG_SPICLK_DIV64 5
++#define SPICFG_SPICLK_DIV128 6
++#define SPICFG_SPICLK_DISABLE 7
++
++/* SPICTL register bit field */
++#define SPICTL_HIZSDO BIT(3)
++#define SPICTL_STARTWR BIT(2)
++#define SPICTL_STARTRD BIT(1)
++#define SPICTL_SPIENA BIT(0)
++
++#ifdef DEBUG
++#define spi_debug(args...) printk(args)
++#else
++#define spi_debug(args...)
++#endif
++
++struct ralink_spi {
++ struct spi_master *master;
++ void __iomem *base;
++ unsigned int sys_freq;
++ unsigned int speed;
++ struct clk *clk;
++};
++
++static inline struct ralink_spi *spidev_to_ralink_spi(struct spi_device *spi)
++{
++ return spi_master_get_devdata(spi->master);
++}
++
++static inline u32 ralink_spi_read(struct ralink_spi *rs, u32 reg)
++{
++ return ioread32(rs->base + reg);
++}
++
++static inline void ralink_spi_write(struct ralink_spi *rs, u32 reg, u32 val)
++{
++ iowrite32(val, rs->base + reg);
++}
++
++static inline void ralink_spi_setbits(struct ralink_spi *rs, u32 reg, u32 mask)
++{
++ void __iomem *addr = rs->base + reg;
++ u32 val;
++
++ val = ioread32(addr);
++ val |= mask;
++ iowrite32(val, addr);
++}
++
++static inline void ralink_spi_clrbits(struct ralink_spi *rs, u32 reg, u32 mask)
++{
++ void __iomem *addr = rs->base + reg;
++ u32 val;
++
++ val = ioread32(addr);
++ val &= ~mask;
++ iowrite32(val, addr);
++}
++
++static int ralink_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
++{
++ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
++ u32 rate;
++ u32 prescale;
++ u32 reg;
++
++ spi_debug("%s: speed:%u\n", __func__, speed);
++
++ /*
++ * the supported rates are: 2, 4, 8, ... 128
++ * round up as we look for equal or less speed
++ */
++ rate = DIV_ROUND_UP(rs->sys_freq, speed);
++ spi_debug("%s: rate-1:%u\n", __func__, rate);
++ rate = roundup_pow_of_two(rate);
++ spi_debug("%s: rate-2:%u\n", __func__, rate);
++
++ /* check if requested speed is too small */
++ if (rate > 128)
++ return -EINVAL;
++
++ if (rate < 2)
++ rate = 2;
++
++ /* Convert the rate to SPI clock divisor value. */
++ prescale = ilog2(rate/2);
++ spi_debug("%s: prescale:%u\n", __func__, prescale);
++
++ reg = ralink_spi_read(rs, RAMIPS_SPI_CFG);
++ reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale);
++ ralink_spi_write(rs, RAMIPS_SPI_CFG, reg);
++ rs->speed = speed;
++ return 0;
++}
++
++/*
++ * called only when no transfer is active on the bus
++ */
++static int
++ralink_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
++{
++ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
++ unsigned int speed = spi->max_speed_hz;
++ int rc;
++ unsigned int bits_per_word = 8;
++
++ if ((t != NULL) && t->speed_hz)
++ speed = t->speed_hz;
++
++ if ((t != NULL) && t->bits_per_word)
++ bits_per_word = t->bits_per_word;
++
++ if (rs->speed != speed) {
++ spi_debug("%s: speed_hz:%u\n", __func__, speed);
++ rc = ralink_spi_baudrate_set(spi, speed);
++ if (rc)
++ return rc;
++ }
++
++ if (bits_per_word != 8) {
++ spi_debug("%s: bad bits_per_word: %u\n", __func__,
++ bits_per_word);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static void ralink_spi_set_cs(struct ralink_spi *rs, int enable)
++{
++ if (enable)
++ ralink_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
++ else
++ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
++}
++
++static inline int ralink_spi_wait_till_ready(struct ralink_spi *rs)
++{
++ int i;
++
++ for (i = 0; i < RALINK_SPI_WAIT_RDY_MAX_LOOP; i++) {
++ u32 status;
++
++ status = ralink_spi_read(rs, RAMIPS_SPI_STAT);
++ if ((status & SPISTAT_BUSY) == 0)
++ return 0;
++
++ udelay(1);
++ }
++
++ return -ETIMEDOUT;
++}
++
++static unsigned int
++ralink_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
++{
++ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
++ unsigned count = 0;
++ u8 *rx = xfer->rx_buf;
++ const u8 *tx = xfer->tx_buf;
++ int err;
++
++ spi_debug("%s(%d): %s %s\n", __func__, xfer->len,
++ (tx != NULL) ? "tx" : " ",
++ (rx != NULL) ? "rx" : " ");
++
++ if (tx) {
++ for (count = 0; count < xfer->len; count++) {
++ ralink_spi_write(rs, RAMIPS_SPI_DATA, tx[count]);
++ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR);
++ err = ralink_spi_wait_till_ready(rs);
++ if (err) {
++ dev_err(&spi->dev, "TX failed, err=%d\n", err);
++ goto out;
++ }
++ }
++ }
++
++ if (rx) {
++ for (count = 0; count < xfer->len; count++) {
++ ralink_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD);
++ err = ralink_spi_wait_till_ready(rs);
++ if (err) {
++ dev_err(&spi->dev, "RX failed, err=%d\n", err);
++ goto out;
++ }
++ rx[count] = (u8) ralink_spi_read(rs, RAMIPS_SPI_DATA);
++ }
++ }
++
++out:
++ return count;
++}
++
++static int ralink_spi_transfer_one_message(struct spi_master *master,
++ struct spi_message *m)
++{
++ struct ralink_spi *rs = spi_master_get_devdata(master);
++ struct spi_device *spi = m->spi;
++ struct spi_transfer *t = NULL;
++ int par_override = 0;
++ int status = 0;
++ int cs_active = 0;
++
++ /* Load defaults */
++ status = ralink_spi_setup_transfer(spi, NULL);
++ if (status < 0)
++ goto msg_done;
++
++ list_for_each_entry(t, &m->transfers, transfer_list) {
++ unsigned int bits_per_word = spi->bits_per_word;
++
++ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) {
++ dev_err(&spi->dev,
++ "message rejected: invalid transfer data buffers\n");
++ status = -EIO;
++ goto msg_done;
++ }
++
++ if (t->bits_per_word)
++ bits_per_word = t->bits_per_word;
++
++ if (bits_per_word != 8) {
++ dev_err(&spi->dev,
++ "message rejected: invalid transfer bits_per_word (%d bits)\n",
++ bits_per_word);
++ status = -EIO;
++ goto msg_done;
++ }
++
++ if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) {
++ dev_err(&spi->dev,
++ "message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n",
++ (rs->sys_freq / 128), t->speed_hz);
++ status = -EIO;
++ goto msg_done;
++ }
++
++ if (par_override || t->speed_hz || t->bits_per_word) {
++ par_override = 1;
++ status = ralink_spi_setup_transfer(spi, t);
++ if (status < 0)
++ goto msg_done;
++ if (!t->speed_hz && !t->bits_per_word)
++ par_override = 0;
++ }
++
++ if (!cs_active) {
++ ralink_spi_set_cs(rs, 1);
++ cs_active = 1;
++ }
++
++ if (t->len)
++ m->actual_length += ralink_spi_write_read(spi, t);
++
++ if (t->delay_usecs)
++ udelay(t->delay_usecs);
++
++ if (t->cs_change) {
++ ralink_spi_set_cs(rs, 0);
++ cs_active = 0;
++ }
++ }
++
++msg_done:
++ if (cs_active)
++ ralink_spi_set_cs(rs, 0);
++
++ m->status = status;
++ spi_finalize_current_message(master);
++
++ return 0;
++}
++
++static int ralink_spi_setup(struct spi_device *spi)
++{
++ struct ralink_spi *rs = spidev_to_ralink_spi(spi);
++
++ if ((spi->max_speed_hz == 0) ||
++ (spi->max_speed_hz > (rs->sys_freq / 2)))
++ spi->max_speed_hz = (rs->sys_freq / 2);
++
++ if (spi->max_speed_hz < (rs->sys_freq / 128)) {
++ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n",
++ spi->max_speed_hz);
++ return -EINVAL;
++ }
++
++ if (spi->bits_per_word != 0 && spi->bits_per_word != 8) {
++ dev_err(&spi->dev,
++ "setup: requested bits per words - os wrong %d bpw\n",
++ spi->bits_per_word);
++ return -EINVAL;
++ }
++
++ if (spi->bits_per_word == 0)
++ spi->bits_per_word = 8;
++
++ /*
++ * baudrate & width will be set ralink_spi_setup_transfer
++ */
++ return 0;
++}
++
++static void ralink_spi_reset(struct ralink_spi *rs)
++{
++ ralink_spi_write(rs, RAMIPS_SPI_CFG,
++ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING |
++ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL);
++ ralink_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA);
++}
++
++static int ralink_spi_probe(struct platform_device *pdev)
++{
++ struct spi_master *master;
++ struct ralink_spi *rs;
++ struct resource *r;
++ int status = 0;
++
++ master = spi_alloc_master(&pdev->dev, sizeof(*rs));
++ if (master == NULL) {
++ dev_dbg(&pdev->dev, "master allocation failed\n");
++ return -ENOMEM;
++ }
++
++ //if (pdev->id != -1)
++ master->bus_num = 0;
++
++ /* we support only mode 0, and no options */
++ master->mode_bits = 0;
++
++ master->setup = ralink_spi_setup;
++ master->transfer_one_message = ralink_spi_transfer_one_message;
++ master->num_chipselect = RALINK_NUM_CHIPSELECTS;
++ master->dev.of_node = pdev->dev.of_node;
++
++ dev_set_drvdata(&pdev->dev, master);
++
++ rs = spi_master_get_devdata(master);
++ rs->master = master;
++
++ rs->clk = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(rs->clk)) {
++ status = PTR_ERR(rs->clk);
++ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n",
++ status);
++ goto out_put_master;
++ }
++
++ status = clk_enable(rs->clk);
++ if (status)
++ goto out_put_clk;
++
++ rs->sys_freq = clk_get_rate(rs->clk);
++ spi_debug("%s: sys_freq: %u\n", __func__, rs->sys_freq);
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (r == NULL) {
++ status = -ENODEV;
++ goto out_disable_clk;
++ }
++
++ rs->base = devm_request_and_ioremap(&pdev->dev, r);
++ if (!rs->base) {
++ status = -EADDRNOTAVAIL;
++ goto out_disable_clk;
++ }
++
++ ralink_spi_reset(rs);
++
++ status = spi_register_master(master);
++ if (status)
++ goto out_disable_clk;
++
++ return 0;
++
++out_disable_clk:
++ clk_disable(rs->clk);
++out_put_clk:
++ clk_put(rs->clk);
++out_put_master:
++ spi_master_put(master);
++ return status;
++}
++
++static int ralink_spi_remove(struct platform_device *pdev)
++{
++ struct spi_master *master;
++ struct ralink_spi *rs;
++
++ master = dev_get_drvdata(&pdev->dev);
++ rs = spi_master_get_devdata(master);
++
++ clk_disable(rs->clk);
++ clk_put(rs->clk);
++ spi_unregister_master(master);
++
++ return 0;
++}
++
++MODULE_ALIAS("platform:" DRIVER_NAME);
++
++static const struct of_device_id ralink_spi_match[] = {
++ { .compatible = "ralink,rt2880-spi" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ralink_spi_match);
++
++static struct platform_driver ralink_spi_driver = {
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = ralink_spi_match,
++ },
++ .probe = ralink_spi_probe,
++ .remove = ralink_spi_remove,
++};
++
++module_platform_driver(ralink_spi_driver);
++
++MODULE_DESCRIPTION("Ralink SPI driver");
++MODULE_AUTHOR("Sergiy <piratfm@gmail.com>");
++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
++MODULE_LICENSE("GPL");
+++ /dev/null
---- a/drivers/net/ethernet/ramips/ramips_main.c
-+++ b/drivers/net/ethernet/ramips/ramips_main.c
-@@ -28,6 +28,7 @@
- #include <linux/of_device.h>
- #include <linux/clk.h>
- #include <linux/of_net.h>
-+#include <linux/of_mdio.h>
-
- #include "ramips_eth.h"
-
-@@ -406,12 +407,25 @@ ramips_mdio_reset(struct mii_bus *bus)
- static int
- ramips_mdio_init(struct raeth_priv *re)
- {
-+ struct device_node *mii_np;
- int err;
-- int i;
-+
-+ mii_np = of_get_child_by_name(re->of_node, "mdio-bus");
-+ if (!mii_np) {
-+ dev_err(re->parent, "no %s child node found", "mdio-bus");
-+ return -ENODEV;
-+ }
-+
-+ if (!of_device_is_available(mii_np)) {
-+ err = 0;
-+ goto err_put_node;
-+ }
-
- re->mii_bus = mdiobus_alloc();
-- if (re->mii_bus == NULL)
-- return -ENOMEM;
-+ if (re->mii_bus == NULL) {
-+ err = -ENOMEM;
-+ goto err_put_node;
-+ }
-
- re->mii_bus->name = "ramips_mdio";
- re->mii_bus->read = ramips_mdio_read;
-@@ -422,12 +436,7 @@ ramips_mdio_init(struct raeth_priv *re)
- re->mii_bus->parent = re->parent;
-
- snprintf(re->mii_bus->id, MII_BUS_ID_SIZE, "%s", "ramips_mdio");
-- re->mii_bus->phy_mask = 0;
--
-- for (i = 0; i < PHY_MAX_ADDR; i++)
-- re->mii_irq[i] = PHY_POLL;
--
-- err = mdiobus_register(re->mii_bus);
-+ err = of_mdiobus_register(re->mii_bus, mii_np);
- if (err)
- goto err_free_bus;
-
-@@ -435,13 +444,20 @@ ramips_mdio_init(struct raeth_priv *re)
-
- err_free_bus:
- kfree(re->mii_bus);
-+err_put_node:
-+ of_node_put(mii_np);
-+ re->mii_bus = NULL;
- return err;
- }
-
- static void
- ramips_mdio_cleanup(struct raeth_priv *re)
- {
-+ if (!re->mii_bus)
-+ return;
-+
- mdiobus_unregister(re->mii_bus);
-+ of_node_put(re->mii_bus->dev.of_node);
- kfree(re->mii_bus);
- }
-
-@@ -474,106 +490,86 @@ ramips_phy_link_adjust(struct net_device
- }
-
- static int
--ramips_phy_connect_multi(struct raeth_priv *re)
-+ramips_phy_connect_by_node(struct raeth_priv *re, struct device_node *phy_node)
- {
-- struct net_device *netdev = re->netdev;
-- struct phy_device *phydev = NULL;
-- int phy_addr;
-- int ret = 0;
--
-- for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-- if (!(re->phy_mask & (1 << phy_addr)))
-- continue;
--
-- if (re->mii_bus->phy_map[phy_addr] == NULL)
-- continue;
-+ struct phy_device *phydev;
-+ int phy_mode;
-
-- RADEBUG("%s: PHY found at %s, uid=%08x\n",
-- netdev->name,
-- dev_name(&re->mii_bus->phy_map[phy_addr]->dev),
-- re->mii_bus->phy_map[phy_addr]->phy_id);
--
-- if (phydev == NULL)
-- phydev = re->mii_bus->phy_map[phy_addr];
-- }
--
-- if (!phydev) {
-- netdev_err(netdev, "no PHY found with phy_mask=%08x\n",
-- re->phy_mask);
-- return -ENODEV;
-+ phy_mode = of_get_phy_mode(re->of_node);
-+ if (phy_mode < 0) {
-+ dev_err(re->parent, "incorrect phy-mode\n");
-+ return -EINVAL;
- }
-
-- re->phy_dev = phy_connect(netdev, dev_name(&phydev->dev),
-- ramips_phy_link_adjust, 0, re->phy_if_mode);
--
-- if (IS_ERR(re->phy_dev)) {
-- netdev_err(netdev, "could not connect to PHY at %s\n",
-- dev_name(&phydev->dev));
-+ phydev = of_phy_connect(re->netdev, phy_node, ramips_phy_link_adjust,
-+ 0, phy_mode);
-+ if (IS_ERR(phydev)) {
-+ dev_err(re->parent, "could not connect to PHY\n");
- return PTR_ERR(re->phy_dev);
- }
-
- phydev->supported &= PHY_GBIT_FEATURES;
- phydev->advertising = phydev->supported;
-
-- RADEBUG("%s: connected to PHY at %s [uid=%08x, driver=%s]\n",
-- netdev->name, dev_name(&phydev->dev),
-- phydev->phy_id, phydev->drv->name);
-+ dev_info(re->parent,
-+ "connected to PHY at %s [uid=%08x, driver=%s]\n",
-+ dev_name(&phydev->dev), phydev->phy_id,
-+ phydev->drv->name);
-
-+ re->phy_dev = phydev;
- re->link = 0;
- re->speed = 0;
- re->duplex = -1;
- re->rx_fc = 0;
- re->tx_fc = 0;
-
-- return ret;
-+ return 0;
- }
-
- static int
--ramips_phy_connect_fixed(struct raeth_priv *re)
-+ramips_phy_connect_fixed(struct raeth_priv *re, const __be32 *link, int size)
- {
-- if (!re->speed) {
-- const __be32 *link;
-- int size;
--
-- link = of_get_property(re->of_node,
-- "ralink,fixed-link", &size);
-- if (!link || size != (4 * sizeof(*link)))
-- return -ENOENT;
--
-- re->speed = be32_to_cpup(link++);
-- re->duplex = be32_to_cpup(link++);
-- re->tx_fc = be32_to_cpup(link++);
-- re->rx_fc = be32_to_cpup(link++);
-+ if (size != (4 * sizeof(*link))) {
-+ dev_err(re->parent, "invalid fixed-link property\n");
-+ return -EINVAL;
- }
-
-+ re->speed = be32_to_cpup(link++);
-+ re->duplex = be32_to_cpup(link++);
-+ re->tx_fc = be32_to_cpup(link++);
-+ re->rx_fc = be32_to_cpup(link++);
-+
- switch (re->speed) {
- case SPEED_10:
- case SPEED_100:
- case SPEED_1000:
- break;
- default:
-- netdev_err(re->netdev, "invalid speed specified\n");
-+ dev_err(re->parent, "invalid link speed: %d\n", re->speed);
- return -EINVAL;
- }
-
-- pr_info("%s: using fixed link parameters\n", re->netdev->name);
-+ dev_info(re->parent, "using fixed link parameters\n");
- return 0;
- }
-
- static int
- ramips_phy_connect(struct raeth_priv *re)
- {
-- const __be32 *mask;
--
-- mask = of_get_property(re->of_node, "ralink,phy-mask", NULL);
-- re->phy_if_mode = of_get_phy_mode(re->of_node);
--
-- if (!re->phy_if_mode || !mask)
-- return ramips_phy_connect_fixed(re);
--
-- re->phy_mask = be32_to_cpup(mask);
-- return ramips_phy_connect_multi(re);
-+ struct device_node *phy_node;
-+ const __be32 *p32;
-+ int size;
-+
-+ phy_node = of_parse_phandle(re->of_node, "phy-handle", 0);
-+ if (phy_node)
-+ return ramips_phy_connect_by_node(re, phy_node);
-+
-+ p32 = of_get_property(re->of_node, "ralink,fixed-link", &size);
-+ if (p32)
-+ return ramips_phy_connect_fixed(re, p32, size);
-
-+ dev_err(re->parent, "unable to get connection type\n");
-+ return -EINVAL;
- }
-
- static void
--- /dev/null
+From 15bcdbd78abacbe0986a1904d2e2b5dcfe780b5b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 22 Jan 2013 16:01:07 +0100
+Subject: [PATCH 132/137] serial: of: allow au1x00 and rt288x to load from OF
+
+In order to make serial_8250 loadable via OF on Au1x00 and Ralink WiSoC we need
+to default the iotype to UPIO_AU.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/tty/serial/of_serial.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/of_serial.c
++++ b/drivers/tty/serial/of_serial.c
+@@ -97,7 +97,10 @@ static int of_platform_serial_setup(stru
+ port->regshift = prop;
+
+ port->irq = irq_of_parse_and_map(np, 0);
+- port->iotype = UPIO_MEM;
++ if (of_device_is_compatible(np, "ralink,rt2880-uart"))
++ port->iotype = UPIO_AU;
++ else
++ port->iotype = UPIO_MEM;
+ if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
+ switch (prop) {
+ case 1:
+++ /dev/null
-From 3f32be8f012fb5476ea916e583e584cccc632a84 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 9 Apr 2013 18:31:15 +0200
-Subject: [PATCH V2 08/16] MIPS: ralink: make early_printk work on RT2880
-
-RT2880 has a different location for the early serial port.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/early_printk.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/mips/ralink/early_printk.c
-+++ b/arch/mips/ralink/early_printk.c
-@@ -11,7 +11,11 @@
-
- #include <asm/addrspace.h>
-
-+#ifdef CONFIG_SOC_RT288X
-+#define EARLY_UART_BASE 0x300c00
-+#else
- #define EARLY_UART_BASE 0x10000c00
-+#endif
-
- #define UART_REG_RX 0x00
- #define UART_REG_TX 0x04
--- /dev/null
+From 6471ee7bbf3f8b70267ba1dc93f067e18803c246 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 15 Mar 2013 18:16:01 +0100
+Subject: [PATCH 133/137] serial: ralink: adds mt7620 serial
+
+Add the config symbol for Mediatek7620 SoC to SERIAL_8250_RT288X
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/tty/serial/8250/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -280,7 +280,7 @@ config SERIAL_8250_EM
+
+ config SERIAL_8250_RT288X
+ bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support"
+- depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883)
++ depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620)
+ help
+ If you have a Ralink RT288x/RT305x SoC based board and want to use the
+ serial port, say Y to this option. The driver can handle up to 2 serial
--- /dev/null
+From 55e9ae6a23cb799b7c1d402e1cfda11a6bd1e86e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 21 Mar 2013 18:27:29 +0100
+Subject: [PATCH 134/137] PCI: MIPS: adds rt2880 pci support
+
+Add support for the pci found on the rt2880 SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/pci/Makefile | 1 +
+ arch/mips/pci/pci-rt2880.c | 281 ++++++++++++++++++++++++++++++++++++++++++++
+ arch/mips/ralink/Kconfig | 1 +
+ 3 files changed, 283 insertions(+)
+ create mode 100644 arch/mips/pci/pci-rt2880.c
+
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1
+ 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_RT2880) += pci-rt2880.o
+ obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
+ obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+--- /dev/null
++++ b/arch/mips/pci/pci-rt2880.c
+@@ -0,0 +1,281 @@
++/*
++ * Ralink RT288x SoC PCI register definitions
++ *
++ * Copyright (C) 2009 John Crispin <blogic@openwrt.org>
++ * Copyright (C) 2009 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/module.h>
++#include <linux/of_platform.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++
++#include <asm/mach-ralink/rt288x.h>
++
++#define RT2880_PCI_BASE 0x00440000
++#define RT288X_CPU_IRQ_PCI 4
++
++#define RT2880_PCI_MEM_BASE 0x20000000
++#define RT2880_PCI_MEM_SIZE 0x10000000
++#define RT2880_PCI_IO_BASE 0x00460000
++#define RT2880_PCI_IO_SIZE 0x00010000
++
++#define RT2880_PCI_REG_PCICFG_ADDR 0x00
++#define RT2880_PCI_REG_PCIMSK_ADDR 0x0c
++#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10
++#define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18
++#define RT2880_PCI_REG_CONFIG_ADDR 0x20
++#define RT2880_PCI_REG_CONFIG_DATA 0x24
++#define RT2880_PCI_REG_MEMBASE 0x28
++#define RT2880_PCI_REG_IOBASE 0x2c
++#define RT2880_PCI_REG_ID 0x30
++#define RT2880_PCI_REG_CLASS 0x34
++#define RT2880_PCI_REG_SUBID 0x38
++#define RT2880_PCI_REG_ARBCTL 0x80
++
++static void __iomem *rt2880_pci_base;
++static DEFINE_SPINLOCK(rt2880_pci_lock);
++
++static u32 rt2880_pci_reg_read(u32 reg)
++{
++ return readl(rt2880_pci_base + reg);
++}
++
++static void rt2880_pci_reg_write(u32 val, u32 reg)
++{
++ writel(val, rt2880_pci_base + reg);
++}
++
++static inline u32 rt2880_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 int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 *val)
++{
++ unsigned long flags;
++ u32 address;
++ u32 data;
++
++ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
++ PCI_FUNC(devfn), where);
++
++ spin_lock_irqsave(&rt2880_pci_lock, flags);
++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
++ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
++ spin_unlock_irqrestore(&rt2880_pci_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 rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ unsigned long flags;
++ u32 address;
++ u32 data;
++
++ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
++ PCI_FUNC(devfn), where);
++
++ spin_lock_irqsave(&rt2880_pci_lock, flags);
++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
++ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
++
++ 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;
++ }
++
++ rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA);
++ spin_unlock_irqrestore(&rt2880_pci_lock, flags);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops rt2880_pci_ops = {
++ .read = rt2880_pci_config_read,
++ .write = rt2880_pci_config_write,
++};
++
++static struct resource rt2880_pci_mem_resource = {
++ .name = "PCI MEM space",
++ .start = RT2880_PCI_MEM_BASE,
++ .end = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource rt2880_pci_io_resource = {
++ .name = "PCI IO space",
++ .start = RT2880_PCI_IO_BASE,
++ .end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1,
++ .flags = IORESOURCE_IO,
++};
++
++static struct pci_controller rt2880_pci_controller = {
++ .pci_ops = &rt2880_pci_ops,
++ .mem_resource = &rt2880_pci_mem_resource,
++ .io_resource = &rt2880_pci_io_resource,
++};
++
++static inline u32 rt2880_pci_read_u32(unsigned long reg)
++{
++ unsigned long flags;
++ u32 address;
++ u32 ret;
++
++ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg);
++
++ spin_lock_irqsave(&rt2880_pci_lock, flags);
++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
++ ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
++ spin_unlock_irqrestore(&rt2880_pci_lock, flags);
++
++ return ret;
++}
++
++static inline void rt2880_pci_write_u32(unsigned long reg, u32 val)
++{
++ unsigned long flags;
++ u32 address;
++
++ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg);
++
++ spin_lock_irqsave(&rt2880_pci_lock, flags);
++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
++ rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA);
++ spin_unlock_irqrestore(&rt2880_pci_lock, flags);
++}
++
++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ u16 cmd;
++ int irq = -1;
++
++ if (dev->bus->number != 0)
++ return irq;
++
++ switch (PCI_SLOT(dev->devfn)) {
++ case 0x00:
++ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
++ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
++ break;
++ case 0x11:
++ irq = RT288X_CPU_IRQ_PCI;
++ break;
++ default:
++ printk("%s:%s[%d] trying to alloc unknown pci irq\n",
++ __FILE__, __func__, __LINE__);
++ BUG();
++ break;
++ }
++
++ pci_write_config_byte((struct pci_dev*)dev, PCI_CACHE_LINE_SIZE, 0x14);
++ pci_write_config_byte((struct pci_dev*)dev, PCI_LATENCY_TIMER, 0xFF);
++ pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
++ PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK |
++ PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY;
++ pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd);
++ pci_write_config_byte((struct pci_dev*)dev, PCI_INTERRUPT_LINE,
++ dev->irq);
++ return irq;
++}
++
++static int rt288x_pci_probe(struct platform_device *pdev)
++{
++ void __iomem *io_map_base;
++ int i;
++
++ rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE);
++
++ io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE);
++ rt2880_pci_controller.io_map_base = (unsigned long) io_map_base;
++ set_io_port_base((unsigned long) io_map_base);
++
++ ioport_resource.start = RT2880_PCI_IO_BASE;
++ ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1;
++
++ rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR);
++ for(i = 0; i < 0xfffff; i++) {}
++
++ rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL);
++ rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR);
++ rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE);
++ rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE);
++ rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR);
++ rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID);
++ rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS);
++ rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID);
++ rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR);
++
++ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
++ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
++
++ register_pci_controller(&rt2880_pci_controller);
++ return 0;
++}
++
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ return 0;
++}
++
++static const struct of_device_id rt288x_pci_match[] = {
++ { .compatible = "ralink,rt288x-pci" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt288x_pci_match);
++
++static struct platform_driver rt288x_pci_driver = {
++ .probe = rt288x_pci_probe,
++ .driver = {
++ .name = "rt288x-pci",
++ .owner = THIS_MODULE,
++ .of_match_table = rt288x_pci_match,
++ },
++};
++
++int __init pcibios_init(void)
++{
++ int ret = platform_driver_register(&rt288x_pci_driver);
++ if (ret)
++ pr_info("rt288x-pci: Error registering platform driver!");
++ return ret;
++}
++
++arch_initcall(pcibios_init);
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -8,6 +8,7 @@ choice
+
+ config SOC_RT288X
+ bool "RT288x"
++ select HW_HAS_PCI
+
+ config SOC_RT305X
+ bool "RT305x"
--- /dev/null
+From 2a5dccdb00d85a6ad6111d7a2b13f9f4fae35838 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 21 Mar 2013 17:34:08 +0100
+Subject: [PATCH 135/137] PCI: MIPS: adds rt3883 pci support
+
+Add support for the pcie found on the rt3883 SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/pci/Makefile | 1 +
+ arch/mips/pci/pci-rt3883.c | 640 ++++++++++++++++++++++++++++++++++++++++++++
+ arch/mips/ralink/Kconfig | 1 +
+ 3 files changed, 642 insertions(+)
+ create mode 100644 arch/mips/pci/pci-rt3883.c
+
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops
+ obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
+ obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
+ obj-$(CONFIG_SOC_RT2880) += pci-rt2880.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
+--- /dev/null
++++ b/arch/mips/pci/pci-rt3883.c
+@@ -0,0 +1,640 @@
++/*
++ * 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 irq_domain *irq_domain;
++
++ struct pci_controller pci_controller;
++ struct resource io_res;
++ struct resource mem_res;
++
++ bool pcie_ready;
++ unsigned char p2p_devnum;
++};
++
++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)
++{
++ struct device_node *np = dev->of_node;
++ struct device_node *intc_np;
++ int irq;
++ int err;
++
++ intc_np = of_get_child_by_name(np, "interrupt-controller");
++ if (!intc_np) {
++ dev_err(dev, "no %s child node found", "interrupt-controller");
++ return -ENODEV;
++ }
++
++ irq = irq_of_parse_and_map(intc_np, 0);
++ if (irq == 0) {
++ dev_err(dev, "%s has no IRQ", of_node_full_name(intc_np));
++ err = -EINVAL;
++ goto err_put_intc;
++ }
++
++ /* disable all interrupts */
++ rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA);
++
++ rpc->irq_domain =
++ irq_domain_add_linear(intc_np, RT3883_PCI_IRQ_COUNT,
++ &rt3883_pci_irq_domain_ops,
++ rpc);
++ if (!rpc->irq_domain) {
++ dev_err(dev, "unable to add IRQ domain\n");
++ err = -ENODEV;
++ goto err_put_intc;
++ }
++
++ irq_set_handler_data(irq, rpc);
++ irq_set_chained_handler(irq, rt3883_pci_irq_handler);
++
++ return 0;
++
++err_put_intc:
++ of_node_put(intc_np);
++ return err;
++}
++
++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 inline void
++rt3883_dump_pci_config(struct rt3883_pci_controller *rpc,
++ int bus, int slot)
++{
++ int i;
++
++ for (i = 0; i < 16; i++) {
++ u32 val;
++
++ val = rt3883_pci_read_cfg32(rpc, bus, slot, 0, i << 2);
++ pr_info("pci %02x:%02x.0 0x%02x = %08x\n",
++ bus, slot, i << 2, val);
++ }
++}
++
++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);
++
++ rpc->pci_controller.of_node = of_get_child_by_name(np, "host-bridge");
++ if (!rpc->pci_controller.of_node) {
++ dev_err(dev, "no %s child node found", "host-bridge");
++ return -ENODEV;
++ }
++
++ mode = RT3883_PCI_MODE_NONE;
++ for_each_child_of_node(rpc->pci_controller.of_node, child) {
++ u32 slot;
++
++ if (!of_device_is_available(child))
++ continue;
++
++ if (of_property_read_u32(child, "ralink,pci-slot",
++ &slot)) {
++ dev_err(dev, "no '%s' property found for %s\n",
++ "ralink,pci-slot",
++ of_node_full_name(child));
++ continue;
++ }
++
++ switch (slot) {
++ 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);
++ return err;
++}
++
++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ struct rt3883_pci_controller *rpc;
++ struct of_irq dev_irq;
++ int err;
++ int irq;
++
++ rpc = pci_bus_to_rt3883_controller(dev->bus);
++ 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);
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -20,6 +20,7 @@ choice
+ bool "RT3883"
+ select USB_ARCH_HAS_OHCI
+ select USB_ARCH_HAS_EHCI
++ select HW_HAS_PCI
+
+ config SOC_MT7620
+ bool "MT7620"
--- /dev/null
+From 34fc7d26c01ba594be347aefcc31f55b36c06a72 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Apr 2013 23:20:03 +0200
+Subject: [PATCH 136/137] NET: MIPS: add ralink SoC ethernet driver
+
+Add support for Ralink FE and ESW.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ .../include/asm/mach-ralink/rt305x_esw_platform.h | 27 +
+ arch/mips/ralink/rt305x.c | 1 +
+ drivers/net/ethernet/Kconfig | 1 +
+ drivers/net/ethernet/Makefile | 1 +
+ drivers/net/ethernet/ramips/Kconfig | 18 +
+ drivers/net/ethernet/ramips/Makefile | 9 +
+ drivers/net/ethernet/ramips/ramips_debugfs.c | 127 ++
+ drivers/net/ethernet/ramips/ramips_esw.c | 1221 +++++++++++++++++++
+ drivers/net/ethernet/ramips/ramips_eth.h | 375 ++++++
+ drivers/net/ethernet/ramips/ramips_main.c | 1281 ++++++++++++++++++++
+ 10 files changed, 3061 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
+ create mode 100644 drivers/net/ethernet/ramips/Kconfig
+ create mode 100644 drivers/net/ethernet/ramips/Makefile
+ create mode 100644 drivers/net/ethernet/ramips/ramips_debugfs.c
+ create mode 100644 drivers/net/ethernet/ramips/ramips_esw.c
+ create mode 100644 drivers/net/ethernet/ramips/ramips_eth.h
+ create mode 100644 drivers/net/ethernet/ramips/ramips_main.c
+
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
+@@ -0,0 +1,27 @@
++/*
++ * Ralink RT305x SoC platform device registration
++ *
++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#ifndef _RT305X_ESW_PLATFORM_H
++#define _RT305X_ESW_PLATFORM_H
++
++enum {
++ RT305X_ESW_VLAN_CONFIG_NONE = 0,
++ RT305X_ESW_VLAN_CONFIG_LLLLW,
++ RT305X_ESW_VLAN_CONFIG_WLLLL,
++};
++
++struct rt305x_esw_platform_data
++{
++ u8 vlan_config;
++ u32 reg_initval_fct2;
++ u32 reg_initval_fpa2;
++};
++
++#endif /* _RT305X_ESW_PLATFORM_H */
+--- a/arch/mips/ralink/rt305x.c
++++ b/arch/mips/ralink/rt305x.c
+@@ -221,6 +221,7 @@ void __init ralink_clk_init(void)
+ }
+
+ ralink_clk_add("cpu", cpu_rate);
++ ralink_clk_add("sys", sys_rate);
+ ralink_clk_add("10000b00.spi", sys_rate);
+ ralink_clk_add("10000100.timer", wdt_rate);
+ ralink_clk_add("10000120.watchdog", wdt_rate);
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -136,6 +136,7 @@ source "drivers/net/ethernet/packetengin
+ source "drivers/net/ethernet/pasemi/Kconfig"
+ source "drivers/net/ethernet/qlogic/Kconfig"
+ source "drivers/net/ethernet/racal/Kconfig"
++source "drivers/net/ethernet/ramips/Kconfig"
+ source "drivers/net/ethernet/realtek/Kconfig"
+ source "drivers/net/ethernet/renesas/Kconfig"
+ source "drivers/net/ethernet/rdc/Kconfig"
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -54,6 +54,7 @@ obj-$(CONFIG_NET_PACKET_ENGINE) += packe
+ obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
+ obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
+ obj-$(CONFIG_NET_VENDOR_RACAL) += racal/
++obj-$(CONFIG_NET_RAMIPS) += ramips/
+ obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
+ obj-$(CONFIG_SH_ETH) += renesas/
+ obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
+--- /dev/null
++++ b/drivers/net/ethernet/ramips/Kconfig
+@@ -0,0 +1,18 @@
++config NET_RAMIPS
++ tristate "Ralink RT288X/RT3X5X/RT3662/RT3883 ethernet driver"
++ depends on RALINK
++ select PHYLIB if (SOC_RT288X || SOC_RT3883)
++ select SWCONFIG if SOC_RT305X
++ help
++ This driver supports the etehrnet mac inside the ralink wisocs
++
++if NET_RAMIPS
++
++config NET_RAMIPS_DEBUG
++ bool "Enable debug messages in the Ralink ethernet driver"
++
++config NET_RAMIPS_DEBUG_FS
++ bool "Enable debugfs support for the Ralink ethernet driver"
++ depends on DEBUG_FS
++
++endif
+--- /dev/null
++++ b/drivers/net/ethernet/ramips/Makefile
+@@ -0,0 +1,9 @@
++#
++# Makefile for the Ramips SoCs built-in ethernet macs
++#
++
++ramips-y += ramips_main.o
++
++ramips-$(CONFIG_NET_RAMIPS_DEBUG_FS) += ramips_debugfs.o
++
++obj-$(CONFIG_NET_RAMIPS) += ramips.o
+--- /dev/null
++++ b/drivers/net/ethernet/ramips/ramips_debugfs.c
+@@ -0,0 +1,127 @@
++/*
++ * Ralink SoC ethernet driver debugfs code
++ *
++ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#include <linux/debugfs.h>
++#include <linux/module.h>
++#include <linux/phy.h>
++
++#include "ramips_eth.h"
++
++static struct dentry *raeth_debugfs_root;
++
++static int raeth_debugfs_generic_open(struct inode *inode, struct file *file)
++{
++ file->private_data = inode->i_private;
++ return 0;
++}
++
++void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status)
++{
++ re->debug.int_stats.total += !!status;
++
++ re->debug.int_stats.rx_delayed += !!(status & RAMIPS_RX_DLY_INT);
++ re->debug.int_stats.rx_done0 += !!(status & RAMIPS_RX_DONE_INT0);
++ re->debug.int_stats.rx_coherent += !!(status & RAMIPS_RX_COHERENT);
++
++ re->debug.int_stats.tx_delayed += !!(status & RAMIPS_TX_DLY_INT);
++ re->debug.int_stats.tx_done0 += !!(status & RAMIPS_TX_DONE_INT0);
++ re->debug.int_stats.tx_done1 += !!(status & RAMIPS_TX_DONE_INT1);
++ re->debug.int_stats.tx_done2 += !!(status & RAMIPS_TX_DONE_INT2);
++ re->debug.int_stats.tx_done3 += !!(status & RAMIPS_TX_DONE_INT3);
++ re->debug.int_stats.tx_coherent += !!(status & RAMIPS_TX_COHERENT);
++
++ re->debug.int_stats.pse_fq_empty += !!(status & RAMIPS_PSE_FQ_EMPTY);
++ re->debug.int_stats.pse_p0_fc += !!(status & RAMIPS_PSE_P0_FC);
++ re->debug.int_stats.pse_p1_fc += !!(status & RAMIPS_PSE_P1_FC);
++ re->debug.int_stats.pse_p2_fc += !!(status & RAMIPS_PSE_P2_FC);
++ re->debug.int_stats.pse_buf_drop += !!(status & RAMIPS_PSE_BUF_DROP);
++}
++
++static ssize_t read_file_int_stats(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++#define PR_INT_STAT(_label, _field) \
++ len += snprintf(buf + len, sizeof(buf) - len, \
++ "%-18s: %10lu\n", _label, re->debug.int_stats._field);
++
++ struct raeth_priv *re = file->private_data;
++ char buf[512];
++ unsigned int len = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&re->page_lock, flags);
++
++ PR_INT_STAT("RX Delayed", rx_delayed);
++ PR_INT_STAT("RX Done 0", rx_done0);
++ PR_INT_STAT("RX Coherent", rx_coherent);
++
++ PR_INT_STAT("TX Delayed", tx_delayed);
++ PR_INT_STAT("TX Done 0", tx_done0);
++ PR_INT_STAT("TX Done 1", tx_done1);
++ PR_INT_STAT("TX Done 2", tx_done2);
++ PR_INT_STAT("TX Done 3", tx_done3);
++ PR_INT_STAT("TX Coherent", tx_coherent);
++
++ PR_INT_STAT("PSE FQ empty", pse_fq_empty);
++ PR_INT_STAT("CDMA Flow control", pse_p0_fc);
++ PR_INT_STAT("GDMA1 Flow control", pse_p1_fc);
++ PR_INT_STAT("GDMA2 Flow control", pse_p2_fc);
++ PR_INT_STAT("PSE discard", pse_buf_drop);
++
++ len += snprintf(buf + len, sizeof(buf) - len, "\n");
++ PR_INT_STAT("Total", total);
++
++ spin_unlock_irqrestore(&re->page_lock, flags);
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++#undef PR_INT_STAT
++}
++
++static const struct file_operations raeth_fops_int_stats = {
++ .open = raeth_debugfs_generic_open,
++ .read = read_file_int_stats,
++ .owner = THIS_MODULE
++};
++
++void raeth_debugfs_exit(struct raeth_priv *re)
++{
++ debugfs_remove_recursive(re->debug.debugfs_dir);
++}
++
++int raeth_debugfs_init(struct raeth_priv *re)
++{
++ re->debug.debugfs_dir = debugfs_create_dir(re->netdev->name,
++ raeth_debugfs_root);
++ if (!re->debug.debugfs_dir)
++ return -ENOMEM;
++
++ debugfs_create_file("int_stats", S_IRUGO, re->debug.debugfs_dir,
++ re, &raeth_fops_int_stats);
++
++ return 0;
++}
++
++int raeth_debugfs_root_init(void)
++{
++ if (raeth_debugfs_root)
++ return -EBUSY;
++
++ raeth_debugfs_root = debugfs_create_dir("raeth", NULL);
++ if (!raeth_debugfs_root)
++ return -ENOENT;
++
++ return 0;
++}
++
++void raeth_debugfs_root_exit(void)
++{
++ debugfs_remove(raeth_debugfs_root);
++ raeth_debugfs_root = NULL;
++}
+--- /dev/null
++++ b/drivers/net/ethernet/ramips/ramips_esw.c
+@@ -0,0 +1,1221 @@
++#include <linux/ioport.h>
++#include <linux/switch.h>
++#include <linux/mii.h>
++
++#include <ralink_regs.h>
++#include <rt305x.h>
++#include <rt305x_esw_platform.h>
++
++/*
++ * HW limitations for this switch:
++ * - No large frame support (PKT_MAX_LEN at most 1536)
++ * - Can't have untagged vlan and tagged vlan on one port at the same time,
++ * though this might be possible using the undocumented PPE.
++ */
++
++#define RT305X_ESW_REG_ISR 0x00
++#define RT305X_ESW_REG_IMR 0x04
++#define RT305X_ESW_REG_FCT0 0x08
++#define RT305X_ESW_REG_PFC1 0x14
++#define RT305X_ESW_REG_ATS 0x24
++#define RT305X_ESW_REG_ATS0 0x28
++#define RT305X_ESW_REG_ATS1 0x2c
++#define RT305X_ESW_REG_ATS2 0x30
++#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
++#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
++#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
++#define RT305X_ESW_REG_POA 0x80
++#define RT305X_ESW_REG_FPA 0x84
++#define RT305X_ESW_REG_SOCPC 0x8c
++#define RT305X_ESW_REG_POC0 0x90
++#define RT305X_ESW_REG_POC1 0x94
++#define RT305X_ESW_REG_POC2 0x98
++#define RT305X_ESW_REG_SGC 0x9c
++#define RT305X_ESW_REG_STRT 0xa0
++#define RT305X_ESW_REG_PCR0 0xc0
++#define RT305X_ESW_REG_PCR1 0xc4
++#define RT305X_ESW_REG_FPA2 0xc8
++#define RT305X_ESW_REG_FCT2 0xcc
++#define RT305X_ESW_REG_SGC2 0xe4
++#define RT305X_ESW_REG_P0LED 0xa4
++#define RT305X_ESW_REG_P1LED 0xa8
++#define RT305X_ESW_REG_P2LED 0xac
++#define RT305X_ESW_REG_P3LED 0xb0
++#define RT305X_ESW_REG_P4LED 0xb4
++#define RT305X_ESW_REG_P0PC 0xe8
++#define RT305X_ESW_REG_P1PC 0xec
++#define RT305X_ESW_REG_P2PC 0xf0
++#define RT305X_ESW_REG_P3PC 0xf4
++#define RT305X_ESW_REG_P4PC 0xf8
++#define RT305X_ESW_REG_P5PC 0xfc
++
++#define RT305X_ESW_LED_LINK 0
++#define RT305X_ESW_LED_100M 1
++#define RT305X_ESW_LED_DUPLEX 2
++#define RT305X_ESW_LED_ACTIVITY 3
++#define RT305X_ESW_LED_COLLISION 4
++#define RT305X_ESW_LED_LINKACT 5
++#define RT305X_ESW_LED_DUPLCOLL 6
++#define RT305X_ESW_LED_10MACT 7
++#define RT305X_ESW_LED_100MACT 8
++/* Additional led states not in datasheet: */
++#define RT305X_ESW_LED_BLINK 10
++#define RT305X_ESW_LED_ON 12
++
++#define RT305X_ESW_LINK_S 25
++#define RT305X_ESW_DUPLEX_S 9
++#define RT305X_ESW_SPD_S 0
++
++#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
++#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
++#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
++
++#define RT305X_ESW_PCR1_WT_DONE BIT(0)
++
++#define RT305X_ESW_ATS_TIMEOUT (5 * HZ)
++#define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
++
++#define RT305X_ESW_PVIDC_PVID_M 0xfff
++#define RT305X_ESW_PVIDC_PVID_S 12
++
++#define RT305X_ESW_VLANI_VID_M 0xfff
++#define RT305X_ESW_VLANI_VID_S 12
++
++#define RT305X_ESW_VMSC_MSC_M 0xff
++#define RT305X_ESW_VMSC_MSC_S 8
++
++#define RT305X_ESW_SOCPC_DISUN2CPU_S 0
++#define RT305X_ESW_SOCPC_DISMC2CPU_S 8
++#define RT305X_ESW_SOCPC_DISBC2CPU_S 16
++#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
++
++#define RT305X_ESW_POC0_EN_BP_S 0
++#define RT305X_ESW_POC0_EN_FC_S 8
++#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16
++#define RT305X_ESW_POC0_DIS_PORT_M 0x7f
++#define RT305X_ESW_POC0_DIS_PORT_S 23
++
++#define RT305X_ESW_POC2_UNTAG_EN_M 0xff
++#define RT305X_ESW_POC2_UNTAG_EN_S 0
++#define RT305X_ESW_POC2_ENAGING_S 8
++#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
++
++#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f
++#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0
++#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f
++#define RT305X_ESW_SGC2_LAN_PMAP_S 24
++
++#define RT305X_ESW_PFC1_EN_VLAN_M 0xff
++#define RT305X_ESW_PFC1_EN_VLAN_S 16
++#define RT305X_ESW_PFC1_EN_TOS_S 24
++
++#define RT305X_ESW_VLAN_NONE 0xfff
++
++#define RT305X_ESW_POA_LINK_MASK 0x1f
++#define RT305X_ESW_POA_LINK_SHIFT 25
++
++#define RT305X_ESW_PORT_ST_CHG BIT(26)
++#define RT305X_ESW_PORT0 0
++#define RT305X_ESW_PORT1 1
++#define RT305X_ESW_PORT2 2
++#define RT305X_ESW_PORT3 3
++#define RT305X_ESW_PORT4 4
++#define RT305X_ESW_PORT5 5
++#define RT305X_ESW_PORT6 6
++
++#define RT305X_ESW_PORTS_NONE 0
++
++#define RT305X_ESW_PMAP_LLLLLL 0x3f
++#define RT305X_ESW_PMAP_LLLLWL 0x2f
++#define RT305X_ESW_PMAP_WLLLLL 0x3e
++
++#define RT305X_ESW_PORTS_INTERNAL \
++ (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
++ BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
++ BIT(RT305X_ESW_PORT4))
++
++#define RT305X_ESW_PORTS_NOCPU \
++ (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
++
++#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
++
++#define RT305X_ESW_PORTS_ALL \
++ (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
++
++#define RT305X_ESW_NUM_VLANS 16
++#define RT305X_ESW_NUM_VIDS 4096
++#define RT305X_ESW_NUM_PORTS 7
++#define RT305X_ESW_NUM_LANWAN 6
++#define RT305X_ESW_NUM_LEDS 5
++
++enum {
++ /* Global attributes. */
++ RT305X_ESW_ATTR_ENABLE_VLAN,
++ RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
++ /* Port attributes. */
++ RT305X_ESW_ATTR_PORT_DISABLE,
++ RT305X_ESW_ATTR_PORT_DOUBLETAG,
++ RT305X_ESW_ATTR_PORT_UNTAG,
++ RT305X_ESW_ATTR_PORT_LED,
++ RT305X_ESW_ATTR_PORT_LAN,
++ RT305X_ESW_ATTR_PORT_RECV_BAD,
++ RT305X_ESW_ATTR_PORT_RECV_GOOD,
++};
++
++struct rt305x_esw_port {
++ bool disable;
++ bool doubletag;
++ bool untag;
++ u8 led;
++ u16 pvid;
++};
++
++struct rt305x_esw_vlan {
++ u8 ports;
++ u16 vid;
++};
++
++struct rt305x_esw {
++ struct device *dev;
++ void __iomem *base;
++ int irq;
++ const struct rt305x_esw_platform_data *pdata;
++ /* Protects against concurrent register rmw operations. */
++ spinlock_t reg_rw_lock;
++
++ unsigned char port_map;
++ unsigned int reg_initval_fct2;
++ unsigned int reg_initval_fpa2;
++
++
++ struct switch_dev swdev;
++ bool global_vlan_enable;
++ bool alt_vlan_disable;
++ struct rt305x_esw_vlan vlans[RT305X_ESW_NUM_VLANS];
++ struct rt305x_esw_port ports[RT305X_ESW_NUM_PORTS];
++
++};
++
++static inline void
++rt305x_esw_wr(struct rt305x_esw *esw, u32 val, unsigned reg)
++{
++ __raw_writel(val, esw->base + reg);
++}
++
++static inline u32
++rt305x_esw_rr(struct rt305x_esw *esw, unsigned reg)
++{
++ return __raw_readl(esw->base + reg);
++}
++
++static inline void
++rt305x_esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, unsigned long mask,
++ unsigned long val)
++{
++ unsigned long t;
++
++ t = __raw_readl(esw->base + reg) & ~mask;
++ __raw_writel(t | val, esw->base + reg);
++}
++
++static void
++rt305x_esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask,
++ unsigned long val)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&esw->reg_rw_lock, flags);
++ rt305x_esw_rmw_raw(esw, reg, mask, val);
++ spin_unlock_irqrestore(&esw->reg_rw_lock, flags);
++}
++
++static u32
++rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register,
++ u32 write_data)
++{
++ unsigned long t_start = jiffies;
++ int ret = 0;
++
++ while (1) {
++ if (!(rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) &
++ RT305X_ESW_PCR1_WT_DONE))
++ break;
++ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
++ ret = 1;
++ goto out;
++ }
++ }
++
++ write_data &= 0xffff;
++ rt305x_esw_wr(esw,
++ (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) |
++ (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) |
++ (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD,
++ RT305X_ESW_REG_PCR0);
++
++ t_start = jiffies;
++ while (1) {
++ if (rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) &
++ RT305X_ESW_PCR1_WT_DONE)
++ break;
++
++ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
++ ret = 1;
++ break;
++ }
++ }
++out:
++ if (ret)
++ printk(KERN_ERR "ramips_eth: MDIO timeout\n");
++ return ret;
++}
++
++static unsigned
++rt305x_esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan)
++{
++ unsigned s;
++ unsigned val;
++
++ s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
++ val = rt305x_esw_rr(esw, RT305X_ESW_REG_VLANI(vlan / 2));
++ val = (val >> s) & RT305X_ESW_VLANI_VID_M;
++
++ return val;
++}
++
++static void
++rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid)
++{
++ unsigned s;
++
++ s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
++ rt305x_esw_rmw(esw,
++ RT305X_ESW_REG_VLANI(vlan / 2),
++ RT305X_ESW_VLANI_VID_M << s,
++ (vid & RT305X_ESW_VLANI_VID_M) << s);
++}
++
++static unsigned
++rt305x_esw_get_pvid(struct rt305x_esw *esw, unsigned port)
++{
++ unsigned s, val;
++
++ s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
++ val = rt305x_esw_rr(esw, RT305X_ESW_REG_PVIDC(port / 2));
++ return (val >> s) & RT305X_ESW_PVIDC_PVID_M;
++}
++
++static void
++rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid)
++{
++ unsigned s;
++
++ s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
++ rt305x_esw_rmw(esw,
++ RT305X_ESW_REG_PVIDC(port / 2),
++ RT305X_ESW_PVIDC_PVID_M << s,
++ (pvid & RT305X_ESW_PVIDC_PVID_M) << s);
++}
++
++static unsigned
++rt305x_esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan)
++{
++ unsigned s, val;
++
++ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
++ val = rt305x_esw_rr(esw, RT305X_ESW_REG_VMSC(vlan / 4));
++ val = (val >> s) & RT305X_ESW_VMSC_MSC_M;
++
++ return val;
++}
++
++static void
++rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
++{
++ unsigned s;
++
++ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
++ rt305x_esw_rmw(esw,
++ RT305X_ESW_REG_VMSC(vlan / 4),
++ RT305X_ESW_VMSC_MSC_M << s,
++ (msc & RT305X_ESW_VMSC_MSC_M) << s);
++}
++
++static unsigned
++rt305x_esw_get_port_disable(struct rt305x_esw *esw)
++{
++ unsigned reg;
++ reg = rt305x_esw_rr(esw, RT305X_ESW_REG_POC0);
++ return (reg >> RT305X_ESW_POC0_DIS_PORT_S) &
++ RT305X_ESW_POC0_DIS_PORT_M;
++}
++
++static void
++rt305x_esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask)
++{
++ unsigned old_mask;
++ unsigned enable_mask;
++ unsigned changed;
++ int i;
++
++ old_mask = rt305x_esw_get_port_disable(esw);
++ changed = old_mask ^ disable_mask;
++ enable_mask = old_mask & disable_mask;
++
++ /* enable before writing to MII */
++ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
++ (RT305X_ESW_POC0_DIS_PORT_M <<
++ RT305X_ESW_POC0_DIS_PORT_S),
++ enable_mask << RT305X_ESW_POC0_DIS_PORT_S);
++
++ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) {
++ if (!(changed & (1 << i)))
++ continue;
++ if (disable_mask & (1 << i)) {
++ /* disable */
++ rt305x_mii_write(esw, i, MII_BMCR,
++ BMCR_PDOWN);
++ } else {
++ /* enable */
++ rt305x_mii_write(esw, i, MII_BMCR,
++ BMCR_FULLDPLX |
++ BMCR_ANENABLE |
++ BMCR_ANRESTART |
++ BMCR_SPEED100);
++ }
++ }
++
++ /* disable after writing to MII */
++ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC0,
++ (RT305X_ESW_POC0_DIS_PORT_M <<
++ RT305X_ESW_POC0_DIS_PORT_S),
++ disable_mask << RT305X_ESW_POC0_DIS_PORT_S);
++}
++
++static int
++rt305x_esw_apply_config(struct switch_dev *dev);
++
++static void
++rt305x_esw_hw_init(struct rt305x_esw *esw)
++{
++ int i;
++ u8 port_disable = 0;
++ u8 port_map = RT305X_ESW_PMAP_LLLLLL;
++
++ /* vodoo from original driver */
++ rt305x_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
++ rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2);
++ /* Port priority 1 for all ports, vlan enabled. */
++ rt305x_esw_wr(esw, 0x00005555 |
++ (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S),
++ RT305X_ESW_REG_PFC1);
++
++ /* Enable Back Pressure, and Flow Control */
++ rt305x_esw_wr(esw,
++ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) |
++ (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)),
++ RT305X_ESW_REG_POC0);
++
++ /* Enable Aging, and VLAN TAG removal */
++ rt305x_esw_wr(esw,
++ ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) |
++ (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)),
++ RT305X_ESW_REG_POC2);
++
++ if (esw->reg_initval_fct2)
++ rt305x_esw_wr(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2);
++ else
++ rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2);
++
++ /*
++ * 300s aging timer, max packet len 1536, broadcast storm prevention
++ * disabled, disable collision abort, mac xor48 hash, 10 packet back
++ * pressure jam, GMII disable was_transmit, back pressure disabled,
++ * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all
++ * ports.
++ */
++ rt305x_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC);
++
++ /* Setup SoC Port control register */
++ rt305x_esw_wr(esw,
++ (RT305X_ESW_SOCPC_CRC_PADDING |
++ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) |
++ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) |
++ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)),
++ RT305X_ESW_REG_SOCPC);
++
++ if (esw->reg_initval_fpa2)
++ rt305x_esw_wr(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
++ else
++ rt305x_esw_wr(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
++ rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_FPA);
++
++ /* Force Link/Activity on ports */
++ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P0LED);
++ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P1LED);
++ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P2LED);
++ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P3LED);
++ rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P4LED);
++
++ /* Copy disabled port configuration from bootloader setup */
++ port_disable = rt305x_esw_get_port_disable(esw);
++ for (i = 0; i < 6; i++)
++ esw->ports[i].disable = (port_disable & (1 << i)) != 0;
++
++ rt305x_mii_write(esw, 0, 31, 0x8000);
++ for (i = 0; i < 5; i++) {
++ if (esw->ports[i].disable) {
++ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
++ } else {
++ rt305x_mii_write(esw, i, MII_BMCR,
++ BMCR_FULLDPLX |
++ BMCR_ANENABLE |
++ BMCR_SPEED100);
++ }
++ /* TX10 waveform coefficient */
++ rt305x_mii_write(esw, i, 26, 0x1601);
++ /* TX100/TX10 AD/DA current bias */
++ rt305x_mii_write(esw, i, 29, 0x7058);
++ /* TX100 slew rate control */
++ rt305x_mii_write(esw, i, 30, 0x0018);
++ }
++
++ /* PHY IOT */
++ /* select global register */
++ rt305x_mii_write(esw, 0, 31, 0x0);
++ /* tune TP_IDL tail and head waveform */
++ rt305x_mii_write(esw, 0, 22, 0x052f);
++ /* set TX10 signal amplitude threshold to minimum */
++ rt305x_mii_write(esw, 0, 17, 0x0fe0);
++ /* set squelch amplitude to higher threshold */
++ rt305x_mii_write(esw, 0, 18, 0x40ba);
++ /* longer TP_IDL tail length */
++ rt305x_mii_write(esw, 0, 14, 0x65);
++ /* select local register */
++ rt305x_mii_write(esw, 0, 31, 0x8000);
++
++ if (esw->port_map)
++ port_map = esw->port_map;
++ else
++ port_map = RT305X_ESW_PMAP_LLLLLL;
++
++ /*
++ * Unused HW feature, but still nice to be consistent here...
++ * This is also exported to userspace ('lan' attribute) so it's
++ * conveniently usable to decide which ports go into the wan vlan by
++ * default.
++ */
++ rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
++ RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S,
++ port_map << RT305X_ESW_SGC2_LAN_PMAP_S);
++
++ /* make the switch leds blink */
++ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++)
++ esw->ports[i].led = 0x05;
++
++ /* Apply the empty config. */
++ rt305x_esw_apply_config(&esw->swdev);
++}
++
++static irqreturn_t
++rt305x_esw_interrupt(int irq, void *_esw)
++{
++ struct rt305x_esw *esw = (struct rt305x_esw *) _esw;
++ u32 status;
++
++ status = rt305x_esw_rr(esw, RT305X_ESW_REG_ISR);
++ if (status & RT305X_ESW_PORT_ST_CHG) {
++ u32 link = rt305x_esw_rr(esw, RT305X_ESW_REG_POA);
++ link >>= RT305X_ESW_POA_LINK_SHIFT;
++ link &= RT305X_ESW_POA_LINK_MASK;
++ dev_info(esw->dev, "link changed 0x%02X\n", link);
++ }
++ rt305x_esw_wr(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR);
++
++ return IRQ_HANDLED;
++}
++
++static void
++rt305x_esw_request_irq(struct rt305x_esw *esw)
++{
++ /* Only unmask the port change interrupt */
++ rt305x_esw_wr(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
++
++ /* request the irq handler */
++ request_irq(esw->irq, rt305x_esw_interrupt, 0, "esw", esw);
++}
++
++static int
++rt305x_esw_apply_config(struct switch_dev *dev)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int i;
++ u8 disable = 0;
++ u8 doubletag = 0;
++ u8 en_vlan = 0;
++ u8 untag = 0;
++
++ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
++ u32 vid, vmsc;
++ if (esw->global_vlan_enable) {
++ vid = esw->vlans[i].vid;
++ vmsc = esw->vlans[i].ports;
++ } else {
++ vid = RT305X_ESW_VLAN_NONE;
++ vmsc = RT305X_ESW_PORTS_NONE;
++ }
++ rt305x_esw_set_vlan_id(esw, i, vid);
++ rt305x_esw_set_vmsc(esw, i, vmsc);
++ }
++
++ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
++ u32 pvid;
++ disable |= esw->ports[i].disable << i;
++ if (esw->global_vlan_enable) {
++ doubletag |= esw->ports[i].doubletag << i;
++ en_vlan |= 1 << i;
++ untag |= esw->ports[i].untag << i;
++ pvid = esw->ports[i].pvid;
++ } else {
++ int x = esw->alt_vlan_disable ? 0 : 1;
++ doubletag |= x << i;
++ en_vlan |= x << i;
++ untag |= x << i;
++ pvid = 0;
++ }
++ rt305x_esw_set_pvid(esw, i, pvid);
++ if (i < RT305X_ESW_NUM_LEDS)
++ rt305x_esw_wr(esw, esw->ports[i].led,
++ RT305X_ESW_REG_P0LED + 4*i);
++ }
++
++ rt305x_esw_set_port_disable(esw, disable);
++ rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2,
++ (RT305X_ESW_SGC2_DOUBLE_TAG_M <<
++ RT305X_ESW_SGC2_DOUBLE_TAG_S),
++ doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S);
++ rt305x_esw_rmw(esw, RT305X_ESW_REG_PFC1,
++ RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S,
++ en_vlan << RT305X_ESW_PFC1_EN_VLAN_S);
++ rt305x_esw_rmw(esw, RT305X_ESW_REG_POC2,
++ RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S,
++ untag << RT305X_ESW_POC2_UNTAG_EN_S);
++
++ if (!esw->global_vlan_enable) {
++ /*
++ * Still need to put all ports into vlan 0 or they'll be
++ * isolated.
++ * NOTE: vlan 0 is special, no vlan tag is prepended
++ */
++ rt305x_esw_set_vlan_id(esw, 0, 0);
++ rt305x_esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL);
++ }
++
++ return 0;
++}
++
++static int
++rt305x_esw_reset_switch(struct switch_dev *dev)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ esw->global_vlan_enable = 0;
++ memset(esw->ports, 0, sizeof(esw->ports));
++ memset(esw->vlans, 0, sizeof(esw->vlans));
++ rt305x_esw_hw_init(esw);
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_vlan_enable(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++
++ val->value.i = esw->global_vlan_enable;
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_vlan_enable(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++
++ esw->global_vlan_enable = val->value.i != 0;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_alt_vlan_disable(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++
++ val->value.i = esw->alt_vlan_disable;
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_alt_vlan_disable(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++
++ esw->alt_vlan_disable = val->value.i != 0;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_port_link(struct switch_dev *dev,
++ int port,
++ struct switch_port_link *link)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ u32 speed, poa;
++
++ if (port < 0 || port >= RT305X_ESW_NUM_PORTS)
++ return -EINVAL;
++
++ poa = rt305x_esw_rr(esw, RT305X_ESW_REG_POA) >> port;
++
++ link->link = (poa >> RT305X_ESW_LINK_S) & 1;
++ link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1;
++ if (port < RT305X_ESW_NUM_LEDS) {
++ speed = (poa >> RT305X_ESW_SPD_S) & 1;
++ } else {
++ if (port == RT305X_ESW_NUM_PORTS - 1)
++ poa >>= 1;
++ speed = (poa >> RT305X_ESW_SPD_S) & 3;
++ }
++ switch (speed) {
++ case 0:
++ link->speed = SWITCH_PORT_SPEED_10;
++ break;
++ case 1:
++ link->speed = SWITCH_PORT_SPEED_100;
++ break;
++ case 2:
++ case 3: /* forced gige speed can be 2 or 3 */
++ link->speed = SWITCH_PORT_SPEED_1000;
++ break;
++ default:
++ link->speed = SWITCH_PORT_SPEED_UNKNOWN;
++ break;
++ }
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_port_bool(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int idx = val->port_vlan;
++ u32 x, reg, shift;
++
++ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS)
++ return -EINVAL;
++
++ switch (attr->id) {
++ case RT305X_ESW_ATTR_PORT_DISABLE:
++ reg = RT305X_ESW_REG_POC0;
++ shift = RT305X_ESW_POC0_DIS_PORT_S;
++ break;
++ case RT305X_ESW_ATTR_PORT_DOUBLETAG:
++ reg = RT305X_ESW_REG_SGC2;
++ shift = RT305X_ESW_SGC2_DOUBLE_TAG_S;
++ break;
++ case RT305X_ESW_ATTR_PORT_UNTAG:
++ reg = RT305X_ESW_REG_POC2;
++ shift = RT305X_ESW_POC2_UNTAG_EN_S;
++ break;
++ case RT305X_ESW_ATTR_PORT_LAN:
++ reg = RT305X_ESW_REG_SGC2;
++ shift = RT305X_ESW_SGC2_LAN_PMAP_S;
++ if (idx >= RT305X_ESW_NUM_LANWAN)
++ return -EINVAL;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ x = rt305x_esw_rr(esw, reg);
++ val->value.i = (x >> (idx + shift)) & 1;
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_port_bool(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int idx = val->port_vlan;
++
++ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
++ val->value.i < 0 || val->value.i > 1)
++ return -EINVAL;
++
++ switch (attr->id) {
++ case RT305X_ESW_ATTR_PORT_DISABLE:
++ esw->ports[idx].disable = val->value.i;
++ break;
++ case RT305X_ESW_ATTR_PORT_DOUBLETAG:
++ esw->ports[idx].doubletag = val->value.i;
++ break;
++ case RT305X_ESW_ATTR_PORT_UNTAG:
++ esw->ports[idx].untag = val->value.i;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_port_recv_badgood(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int idx = val->port_vlan;
++ int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16;
++ u32 reg;
++
++ if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN)
++ return -EINVAL;
++
++ reg = rt305x_esw_rr(esw, RT305X_ESW_REG_P0PC + 4*idx);
++ val->value.i = (reg >> shift) & 0xffff;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_port_led(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int idx = val->port_vlan;
++
++ if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
++ idx >= RT305X_ESW_NUM_LEDS)
++ return -EINVAL;
++
++ val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0LED + 4*idx);
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_port_led(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int idx = val->port_vlan;
++
++ if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS)
++ return -EINVAL;
++
++ esw->ports[idx].led = val->value.i;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_port_pvid(struct switch_dev *dev, int port, int *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++
++ if (port >= RT305X_ESW_NUM_PORTS)
++ return -EINVAL;
++
++ *val = rt305x_esw_get_pvid(esw, port);
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_port_pvid(struct switch_dev *dev, int port, int val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++
++ if (port >= RT305X_ESW_NUM_PORTS)
++ return -EINVAL;
++
++ esw->ports[port].pvid = val;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ u32 vmsc, poc2;
++ int vlan_idx = -1;
++ int i;
++
++ val->len = 0;
++
++ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS)
++ return -EINVAL;
++
++ /* valid vlan? */
++ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
++ if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan &&
++ rt305x_esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) {
++ vlan_idx = i;
++ break;
++ }
++ }
++
++ if (vlan_idx == -1)
++ return -EINVAL;
++
++ vmsc = rt305x_esw_get_vmsc(esw, vlan_idx);
++ poc2 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC2);
++
++ for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
++ struct switch_port *p;
++ int port_mask = 1 << i;
++
++ if (!(vmsc & port_mask))
++ continue;
++
++ p = &val->value.ports[val->len++];
++ p->id = i;
++ if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S))
++ p->flags = 0;
++ else
++ p->flags = 1 << SWITCH_PORT_FLAG_TAGGED;
++ }
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
++{
++ struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
++ int ports;
++ int vlan_idx = -1;
++ int i;
++
++ if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS ||
++ val->len > RT305X_ESW_NUM_PORTS)
++ return -EINVAL;
++
++ /* one of the already defined vlans? */
++ for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
++ if (esw->vlans[i].vid == val->port_vlan &&
++ esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) {
++ vlan_idx = i;
++ break;
++ }
++ }
++
++ /* select a free slot */
++ for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) {
++ if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE)
++ vlan_idx = i;
++ }
++
++ /* bail if all slots are in use */
++ if (vlan_idx == -1)
++ return -EINVAL;
++
++ ports = RT305X_ESW_PORTS_NONE;
++ for (i = 0; i < val->len; i++) {
++ struct switch_port *p = &val->value.ports[i];
++ int port_mask = 1 << p->id;
++ bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED));
++
++ if (p->id >= RT305X_ESW_NUM_PORTS)
++ return -EINVAL;
++
++ ports |= port_mask;
++ esw->ports[p->id].untag = untagged;
++ }
++ esw->vlans[vlan_idx].ports = ports;
++ if (ports == RT305X_ESW_PORTS_NONE)
++ esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE;
++ else
++ esw->vlans[vlan_idx].vid = val->port_vlan;
++
++ return 0;
++}
++
++static const struct switch_attr rt305x_esw_global[] = {
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "enable_vlan",
++ .description = "VLAN mode (1:enabled)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_ENABLE_VLAN,
++ .get = rt305x_esw_get_vlan_enable,
++ .set = rt305x_esw_set_vlan_enable,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "alternate_vlan_disable",
++ .description = "Use en_vlan instead of doubletag to disable"
++ " VLAN mode",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
++ .get = rt305x_esw_get_alt_vlan_disable,
++ .set = rt305x_esw_set_alt_vlan_disable,
++ },
++};
++
++static const struct switch_attr rt305x_esw_port[] = {
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "disable",
++ .description = "Port state (1:disabled)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_PORT_DISABLE,
++ .get = rt305x_esw_get_port_bool,
++ .set = rt305x_esw_set_port_bool,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "doubletag",
++ .description = "Double tagging for incoming vlan packets "
++ "(1:enabled)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_PORT_DOUBLETAG,
++ .get = rt305x_esw_get_port_bool,
++ .set = rt305x_esw_set_port_bool,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "untag",
++ .description = "Untag (1:strip outgoing vlan tag)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_PORT_UNTAG,
++ .get = rt305x_esw_get_port_bool,
++ .set = rt305x_esw_set_port_bool,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "led",
++ .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity,"
++ " 4:collision, 5:linkact, 6:duplcoll, 7:10mact,"
++ " 8:100mact, 10:blink, 12:on)",
++ .max = 15,
++ .id = RT305X_ESW_ATTR_PORT_LED,
++ .get = rt305x_esw_get_port_led,
++ .set = rt305x_esw_set_port_led,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "lan",
++ .description = "HW port group (0:wan, 1:lan)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_PORT_LAN,
++ .get = rt305x_esw_get_port_bool,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "recv_bad",
++ .description = "Receive bad packet counter",
++ .id = RT305X_ESW_ATTR_PORT_RECV_BAD,
++ .get = rt305x_esw_get_port_recv_badgood,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "recv_good",
++ .description = "Receive good packet counter",
++ .id = RT305X_ESW_ATTR_PORT_RECV_GOOD,
++ .get = rt305x_esw_get_port_recv_badgood,
++ },
++};
++
++static const struct switch_attr rt305x_esw_vlan[] = {
++};
++
++static const struct switch_dev_ops rt305x_esw_ops = {
++ .attr_global = {
++ .attr = rt305x_esw_global,
++ .n_attr = ARRAY_SIZE(rt305x_esw_global),
++ },
++ .attr_port = {
++ .attr = rt305x_esw_port,
++ .n_attr = ARRAY_SIZE(rt305x_esw_port),
++ },
++ .attr_vlan = {
++ .attr = rt305x_esw_vlan,
++ .n_attr = ARRAY_SIZE(rt305x_esw_vlan),
++ },
++ .get_vlan_ports = rt305x_esw_get_vlan_ports,
++ .set_vlan_ports = rt305x_esw_set_vlan_ports,
++ .get_port_pvid = rt305x_esw_get_port_pvid,
++ .set_port_pvid = rt305x_esw_set_port_pvid,
++ .get_port_link = rt305x_esw_get_port_link,
++ .apply_config = rt305x_esw_apply_config,
++ .reset_switch = rt305x_esw_reset_switch,
++};
++
++static struct rt305x_esw_platform_data rt3050_esw_data = {
++ /* All ports are LAN ports. */
++ .vlan_config = RT305X_ESW_VLAN_CONFIG_NONE,
++ .reg_initval_fct2 = 0x00d6500c,
++ /*
++ * ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1,
++ * turbo mii off, rgmi 3.3v off
++ * port5: disabled
++ * port6: enabled, gige, full-duplex, rx/tx-flow-control
++ */
++ .reg_initval_fpa2 = 0x3f502b28,
++};
++
++static const struct of_device_id ralink_esw_match[] = {
++ { .compatible = "ralink,rt3050-esw", .data = &rt3050_esw_data },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ralink_esw_match);
++
++static int
++rt305x_esw_probe(struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ const struct rt305x_esw_platform_data *pdata;
++ const __be32 *port_map, *reg_init;
++ struct rt305x_esw *esw;
++ struct switch_dev *swdev;
++ struct resource *res, *irq;
++ int err;
++
++ pdata = pdev->dev.platform_data;
++ if (!pdata) {
++ const struct of_device_id *match;
++ match = of_match_device(ralink_esw_match, &pdev->dev);
++ if (match)
++ pdata = (struct rt305x_esw_platform_data *) match->data;
++ }
++ if (!pdata)
++ return -EINVAL;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource found\n");
++ return -ENOMEM;
++ }
++
++ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!irq) {
++ dev_err(&pdev->dev, "no irq resource found\n");
++ return -ENOMEM;
++ }
++
++ esw = kzalloc(sizeof(struct rt305x_esw), GFP_KERNEL);
++ if (!esw) {
++ dev_err(&pdev->dev, "no memory for private data\n");
++ return -ENOMEM;
++ }
++
++ esw->dev = &pdev->dev;
++ esw->irq = irq->start;
++ esw->base = ioremap(res->start, resource_size(res));
++ if (!esw->base) {
++ dev_err(&pdev->dev, "ioremap failed\n");
++ err = -ENOMEM;
++ goto free_esw;
++ }
++
++ port_map = of_get_property(np, "ralink,portmap", NULL);
++ if (port_map)
++ esw->port_map = be32_to_cpu(*port_map);
++
++ reg_init = of_get_property(np, "ralink,fct2", NULL);
++ if (reg_init)
++ esw->reg_initval_fct2 = be32_to_cpu(*reg_init);
++
++ reg_init = of_get_property(np, "ralink,fpa2", NULL);
++ if (reg_init)
++ esw->reg_initval_fpa2 = be32_to_cpu(*reg_init);
++
++ swdev = &esw->swdev;
++ swdev->of_node = pdev->dev.of_node;
++ swdev->name = "rt305x-esw";
++ swdev->alias = "rt305x";
++ swdev->cpu_port = RT305X_ESW_PORT6;
++ swdev->ports = RT305X_ESW_NUM_PORTS;
++ swdev->vlans = RT305X_ESW_NUM_VIDS;
++ swdev->ops = &rt305x_esw_ops;
++
++ err = register_switch(swdev, NULL);
++ if (err < 0) {
++ dev_err(&pdev->dev, "register_switch failed\n");
++ goto unmap_base;
++ }
++
++ platform_set_drvdata(pdev, esw);
++
++ esw->pdata = pdata;
++ spin_lock_init(&esw->reg_rw_lock);
++ rt305x_esw_hw_init(esw);
++ rt305x_esw_request_irq(esw);
++
++ return 0;
++
++unmap_base:
++ iounmap(esw->base);
++free_esw:
++ kfree(esw);
++ return err;
++}
++
++static int
++rt305x_esw_remove(struct platform_device *pdev)
++{
++ struct rt305x_esw *esw;
++
++ esw = platform_get_drvdata(pdev);
++ if (esw) {
++ unregister_switch(&esw->swdev);
++ platform_set_drvdata(pdev, NULL);
++ iounmap(esw->base);
++ kfree(esw);
++ }
++
++ return 0;
++}
++
++static struct platform_driver rt305x_esw_driver = {
++ .probe = rt305x_esw_probe,
++ .remove = rt305x_esw_remove,
++ .driver = {
++ .name = "rt305x-esw",
++ .owner = THIS_MODULE,
++ .of_match_table = ralink_esw_match,
++ },
++};
++
++static int __init
++rt305x_esw_init(void)
++{
++ return platform_driver_register(&rt305x_esw_driver);
++}
++
++static void
++rt305x_esw_exit(void)
++{
++ platform_driver_unregister(&rt305x_esw_driver);
++}
+--- /dev/null
++++ b/drivers/net/ethernet/ramips/ramips_eth.h
+@@ -0,0 +1,375 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * based on Ralink SDK3.3
++ * Copyright (C) 2009 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef RAMIPS_ETH_H
++#define RAMIPS_ETH_H
++
++#include <linux/mii.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <linux/dma-mapping.h>
++
++#define NUM_RX_DESC 256
++#define NUM_TX_DESC 256
++
++#define RAMIPS_DELAY_EN_INT 0x80
++#define RAMIPS_DELAY_MAX_INT 0x04
++#define RAMIPS_DELAY_MAX_TOUT 0x04
++#define RAMIPS_DELAY_CHAN (((RAMIPS_DELAY_EN_INT | RAMIPS_DELAY_MAX_INT) << 8) | RAMIPS_DELAY_MAX_TOUT)
++#define RAMIPS_DELAY_INIT ((RAMIPS_DELAY_CHAN << 16) | RAMIPS_DELAY_CHAN)
++#define RAMIPS_PSE_FQFC_CFG_INIT 0x80504000
++
++/* interrupt bits */
++#define RAMIPS_CNT_PPE_AF BIT(31)
++#define RAMIPS_CNT_GDM_AF BIT(29)
++#define RAMIPS_PSE_P2_FC BIT(26)
++#define RAMIPS_PSE_BUF_DROP BIT(24)
++#define RAMIPS_GDM_OTHER_DROP BIT(23)
++#define RAMIPS_PSE_P1_FC BIT(22)
++#define RAMIPS_PSE_P0_FC BIT(21)
++#define RAMIPS_PSE_FQ_EMPTY BIT(20)
++#define RAMIPS_GE1_STA_CHG BIT(18)
++#define RAMIPS_TX_COHERENT BIT(17)
++#define RAMIPS_RX_COHERENT BIT(16)
++#define RAMIPS_TX_DONE_INT3 BIT(11)
++#define RAMIPS_TX_DONE_INT2 BIT(10)
++#define RAMIPS_TX_DONE_INT1 BIT(9)
++#define RAMIPS_TX_DONE_INT0 BIT(8)
++#define RAMIPS_RX_DONE_INT0 BIT(2)
++#define RAMIPS_TX_DLY_INT BIT(1)
++#define RAMIPS_RX_DLY_INT BIT(0)
++
++#define RT5350_RX_DLY_INT BIT(30)
++#define RT5350_TX_DLY_INT BIT(28)
++
++/* registers */
++#define RAMIPS_FE_OFFSET 0x0000
++#define RAMIPS_GDMA_OFFSET 0x0020
++#define RAMIPS_PSE_OFFSET 0x0040
++#define RAMIPS_GDMA2_OFFSET 0x0060
++#define RAMIPS_CDMA_OFFSET 0x0080
++#define RAMIPS_PDMA_OFFSET 0x0100
++#define RAMIPS_PPE_OFFSET 0x0200
++#define RAMIPS_CMTABLE_OFFSET 0x0400
++#define RAMIPS_POLICYTABLE_OFFSET 0x1000
++
++#define RT5350_PDMA_OFFSET 0x0800
++#define RT5350_SDM_OFFSET 0x0c00
++
++#define RAMIPS_MDIO_ACCESS (RAMIPS_FE_OFFSET + 0x00)
++#define RAMIPS_MDIO_CFG (RAMIPS_FE_OFFSET + 0x04)
++#define RAMIPS_FE_GLO_CFG (RAMIPS_FE_OFFSET + 0x08)
++#define RAMIPS_FE_RST_GL (RAMIPS_FE_OFFSET + 0x0C)
++#define RAMIPS_FE_INT_STATUS (RAMIPS_FE_OFFSET + 0x10)
++#define RAMIPS_FE_INT_ENABLE (RAMIPS_FE_OFFSET + 0x14)
++#define RAMIPS_MDIO_CFG2 (RAMIPS_FE_OFFSET + 0x18)
++#define RAMIPS_FOC_TS_T (RAMIPS_FE_OFFSET + 0x1C)
++
++#define RAMIPS_GDMA1_FWD_CFG (RAMIPS_GDMA_OFFSET + 0x00)
++#define RAMIPS_GDMA1_SCH_CFG (RAMIPS_GDMA_OFFSET + 0x04)
++#define RAMIPS_GDMA1_SHPR_CFG (RAMIPS_GDMA_OFFSET + 0x08)
++#define RAMIPS_GDMA1_MAC_ADRL (RAMIPS_GDMA_OFFSET + 0x0C)
++#define RAMIPS_GDMA1_MAC_ADRH (RAMIPS_GDMA_OFFSET + 0x10)
++
++#define RAMIPS_GDMA2_FWD_CFG (RAMIPS_GDMA2_OFFSET + 0x00)
++#define RAMIPS_GDMA2_SCH_CFG (RAMIPS_GDMA2_OFFSET + 0x04)
++#define RAMIPS_GDMA2_SHPR_CFG (RAMIPS_GDMA2_OFFSET + 0x08)
++#define RAMIPS_GDMA2_MAC_ADRL (RAMIPS_GDMA2_OFFSET + 0x0C)
++#define RAMIPS_GDMA2_MAC_ADRH (RAMIPS_GDMA2_OFFSET + 0x10)
++
++#define RAMIPS_PSE_FQ_CFG (RAMIPS_PSE_OFFSET + 0x00)
++#define RAMIPS_CDMA_FC_CFG (RAMIPS_PSE_OFFSET + 0x04)
++#define RAMIPS_GDMA1_FC_CFG (RAMIPS_PSE_OFFSET + 0x08)
++#define RAMIPS_GDMA2_FC_CFG (RAMIPS_PSE_OFFSET + 0x0C)
++
++#define RAMIPS_CDMA_CSG_CFG (RAMIPS_CDMA_OFFSET + 0x00)
++#define RAMIPS_CDMA_SCH_CFG (RAMIPS_CDMA_OFFSET + 0x04)
++
++#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00)
++#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04)
++#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08)
++#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C)
++#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10)
++#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14)
++#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18)
++#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C)
++#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20)
++#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24)
++#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28)
++#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C)
++#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30)
++#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34)
++#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38)
++#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C)
++#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100)
++#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104)
++#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108)
++#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C)
++#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110)
++#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114)
++#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118)
++#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C)
++#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204)
++#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208)
++#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c)
++#define RT5350_FE_INT_STATUS (RT5350_PDMA_OFFSET + 0x220)
++#define RT5350_FE_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228)
++#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280)
++
++
++#define RAMIPS_PDMA_GLO_CFG (RAMIPS_PDMA_OFFSET + 0x00)
++#define RAMIPS_PDMA_RST_CFG (RAMIPS_PDMA_OFFSET + 0x04)
++#define RAMIPS_PDMA_SCH_CFG (RAMIPS_PDMA_OFFSET + 0x08)
++#define RAMIPS_DLY_INT_CFG (RAMIPS_PDMA_OFFSET + 0x0C)
++#define RAMIPS_TX_BASE_PTR0 (RAMIPS_PDMA_OFFSET + 0x10)
++#define RAMIPS_TX_MAX_CNT0 (RAMIPS_PDMA_OFFSET + 0x14)
++#define RAMIPS_TX_CTX_IDX0 (RAMIPS_PDMA_OFFSET + 0x18)
++#define RAMIPS_TX_DTX_IDX0 (RAMIPS_PDMA_OFFSET + 0x1C)
++#define RAMIPS_TX_BASE_PTR1 (RAMIPS_PDMA_OFFSET + 0x20)
++#define RAMIPS_TX_MAX_CNT1 (RAMIPS_PDMA_OFFSET + 0x24)
++#define RAMIPS_TX_CTX_IDX1 (RAMIPS_PDMA_OFFSET + 0x28)
++#define RAMIPS_TX_DTX_IDX1 (RAMIPS_PDMA_OFFSET + 0x2C)
++#define RAMIPS_RX_BASE_PTR0 (RAMIPS_PDMA_OFFSET + 0x30)
++#define RAMIPS_RX_MAX_CNT0 (RAMIPS_PDMA_OFFSET + 0x34)
++#define RAMIPS_RX_CALC_IDX0 (RAMIPS_PDMA_OFFSET + 0x38)
++#define RAMIPS_RX_DRX_IDX0 (RAMIPS_PDMA_OFFSET + 0x3C)
++#define RAMIPS_TX_BASE_PTR2 (RAMIPS_PDMA_OFFSET + 0x40)
++#define RAMIPS_TX_MAX_CNT2 (RAMIPS_PDMA_OFFSET + 0x44)
++#define RAMIPS_TX_CTX_IDX2 (RAMIPS_PDMA_OFFSET + 0x48)
++#define RAMIPS_TX_DTX_IDX2 (RAMIPS_PDMA_OFFSET + 0x4C)
++#define RAMIPS_TX_BASE_PTR3 (RAMIPS_PDMA_OFFSET + 0x50)
++#define RAMIPS_TX_MAX_CNT3 (RAMIPS_PDMA_OFFSET + 0x54)
++#define RAMIPS_TX_CTX_IDX3 (RAMIPS_PDMA_OFFSET + 0x58)
++#define RAMIPS_TX_DTX_IDX3 (RAMIPS_PDMA_OFFSET + 0x5C)
++#define RAMIPS_RX_BASE_PTR1 (RAMIPS_PDMA_OFFSET + 0x60)
++#define RAMIPS_RX_MAX_CNT1 (RAMIPS_PDMA_OFFSET + 0x64)
++#define RAMIPS_RX_CALC_IDX1 (RAMIPS_PDMA_OFFSET + 0x68)
++#define RAMIPS_RX_DRX_IDX1 (RAMIPS_PDMA_OFFSET + 0x6C)
++
++#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00) //Switch DMA configuration
++#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04) //Switch DMA Rx Ring
++#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08) //Switch DMA Tx Ring
++#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C) //Switch MAC address LSB
++#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10) //Switch MAC Address MSB
++#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100) //Switch DMA Tx packet count
++#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104) //Switch DMA Tx byte count
++#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108) //Switch DMA rx packet count
++#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C) //Switch DMA rx byte count
++#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110) //Switch DMA rx checksum error count
++
++#define RT5350_SDM_ICS_EN BIT(16)
++#define RT5350_SDM_TCS_EN BIT(17)
++#define RT5350_SDM_UCS_EN BIT(18)
++
++
++/* MDIO_CFG register bits */
++#define RAMIPS_MDIO_CFG_AUTO_POLL_EN BIT(29)
++#define RAMIPS_MDIO_CFG_GP1_BP_EN BIT(16)
++#define RAMIPS_MDIO_CFG_GP1_FRC_EN BIT(15)
++#define RAMIPS_MDIO_CFG_GP1_SPEED_10 (0 << 13)
++#define RAMIPS_MDIO_CFG_GP1_SPEED_100 (1 << 13)
++#define RAMIPS_MDIO_CFG_GP1_SPEED_1000 (2 << 13)
++#define RAMIPS_MDIO_CFG_GP1_DUPLEX BIT(12)
++#define RAMIPS_MDIO_CFG_GP1_FC_TX BIT(11)
++#define RAMIPS_MDIO_CFG_GP1_FC_RX BIT(10)
++#define RAMIPS_MDIO_CFG_GP1_LNK_DWN BIT(9)
++#define RAMIPS_MDIO_CFG_GP1_AN_FAIL BIT(8)
++#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6)
++#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6)
++#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6)
++#define RAMIPS_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6)
++#define RAMIPS_MDIO_CFG_TURBO_MII_FREQ BIT(5)
++#define RAMIPS_MDIO_CFG_TURBO_MII_MODE BIT(4)
++#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2)
++#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2)
++#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2)
++#define RAMIPS_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2)
++#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_0 0
++#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 1
++#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_400 2
++#define RAMIPS_MDIO_CFG_TX_CLK_SKEW_INV 3
++
++/* uni-cast port */
++#define RAMIPS_GDM1_ICS_EN BIT(22)
++#define RAMIPS_GDM1_TCS_EN BIT(21)
++#define RAMIPS_GDM1_UCS_EN BIT(20)
++#define RAMIPS_GDM1_JMB_EN BIT(19)
++#define RAMIPS_GDM1_STRPCRC BIT(16)
++#define RAMIPS_GDM1_UFRC_P_CPU (0 << 12)
++#define RAMIPS_GDM1_UFRC_P_GDMA1 (1 << 12)
++#define RAMIPS_GDM1_UFRC_P_PPE (6 << 12)
++
++/* checksums */
++#define RAMIPS_ICS_GEN_EN BIT(2)
++#define RAMIPS_UCS_GEN_EN BIT(1)
++#define RAMIPS_TCS_GEN_EN BIT(0)
++
++/* dma ring */
++#define RAMIPS_PST_DRX_IDX0 BIT(16)
++#define RAMIPS_PST_DTX_IDX3 BIT(3)
++#define RAMIPS_PST_DTX_IDX2 BIT(2)
++#define RAMIPS_PST_DTX_IDX1 BIT(1)
++#define RAMIPS_PST_DTX_IDX0 BIT(0)
++
++#define RAMIPS_TX_WB_DDONE BIT(6)
++#define RAMIPS_RX_DMA_BUSY BIT(3)
++#define RAMIPS_TX_DMA_BUSY BIT(1)
++#define RAMIPS_RX_DMA_EN BIT(2)
++#define RAMIPS_TX_DMA_EN BIT(0)
++
++#define RAMIPS_PDMA_SIZE_4DWORDS (0 << 4)
++#define RAMIPS_PDMA_SIZE_8DWORDS (1 << 4)
++#define RAMIPS_PDMA_SIZE_16DWORDS (2 << 4)
++
++#define RAMIPS_US_CYC_CNT_MASK 0xff
++#define RAMIPS_US_CYC_CNT_SHIFT 0x8
++#define RAMIPS_US_CYC_CNT_DIVISOR 1000000
++
++#define RX_DMA_PLEN0(_x) (((_x) >> 16) & 0x3fff)
++#define RX_DMA_LSO BIT(30)
++#define RX_DMA_DONE BIT(31)
++
++struct ramips_rx_dma {
++ unsigned int rxd1;
++ unsigned int rxd2;
++ unsigned int rxd3;
++ unsigned int rxd4;
++} __packed __aligned(4);
++
++#define TX_DMA_PLEN0_MASK ((0x3fff) << 16)
++#define TX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16)
++#define TX_DMA_LSO BIT(30)
++#define TX_DMA_DONE BIT(31)
++#define TX_DMA_QN(_x) ((_x) << 16)
++#define TX_DMA_PN(_x) ((_x) << 24)
++#define TX_DMA_QN_MASK TX_DMA_QN(0x7)
++#define TX_DMA_PN_MASK TX_DMA_PN(0x7)
++
++struct ramips_tx_dma {
++ unsigned int txd1;
++ unsigned int txd2;
++ unsigned int txd3;
++ unsigned int txd4;
++} __packed __aligned(4);
++
++struct raeth_tx_info {
++ struct ramips_tx_dma *tx_desc;
++ struct sk_buff *tx_skb;
++};
++
++struct raeth_rx_info {
++ struct ramips_rx_dma *rx_desc;
++ struct sk_buff *rx_skb;
++ dma_addr_t rx_dma;
++ unsigned int pad;
++};
++
++struct raeth_int_stats {
++ unsigned long rx_delayed;
++ unsigned long tx_delayed;
++ unsigned long rx_done0;
++ unsigned long tx_done0;
++ unsigned long tx_done1;
++ unsigned long tx_done2;
++ unsigned long tx_done3;
++ unsigned long rx_coherent;
++ unsigned long tx_coherent;
++
++ unsigned long pse_fq_empty;
++ unsigned long pse_p0_fc;
++ unsigned long pse_p1_fc;
++ unsigned long pse_p2_fc;
++ unsigned long pse_buf_drop;
++
++ unsigned long total;
++};
++
++struct raeth_debug {
++ struct dentry *debugfs_dir;
++
++ struct raeth_int_stats int_stats;
++};
++
++struct raeth_priv
++{
++ struct device_node *of_node;
++
++ struct raeth_rx_info *rx_info;
++ dma_addr_t rx_desc_dma;
++ struct tasklet_struct rx_tasklet;
++ struct ramips_rx_dma *rx;
++
++ struct raeth_tx_info *tx_info;
++ dma_addr_t tx_desc_dma;
++ struct tasklet_struct tx_housekeeping_tasklet;
++ struct ramips_tx_dma *tx;
++
++ unsigned int skb_free_idx;
++
++ spinlock_t page_lock;
++ struct net_device *netdev;
++ struct device *parent;
++
++ int link;
++ int speed;
++ int duplex;
++ int tx_fc;
++ int rx_fc;
++
++ struct mii_bus *mii_bus;
++ int mii_irq[PHY_MAX_ADDR];
++ struct phy_device *phy_dev;
++ spinlock_t phy_lock;
++ unsigned long sys_freq;
++
++ unsigned char mac[6];
++ void (*reset_fe)(void);
++ int min_pkt_len;
++
++ u32 phy_mask;
++ phy_interface_t phy_if_mode;
++
++#ifdef CONFIG_NET_RAMIPS_DEBUG_FS
++ struct raeth_debug debug;
++#endif
++};
++
++struct ramips_soc_data
++{
++ unsigned char mac[6];
++ void (*reset_fe)(void);
++ int min_pkt_len;
++};
++
++
++#ifdef CONFIG_NET_RAMIPS_DEBUG_FS
++int raeth_debugfs_root_init(void);
++void raeth_debugfs_root_exit(void);
++int raeth_debugfs_init(struct raeth_priv *re);
++void raeth_debugfs_exit(struct raeth_priv *re);
++void raeth_debugfs_update_int_stats(struct raeth_priv *re, u32 status);
++#else
++static inline int raeth_debugfs_root_init(void) { return 0; }
++static inline void raeth_debugfs_root_exit(void) {}
++static inline int raeth_debugfs_init(struct raeth_priv *re) { return 0; }
++static inline void raeth_debugfs_exit(struct raeth_priv *re) {}
++static inline void raeth_debugfs_update_int_stats(struct raeth_priv *re,
++ u32 status) {}
++#endif /* CONFIG_NET_RAMIPS_DEBUG_FS */
++
++#endif /* RAMIPS_ETH_H */
+--- /dev/null
++++ b/drivers/net/ethernet/ramips/ramips_main.c
+@@ -0,0 +1,1281 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * Copyright (C) 2009 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/dma-mapping.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++#include <linux/platform_device.h>
++#include <linux/phy.h>
++#include <linux/of_device.h>
++#include <linux/clk.h>
++#include <linux/of_net.h>
++#include <linux/of_mdio.h>
++
++#include "ramips_eth.h"
++
++#define TX_TIMEOUT (20 * HZ / 100)
++#define MAX_RX_LENGTH 1600
++
++#ifdef CONFIG_SOC_RT305X
++#include <rt305x.h>
++#include "ramips_esw.c"
++#else
++#include <asm/mach-ralink/ralink_regs.h>
++static inline int rt305x_esw_init(void) { return 0; }
++static inline void rt305x_esw_exit(void) { }
++static inline int soc_is_rt5350(void) { return 0; }
++#endif
++
++#define phys_to_bus(a) (a & 0x1FFFFFFF)
++
++#ifdef CONFIG_NET_RAMIPS_DEBUG
++#define RADEBUG(fmt, args...) printk(KERN_DEBUG fmt, ## args)
++#else
++#define RADEBUG(fmt, args...) do {} while (0)
++#endif
++
++#define RX_DLY_INT ((soc_is_rt5350())?(RT5350_RX_DLY_INT):(RAMIPS_RX_DLY_INT))
++#define TX_DLY_INT ((soc_is_rt5350())?(RT5350_TX_DLY_INT):(RAMIPS_TX_DLY_INT))
++
++enum raeth_reg {
++ RAETH_REG_PDMA_GLO_CFG = 0,
++ RAETH_REG_PDMA_RST_CFG,
++ RAETH_REG_DLY_INT_CFG,
++ RAETH_REG_TX_BASE_PTR0,
++ RAETH_REG_TX_MAX_CNT0,
++ RAETH_REG_TX_CTX_IDX0,
++ RAETH_REG_RX_BASE_PTR0,
++ RAETH_REG_RX_MAX_CNT0,
++ RAETH_REG_RX_CALC_IDX0,
++ RAETH_REG_FE_INT_ENABLE,
++ RAETH_REG_FE_INT_STATUS,
++ RAETH_REG_COUNT
++};
++
++static const u32 ramips_reg_table[RAETH_REG_COUNT] = {
++ [RAETH_REG_PDMA_GLO_CFG] = RAMIPS_PDMA_GLO_CFG,
++ [RAETH_REG_PDMA_RST_CFG] = RAMIPS_PDMA_RST_CFG,
++ [RAETH_REG_DLY_INT_CFG] = RAMIPS_DLY_INT_CFG,
++ [RAETH_REG_TX_BASE_PTR0] = RAMIPS_TX_BASE_PTR0,
++ [RAETH_REG_TX_MAX_CNT0] = RAMIPS_TX_MAX_CNT0,
++ [RAETH_REG_TX_CTX_IDX0] = RAMIPS_TX_CTX_IDX0,
++ [RAETH_REG_RX_BASE_PTR0] = RAMIPS_RX_BASE_PTR0,
++ [RAETH_REG_RX_MAX_CNT0] = RAMIPS_RX_MAX_CNT0,
++ [RAETH_REG_RX_CALC_IDX0] = RAMIPS_RX_CALC_IDX0,
++ [RAETH_REG_FE_INT_ENABLE] = RAMIPS_FE_INT_ENABLE,
++ [RAETH_REG_FE_INT_STATUS] = RAMIPS_FE_INT_STATUS,
++};
++
++static const u32 rt5350_reg_table[RAETH_REG_COUNT] = {
++ [RAETH_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG,
++ [RAETH_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG,
++ [RAETH_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG,
++ [RAETH_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0,
++ [RAETH_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0,
++ [RAETH_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0,
++ [RAETH_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0,
++ [RAETH_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0,
++ [RAETH_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0,
++ [RAETH_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE,
++ [RAETH_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS,
++};
++
++static struct net_device * ramips_dev;
++static void __iomem *ramips_fe_base = 0;
++
++static inline u32 get_reg_offset(enum raeth_reg reg)
++{
++ const u32 *table;
++
++ if (soc_is_rt5350())
++ table = rt5350_reg_table;
++ else
++ table = ramips_reg_table;
++
++ return table[reg];
++}
++
++static inline void
++ramips_fe_wr(u32 val, unsigned reg)
++{
++ __raw_writel(val, ramips_fe_base + reg);
++}
++
++static inline u32
++ramips_fe_rr(unsigned reg)
++{
++ return __raw_readl(ramips_fe_base + reg);
++}
++
++static inline void
++ramips_fe_twr(u32 val, enum raeth_reg reg)
++{
++ ramips_fe_wr(val, get_reg_offset(reg));
++}
++
++static inline u32
++ramips_fe_trr(enum raeth_reg reg)
++{
++ return ramips_fe_rr(get_reg_offset(reg));
++}
++
++static inline void
++ramips_fe_int_disable(u32 mask)
++{
++ ramips_fe_twr(ramips_fe_trr(RAETH_REG_FE_INT_ENABLE) & ~mask,
++ RAETH_REG_FE_INT_ENABLE);
++ /* flush write */
++ ramips_fe_trr(RAETH_REG_FE_INT_ENABLE);
++}
++
++static inline void
++ramips_fe_int_enable(u32 mask)
++{
++ ramips_fe_twr(ramips_fe_trr(RAETH_REG_FE_INT_ENABLE) | mask,
++ RAETH_REG_FE_INT_ENABLE);
++ /* flush write */
++ ramips_fe_trr(RAETH_REG_FE_INT_ENABLE);
++}
++
++static inline void
++ramips_hw_set_macaddr(unsigned char *mac)
++{
++ if (soc_is_rt5350()) {
++ ramips_fe_wr((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH);
++ ramips_fe_wr((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
++ RT5350_SDM_MAC_ADRL);
++ } else {
++ ramips_fe_wr((mac[0] << 8) | mac[1], RAMIPS_GDMA1_MAC_ADRH);
++ ramips_fe_wr((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
++ RAMIPS_GDMA1_MAC_ADRL);
++ }
++}
++
++static struct sk_buff *
++ramips_alloc_skb(struct raeth_priv *re)
++{
++ struct sk_buff *skb;
++
++ skb = netdev_alloc_skb(re->netdev, MAX_RX_LENGTH + NET_IP_ALIGN);
++ if (!skb)
++ return NULL;
++
++ skb_reserve(skb, NET_IP_ALIGN);
++
++ return skb;
++}
++
++static void
++ramips_ring_setup(struct raeth_priv *re)
++{
++ int len;
++ int i;
++
++ memset(re->tx_info, 0, NUM_TX_DESC * sizeof(struct raeth_tx_info));
++
++ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma);
++ memset(re->tx, 0, len);
++
++ for (i = 0; i < NUM_TX_DESC; i++) {
++ struct raeth_tx_info *txi;
++ struct ramips_tx_dma *txd;
++
++ txd = &re->tx[i];
++ txd->txd4 = TX_DMA_QN(3) | TX_DMA_PN(1);
++ txd->txd2 = TX_DMA_LSO | TX_DMA_DONE;
++
++ txi = &re->tx_info[i];
++ txi->tx_desc = txd;
++ if (txi->tx_skb != NULL) {
++ netdev_warn(re->netdev,
++ "dirty skb for TX desc %d\n", i);
++ txi->tx_skb = NULL;
++ }
++ }
++
++ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma);
++ memset(re->rx, 0, len);
++
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ struct raeth_rx_info *rxi;
++ struct ramips_rx_dma *rxd;
++ dma_addr_t dma_addr;
++
++ rxd = &re->rx[i];
++ rxi = &re->rx_info[i];
++ BUG_ON(rxi->rx_skb == NULL);
++ dma_addr = dma_map_single(&re->netdev->dev, rxi->rx_skb->data,
++ MAX_RX_LENGTH, DMA_FROM_DEVICE);
++ rxi->rx_dma = dma_addr;
++ rxi->rx_desc = rxd;
++
++ rxd->rxd1 = (unsigned int) dma_addr;
++ rxd->rxd2 = RX_DMA_LSO;
++ }
++
++ /* flush descriptors */
++ wmb();
++}
++
++static void
++ramips_ring_cleanup(struct raeth_priv *re)
++{
++ int i;
++
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ struct raeth_rx_info *rxi;
++
++ rxi = &re->rx_info[i];
++ if (rxi->rx_skb)
++ dma_unmap_single(&re->netdev->dev, rxi->rx_dma,
++ MAX_RX_LENGTH, DMA_FROM_DEVICE);
++ }
++
++ for (i = 0; i < NUM_TX_DESC; i++) {
++ struct raeth_tx_info *txi;
++
++ txi = &re->tx_info[i];
++ if (txi->tx_skb) {
++ dev_kfree_skb_any(txi->tx_skb);
++ txi->tx_skb = NULL;
++ }
++ }
++
++ netdev_reset_queue(re->netdev);
++}
++
++#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT3883)
++
++#define RAMIPS_MDIO_RETRY 1000
++
++static unsigned char *ramips_speed_str(struct raeth_priv *re)
++{
++ switch (re->speed) {
++ case SPEED_1000:
++ return "1000";
++ case SPEED_100:
++ return "100";
++ case SPEED_10:
++ return "10";
++ }
++
++ return "?";
++}
++
++static void ramips_link_adjust(struct raeth_priv *re)
++{
++ u32 mdio_cfg;
++
++ if (!re->link) {
++ netif_carrier_off(re->netdev);
++ netdev_info(re->netdev, "link down\n");
++ return;
++ }
++
++ mdio_cfg = RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 |
++ RAMIPS_MDIO_CFG_TX_CLK_SKEW_200 |
++ RAMIPS_MDIO_CFG_GP1_FRC_EN;
++
++ if (re->duplex == DUPLEX_FULL)
++ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_DUPLEX;
++
++ if (re->tx_fc)
++ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_FC_TX;
++
++ if (re->rx_fc)
++ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_FC_RX;
++
++ switch (re->speed) {
++ case SPEED_10:
++ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_10;
++ break;
++ case SPEED_100:
++ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_100;
++ break;
++ case SPEED_1000:
++ mdio_cfg |= RAMIPS_MDIO_CFG_GP1_SPEED_1000;
++ break;
++ default:
++ BUG();
++ }
++
++ ramips_fe_wr(mdio_cfg, RAMIPS_MDIO_CFG);
++
++ netif_carrier_on(re->netdev);
++ netdev_info(re->netdev, "link up (%sMbps/%s duplex)\n",
++ ramips_speed_str(re),
++ (DUPLEX_FULL == re->duplex) ? "Full" : "Half");
++}
++
++static int
++ramips_mdio_wait_ready(struct raeth_priv *re)
++{
++ int retries;
++
++ retries = RAMIPS_MDIO_RETRY;
++ while (1) {
++ u32 t;
++
++ t = ramips_fe_rr(RAMIPS_MDIO_ACCESS);
++ if ((t & (0x1 << 31)) == 0)
++ return 0;
++
++ if (retries-- == 0)
++ break;
++
++ udelay(1);
++ }
++
++ dev_err(re->parent, "MDIO operation timed out\n");
++ return -ETIMEDOUT;
++}
++
++static int
++ramips_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
++{
++ struct raeth_priv *re = bus->priv;
++ int err;
++ u32 t;
++
++ err = ramips_mdio_wait_ready(re);
++ if (err)
++ return 0xffff;
++
++ t = (phy_addr << 24) | (phy_reg << 16);
++ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
++ t |= (1 << 31);
++ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
++
++ err = ramips_mdio_wait_ready(re);
++ if (err)
++ return 0xffff;
++
++ RADEBUG("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
++ phy_addr, phy_reg, ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff);
++
++ return ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff;
++}
++
++static int
++ramips_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
++{
++ struct raeth_priv *re = bus->priv;
++ int err;
++ u32 t;
++
++ RADEBUG("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
++ phy_addr, phy_reg, ramips_fe_rr(RAMIPS_MDIO_ACCESS) & 0xffff);
++
++ err = ramips_mdio_wait_ready(re);
++ if (err)
++ return err;
++
++ t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val;
++ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
++ t |= (1 << 31);
++ ramips_fe_wr(t, RAMIPS_MDIO_ACCESS);
++
++ return ramips_mdio_wait_ready(re);
++}
++
++static int
++ramips_mdio_reset(struct mii_bus *bus)
++{
++ /* TODO */
++ return 0;
++}
++
++static int
++ramips_mdio_init(struct raeth_priv *re)
++{
++ struct device_node *mii_np;
++ int err;
++
++ mii_np = of_get_child_by_name(re->of_node, "mdio-bus");
++ if (!mii_np) {
++ dev_err(re->parent, "no %s child node found", "mdio-bus");
++ return -ENODEV;
++ }
++
++ if (!of_device_is_available(mii_np)) {
++ err = 0;
++ goto err_put_node;
++ }
++
++ re->mii_bus = mdiobus_alloc();
++ if (re->mii_bus == NULL) {
++ err = -ENOMEM;
++ goto err_put_node;
++ }
++
++ re->mii_bus->name = "ramips_mdio";
++ re->mii_bus->read = ramips_mdio_read;
++ re->mii_bus->write = ramips_mdio_write;
++ re->mii_bus->reset = ramips_mdio_reset;
++ re->mii_bus->irq = re->mii_irq;
++ re->mii_bus->priv = re;
++ re->mii_bus->parent = re->parent;
++
++ snprintf(re->mii_bus->id, MII_BUS_ID_SIZE, "%s", "ramips_mdio");
++ err = of_mdiobus_register(re->mii_bus, mii_np);
++ if (err)
++ goto err_free_bus;
++
++ return 0;
++
++err_free_bus:
++ kfree(re->mii_bus);
++err_put_node:
++ of_node_put(mii_np);
++ re->mii_bus = NULL;
++ return err;
++}
++
++static void
++ramips_mdio_cleanup(struct raeth_priv *re)
++{
++ if (!re->mii_bus)
++ return;
++
++ mdiobus_unregister(re->mii_bus);
++ of_node_put(re->mii_bus->dev.of_node);
++ kfree(re->mii_bus);
++}
++
++static void
++ramips_phy_link_adjust(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++ struct phy_device *phydev = re->phy_dev;
++ unsigned long flags;
++ int status_change = 0;
++
++ spin_lock_irqsave(&re->phy_lock, flags);
++
++ if (phydev->link)
++ if (re->duplex != phydev->duplex ||
++ re->speed != phydev->speed)
++ status_change = 1;
++
++ if (phydev->link != re->link)
++ status_change = 1;
++
++ re->link = phydev->link;
++ re->duplex = phydev->duplex;
++ re->speed = phydev->speed;
++
++ if (status_change)
++ ramips_link_adjust(re);
++
++ spin_unlock_irqrestore(&re->phy_lock, flags);
++}
++
++static int
++ramips_phy_connect_by_node(struct raeth_priv *re, struct device_node *phy_node)
++{
++ struct phy_device *phydev;
++ int phy_mode;
++
++ phy_mode = of_get_phy_mode(re->of_node);
++ if (phy_mode < 0) {
++ dev_err(re->parent, "incorrect phy-mode\n");
++ return -EINVAL;
++ }
++
++ phydev = of_phy_connect(re->netdev, phy_node, ramips_phy_link_adjust,
++ 0, phy_mode);
++ if (IS_ERR(phydev)) {
++ dev_err(re->parent, "could not connect to PHY\n");
++ return PTR_ERR(re->phy_dev);
++ }
++
++ phydev->supported &= PHY_GBIT_FEATURES;
++ phydev->advertising = phydev->supported;
++
++ dev_info(re->parent,
++ "connected to PHY at %s [uid=%08x, driver=%s]\n",
++ dev_name(&phydev->dev), phydev->phy_id,
++ phydev->drv->name);
++
++ re->phy_dev = phydev;
++ re->link = 0;
++ re->speed = 0;
++ re->duplex = -1;
++ re->rx_fc = 0;
++ re->tx_fc = 0;
++
++ return 0;
++}
++
++static int
++ramips_phy_connect_fixed(struct raeth_priv *re, const __be32 *link, int size)
++{
++ if (size != (4 * sizeof(*link))) {
++ dev_err(re->parent, "invalid fixed-link property\n");
++ return -EINVAL;
++ }
++
++ re->speed = be32_to_cpup(link++);
++ re->duplex = be32_to_cpup(link++);
++ re->tx_fc = be32_to_cpup(link++);
++ re->rx_fc = be32_to_cpup(link++);
++
++ switch (re->speed) {
++ case SPEED_10:
++ case SPEED_100:
++ case SPEED_1000:
++ break;
++ default:
++ dev_err(re->parent, "invalid link speed: %d\n", re->speed);
++ return -EINVAL;
++ }
++
++ dev_info(re->parent, "using fixed link parameters\n");
++ return 0;
++}
++
++static int
++ramips_phy_connect(struct raeth_priv *re)
++{
++ struct device_node *phy_node;
++ const __be32 *p32;
++ int size;
++
++ phy_node = of_parse_phandle(re->of_node, "phy-handle", 0);
++ if (phy_node)
++ return ramips_phy_connect_by_node(re, phy_node);
++
++ p32 = of_get_property(re->of_node, "ralink,fixed-link", &size);
++ if (p32)
++ return ramips_phy_connect_fixed(re, p32, size);
++
++ dev_err(re->parent, "unable to get connection type\n");
++ return -EINVAL;
++}
++
++static void
++ramips_phy_disconnect(struct raeth_priv *re)
++{
++ if (re->phy_dev)
++ phy_disconnect(re->phy_dev);
++}
++
++static void
++ramips_phy_start(struct raeth_priv *re)
++{
++ unsigned long flags;
++
++ if (re->phy_dev) {
++ phy_start(re->phy_dev);
++ } else {
++ spin_lock_irqsave(&re->phy_lock, flags);
++ re->link = 1;
++ ramips_link_adjust(re);
++ spin_unlock_irqrestore(&re->phy_lock, flags);
++ }
++}
++
++static void
++ramips_phy_stop(struct raeth_priv *re)
++{
++ unsigned long flags;
++
++ if (re->phy_dev)
++ phy_stop(re->phy_dev);
++
++ spin_lock_irqsave(&re->phy_lock, flags);
++ re->link = 0;
++ ramips_link_adjust(re);
++ spin_unlock_irqrestore(&re->phy_lock, flags);
++}
++#else
++static inline int
++ramips_mdio_init(struct raeth_priv *re)
++{
++ return 0;
++}
++
++static inline void
++ramips_mdio_cleanup(struct raeth_priv *re)
++{
++}
++
++static inline int
++ramips_phy_connect(struct raeth_priv *re)
++{
++ return 0;
++}
++
++static inline void
++ramips_phy_disconnect(struct raeth_priv *re)
++{
++}
++
++static inline void
++ramips_phy_start(struct raeth_priv *re)
++{
++}
++
++static inline void
++ramips_phy_stop(struct raeth_priv *re)
++{
++}
++#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT3883 */
++
++static void
++ramips_ring_free(struct raeth_priv *re)
++{
++ int len;
++ int i;
++
++ if (re->rx_info) {
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ struct raeth_rx_info *rxi;
++
++ rxi = &re->rx_info[i];
++ if (rxi->rx_skb)
++ dev_kfree_skb_any(rxi->rx_skb);
++ }
++ kfree(re->rx_info);
++ }
++
++ if (re->rx) {
++ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma);
++ dma_free_coherent(&re->netdev->dev, len, re->rx,
++ re->rx_desc_dma);
++ }
++
++ if (re->tx) {
++ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma);
++ dma_free_coherent(&re->netdev->dev, len, re->tx,
++ re->tx_desc_dma);
++ }
++
++ kfree(re->tx_info);
++}
++
++static int
++ramips_ring_alloc(struct raeth_priv *re)
++{
++ int len;
++ int err = -ENOMEM;
++ int i;
++
++ re->tx_info = kzalloc(NUM_TX_DESC * sizeof(struct raeth_tx_info),
++ GFP_ATOMIC);
++ if (!re->tx_info)
++ goto err_cleanup;
++
++ re->rx_info = kzalloc(NUM_RX_DESC * sizeof(struct raeth_rx_info),
++ GFP_ATOMIC);
++ if (!re->rx_info)
++ goto err_cleanup;
++
++ /* allocate tx ring */
++ len = NUM_TX_DESC * sizeof(struct ramips_tx_dma);
++ re->tx = dma_alloc_coherent(&re->netdev->dev, len,
++ &re->tx_desc_dma, GFP_ATOMIC);
++ if (!re->tx)
++ goto err_cleanup;
++
++ /* allocate rx ring */
++ len = NUM_RX_DESC * sizeof(struct ramips_rx_dma);
++ re->rx = dma_alloc_coherent(&re->netdev->dev, len,
++ &re->rx_desc_dma, GFP_ATOMIC);
++ if (!re->rx)
++ goto err_cleanup;
++
++ for (i = 0; i < NUM_RX_DESC; i++) {
++ struct sk_buff *skb;
++
++ skb = ramips_alloc_skb(re);
++ if (!skb)
++ goto err_cleanup;
++
++ re->rx_info[i].rx_skb = skb;
++ }
++
++ return 0;
++
++err_cleanup:
++ ramips_ring_free(re);
++ return err;
++}
++
++static void
++ramips_setup_dma(struct raeth_priv *re)
++{
++ ramips_fe_twr(re->tx_desc_dma, RAETH_REG_TX_BASE_PTR0);
++ ramips_fe_twr(NUM_TX_DESC, RAETH_REG_TX_MAX_CNT0);
++ ramips_fe_twr(0, RAETH_REG_TX_CTX_IDX0);
++ ramips_fe_twr(RAMIPS_PST_DTX_IDX0, RAETH_REG_PDMA_RST_CFG);
++
++ ramips_fe_twr(re->rx_desc_dma, RAETH_REG_RX_BASE_PTR0);
++ ramips_fe_twr(NUM_RX_DESC, RAETH_REG_RX_MAX_CNT0);
++ ramips_fe_twr((NUM_RX_DESC - 1), RAETH_REG_RX_CALC_IDX0);
++ ramips_fe_twr(RAMIPS_PST_DRX_IDX0, RAETH_REG_PDMA_RST_CFG);
++}
++
++static int
++ramips_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++ struct raeth_tx_info *txi, *txi_next;
++ struct ramips_tx_dma *txd, *txd_next;
++ unsigned long tx;
++ unsigned int tx_next;
++ dma_addr_t mapped_addr;
++
++ if (re->min_pkt_len) {
++ if (skb->len < re->min_pkt_len) {
++ if (skb_padto(skb, re->min_pkt_len)) {
++ printk(KERN_ERR
++ "ramips_eth: skb_padto failed\n");
++ kfree_skb(skb);
++ return 0;
++ }
++ skb_put(skb, re->min_pkt_len - skb->len);
++ }
++ }
++
++ dev->trans_start = jiffies;
++ mapped_addr = dma_map_single(&re->netdev->dev, skb->data, skb->len,
++ DMA_TO_DEVICE);
++
++ spin_lock(&re->page_lock);
++ tx = ramips_fe_trr(RAETH_REG_TX_CTX_IDX0);
++ tx_next = (tx + 1) % NUM_TX_DESC;
++
++ txi = &re->tx_info[tx];
++ txd = txi->tx_desc;
++ txi_next = &re->tx_info[tx_next];
++ txd_next = txi_next->tx_desc;
++
++ if ((txi->tx_skb) || (txi_next->tx_skb) ||
++ !(txd->txd2 & TX_DMA_DONE) ||
++ !(txd_next->txd2 & TX_DMA_DONE))
++ goto out;
++
++ txi->tx_skb = skb;
++
++ txd->txd1 = (unsigned int) mapped_addr;
++ wmb();
++ txd->txd2 = TX_DMA_LSO | TX_DMA_PLEN0(skb->len);
++ dev->stats.tx_packets++;
++ dev->stats.tx_bytes += skb->len;
++ ramips_fe_twr(tx_next, RAETH_REG_TX_CTX_IDX0);
++ netdev_sent_queue(dev, skb->len);
++ spin_unlock(&re->page_lock);
++ return NETDEV_TX_OK;
++
++ out:
++ spin_unlock(&re->page_lock);
++ dev->stats.tx_dropped++;
++ kfree_skb(skb);
++ return NETDEV_TX_OK;
++}
++
++static void
++ramips_eth_rx_hw(unsigned long ptr)
++{
++ struct net_device *dev = (struct net_device *) ptr;
++ struct raeth_priv *re = netdev_priv(dev);
++ int rx;
++ int max_rx = 16;
++
++ rx = ramips_fe_trr(RAETH_REG_RX_CALC_IDX0);
++
++ while (max_rx) {
++ struct raeth_rx_info *rxi;
++ struct ramips_rx_dma *rxd;
++ struct sk_buff *rx_skb, *new_skb;
++ int pktlen;
++
++ rx = (rx + 1) % NUM_RX_DESC;
++
++ rxi = &re->rx_info[rx];
++ rxd = rxi->rx_desc;
++ if (!(rxd->rxd2 & RX_DMA_DONE))
++ break;
++
++ rx_skb = rxi->rx_skb;
++ pktlen = RX_DMA_PLEN0(rxd->rxd2);
++
++ new_skb = ramips_alloc_skb(re);
++ /* Reuse the buffer on allocation failures */
++ if (new_skb) {
++ dma_addr_t dma_addr;
++
++ dma_unmap_single(&re->netdev->dev, rxi->rx_dma,
++ MAX_RX_LENGTH, DMA_FROM_DEVICE);
++
++ skb_put(rx_skb, pktlen);
++ rx_skb->dev = dev;
++ rx_skb->protocol = eth_type_trans(rx_skb, dev);
++ rx_skb->ip_summed = CHECKSUM_NONE;
++ dev->stats.rx_packets++;
++ dev->stats.rx_bytes += pktlen;
++ netif_rx(rx_skb);
++
++ rxi->rx_skb = new_skb;
++
++ dma_addr = dma_map_single(&re->netdev->dev,
++ new_skb->data,
++ MAX_RX_LENGTH,
++ DMA_FROM_DEVICE);
++ rxi->rx_dma = dma_addr;
++ rxd->rxd1 = (unsigned int) dma_addr;
++ wmb();
++ } else {
++ dev->stats.rx_dropped++;
++ }
++
++ rxd->rxd2 = RX_DMA_LSO;
++ ramips_fe_twr(rx, RAETH_REG_RX_CALC_IDX0);
++ max_rx--;
++ }
++
++ if (max_rx == 0)
++ tasklet_schedule(&re->rx_tasklet);
++ else
++ ramips_fe_int_enable(RX_DLY_INT);
++}
++
++static void
++ramips_eth_tx_housekeeping(unsigned long ptr)
++{
++ struct net_device *dev = (struct net_device*)ptr;
++ struct raeth_priv *re = netdev_priv(dev);
++ unsigned int bytes_compl = 0, pkts_compl = 0;
++
++ spin_lock(&re->page_lock);
++ while (1) {
++ struct raeth_tx_info *txi;
++ struct ramips_tx_dma *txd;
++
++ txi = &re->tx_info[re->skb_free_idx];
++ txd = txi->tx_desc;
++
++ if (!(txd->txd2 & TX_DMA_DONE) || !(txi->tx_skb))
++ break;
++
++ pkts_compl++;
++ bytes_compl += txi->tx_skb->len;
++
++ dev_kfree_skb_irq(txi->tx_skb);
++ txi->tx_skb = NULL;
++ re->skb_free_idx++;
++ if (re->skb_free_idx >= NUM_TX_DESC)
++ re->skb_free_idx = 0;
++ }
++ netdev_completed_queue(dev, pkts_compl, bytes_compl);
++ spin_unlock(&re->page_lock);
++
++ ramips_fe_int_enable(TX_DLY_INT);
++}
++
++static void
++ramips_eth_timeout(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++
++ tasklet_schedule(&re->tx_housekeeping_tasklet);
++}
++
++static irqreturn_t
++ramips_eth_irq(int irq, void *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++ unsigned int status;
++
++ status = ramips_fe_trr(RAETH_REG_FE_INT_STATUS);
++ status &= ramips_fe_trr(RAETH_REG_FE_INT_ENABLE);
++
++ if (!status)
++ return IRQ_NONE;
++
++ ramips_fe_twr(status, RAETH_REG_FE_INT_STATUS);
++
++ if (status & RX_DLY_INT) {
++ ramips_fe_int_disable(RX_DLY_INT);
++ tasklet_schedule(&re->rx_tasklet);
++ }
++
++ if (status & TX_DLY_INT) {
++ ramips_fe_int_disable(TX_DLY_INT);
++ tasklet_schedule(&re->tx_housekeeping_tasklet);
++ }
++
++ raeth_debugfs_update_int_stats(re, status);
++
++ return IRQ_HANDLED;
++}
++
++static int
++ramips_eth_hw_init(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++ int err;
++
++ err = request_irq(dev->irq, ramips_eth_irq, IRQF_DISABLED,
++ dev_name(re->parent), dev);
++ if (err)
++ return err;
++
++ err = ramips_ring_alloc(re);
++ if (err)
++ goto err_free_irq;
++
++ ramips_ring_setup(re);
++ ramips_hw_set_macaddr(dev->dev_addr);
++
++ ramips_setup_dma(re);
++ ramips_fe_wr((ramips_fe_rr(RAMIPS_FE_GLO_CFG) &
++ ~(RAMIPS_US_CYC_CNT_MASK << RAMIPS_US_CYC_CNT_SHIFT)) |
++ ((re->sys_freq / RAMIPS_US_CYC_CNT_DIVISOR) << RAMIPS_US_CYC_CNT_SHIFT),
++ RAMIPS_FE_GLO_CFG);
++
++ tasklet_init(&re->tx_housekeeping_tasklet, ramips_eth_tx_housekeeping,
++ (unsigned long)dev);
++ tasklet_init(&re->rx_tasklet, ramips_eth_rx_hw, (unsigned long)dev);
++
++
++ ramips_fe_twr(RAMIPS_DELAY_INIT, RAETH_REG_DLY_INT_CFG);
++ ramips_fe_twr(TX_DLY_INT | RX_DLY_INT, RAETH_REG_FE_INT_ENABLE);
++ if (soc_is_rt5350()) {
++ ramips_fe_wr(ramips_fe_rr(RT5350_SDM_CFG) &
++ ~(RT5350_SDM_ICS_EN | RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN | 0xffff),
++ RT5350_SDM_CFG);
++ } else {
++ ramips_fe_wr(ramips_fe_rr(RAMIPS_GDMA1_FWD_CFG) &
++ ~(RAMIPS_GDM1_ICS_EN | RAMIPS_GDM1_TCS_EN | RAMIPS_GDM1_UCS_EN | 0xffff),
++ RAMIPS_GDMA1_FWD_CFG);
++ ramips_fe_wr(ramips_fe_rr(RAMIPS_CDMA_CSG_CFG) &
++ ~(RAMIPS_ICS_GEN_EN | RAMIPS_TCS_GEN_EN | RAMIPS_UCS_GEN_EN),
++ RAMIPS_CDMA_CSG_CFG);
++ ramips_fe_wr(RAMIPS_PSE_FQFC_CFG_INIT, RAMIPS_PSE_FQ_CFG);
++ }
++ ramips_fe_wr(1, RAMIPS_FE_RST_GL);
++ ramips_fe_wr(0, RAMIPS_FE_RST_GL);
++
++ return 0;
++
++err_free_irq:
++ free_irq(dev->irq, dev);
++ return err;
++}
++
++static int
++ramips_eth_open(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++
++ ramips_fe_twr((ramips_fe_trr(RAETH_REG_PDMA_GLO_CFG) & 0xff) |
++ (RAMIPS_TX_WB_DDONE | RAMIPS_RX_DMA_EN |
++ RAMIPS_TX_DMA_EN | RAMIPS_PDMA_SIZE_4DWORDS),
++ RAETH_REG_PDMA_GLO_CFG);
++ ramips_phy_start(re);
++ netif_start_queue(dev);
++ return 0;
++}
++
++static int
++ramips_eth_stop(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++
++ ramips_fe_twr(ramips_fe_trr(RAETH_REG_PDMA_GLO_CFG) &
++ ~(RAMIPS_TX_WB_DDONE | RAMIPS_RX_DMA_EN | RAMIPS_TX_DMA_EN),
++ RAETH_REG_PDMA_GLO_CFG);
++
++ netif_stop_queue(dev);
++ ramips_phy_stop(re);
++ RADEBUG("ramips_eth: stopped\n");
++ return 0;
++}
++
++static int __init
++ramips_eth_probe(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++ int err;
++
++ BUG_ON(!re->reset_fe);
++ re->reset_fe();
++ net_srandom(jiffies);
++ memcpy(dev->dev_addr, re->mac, ETH_ALEN);
++ of_get_mac_address_mtd(re->of_node, dev->dev_addr);
++ ether_setup(dev);
++ dev->mtu = 1500;
++ dev->watchdog_timeo = TX_TIMEOUT;
++ spin_lock_init(&re->page_lock);
++ spin_lock_init(&re->phy_lock);
++
++ err = ramips_mdio_init(re);
++ if (err)
++ return err;
++
++ err = ramips_phy_connect(re);
++ if (err)
++ goto err_mdio_cleanup;
++
++ err = raeth_debugfs_init(re);
++ if (err)
++ goto err_phy_disconnect;
++
++ err = ramips_eth_hw_init(dev);
++ if (err)
++ goto err_debugfs;
++
++ return 0;
++
++err_debugfs:
++ raeth_debugfs_exit(re);
++err_phy_disconnect:
++ ramips_phy_disconnect(re);
++err_mdio_cleanup:
++ ramips_mdio_cleanup(re);
++ return err;
++}
++
++static void
++ramips_eth_uninit(struct net_device *dev)
++{
++ struct raeth_priv *re = netdev_priv(dev);
++
++ raeth_debugfs_exit(re);
++ ramips_phy_disconnect(re);
++ ramips_mdio_cleanup(re);
++ ramips_fe_twr(0, RAETH_REG_FE_INT_ENABLE);
++ free_irq(dev->irq, dev);
++ tasklet_kill(&re->tx_housekeeping_tasklet);
++ tasklet_kill(&re->rx_tasklet);
++ ramips_ring_cleanup(re);
++ ramips_ring_free(re);
++}
++
++static const struct net_device_ops ramips_eth_netdev_ops = {
++ .ndo_init = ramips_eth_probe,
++ .ndo_uninit = ramips_eth_uninit,
++ .ndo_open = ramips_eth_open,
++ .ndo_stop = ramips_eth_stop,
++ .ndo_start_xmit = ramips_eth_hard_start_xmit,
++ .ndo_tx_timeout = ramips_eth_timeout,
++ .ndo_change_mtu = eth_change_mtu,
++ .ndo_set_mac_address = eth_mac_addr,
++ .ndo_validate_addr = eth_validate_addr,
++};
++
++#ifdef CONFIG_SOC_RT305X
++static void rt305x_fe_reset(void)
++{
++#define RT305X_RESET_FE BIT(21)
++#define RT305X_RESET_ESW BIT(23)
++#define SYSC_REG_RESET_CTRL 0x034
++ u32 reset_bits = RT305X_RESET_FE;
++
++ if (soc_is_rt5350())
++ reset_bits |= RT305X_RESET_ESW;
++ rt_sysc_w32(reset_bits, SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL);
++}
++
++struct ramips_soc_data rt3050_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reset_fe = rt305x_fe_reset,
++ .min_pkt_len = 64,
++};
++
++static const struct of_device_id ralink_eth_match[] = {
++ { .compatible = "ralink,rt3050-eth", .data = &rt3050_data },
++ {},
++};
++#else
++static void rt3883_fe_reset(void)
++{
++#define RT3883_SYSC_REG_RSTCTRL 0x34
++#define RT3883_RSTCTRL_FE BIT(21)
++ u32 t;
++
++ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
++ t |= RT3883_RSTCTRL_FE;
++ rt_sysc_w32(t , RT3883_SYSC_REG_RSTCTRL);
++
++ t &= ~RT3883_RSTCTRL_FE;
++ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
++}
++
++struct ramips_soc_data rt3883_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reset_fe = rt3883_fe_reset,
++ .min_pkt_len = 64,
++};
++
++static const struct of_device_id ralink_eth_match[] = {
++ { .compatible = "ralink,rt3883-eth", .data = &rt3883_data },
++ {},
++};
++#endif
++MODULE_DEVICE_TABLE(of, ralink_eth_match);
++
++static int
++ramips_eth_plat_probe(struct platform_device *plat)
++{
++ struct raeth_priv *re;
++ struct resource *res;
++ struct clk *clk;
++ int err;
++ const struct of_device_id *match;
++ const struct ramips_soc_data *soc = NULL;
++
++ match = of_match_device(ralink_eth_match, &plat->dev);
++ if (match)
++ soc = (const struct ramips_soc_data *) match->data;
++
++ if (!soc) {
++ dev_err(&plat->dev, "no platform data specified\n");
++ return -EINVAL;
++ }
++
++ res = platform_get_resource(plat, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&plat->dev, "no memory resource found\n");
++ return -ENXIO;
++ }
++
++ ramips_fe_base = ioremap_nocache(res->start, res->end - res->start + 1);
++ if (!ramips_fe_base)
++ return -ENOMEM;
++
++ ramips_dev = alloc_etherdev(sizeof(struct raeth_priv));
++ if (!ramips_dev) {
++ dev_err(&plat->dev, "alloc_etherdev failed\n");
++ err = -ENOMEM;
++ goto err_unmap;
++ }
++
++ strcpy(ramips_dev->name, "eth%d");
++ ramips_dev->irq = platform_get_irq(plat, 0);
++ if (ramips_dev->irq < 0) {
++ dev_err(&plat->dev, "no IRQ resource found\n");
++ err = -ENXIO;
++ goto err_free_dev;
++ }
++ ramips_dev->addr_len = ETH_ALEN;
++ ramips_dev->base_addr = (unsigned long)ramips_fe_base;
++ ramips_dev->netdev_ops = &ramips_eth_netdev_ops;
++
++ re = netdev_priv(ramips_dev);
++
++ clk = clk_get(&plat->dev, NULL);
++ if (IS_ERR(clk))
++ panic("unable to get SYS clock, err=%ld", PTR_ERR(clk));
++ re->sys_freq = clk_get_rate(clk);
++
++ re->netdev = ramips_dev;
++ re->of_node = plat->dev.of_node;
++ re->parent = &plat->dev;
++ memcpy(re->mac, soc->mac, 6);
++ re->reset_fe = soc->reset_fe;
++ re->min_pkt_len = soc->min_pkt_len;
++
++ err = register_netdev(ramips_dev);
++ if (err) {
++ dev_err(&plat->dev, "error bringing up device\n");
++ goto err_free_dev;
++ }
++
++ netdev_info(ramips_dev, "done loading\n");
++ return 0;
++
++ err_free_dev:
++ kfree(ramips_dev);
++ err_unmap:
++ iounmap(ramips_fe_base);
++ return err;
++}
++
++static int
++ramips_eth_plat_remove(struct platform_device *plat)
++{
++ unregister_netdev(ramips_dev);
++ free_netdev(ramips_dev);
++ RADEBUG("ramips_eth: unloaded\n");
++ return 0;
++}
++
++
++
++static struct platform_driver ramips_eth_driver = {
++ .probe = ramips_eth_plat_probe,
++ .remove = ramips_eth_plat_remove,
++ .driver = {
++ .name = "ramips_eth",
++ .owner = THIS_MODULE,
++ .of_match_table = ralink_eth_match
++ },
++};
++
++static int __init
++ramips_eth_init(void)
++{
++ int ret;
++
++ ret = raeth_debugfs_root_init();
++ if (ret)
++ goto err_out;
++
++ ret = rt305x_esw_init();
++ if (ret)
++ goto err_debugfs_exit;
++
++ ret = platform_driver_register(&ramips_eth_driver);
++ if (ret) {
++ printk(KERN_ERR
++ "ramips_eth: Error registering platfom driver!\n");
++ goto esw_cleanup;
++ }
++
++ return 0;
++
++esw_cleanup:
++ rt305x_esw_exit();
++err_debugfs_exit:
++ raeth_debugfs_root_exit();
++err_out:
++ return ret;
++}
++
++static void __exit
++ramips_eth_cleanup(void)
++{
++ platform_driver_unregister(&ramips_eth_driver);
++ rt305x_esw_exit();
++ raeth_debugfs_root_exit();
++}
++
++module_init(ramips_eth_init);
++module_exit(ramips_eth_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
++MODULE_DESCRIPTION("ethernet driver for ramips boards");
--- /dev/null
+From 14c1b064274d28cf88113a685c58374a515f3018 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Apr 2013 23:23:07 +0200
+Subject: [PATCH 137/137] watchdog: adds ralink wdt
+
+Adds the watchdog driver for ralink SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/watchdog/Kconfig | 6 +
+ drivers/watchdog/Makefile | 1 +
+ drivers/watchdog/ralink_wdt.c | 352 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 359 insertions(+)
+ create mode 100644 drivers/watchdog/ralink_wdt.c
+
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -1077,6 +1077,12 @@ config LANTIQ_WDT
+ help
+ Hardware driver for the Lantiq SoC Watchdog Timer.
+
++config RALINK_WDT
++ tristate "Ralink SoC watchdog"
++ depends on RALINK
++ help
++ Hardware driver for the Ralink SoC Watchdog Timer.
++
+ # PARISC Architecture
+
+ # POWERPC Architecture
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -132,6 +132,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
+ obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
+ octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
+ obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
++obj-$(CONFIG_RALINK_WDT) += ralink_wdt.o
+
+ # PARISC Architecture
+
+--- /dev/null
++++ b/drivers/watchdog/ralink_wdt.c
+@@ -0,0 +1,352 @@
++/*
++ * Ralink RT288X/RT305X built-in hardware watchdog timer
++ *
++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This driver was based on: drivers/watchdog/ixp4xx_wdt.c
++ * Author: Deepak Saxena <dsaxena@plexity.net>
++ * Copyright 2004 (c) MontaVista, Software, Inc.
++ *
++ * which again was based on sa1100 driver,
++ * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
++ *
++ * parts of the driver 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/bitops.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <linux/watchdog.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++
++#define DRIVER_NAME "ralink-wdt"
++
++#define RALINK_WDT_TIMEOUT 30 /* seconds */
++#define RALINK_WDT_PRESCALE 65536
++
++#define TIMER_REG_TMR1LOAD 0x00
++#define TIMER_REG_TMR1CTL 0x08
++
++#define TMRSTAT_TMR1RST BIT(5)
++
++#define TMR1CTL_ENABLE BIT(7)
++#define TMR1CTL_MODE_SHIFT 4
++#define TMR1CTL_MODE_MASK 0x3
++#define TMR1CTL_MODE_FREE_RUNNING 0x0
++#define TMR1CTL_MODE_PERIODIC 0x1
++#define TMR1CTL_MODE_TIMEOUT 0x2
++#define TMR1CTL_MODE_WDT 0x3
++#define TMR1CTL_PRESCALE_MASK 0xf
++#define TMR1CTL_PRESCALE_65536 0xf
++
++static int nowayout = WATCHDOG_NOWAYOUT;
++module_param(nowayout, int, 0);
++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
++ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
++
++static int ralink_wdt_timeout = RALINK_WDT_TIMEOUT;
++module_param_named(timeout, ralink_wdt_timeout, int, 0);
++MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 means use maximum "
++ "(default=" __MODULE_STRING(RALINK_WDT_TIMEOUT) "s)");
++
++static unsigned long ralink_wdt_flags;
++
++#define WDT_FLAGS_BUSY 0
++#define WDT_FLAGS_EXPECT_CLOSE 1
++
++static struct clk *ralink_wdt_clk;
++static unsigned long ralink_wdt_freq;
++static int ralink_wdt_max_timeout;
++static void __iomem *ralink_wdt_base;
++
++static inline void rt_wdt_w32(unsigned reg, u32 val)
++{
++ __raw_writel(val, ralink_wdt_base + reg);
++}
++
++static inline u32 rt_wdt_r32(unsigned reg)
++{
++ return __raw_readl(ralink_wdt_base + reg);
++}
++
++static inline void ralink_wdt_keepalive(void)
++{
++ rt_wdt_w32(TIMER_REG_TMR1LOAD, ralink_wdt_timeout * ralink_wdt_freq);
++}
++
++static inline void ralink_wdt_enable(void)
++{
++ u32 t;
++
++ ralink_wdt_keepalive();
++
++ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
++ t |= TMR1CTL_ENABLE;
++ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
++}
++
++static inline void ralink_wdt_disable(void)
++{
++ u32 t;
++
++ ralink_wdt_keepalive();
++
++ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
++ t &= ~TMR1CTL_ENABLE;
++ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
++}
++
++static int ralink_wdt_set_timeout(int val)
++{
++ if (val < 1 || val > ralink_wdt_max_timeout) {
++ pr_warn(DRIVER_NAME
++ ": timeout value %d must be 0 < timeout <= %d, using %d\n",
++ val, ralink_wdt_max_timeout, ralink_wdt_timeout);
++ return -EINVAL;
++ }
++
++ ralink_wdt_timeout = val;
++ ralink_wdt_keepalive();
++
++ return 0;
++}
++
++static int ralink_wdt_open(struct inode *inode, struct file *file)
++{
++ u32 t;
++
++ if (test_and_set_bit(WDT_FLAGS_BUSY, &ralink_wdt_flags))
++ return -EBUSY;
++
++ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags);
++
++ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
++ t &= ~(TMR1CTL_MODE_MASK << TMR1CTL_MODE_SHIFT |
++ TMR1CTL_PRESCALE_MASK);
++ t |= (TMR1CTL_MODE_WDT << TMR1CTL_MODE_SHIFT |
++ TMR1CTL_PRESCALE_65536);
++ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
++
++ ralink_wdt_enable();
++
++ return nonseekable_open(inode, file);
++}
++
++static int ralink_wdt_release(struct inode *inode, struct file *file)
++{
++ if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags))
++ ralink_wdt_disable();
++ else {
++ pr_crit(DRIVER_NAME ": device closed unexpectedly, "
++ "watchdog timer will not stop!\n");
++ ralink_wdt_keepalive();
++ }
++
++ clear_bit(WDT_FLAGS_BUSY, &ralink_wdt_flags);
++ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags);
++
++ return 0;
++}
++
++static ssize_t rt_wdt_w32ite(struct file *file, const char *data,
++ size_t len, loff_t *ppos)
++{
++ if (len) {
++ if (!nowayout) {
++ size_t i;
++
++ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &ralink_wdt_flags);
++
++ for (i = 0; i != len; i++) {
++ char c;
++
++ if (get_user(c, data + i))
++ return -EFAULT;
++
++ if (c == 'V')
++ set_bit(WDT_FLAGS_EXPECT_CLOSE,
++ &ralink_wdt_flags);
++ }
++ }
++
++ ralink_wdt_keepalive();
++ }
++
++ return len;
++}
++
++static const struct watchdog_info ralink_wdt_info = {
++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
++ WDIOF_MAGICCLOSE,
++ .firmware_version = 0,
++ .identity = "RALINK watchdog",
++};
++
++static long ralink_wdt_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ void __user *argp = (void __user *)arg;
++ int __user *p = argp;
++ int err;
++ int t;
++
++ switch (cmd) {
++ case WDIOC_GETSUPPORT:
++ err = copy_to_user(argp, &ralink_wdt_info,
++ sizeof(ralink_wdt_info)) ? -EFAULT : 0;
++ break;
++
++ case WDIOC_GETSTATUS:
++ err = put_user(0, p);
++ break;
++
++ case WDIOC_KEEPALIVE:
++ ralink_wdt_keepalive();
++ err = 0;
++ break;
++
++ case WDIOC_SETTIMEOUT:
++ err = get_user(t, p);
++ if (err)
++ break;
++
++ err = ralink_wdt_set_timeout(t);
++ if (err)
++ break;
++
++ /* fallthrough */
++ case WDIOC_GETTIMEOUT:
++ err = put_user(ralink_wdt_timeout, p);
++ break;
++
++ default:
++ err = -ENOTTY;
++ break;
++ }
++
++ return err;
++}
++
++static const struct file_operations ralink_wdt_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .write = rt_wdt_w32ite,
++ .unlocked_ioctl = ralink_wdt_ioctl,
++ .open = ralink_wdt_open,
++ .release = ralink_wdt_release,
++};
++
++static struct miscdevice ralink_wdt_miscdev = {
++ .minor = WATCHDOG_MINOR,
++ .name = "watchdog",
++ .fops = &ralink_wdt_fops,
++};
++
++static int ralink_wdt_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int err;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource found\n");
++ return -EINVAL;
++ }
++
++ ralink_wdt_base = ioremap(res->start, resource_size(res));
++ if (!ralink_wdt_base)
++ return -ENOMEM;
++
++ ralink_wdt_clk = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(ralink_wdt_clk)) {
++ err = PTR_ERR(ralink_wdt_clk);
++ goto err_unmap;
++ }
++
++ err = clk_enable(ralink_wdt_clk);
++ if (err)
++ goto err_clk_put;
++
++ ralink_wdt_freq = clk_get_rate(ralink_wdt_clk) / RALINK_WDT_PRESCALE;
++ if (!ralink_wdt_freq) {
++ err = -EINVAL;
++ goto err_clk_disable;
++ }
++
++ ralink_wdt_max_timeout = (0xfffful / ralink_wdt_freq);
++ if (ralink_wdt_timeout < 1 ||
++ ralink_wdt_timeout > ralink_wdt_max_timeout) {
++ ralink_wdt_timeout = ralink_wdt_max_timeout;
++ dev_info(&pdev->dev,
++ "timeout value must be 0 < timeout <= %d, using %d\n",
++ ralink_wdt_max_timeout, ralink_wdt_timeout);
++ }
++
++ err = misc_register(&ralink_wdt_miscdev);
++ if (err) {
++ dev_err(&pdev->dev,
++ "unable to register misc device, err=%d\n", err);
++ goto err_clk_disable;
++ }
++
++ return 0;
++
++err_clk_disable:
++ clk_disable(ralink_wdt_clk);
++err_clk_put:
++ clk_put(ralink_wdt_clk);
++err_unmap:
++ iounmap(ralink_wdt_base);
++ return err;
++}
++
++static int ralink_wdt_remove(struct platform_device *pdev)
++{
++ misc_deregister(&ralink_wdt_miscdev);
++ clk_disable(ralink_wdt_clk);
++ clk_put(ralink_wdt_clk);
++ iounmap(ralink_wdt_base);
++ return 0;
++}
++
++static void ralink_wdt_shutdown(struct platform_device *pdev)
++{
++ ralink_wdt_disable();
++}
++
++static const struct of_device_id ralink_wdt_match[] = {
++ { .compatible = "ralink,rt2880-wdt" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ralink_wdt_match);
++
++static struct platform_driver ralink_wdt_driver = {
++ .probe = ralink_wdt_probe,
++ .remove = ralink_wdt_remove,
++ .shutdown = ralink_wdt_shutdown,
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = ralink_wdt_match,
++ },
++};
++
++module_platform_driver(ralink_wdt_driver);
++
++MODULE_DESCRIPTION("MediaTek/Ralink RT288X/RT305X hardware watchdog driver");
++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:" DRIVER_NAME);
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+++ /dev/null
-From 0184f7b64c68fe9606559e86bdd288de01c87a85 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 17 Mar 2013 10:30:48 +0100
-Subject: [PATCH 200/208] MIPS: read the mips_machine name from OF and output
- it in /proc/cpuinfo
-
-This allows the userland to be compatible to the devive probing of mips_machine.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/include/asm/prom.h | 3 +++
- arch/mips/kernel/proc.c | 6 +++++-
- arch/mips/kernel/prom.c | 24 ++++++++++++++++++++++++
- 3 files changed, 32 insertions(+), 1 deletion(-)
-
---- a/arch/mips/include/asm/prom.h
-+++ b/arch/mips/include/asm/prom.h
-@@ -44,8 +44,11 @@ extern void __dt_setup_arch(struct boot_
- __dt_setup_arch(&__dtb_##sym##_begin); \
- })
-
-+extern char *of_mips_get_machine_name(void);
-+
- #else /* CONFIG_OF */
- static inline void device_tree_init(void) { }
-+static char *of_mips_get_machine_name(void) { return NULL; }
- #endif /* CONFIG_OF */
-
- #endif /* __ASM_PROM_H */
---- a/arch/mips/kernel/proc.c
-+++ b/arch/mips/kernel/proc.c
-@@ -12,6 +12,7 @@
- #include <asm/cpu-features.h>
- #include <asm/mipsregs.h>
- #include <asm/processor.h>
-+#include <asm/prom.h>
- #include <asm/mips_machine.h>
-
- unsigned int vced_count, vcei_count;
-@@ -34,7 +35,10 @@ static int show_cpuinfo(struct seq_file
- */
- if (n == 0) {
- seq_printf(m, "system type\t\t: %s\n", get_system_type());
-- if (mips_get_machine_name())
-+ if (of_mips_get_machine_name())
-+ seq_printf(m, "machine\t\t\t: %s\n",
-+ of_mips_get_machine_name());
-+ else if (mips_get_machine_name())
- seq_printf(m, "machine\t\t\t: %s\n",
- mips_get_machine_name());
- }
---- a/arch/mips/kernel/prom.c
-+++ b/arch/mips/kernel/prom.c
-@@ -23,6 +23,13 @@
- #include <asm/page.h>
- #include <asm/prom.h>
-
-+static char of_mips_machine_name[64] = "Unknown";
-+
-+char *of_mips_get_machine_name(void)
-+{
-+ return of_mips_machine_name;
-+}
-+
- int __init early_init_dt_scan_memory_arch(unsigned long node,
- const char *uname, int depth,
- void *data)
-@@ -50,6 +57,20 @@ void __init early_init_dt_setup_initrd_a
- }
- #endif
-
-+int __init early_init_dt_scan_model(unsigned long node,
-+ const char *uname, int depth,
-+ void *data)
-+{
-+ if (!depth) {
-+ char *model = of_get_flat_dt_prop(node, "model", NULL);
-+ if (model) {
-+ snprintf(of_mips_machine_name, sizeof(of_mips_machine_name), model);
-+ pr_info("MIPS: machine is %s\n", of_mips_machine_name);
-+ }
-+ }
-+ return 0;
-+}
-+
- void __init early_init_devtree(void *params)
- {
- /* Setup flat device-tree pointer */
-@@ -65,6 +86,9 @@ void __init early_init_devtree(void *par
- /* Scan memory nodes */
- of_scan_flat_dt(early_init_dt_scan_root, NULL);
- of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
-+
-+ /* try to load the mips machine name */
-+ of_scan_flat_dt(early_init_dt_scan_model, NULL);
- }
-
- void __init __dt_setup_arch(struct boot_param_header *bph)
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
-@@ -46,5 +46,6 @@ extern void prom_soc_init(struct ralink_
+@@ -51,5 +51,6 @@ extern void prom_soc_init(struct ralink_
__iomem void *plat_of_remap_node(const char *node);
void ralink_pinmux(void);
#endif /* _RALINK_COMMON_H__ */
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
-@@ -146,6 +146,11 @@ struct ralink_pinmux rt_pinmux = {
- // .wdt_reset = rt305x_wdt_reset,
+@@ -140,6 +140,11 @@ struct ralink_pinmux rt_gpio_pinmux = {
+ .uart_mask = MT7620_GPIO_MODE_GPIO,
};
+void ralink_usb_platform(void)
unsigned long cpu_rate, sys_rate;
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
-@@ -102,6 +102,7 @@ static int __init plat_of_setup(void)
+@@ -111,6 +111,7 @@ static int __init plat_of_setup(void)
panic("failed to populate DT\n");
ralink_pinmux();
+#obj-y += dts/
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
-@@ -76,6 +76,8 @@ void __init device_tree_init(void)
+@@ -77,6 +77,8 @@ void __init device_tree_init(void)
free_bootmem(base, size);
}
void __init plat_mem_setup(void)
{
set_io_port_base(KSEG1);
-@@ -84,7 +86,7 @@ void __init plat_mem_setup(void)
+@@ -85,7 +87,7 @@ void __init plat_mem_setup(void)
* Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing
*/
- __dt_setup_arch(&__dtb_start);
+ __dt_setup_arch(&__image_dtb);
- }
- static int __init plat_of_setup(void)
+ if (soc_info.mem_size)
+ add_memory_region(soc_info.mem_base, soc_info.mem_size,
+++ /dev/null
-From bcd97dbdcb7bc0300397db481872252e8849307b Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 25 Mar 2013 10:50:53 +0100
-Subject: [PATCH 207/208] owrt: MIPS: ralink: add support for runtime memory
- detection
-
-This allows us to add a device_node called "memorydetect" to the DT with
-information about the memory windoe of the SoC. Based on this the memory is
-detected ar runtime.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/include/asm/prom.h | 3 ++
- arch/mips/kernel/prom.c | 3 ++
- arch/mips/ralink/Makefile | 2 +-
- arch/mips/ralink/memory.c | 119 ++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 126 insertions(+), 1 deletion(-)
- create mode 100644 arch/mips/ralink/memory.c
-
---- a/arch/mips/include/asm/prom.h
-+++ b/arch/mips/include/asm/prom.h
-@@ -20,6 +20,9 @@
- extern int early_init_dt_scan_memory_arch(unsigned long node,
- const char *uname, int depth, void *data);
-
-+extern int early_init_dt_detect_memory(unsigned long node,
-+ const char *uname, int depth, void *data);
-+
- extern void device_tree_init(void);
-
- static inline unsigned long pci_address_to_pio(phys_addr_t address)
---- a/arch/mips/kernel/prom.c
-+++ b/arch/mips/kernel/prom.c
-@@ -88,6 +88,9 @@ void __init early_init_devtree(void *par
- of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
-
- /* try to load the mips machine name */
-+ of_scan_flat_dt(early_init_dt_detect_memory, NULL);
-+
-+ /* try to load the mips machine name */
- of_scan_flat_dt(early_init_dt_scan_model, NULL);
- }
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -6,7 +6,7 @@
- # 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 pinmux.o timer.o
-+obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o memory.o
-
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o rt305x-usb.o
---- /dev/null
-+++ b/arch/mips/ralink/memory.c
-@@ -0,0 +1,119 @@
-+/*
-+ * 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) 2009 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/of_fdt.h>
-+#include <linux/of_platform.h>
-+
-+#include <asm/bootinfo.h>
-+#include <asm/addrspace.h>
-+
-+#include "common.h"
-+
-+#define MB (1024 * 1024)
-+
-+unsigned long ramips_mem_base;
-+unsigned long ramips_mem_size_min;
-+unsigned long ramips_mem_size_max;
-+
-+#ifdef CONFIG_SOC_RT305X
-+
-+#include <asm/mach-ralink/rt305x.h>
-+
-+static unsigned long rt5350_get_mem_size(void)
-+{
-+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE);
-+ unsigned long ret;
-+ u32 t;
-+
-+ t = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG);
-+ t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) &
-+ RT5350_SYSCFG0_DRAM_SIZE_MASK;
-+
-+ switch (t) {
-+ case RT5350_SYSCFG0_DRAM_SIZE_2M:
-+ ret = 2 * 1024 * 1024;
-+ break;
-+ case RT5350_SYSCFG0_DRAM_SIZE_8M:
-+ ret = 8 * 1024 * 1024;
-+ break;
-+ case RT5350_SYSCFG0_DRAM_SIZE_16M:
-+ ret = 16 * 1024 * 1024;
-+ break;
-+ case RT5350_SYSCFG0_DRAM_SIZE_32M:
-+ ret = 32 * 1024 * 1024;
-+ break;
-+ case RT5350_SYSCFG0_DRAM_SIZE_64M:
-+ ret = 64 * 1024 * 1024;
-+ break;
-+ default:
-+ panic("rt5350: invalid DRAM size: %u", t);
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+#endif
-+
-+static void __init detect_mem_size(void)
-+{
-+ unsigned long size;
-+
-+#ifdef CONFIG_SOC_RT305X
-+ if (soc_is_rt5350()) {
-+ size = rt5350_get_mem_size();
-+ } else
-+#endif
-+ {
-+ void *base;
-+
-+ base = (void *) KSEG1ADDR(detect_mem_size);
-+ for (size = ramips_mem_size_min; size < ramips_mem_size_max;
-+ size <<= 1 ) {
-+ if (!memcmp(base, base + size, 1024))
-+ break;
-+ }
-+ }
-+
-+ pr_info("memory detected: %uMB\n", (unsigned int) size / MB);
-+
-+ add_memory_region(ramips_mem_base, size, BOOT_MEM_RAM);
-+}
-+
-+int __init early_init_dt_detect_memory(unsigned long node, const char *uname,
-+ int depth, void *data)
-+{
-+ unsigned long l;
-+ __be32 *mem;
-+
-+ /* We are scanning "memorydetect" nodes only */
-+ if (depth != 1 || strcmp(uname, "memorydetect") != 0)
-+ return 0;
-+
-+ mem = of_get_flat_dt_prop(node, "ralink,memory", &l);
-+ if (mem == NULL)
-+ return 0;
-+
-+ if ((l / sizeof(__be32)) != 3)
-+ panic("invalid memorydetect node\n");
-+
-+ ramips_mem_base = dt_mem_next_cell(dt_root_addr_cells, &mem);
-+ ramips_mem_size_min = dt_mem_next_cell(dt_root_size_cells, &mem);
-+ ramips_mem_size_max = dt_mem_next_cell(dt_root_size_cells, &mem);
-+
-+ pr_info("memory window: 0x%llx, min: %uMB, max: %uMB\n",
-+ (unsigned long long) ramips_mem_base,
-+ (unsigned int) ramips_mem_size_min / MB,
-+ (unsigned int) ramips_mem_size_max / MB);
-+
-+ detect_mem_size();
-+
-+ return 0;
-+}
+++ /dev/null
---- a/arch/mips/ralink/rt305x.c
-+++ b/arch/mips/ralink/rt305x.c
-@@ -97,6 +97,11 @@ struct ralink_pinmux_grp uart_mux[] = {
- .mask = RT305X_GPIO_MODE_GPIO_I2S,
- .gpio_first = RT305X_GPIO_7,
- .gpio_last = RT305X_GPIO_14,
-+ }, {
-+ .name = "gpio",
-+ .mask = RT305X_GPIO_MODE_GPIO,
-+ .gpio_first = RT305X_GPIO_7,
-+ .gpio_last = RT305X_GPIO_14,
- }, {0}
- };
-