summaryrefslogtreecommitdiff
path: root/target/linux/ramips/patches-3.8
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ramips/patches-3.8')
-rw-r--r--target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch16
-rw-r--r--target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch13
-rw-r--r--target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch13
-rw-r--r--target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch23
-rw-r--r--target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch10
-rw-r--r--target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch11
-rw-r--r--target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch17
-rw-r--r--target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch19
-rw-r--r--target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch (renamed from target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch)25
-rw-r--r--target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch (renamed from target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch (renamed from target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch (renamed from target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch (renamed from target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch)11
-rw-r--r--target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch (renamed from target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch (renamed from target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch (renamed from target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch)11
-rw-r--r--target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch (renamed from target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch (renamed from target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch (renamed from target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch)13
-rw-r--r--target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch (renamed from target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch)25
-rw-r--r--target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch (renamed from target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch)24
-rw-r--r--target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch (renamed from target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch)21
-rw-r--r--target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch (renamed from target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch)20
-rw-r--r--target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch (renamed from target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch (renamed from target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch)10
-rw-r--r--target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch (renamed from target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch)28
-rw-r--r--target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch (renamed from target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch)17
-rw-r--r--target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch (renamed from target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch)17
-rw-r--r--target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch (renamed from target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch)17
-rw-r--r--target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch (renamed from target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch)13
-rw-r--r--target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch (renamed from target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch)11
-rw-r--r--target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch (renamed from target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch)15
-rw-r--r--target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch (renamed from target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch)13
-rw-r--r--target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch (renamed from target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch)27
-rw-r--r--target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch (renamed from target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch)13
-rw-r--r--target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch (renamed from target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch23
-rw-r--r--target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch (renamed from target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch)22
-rw-r--r--target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch (renamed from target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch)12
-rw-r--r--target/linux/ramips/patches-3.8/0047-MIPS-ralink-add-rt_sysc_m32-helper.patch31
-rw-r--r--target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch39
-rw-r--r--target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch64
-rw-r--r--target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch83
-rw-r--r--target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch29
-rw-r--r--target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch78
-rw-r--r--target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch121
-rw-r--r--target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch29
-rw-r--r--target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch25
-rw-r--r--target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch1006
-rw-r--r--target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch (renamed from target/linux/ramips/patches-3.8/0130-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch)217
-rw-r--r--target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch (renamed from target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch)31
-rw-r--r--target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch (renamed from target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch)11
-rw-r--r--target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch (renamed from target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch)9
-rw-r--r--target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch341
-rw-r--r--target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch (renamed from target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch)16
-rw-r--r--target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch (renamed from target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch)16
-rw-r--r--target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch409
-rw-r--r--target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch275
-rw-r--r--target/linux/ramips/patches-3.8/0066-i2c-MIPS-adds-ralink-I2C-driver.patch358
-rw-r--r--target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch554
-rw-r--r--target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch135
-rw-r--r--target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch (renamed from target/linux/ramips/patches-3.8/0201-owrt-OF-NET-add-of_get_mac_address_mtd.patch)13
-rw-r--r--target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch61
-rw-r--r--target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch4732
-rw-r--r--target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch238
-rw-r--r--target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch48
-rw-r--r--target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch38
-rw-r--r--target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch3446
-rw-r--r--target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch132
-rw-r--r--target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch36
-rw-r--r--target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch282
-rw-r--r--target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch227
-rw-r--r--target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch3137
-rw-r--r--target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch395
-rw-r--r--target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch59
-rw-r--r--target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch325
83 files changed, 13616 insertions, 4091 deletions
diff --git a/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch b/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch
index 3539ece..cc32caa 100644
--- a/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch
+++ b/target/linux/ramips/patches-3.8/0001-MIPS-ralink-adds-include-files.patch
@@ -1,7 +1,7 @@
-From 8563991026ee98bb5e477167236972a45dfea0e3 Mon Sep 17 00:00:00 2001
+From 72bd3fcd16225f46ca318435a4d8f3f3f154b1bc Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 21 Jan 2013 18:25:59 +0100
-Subject: [PATCH 01/14] MIPS: ralink: adds include files
+Subject: [PATCH 01/79] MIPS: ralink: adds include files
Before we start adding the platform code we add the common include files.
@@ -17,6 +17,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/
create mode 100644 arch/mips/include/asm/mach-ralink/war.h
create mode 100644 arch/mips/ralink/common.h
+diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h
+new file mode 100644
+index 0000000..5a508f9
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h
@@ -0,0 +1,39 @@
@@ -59,6 +62,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/
+}
+
+#endif /* _RALINK_REGS_H_ */
+diff --git a/arch/mips/include/asm/mach-ralink/war.h b/arch/mips/include/asm/mach-ralink/war.h
+new file mode 100644
+index 0000000..a7b712c
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/war.h
@@ -0,0 +1,25 @@
@@ -87,6 +93,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MACH_RALINK_WAR_H */
+diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
+new file mode 100644
+index 0000000..3009903
--- /dev/null
+++ b/arch/mips/ralink/common.h
@@ -0,0 +1,44 @@
@@ -134,3 +143,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4893/
+__iomem void *plat_of_remap_node(const char *node);
+
+#endif /* _RALINK_COMMON_H__ */
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch b/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch
index c559a87..01beef7 100644
--- a/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch
+++ b/target/linux/ramips/patches-3.8/0002-MIPS-ralink-adds-irq-code.patch
@@ -1,7 +1,7 @@
-From 19d3814e7b325f8965fd71f329b3467a97f8d217 Mon Sep 17 00:00:00 2001
+From 833836f47b4191e93267b91fcab38dd15affcd28 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:00:50 +0100
-Subject: [PATCH 02/14] MIPS: ralink: adds irq code
+Subject: [PATCH 02/79] MIPS: ralink: adds irq code
All of the Ralink Wifi SoC currently supported by this series share the same
interrupt controller (INTC).
@@ -14,6 +14,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4890/
1 file changed, 176 insertions(+)
create mode 100644 arch/mips/ralink/irq.c
+diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
+new file mode 100644
+index 0000000..e62c975
--- /dev/null
+++ b/arch/mips/ralink/irq.c
@@ -0,0 +1,176 @@
@@ -193,3 +196,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4890/
+ of_irq_init(of_irq_ids);
+}
+
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch b/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch
index 57cad76..ee9a509 100644
--- a/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch
+++ b/target/linux/ramips/patches-3.8/0003-MIPS-ralink-adds-reset-code.patch
@@ -1,7 +1,7 @@
-From c06e836ada59fbc6d1109277e693e5b3e056ac12 Mon Sep 17 00:00:00 2001
+From 3cdf3d713c81ffd3032d7c664f0be89d1ddce3e3 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:00:57 +0100
-Subject: [PATCH 03/14] MIPS: ralink: adds reset code
+Subject: [PATCH 03/79] MIPS: ralink: adds reset code
Resetting these SoCs requires no real magic. The code is straight forward.
@@ -13,6 +13,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4891/
1 file changed, 44 insertions(+)
create mode 100644 arch/mips/ralink/reset.c
+diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c
+new file mode 100644
+index 0000000..22120e5
--- /dev/null
+++ b/arch/mips/ralink/reset.c
@@ -0,0 +1,44 @@
@@ -60,3 +63,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4891/
+}
+
+arch_initcall(mips_reboot_setup);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch b/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch
index da38629..8b8bb56 100644
--- a/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch
+++ b/target/linux/ramips/patches-3.8/0004-MIPS-ralink-adds-prom-and-cmdline-code.patch
@@ -1,7 +1,7 @@
-From 7e47cefa69c8ed2c889522ce29fcce73ce8cf08e Mon Sep 17 00:00:00 2001
+From 36424b3f1f184c752562d19d0df1a427c8c584a2 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:01:05 +0100
-Subject: [PATCH 04/14] MIPS: ralink: adds prom and cmdline code
+Subject: [PATCH 04/79] MIPS: ralink: adds prom and cmdline code
Add minimal code to handle commandlines.
@@ -13,6 +13,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4892/
1 file changed, 69 insertions(+)
create mode 100644 arch/mips/ralink/prom.c
+diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c
+new file mode 100644
+index 0000000..9c64f02
--- /dev/null
+++ b/arch/mips/ralink/prom.c
@@ -0,0 +1,69 @@
@@ -85,3 +88,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4892/
+void __init prom_free_prom_memory(void)
+{
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch b/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch
index a8218d1..1fd6057 100644
--- a/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch
+++ b/target/linux/ramips/patches-3.8/0005-MIPS-ralink-adds-clkdev-code.patch
@@ -1,7 +1,7 @@
-From 3f0a06b0368d25608841843e9d65a7289ad9f14a Mon Sep 17 00:00:00 2001
+From b99289db258ee8a84e1bd555b2897476acf390c1 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:01:29 +0100
-Subject: [PATCH 05/14] MIPS: ralink: adds clkdev code
+Subject: [PATCH 05/79] MIPS: ralink: adds clkdev code
These SoCs have a limited number of fixed rate clocks. Add support for the
clk and clkdev api.
@@ -14,6 +14,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4894/
1 file changed, 72 insertions(+)
create mode 100644 arch/mips/ralink/clk.c
+diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c
+new file mode 100644
+index 0000000..8dfa22f
--- /dev/null
+++ b/arch/mips/ralink/clk.c
@@ -0,0 +1,72 @@
@@ -89,3 +92,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4894/
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+ clk_put(clk);
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch b/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch
index b6bd78b..7747c81 100644
--- a/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch
+++ b/target/linux/ramips/patches-3.8/0006-MIPS-ralink-adds-OF-code.patch
@@ -1,7 +1,7 @@
-From 3a5bfe7bdbfd37c9206d7c6dfd7eb9664ccc5038 Mon Sep 17 00:00:00 2001
+From 4b2f9abbbaf3463a0fc1a65afeb0d12f890ada35 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:02:01 +0100
-Subject: [PATCH 06/14] MIPS: ralink: adds OF code
+Subject: [PATCH 06/79] MIPS: ralink: adds OF code
Until there is a generic MIPS way of handing the DTB over from bootloader to
kernel we rely on a built in devicetrees. The OF code also remaps those register
@@ -15,6 +15,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4895/
1 file changed, 107 insertions(+)
create mode 100644 arch/mips/ralink/of.c
+diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
+new file mode 100644
+index 0000000..4165e70
--- /dev/null
+++ b/arch/mips/ralink/of.c
@@ -0,0 +1,107 @@
@@ -125,3 +128,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4895/
+}
+
+arch_initcall(plat_of_setup);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch b/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch
index 80a5b1e..e22bbbd 100644
--- a/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch
+++ b/target/linux/ramips/patches-3.8/0007-MIPS-ralink-adds-early_printk-support.patch
@@ -1,7 +1,7 @@
-From 5fff610b7c60195de98e68bec00c357f393ce634 Mon Sep 17 00:00:00 2001
+From 4efba82d0e4059588f2b2fc0ac2576eaf37f1d22 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:02:55 +0100
-Subject: [PATCH 07/14] MIPS: ralink: adds early_printk support
+Subject: [PATCH 07/79] MIPS: ralink: adds early_printk support
Add the code needed to make early printk work.
@@ -13,6 +13,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4897/
1 file changed, 44 insertions(+)
create mode 100644 arch/mips/ralink/early_printk.c
+diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c
+new file mode 100644
+index 0000000..c4ae47e
--- /dev/null
+++ b/arch/mips/ralink/early_printk.c
@@ -0,0 +1,44 @@
@@ -60,3 +63,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4897/
+ while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
+ ;
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch b/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch
index 083526b..01b0869 100644
--- a/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch
+++ b/target/linux/ramips/patches-3.8/0008-MIPS-ralink-adds-support-for-RT305x-SoC-family.patch
@@ -1,7 +1,7 @@
-From 2809b31770d7fd934a748692e1922a5e613f06e5 Mon Sep 17 00:00:00 2001
+From 433f4f524aba81358353ca4ebc00c3e916521ec6 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:03:46 +0100
-Subject: [PATCH 08/14] MIPS: ralink: adds support for RT305x SoC family
+Subject: [PATCH 08/79] MIPS: ralink: adds support for RT305x SoC family
Add support code for rt3050, rt3052, rt3350, rt3352 and rt5350 SOC.
@@ -17,6 +17,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4896/
create mode 100644 arch/mips/include/asm/mach-ralink/rt305x.h
create mode 100644 arch/mips/ralink/rt305x.c
+diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h
+new file mode 100644
+index 0000000..7d344f2
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/rt305x.h
@@ -0,0 +1,139 @@
@@ -159,6 +162,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4896/
+#define RT305X_GPIO_MODE_RGMII BIT(9)
+
+#endif
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+new file mode 100644
+index 0000000..0a4bbdc
--- /dev/null
+++ b/arch/mips/ralink/rt305x.c
@@ -0,0 +1,242 @@
@@ -404,3 +410,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4896/
+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
+ (id & CHIP_ID_REV_MASK));
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch b/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch
index 2c2bb14..81d9fea 100644
--- a/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch
+++ b/target/linux/ramips/patches-3.8/0009-MIPS-ralink-adds-rt305x-devicetree.patch
@@ -1,7 +1,7 @@
-From 5644da4f635a30fc03b4f12d81b2197d716d9cef Mon Sep 17 00:00:00 2001
+From 8208a43c301d9164802dedeec7455dbdd70ca286 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 22 Jan 2013 20:19:33 +0100
-Subject: [PATCH 09/14] MIPS: ralink: adds rt305x devicetree
+Subject: [PATCH 09/79] MIPS: ralink: adds rt305x devicetree
This adds the devicetree file that describes the rt305x evaluation kit.
@@ -15,6 +15,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4898/
create mode 100644 arch/mips/ralink/dts/rt3050.dtsi
create mode 100644 arch/mips/ralink/dts/rt3052_eval.dts
+diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi
+new file mode 100644
+index 0000000..fd49daa
--- /dev/null
+++ b/arch/mips/ralink/dts/rt3050.dtsi
@@ -0,0 +1,96 @@
@@ -114,6 +117,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4898/
+ };
+ };
+};
+diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
+new file mode 100644
+index 0000000..dc56e58
--- /dev/null
+++ b/arch/mips/ralink/dts/rt3052_eval.dts
@@ -0,0 +1,52 @@
@@ -169,3 +175,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4898/
+ };
+ };
+};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch b/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch
index bccc3b8..88c018c 100644
--- a/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch
+++ b/target/linux/ramips/patches-3.8/0010-MIPS-ralink-adds-Kbuild-files.patch
@@ -1,7 +1,7 @@
-From ae2b5bb6570481b50a7175c64176b82da0a81836 Mon Sep 17 00:00:00 2001
+From 79e69b7a01246e945448039f7dce170eef0b6e3b Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 20 Jan 2013 22:05:30 +0100
-Subject: [PATCH 10/14] MIPS: ralink: adds Kbuild files
+Subject: [PATCH 10/79] MIPS: ralink: adds Kbuild files
Add the Kbuild symbols and Makefiles needed to actually build the ralink code
from this series
@@ -22,6 +22,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/
create mode 100644 arch/mips/ralink/Platform
create mode 100644 arch/mips/ralink/dts/Makefile
+diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
+index 91b9d69..9a73ce6 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -22,6 +22,7 @@ platforms += pmc-sierra
@@ -32,6 +34,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/
platforms += rb532
platforms += sgi-ip22
platforms += sgi-ip27
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 2ac626a..b5081b5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -434,6 +434,22 @@ config POWERTV
@@ -65,6 +69,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
source "arch/mips/txx9/Kconfig"
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+new file mode 100644
+index 0000000..a0b0197
--- /dev/null
+++ b/arch/mips/ralink/Kconfig
@@ -0,0 +1,32 @@
@@ -100,6 +107,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/
+endchoice
+
+endif
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+new file mode 100644
+index 0000000..939757f
--- /dev/null
+++ b/arch/mips/ralink/Makefile
@@ -0,0 +1,15 @@
@@ -118,6 +128,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+obj-y += dts/
+diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
+new file mode 100644
+index 0000000..6babd65
--- /dev/null
+++ b/arch/mips/ralink/Platform
@@ -0,0 +1,10 @@
@@ -131,7 +144,13 @@ Patchwork: http://patchwork.linux-mips.org/patch/4899/
+# Ralink RT305x
+#
+load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
+diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile
+new file mode 100644
+index 0000000..1a69fb3
--- /dev/null
+++ b/arch/mips/ralink/dts/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch b/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch
index 5998b11..1f4a1e2 100644
--- a/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch
+++ b/target/linux/ramips/patches-3.8/0011-MIPS-ralink-adds-default-config-file.patch
@@ -1,7 +1,7 @@
-From 6d63d70f9fe4c1b3d293ac3b9d2fcaf937d95cea Mon Sep 17 00:00:00 2001
+From 428bb7af86ffb6171e11c36dfcdacd87ed5341e6 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 1 Feb 2013 12:50:49 +0100
-Subject: [PATCH 11/14] MIPS: ralink: adds default config file
+Subject: [PATCH 11/79] MIPS: ralink: adds default config file
Signed-off-by: John Crispin <blogic@openwrt.org>
---
@@ -9,6 +9,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
1 file changed, 167 insertions(+)
create mode 100644 arch/mips/configs/rt305x_defconfig
+diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig
+new file mode 100644
+index 0000000..d1741bc
--- /dev/null
+++ b/arch/mips/configs/rt305x_defconfig
@@ -0,0 +1,167 @@
@@ -179,3 +182,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+CONFIG_AVERAGE=y
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch b/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch
index 6a07d8d..b7ce7c9 100644
--- a/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch
+++ b/target/linux/ramips/patches-3.8/0012-Document-devicetree-add-OF-documents-for-MIPS-interr.patch
@@ -1,7 +1,7 @@
-From dcc7310e144c3bf17a86d2f058d60fb525d4b34a Mon Sep 17 00:00:00 2001
+From dae867771332e7541783ebb6bacf33356ad449b3 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 31 Jan 2013 13:44:10 +0100
-Subject: [PATCH 12/14] Document: devicetree: add OF documents for MIPS
+Subject: [PATCH 12/79] Document: devicetree: add OF documents for MIPS
interrupt controller
Signed-off-by: John Crispin <blogic@openwrt.org>
@@ -12,6 +12,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/4901/
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mips/cpu_irq.txt
+diff --git a/Documentation/devicetree/bindings/mips/cpu_irq.txt b/Documentation/devicetree/bindings/mips/cpu_irq.txt
+new file mode 100644
+index 0000000..13aa4b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cpu_irq.txt
@@ -0,0 +1,47 @@
@@ -62,3 +65,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4901/
+{
+ of_irq_init(of_irq_ids);
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch b/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch
index 3139106..e5387a2 100644
--- a/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch
+++ b/target/linux/ramips/patches-3.8/0013-MIPS-add-irqdomain-support-for-the-CPU-IRQ-controlle.patch
@@ -1,7 +1,7 @@
-From 0916b46962cbcac9465d253d0a398435b3965fd5 Mon Sep 17 00:00:00 2001
+From 65e39f763eeca6fb93f48ed5a9b296277a543429 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 31 Jan 2013 12:20:43 +0000
-Subject: [PATCH 13/14] MIPS: add irqdomain support for the CPU IRQ controller
+Subject: [PATCH 13/79] MIPS: add irqdomain support for the CPU IRQ controller
Add code to load a irq_domain for the MIPS IRQ controller from a devicetree
file.
@@ -15,6 +15,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4902/
arch/mips/kernel/irq_cpu.c | 42 +++++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
+diff --git a/arch/mips/include/asm/irq_cpu.h b/arch/mips/include/asm/irq_cpu.h
+index ef6a07c..3f11fdb 100644
--- a/arch/mips/include/asm/irq_cpu.h
+++ b/arch/mips/include/asm/irq_cpu.h
@@ -17,4 +17,10 @@ extern void mips_cpu_irq_init(void);
@@ -28,6 +30,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4902/
+#endif
+
#endif /* _ASM_IRQ_CPU_H */
+diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
+index 972263b..49bc9ca 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -31,6 +31,7 @@
@@ -83,3 +87,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4902/
+ return 0;
+}
+#endif /* CONFIG_IRQ_DOMAIN */
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch b/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch
index e9e2f56..e346131 100644
--- a/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch
+++ b/target/linux/ramips/patches-3.8/0014-MIPS-ralink-add-CPU-interrupt-controller-to-of_irq_i.patch
@@ -1,7 +1,7 @@
-From d3d2b4200b5a42851365e903d101f8f0882eb9eb Mon Sep 17 00:00:00 2001
+From 9afd2ba44145009578d9d445183480a698cc04f2 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 31 Jan 2013 20:43:30 +0100
-Subject: [PATCH 14/14] MIPS: ralink: add CPU interrupt controller to
+Subject: [PATCH 14/79] MIPS: ralink: add CPU interrupt controller to
of_irq_ids
Convert the ralink IRQ code to make use of the new MIPS IRQ controller OF
@@ -16,6 +16,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/
arch/mips/ralink/irq.c | 10 +++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
+diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi
+index fd49daa..069d066 100644
--- a/arch/mips/ralink/dts/rt3050.dtsi
+++ b/arch/mips/ralink/dts/rt3050.dtsi
@@ -13,6 +13,13 @@
@@ -42,9 +44,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/
};
memc@300 {
+diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
+index e62c975..6d054c5 100644
--- a/arch/mips/ralink/irq.c
+++ b/arch/mips/ralink/irq.c
-@@ -128,8 +128,11 @@ static int __init intc_of_init(struct de
+@@ -128,8 +128,11 @@ static int __init intc_of_init(struct device_node *node,
{
struct resource res;
struct irq_domain *domain;
@@ -57,7 +61,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/
if (of_address_to_resource(node, 0, &res))
panic("Failed to get intc memory range");
-@@ -156,8 +159,8 @@ static int __init intc_of_init(struct de
+@@ -156,8 +159,8 @@ static int __init intc_of_init(struct device_node *node,
rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);
@@ -68,7 +72,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/
cp0_perfcount_irq = irq_create_mapping(domain, 9);
-@@ -165,6 +168,7 @@ static int __init intc_of_init(struct de
+@@ -165,6 +168,7 @@ static int __init intc_of_init(struct device_node *node,
}
static struct of_device_id __initdata of_irq_ids[] = {
@@ -76,3 +80,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/4900/
{ .compatible = "ralink,rt2880-intc", .data = intc_of_init },
{},
};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch b/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch
index 38ef41a..b995422 100644
--- a/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch
+++ b/target/linux/ramips/patches-3.8/0015-serial-ralink-adds-support-for-the-serial-core-found.patch
@@ -1,8 +1,8 @@
-From c420811f117a59a4a7d4e34b362437b91c7fafa1 Mon Sep 17 00:00:00 2001
+From 219ec2244c2e9085e6900dc515a24f6655c79827 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 25 Jan 2013 19:39:51 +0100
-Subject: [PATCH] serial: ralink: adds support for the serial core found on
- ralink wisoc
+Subject: [PATCH 15/79] serial: ralink: adds support for the serial core found
+ on ralink wisoc
The MIPS based Ralink WiSoC platform has 1 or more 8250 compatible serial cores.
To make them work we require the same quirks that are used by AU1x00.
@@ -15,9 +15,11 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/serial_core.h | 2 +-
3 files changed, 12 insertions(+), 4 deletions(-)
+diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
+index f932043..f72eb7d 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
-@@ -345,9 +345,9 @@ static void default_serial_dl_write(stru
+@@ -324,9 +324,9 @@ static void default_serial_dl_write(struct uart_8250_port *up, int value)
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
@@ -29,7 +31,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
static const u8 au_io_in_map[] = {
[UART_RX] = 0,
[UART_IER] = 2,
-@@ -527,7 +527,7 @@ static void set_io_from_upio(struct uart
+@@ -506,7 +506,7 @@ static void set_io_from_upio(struct uart_port *p)
break;
#endif
@@ -38,6 +40,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
case UPIO_AU:
p->serial_in = au_serial_in;
p->serial_out = au_serial_out;
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+index c31133a..9e4febd 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -277,3 +277,11 @@ config SERIAL_8250_EM
@@ -52,6 +56,8 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ 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
+ ports. If unsure, say N.
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index c6690a2..0b428d6 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -134,7 +134,7 @@ struct uart_port {
@@ -63,3 +69,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
#define UPIO_TSI (5) /* Tsi108/109 type IO */
#define UPIO_RM9000 (6) /* RM9000 type IO */
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch b/target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch
index d5fe653..8886cd7 100644
--- a/target/linux/ramips/patches-3.8/0100-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch
+++ b/target/linux/ramips/patches-3.8/0016-MIPS-move-mips_-set-get-_machine_name-to-a-more-gene.patch
@@ -1,7 +1,7 @@
-From dd4bb7e821d112bff981016fd4e7c014ca9425f9 Mon Sep 17 00:00:00 2001
+From 231e989ef4a11073ad6be8af797f96d51256d07a 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
+Subject: [PATCH 16/79] MIPS: move mips_{set,get}_machine_name() to a more
generic place
Previously this functionality was only available to users of the mips_machine
@@ -17,6 +17,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
arch/mips/kernel/prom.c | 31 +++++++++++++++++++++++++++++++
5 files changed, 35 insertions(+), 26 deletions(-)
+diff --git a/arch/mips/include/asm/mips_machine.h b/arch/mips/include/asm/mips_machine.h
+index 363bb35..9d00aeb 100644
--- 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;
@@ -33,9 +35,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
#endif /* CONFIG_MIPS_MACHINE */
#endif /* __ASM_MIPS_MACHINE_H */
+diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h
+index 8808bf5..1e7e096 100644
--- 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_
+@@ -48,4 +48,7 @@ extern void __dt_setup_arch(struct boot_param_header *bph);
static inline void device_tree_init(void) { }
#endif /* CONFIG_OF */
@@ -43,6 +47,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
+extern void mips_set_machine_name(const char *name);
+
#endif /* __ASM_PROM_H */
+diff --git a/arch/mips/kernel/mips_machine.c b/arch/mips/kernel/mips_machine.c
+index 411a058..6dc5866 100644
--- a/arch/mips/kernel/mips_machine.c
+++ b/arch/mips/kernel/mips_machine.c
@@ -13,7 +13,6 @@
@@ -53,7 +59,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
#define for_each_machine(mach) \
for ((mach) = (struct mips_machine *)&__mips_machines_start; \
-@@ -21,25 +20,6 @@ static char *mips_machine_name = "Unknow
+@@ -21,25 +20,6 @@ static char *mips_machine_name = "Unknown";
(unsigned long)(mach) < (unsigned long)&__mips_machines_end; \
(mach)++)
@@ -87,6 +93,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
if (mips_machine->mach_setup)
mips_machine->mach_setup();
+diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
+index 07dff54..8779237 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -12,7 +12,7 @@
@@ -98,6 +106,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
unsigned int vced_count, vcei_count;
+diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
+index 028f6f8..b68e53b 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -23,6 +23,22 @@
@@ -123,7 +133,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
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
+@@ -50,6 +66,18 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
}
#endif
@@ -142,7 +152,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
void __init early_init_devtree(void *params)
{
/* Setup flat device-tree pointer */
-@@ -65,6 +93,9 @@ void __init early_init_devtree(void *par
+@@ -65,6 +93,9 @@ void __init early_init_devtree(void *params)
/* Scan memory nodes */
of_scan_flat_dt(early_init_dt_scan_root, NULL);
of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
@@ -152,3 +162,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5164/
}
void __init __dt_setup_arch(struct boot_param_header *bph)
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch b/target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch
index bdb5cfc..c18817e 100644
--- a/target/linux/ramips/patches-3.8/0101-MIPS-ralink-add-PCI-IRQ-handling.patch
+++ b/target/linux/ramips/patches-3.8/0017-MIPS-ralink-add-PCI-IRQ-handling.patch
@@ -1,7 +1,7 @@
-From 16d9eaf22f30ed0b0deddfe8e11426889ccdb556 Mon Sep 17 00:00:00 2001
+From 98ab228172e66e43766d9e2a0ddb73603c22dbd1 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
+Subject: [PATCH 17/79] 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.
@@ -13,6 +13,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5165/
arch/mips/ralink/irq.c | 4 ++++
1 file changed, 4 insertions(+)
+diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
+index 6d054c5..d9807d0 100644
--- a/arch/mips/ralink/irq.c
+++ b/arch/mips/ralink/irq.c
@@ -31,6 +31,7 @@
@@ -33,3 +35,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5165/
else if (pending & STATUSF_IP2)
do_IRQ(RALINK_CPU_IRQ_INTC);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch b/target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch
index 2d296db..1a8950f 100644
--- a/target/linux/ramips/patches-3.8/0102-MIPS-ralink-add-RT3352-register-defines.patch
+++ b/target/linux/ramips/patches-3.8/0018-MIPS-ralink-add-RT3352-register-defines.patch
@@ -1,7 +1,7 @@
-From e6bcdad6f0811daedc2a448f5d7fb98c116a5241 Mon Sep 17 00:00:00 2001
+From 8667d984d1b4f3be1c5da71788762b9945a25c90 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
+Subject: [PATCH 18/79] MIPS: ralink: add RT3352 register defines
Add a few missing defines that are needed to make USB and clock detection work
on the RT3352.
@@ -13,6 +13,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5166/
arch/mips/include/asm/mach-ralink/rt305x.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
+diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h
+index 7d344f2..e36c3c5 100644
--- 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)
@@ -33,3 +35,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5166/
+#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10)
+
#endif
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch b/target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch
index 7d682e7..ebecdf2 100644
--- a/target/linux/ramips/patches-3.8/0103-MIPS-ralink-fix-RT305x-clock-setup.patch
+++ b/target/linux/ramips/patches-3.8/0019-MIPS-ralink-fix-RT305x-clock-setup.patch
@@ -1,7 +1,7 @@
-From 845f786c561c0991d9b4088a2d77b8fd4831d487 Mon Sep 17 00:00:00 2001
+From 853823a469a8123657bf32bc5e1843c40529a20d 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
+Subject: [PATCH 19/79] MIPS: ralink: fix RT305x clock setup
Add a few missing clocks.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5167/
arch/mips/ralink/rt305x.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+index 0a4bbdc..5d49a54 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -124,6 +124,8 @@ struct ralink_pinmux gpio_pinmux = {
@@ -45,3 +47,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5167/
}
void __init ralink_of_remap(void)
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch b/target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch
index 3218384..51cfe0c 100644
--- a/target/linux/ramips/patches-3.8/0104-MIPS-ralink-add-missing-comment-in-irq-driver.patch
+++ b/target/linux/ramips/patches-3.8/0020-MIPS-ralink-add-missing-comment-in-irq-driver.patch
@@ -1,7 +1,7 @@
-From 2747613b1bba0d4497ed2c4a77e2011d02029153 Mon Sep 17 00:00:00 2001
+From 7c268f1b47669be2efce1607ee02193cb49424cf 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
+Subject: [PATCH 20/79] MIPS: ralink: add missing comment in irq driver
Trivial patch that adds a comment that makes the code more readable.
@@ -12,9 +12,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5168/
arch/mips/ralink/irq.c | 1 +
1 file changed, 1 insertion(+)
+diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
+index d9807d0..320b1f1 100644
--- a/arch/mips/ralink/irq.c
+++ b/arch/mips/ralink/irq.c
-@@ -166,6 +166,7 @@ static int __init intc_of_init(struct de
+@@ -166,6 +166,7 @@ static int __init intc_of_init(struct device_node *node,
irq_set_chained_handler(irq, ralink_intc_irq_handler);
irq_set_handler_data(irq, domain);
@@ -22,3 +24,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5168/
cp0_perfcount_irq = irq_create_mapping(domain, 9);
return 0;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch b/target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch
index ccabcbd..8ecaea2 100644
--- a/target/linux/ramips/patches-3.8/0105-MIPS-ralink-add-RT5350-sdram-register-defines.patch
+++ b/target/linux/ramips/patches-3.8/0021-MIPS-ralink-add-RT5350-sdram-register-defines.patch
@@ -1,7 +1,7 @@
-From 31f4b3ca1c9bb4bcbbebbe5db5a33ac82f130d9c Mon Sep 17 00:00:00 2001
+From 0df8c2fdd0fe1095b834fbf2b098d6f1b3e56608 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
+Subject: [PATCH 21/79] MIPS: ralink: add RT5350 sdram register defines
Add a few missing defines that are needed to make memory detection work on the
RT5350.
@@ -13,6 +13,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5169/
arch/mips/include/asm/mach-ralink/rt305x.h | 8 ++++++++
1 file changed, 8 insertions(+)
+diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h
+index e36c3c5..80cda8a 100644
--- 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)
@@ -30,3 +32,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5169/
/* multi function gpio pins */
#define RT305X_GPIO_I2C_SD 1
#define RT305X_GPIO_I2C_SCLK 2
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch b/target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch
index 4636862..2788397 100644
--- a/target/linux/ramips/patches-3.8/0106-MIPS-ralink-make-early_printk-work-on-RT2880.patch
+++ b/target/linux/ramips/patches-3.8/0022-MIPS-ralink-make-early_printk-work-on-RT2880.patch
@@ -1,7 +1,7 @@
-From d83e83a544258b68b4411232a31ccce134244a19 Mon Sep 17 00:00:00 2001
+From 9ed190912864c8b96d888af2cb66efcf1dc5562a 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
+Subject: [PATCH 22/79] MIPS: ralink: make early_printk work on RT2880
RT2880 has a different location for the early serial port.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5170/
arch/mips/ralink/early_printk.c | 4 ++++
1 file changed, 4 insertions(+)
+diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c
+index c4ae47e..b46d041 100644
--- a/arch/mips/ralink/early_printk.c
+++ b/arch/mips/ralink/early_printk.c
@@ -11,7 +11,11 @@
@@ -26,3 +28,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5170/
#define UART_REG_RX 0x00
#define UART_REG_TX 0x04
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch b/target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch
index d10b159..03d95df 100644
--- a/target/linux/ramips/patches-3.8/0107-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch
+++ b/target/linux/ramips/patches-3.8/0023-MIPS-ralink-rename-gpio_pinmux-to-rt_gpio_pinmux.patch
@@ -1,7 +1,7 @@
-From b4c597bd073d5e4c9cee800ac5a25fb9ff1c0ef7 Mon Sep 17 00:00:00 2001
+From d5b75031f6ad0f9f82c3b8faeab3cda1cb4ebfe9 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
+Subject: [PATCH 23/79] MIPS: ralink: rename gpio_pinmux to rt_gpio_pinmux
Add proper namespacing to the variable.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5171/
arch/mips/ralink/rt305x.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
+diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
+index 3009903..f4b19c6 100644
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
@@ -24,7 +24,7 @@ struct ralink_pinmux {
@@ -23,6 +25,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5171/
struct ralink_soc_info {
unsigned char sys_type[RAMIPS_SYS_TYPE_LEN];
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+index 5d49a54..f1a6c33 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -114,7 +114,7 @@ void rt305x_wdt_reset(void)
@@ -34,3 +38,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5171/
.mode = mode_mux,
.uart = uart_mux,
.uart_shift = RT305X_GPIO_MODE_UART0_SHIFT,
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch b/target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch
index f09d57f..60a8a53 100644
--- a/target/linux/ramips/patches-3.8/0108-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch
+++ b/target/linux/ramips/patches-3.8/0024-MIPS-ralink-make-the-RT305x-pinmuxing-structure-stat.patch
@@ -1,7 +1,7 @@
-From 96eba63bf18cd3d96ded62fb809c8cf7e0f2e2c1 Mon Sep 17 00:00:00 2001
+From 2793deaf4d3d364ba2ed075abf2b9022a152f253 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
+Subject: [PATCH 24/79] MIPS: ralink: make the RT305x pinmuxing structure
static
These structures are exported via struct ralink_pinmux rt_gpio_pinmux and can
@@ -13,6 +13,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5172/
arch/mips/ralink/rt305x.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+index f1a6c33..5b42078 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -22,7 +22,7 @@
@@ -42,3 +44,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5172/
{
u32 t;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch b/target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch
index 36e187d..368fcde 100644
--- a/target/linux/ramips/patches-3.8/0109-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch
+++ b/target/linux/ramips/patches-3.8/0025-MIPS-ralink-add-pci-group-to-struct-ralink_pinmux.patch
@@ -1,7 +1,7 @@
-From 61d50d9625dcb454759950ebd45a335c3aaacf84 Mon Sep 17 00:00:00 2001
+From e859bf709e73acb5735cf1207422f53fc3202632 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
+Subject: [PATCH 25/79] MIPS: ralink: add pci group to struct ralink_pinmux
This will be used for RT3662/RT3883.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5173/
arch/mips/ralink/common.h | 3 +++
1 file changed, 3 insertions(+)
+diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
+index f4b19c6..bebd149 100644
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
@@ -23,6 +23,9 @@ struct ralink_pinmux {
@@ -24,3 +26,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5173/
};
extern struct ralink_pinmux rt_gpio_pinmux;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch b/target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch
index d4474e1..1ee9fd4 100644
--- a/target/linux/ramips/patches-3.8/0110-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch
+++ b/target/linux/ramips/patches-3.8/0026-MIPS-ralink-add-uart-mask-to-struct-ralink_pinmux.patch
@@ -1,7 +1,7 @@
-From faf5989efed503b2ee689dad82bb2d60da718d99 Mon Sep 17 00:00:00 2001
+From 6e09e0465b342b52ecda583cbc41e6a31c363b3f 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
+Subject: [PATCH 26/79] 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.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5744/
arch/mips/ralink/rt305x.c | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
+diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
+index bebd149..299119b 100644
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
@@ -22,6 +22,7 @@ struct ralink_pinmux {
@@ -22,9 +24,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5744/
void (*wdt_reset)(void);
struct ralink_pinmux_grp *pci;
int pci_shift;
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+index 5b42078..6aa3cb1 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
-@@ -91,12 +91,12 @@ static struct ralink_pinmux_grp uart_mux
+@@ -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,
@@ -47,3 +51,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5744/
.wdt_reset = rt305x_wdt_reset,
};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch b/target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch
index 9cfa509..bd8ad22 100644
--- a/target/linux/ramips/patches-3.8/0111-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch
+++ b/target/linux/ramips/patches-3.8/0027-MIPS-ralink-adds-support-for-RT2880-SoC-family.patch
@@ -1,7 +1,7 @@
-From cccb9a7b42227a442ca42d590c838c8b6fa0eba1 Mon Sep 17 00:00:00 2001
+From 2a0d9878985bb3274bb61535f76ea293991635a9 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
+Subject: [PATCH 27/79] MIPS: ralink: adds support for RT2880 SoC family
Add support code for rt2880 SOC.
@@ -21,9 +21,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
create mode 100644 arch/mips/include/asm/mach-ralink/rt288x.h
create mode 100644 arch/mips/ralink/rt288x.c
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index b5081b5..b5fd476 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
-@@ -1189,7 +1189,7 @@ config BOOT_ELF32
+@@ -1177,7 +1177,7 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT
int
@@ -32,6 +34,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
default "6" if MIPS_CPU_SCACHE
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
default "5"
+diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h
+new file mode 100644
+index 0000000..ad8b42d
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/rt288x.h
@@ -0,0 +1,49 @@
@@ -84,6 +89,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
+#define CLKCFG_SRAM_CS_N_WDT BIT(9)
+
+#endif
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index a0b0197..6723b94 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -6,6 +6,9 @@ choice
@@ -96,6 +103,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
config SOC_RT305X
bool "RT305x"
select USB_ARCH_HAS_HCD
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index 939757f..6d826f2 100644
--- a/arch/mips/ralink/Makefile
+++ b/arch/mips/ralink/Makefile
@@ -8,6 +8,7 @@
@@ -106,9 +115,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
obj-$(CONFIG_SOC_RT305X) += rt305x.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
+index 6babd65..3f49e51 100644
--- a/arch/mips/ralink/Platform
+++ b/arch/mips/ralink/Platform
-@@ -5,6 +5,11 @@ core-$(CONFIG_RALINK) += arch/mips/rali
+@@ -5,6 +5,11 @@ core-$(CONFIG_RALINK) += arch/mips/ralink/
cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink
#
@@ -120,6 +131,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
# Ralink RT305x
#
load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
+diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c
+new file mode 100644
+index 0000000..1e0788e
--- /dev/null
+++ b/arch/mips/ralink/rt288x.c
@@ -0,0 +1,139 @@
@@ -262,3 +276,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5176/
+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
+ (id & CHIP_ID_REV_MASK));
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch b/target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch
index 162d0cc..f124fec 100644
--- a/target/linux/ramips/patches-3.8/0112-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch
+++ b/target/linux/ramips/patches-3.8/0028-MIPS-ralink-adds-support-for-RT3883-SoC-family.patch
@@ -1,7 +1,7 @@
-From 5eb4dfe5072595e0706de3364f2da45378dbaca6 Mon Sep 17 00:00:00 2001
+From c75f4a5af758494595fded27efb95732365d10db 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
+Subject: [PATCH 28/79] MIPS: ralink: adds support for RT3883 SoC family
Add support code for rt3883 SOC.
@@ -20,9 +20,12 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
create mode 100644 arch/mips/include/asm/mach-ralink/rt3883.h
create mode 100644 arch/mips/ralink/rt3883.c
+diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h
+new file mode 100644
+index 0000000..b91c6c1
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/rt3883.h
-@@ -0,0 +1,248 @@
+@@ -0,0 +1,247 @@
+/*
+ * Ralink RT3662/RT3883 SoC register definitions
+ *
@@ -177,7 +180,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
+#define RT3883_GPIO_SPI_MISO 6
+#define RT3883_GPIO_7 7
+#define RT3883_GPIO_10 10
-+#define RT3883_GPIO_11 11
+#define RT3883_GPIO_14 14
+#define RT3883_GPIO_UART1_TXD 15
+#define RT3883_GPIO_UART1_RXD 16
@@ -271,6 +273,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
+#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2
+
+#endif /* _RT3883_REGS_H_ */
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 6723b94..ce57d3e 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -15,6 +15,11 @@ choice
@@ -285,6 +289,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
endchoice
choice
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index 6d826f2..ba9669c 100644
--- 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
@@ -295,9 +301,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
+index 3f49e51..f67c08d 100644
--- a/arch/mips/ralink/Platform
+++ b/arch/mips/ralink/Platform
-@@ -13,3 +13,8 @@ load-$(CONFIG_SOC_RT288X) += 0xffffffff8
+@@ -13,3 +13,8 @@ load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000
# Ralink RT305x
#
load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
@@ -306,6 +314,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
+# Ralink RT3883
+#
+load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
+diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c
+new file mode 100644
+index 0000000..2d90aa9
--- /dev/null
+++ b/arch/mips/ralink/rt3883.c
@@ -0,0 +1,242 @@
@@ -551,3 +562,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5185/
+ (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK,
+ (id & RT3883_REVID_ECO_ID_MASK));
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch b/target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch
index d528034..f03c10f 100644
--- a/target/linux/ramips/patches-3.8/0113-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch
+++ b/target/linux/ramips/patches-3.8/0029-MIPS-ralink-adds-support-for-MT7620-SoC-family.patch
@@ -1,7 +1,7 @@
-From a8d7045a9530d0a9e0c65c0f81852bd57ebde53c Mon Sep 17 00:00:00 2001
+From 41b7b06b494eef5a081363566314960306437d73 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
+Subject: [PATCH 29/79] MIPS: ralink: adds support for MT7620 SoC family
Add support code for mt7620 SOC.
@@ -20,6 +20,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5177/
create mode 100644 arch/mips/include/asm/mach-ralink/mt7620.h
create mode 100644 arch/mips/ralink/mt7620.c
+diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h
+new file mode 100644
+index 0000000..b272649
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
@@ -0,0 +1,76 @@
@@ -99,6 +102,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5177/
+#define MT7620_GPIO_MODE_WDT BIT(22)
+
+#endif
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index ce57d3e..86f6c77 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -20,6 +20,9 @@ choice
@@ -111,6 +116,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5177/
endchoice
choice
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index ba9669c..38cf1a8 100644
--- 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
@@ -121,9 +128,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5177/
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
+index f67c08d..b2cbf16 100644
--- a/arch/mips/ralink/Platform
+++ b/arch/mips/ralink/Platform
-@@ -18,3 +18,8 @@ load-$(CONFIG_SOC_RT305X) += 0xffffffff8
+@@ -18,3 +18,8 @@ load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
# Ralink RT3883
#
load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
@@ -132,6 +141,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5177/
+# Ralink MT7620
+#
+load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+new file mode 100644
+index 0000000..eb00ab8
--- /dev/null
+++ b/arch/mips/ralink/mt7620.c
@@ -0,0 +1,214 @@
@@ -349,3 +361,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5177/
+ cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
+ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch b/target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch
index dc5dab9..21205a3 100644
--- a/target/linux/ramips/patches-3.8/0114-MIPS-ralink-add-cpu-feature-overrides.h.patch
+++ b/target/linux/ramips/patches-3.8/0030-MIPS-ralink-add-cpu-feature-overrides.h.patch
@@ -1,7 +1,7 @@
-From 33c525913af22d1b799a7218ee48579c22a50cf8 Mon Sep 17 00:00:00 2001
+From 8a7cac5e324f044f3970d686d79e3489260f6d21 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
+Subject: [PATCH 30/79] MIPS: ralink: add cpu-feature-overrides.h
Add cpu-feature-overrides.h for RT288x, RT305x and RT3883.
@@ -18,6 +18,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5175/
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
+diff --git a/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h
+new file mode 100644
+index 0000000..72fc106
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h
@@ -0,0 +1,56 @@
@@ -77,6 +80,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5175/
+#define cpu_icache_line_size() 16
+
+#endif /* _RT288X_CPU_FEATURE_OVERRIDES_H */
+diff --git a/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h
+new file mode 100644
+index 0000000..917c286
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h
@@ -0,0 +1,56 @@
@@ -136,6 +142,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5175/
+#define cpu_icache_line_size() 32
+
+#endif /* _RT305X_CPU_FEATURE_OVERRIDES_H */
+diff --git a/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h
+new file mode 100644
+index 0000000..181fbf4
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h
@@ -0,0 +1,55 @@
@@ -194,9 +203,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5175/
+#define cpu_icache_line_size() 32
+
+#endif /* _RT3883_CPU_FEATURE_OVERRIDES_H */
+diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
+index b2cbf16..cda4b66 100644
--- a/arch/mips/ralink/Platform
+++ b/arch/mips/ralink/Platform
-@@ -8,16 +8,19 @@ cflags-$(CONFIG_RALINK) += -I$(srctree)
+@@ -8,16 +8,19 @@ cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink
# Ralink RT288x
#
load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000
@@ -216,3 +227,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5175/
#
# Ralink MT7620
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch b/target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch
index a9a99b4..7a81af6 100644
--- a/target/linux/ramips/patches-3.8/0115-DT-add-vendor-prefixes-for-Ralink.patch
+++ b/target/linux/ramips/patches-3.8/0031-DT-add-vendor-prefixes-for-Ralink.patch
@@ -1,7 +1,7 @@
-From 9377ecb9f1fb5da25a0fbd324e7add7644b1d43d Mon Sep 17 00:00:00 2001
+From f13cb76f8ad8714eaf691ef24aebfb57f62dab66 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
+Subject: [PATCH 31/79] DT: add vendor prefixes for Ralink
Signed-off-by: John Crispin <blogic@openwrt.org>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
@@ -9,6 +9,8 @@ Acked-by: Grant Likely <grant.likely@secretlab.ca>
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
+index 902b1b1..d1cc7bb 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -40,6 +40,7 @@ onnn ON Semiconductor Corp.
@@ -19,3 +21,6 @@ Acked-by: Grant Likely <grant.likely@secretlab.ca>
ramtron Ramtron International
realtek Realtek Semiconductor Corp.
samsung Samsung Semiconductor
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch b/target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch
index f9463c4..1a66e63 100644
--- a/target/linux/ramips/patches-3.8/0116-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch
+++ b/target/linux/ramips/patches-3.8/0032-DT-add-documentation-for-the-Ralink-MIPS-SoCs.patch
@@ -1,7 +1,7 @@
-From fed1ff0d85b481bb3dbebf31e0720d65ce4170c9 Mon Sep 17 00:00:00 2001
+From 441d0189a47391c6882bbc6a11494e7cd394f1fc 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
+Subject: [PATCH 32/79] DT: add documentation for the Ralink MIPS SoCs
This patch adds binding documentation for the
compatible values of the Ralink MIPS SoCs.
@@ -15,6 +15,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5187/
1 file changed, 18 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mips/ralink.txt
+diff --git a/Documentation/devicetree/bindings/mips/ralink.txt b/Documentation/devicetree/bindings/mips/ralink.txt
+new file mode 100644
+index 0000000..59b6a35
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/ralink.txt
@@ -0,0 +1,18 @@
@@ -36,3 +39,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5187/
+ ralink,mt7620a-soc
+ ralink,mt7620n-soc
+
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch b/target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch
index 1328b43..a3a674f 100644
--- a/target/linux/ramips/patches-3.8/0117-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch
+++ b/target/linux/ramips/patches-3.8/0033-DT-MIPS-ralink-clean-up-RT3050-dtsi-and-dts-file.patch
@@ -1,7 +1,7 @@
-From 7a30e00a278fe94ac8e42d0967ffde99d1ab74ee Mon Sep 17 00:00:00 2001
+From 29d1bb6fc97d4391e4ecf96298b6ac42d0daefca 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
+Date: Thu, 20 Jun 2013 18:44:43 +0200
+Subject: [PATCH 33/79] 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
@@ -15,6 +15,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5186/
arch/mips/ralink/dts/rt3052_eval.dts | 10 ++-----
2 files changed, 4 insertions(+), 58 deletions(-)
+diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi
+index 069d066..ef7da1e 100644
--- a/arch/mips/ralink/dts/rt3050.dtsi
+++ b/arch/mips/ralink/dts/rt3050.dtsi
@@ -1,7 +1,7 @@
@@ -104,6 +106,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5186/
uartlite@c00 {
compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a";
reg = <0xc00 0x100>;
+diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
+index dc56e58..df17f5f 100644
--- a/arch/mips/ralink/dts/rt3052_eval.dts
+++ b/arch/mips/ralink/dts/rt3052_eval.dts
@@ -3,8 +3,6 @@
@@ -115,3 +119,21 @@ Patchwork: http://patchwork.linux-mips.org/patch/5186/
compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc";
model = "Ralink RT3052 evaluation board";
+@@ -12,12 +10,8 @@
+ reg = <0x0 0x2000000>;
+ };
+
+- palmbus@10000000 {
+- sysc@0 {
+- ralink,pinmux = "uartlite", "spi";
+- ralink,uartmux = "gpio";
+- ralink,wdtmux = <0>;
+- };
++ chosen {
++ bootargs = "console=ttyS0,57600";
+ };
+
+ cfi@1f000000 {
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch b/target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch
index 8ad9b18..affa771 100644
--- a/target/linux/ramips/patches-3.8/0118-DT-MIPS-ralink-add-RT2880-dts-files.patch
+++ b/target/linux/ramips/patches-3.8/0034-DT-MIPS-ralink-add-RT2880-dts-files.patch
@@ -1,7 +1,7 @@
-From b39e659770cb71939765de8c9e73c0a0cfa832db Mon Sep 17 00:00:00 2001
+From b3cda181b5f9986b05bd95ee322504a8f2ed0b69 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
+Subject: [PATCH 34/79] DT: MIPS: ralink: add RT2880 dts files
Add a dtsi file for RT2880 SoC and a sample dts file.
@@ -17,6 +17,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5188/
create mode 100644 arch/mips/ralink/dts/rt2880.dtsi
create mode 100644 arch/mips/ralink/dts/rt2880_eval.dts
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 86f6c77..2f6fbb8 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -34,6 +34,10 @@ choice
@@ -30,11 +32,16 @@ Patchwork: http://patchwork.linux-mips.org/patch/5188/
config DTB_RT305X_EVAL
bool "RT305x eval kit"
depends on SOC_RT305X
+diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile
+index 1a69fb3..f635a01 100644
--- 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
+diff --git a/arch/mips/ralink/dts/rt2880.dtsi b/arch/mips/ralink/dts/rt2880.dtsi
+new file mode 100644
+index 0000000..182afde
--- /dev/null
+++ b/arch/mips/ralink/dts/rt2880.dtsi
@@ -0,0 +1,58 @@
@@ -96,6 +103,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5188/
+ };
+ };
+};
+diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts
+new file mode 100644
+index 0000000..322d700
--- /dev/null
+++ b/arch/mips/ralink/dts/rt2880_eval.dts
@@ -0,0 +1,46 @@
@@ -145,3 +155,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5188/
+ };
+ };
+};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch b/target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch
index 90b50ed..e416036 100644
--- a/target/linux/ramips/patches-3.8/0119-DT-MIPS-ralink-add-RT3883-dts-files.patch
+++ b/target/linux/ramips/patches-3.8/0035-DT-MIPS-ralink-add-RT3883-dts-files.patch
@@ -1,7 +1,7 @@
-From 8b02459b5aa171dc8726698c4b19341a4e441bb8 Mon Sep 17 00:00:00 2001
+From d702c2e334db0a75298654b12755fd5879dd29df 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
+Subject: [PATCH 35/79] DT: MIPS: ralink: add RT3883 dts files
Add a dtsi file for RT3883 SoC and a sample dts file.
@@ -17,6 +17,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5189/
create mode 100644 arch/mips/ralink/dts/rt3883.dtsi
create mode 100644 arch/mips/ralink/dts/rt3883_eval.dts
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 2f6fbb8..493411f 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -42,6 +42,10 @@ choice
@@ -30,12 +32,17 @@ Patchwork: http://patchwork.linux-mips.org/patch/5189/
endchoice
endif
+diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile
+index f635a01..040a986 100644
--- 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
+diff --git a/arch/mips/ralink/dts/rt3883.dtsi b/arch/mips/ralink/dts/rt3883.dtsi
+new file mode 100644
+index 0000000..3b131dd
--- /dev/null
+++ b/arch/mips/ralink/dts/rt3883.dtsi
@@ -0,0 +1,58 @@
@@ -97,6 +104,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5189/
+ };
+ };
+};
+diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts
+new file mode 100644
+index 0000000..2fa6b33
--- /dev/null
+++ b/arch/mips/ralink/dts/rt3883_eval.dts
@@ -0,0 +1,16 @@
@@ -116,3 +126,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5189/
+ bootargs = "console=ttyS0,57600";
+ };
+};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch b/target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch
index 82a3086..1013c19 100644
--- a/target/linux/ramips/patches-3.8/0120-DT-MIPS-ralink-add-MT7620A-dts-files.patch
+++ b/target/linux/ramips/patches-3.8/0036-DT-MIPS-ralink-add-MT7620A-dts-files.patch
@@ -1,7 +1,7 @@
-From 07741f61fc94fad3c3d21fa1a2ad6f01455cc1dd Mon Sep 17 00:00:00 2001
+From 0757f88781dca6b29de4e1578a4900715371a926 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
+Subject: [PATCH 36/79] DT: MIPS: ralink: add MT7620A dts files
Add a dtsi file for MT7620A SoC and a sample dts file.
@@ -17,6 +17,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5190/
create mode 100644 arch/mips/ralink/dts/mt7620a.dtsi
create mode 100644 arch/mips/ralink/dts/mt7620a_eval.dts
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 493411f..026e823 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -46,6 +46,10 @@ choice
@@ -30,6 +32,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5190/
endchoice
endif
+diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile
+index 040a986..18194fa 100644
--- a/arch/mips/ralink/dts/Makefile
+++ b/arch/mips/ralink/dts/Makefile
@@ -1,3 +1,4 @@
@@ -37,6 +41,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5190/
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
+diff --git a/arch/mips/ralink/dts/mt7620a.dtsi b/arch/mips/ralink/dts/mt7620a.dtsi
+new file mode 100644
+index 0000000..08bf24f
--- /dev/null
+++ b/arch/mips/ralink/dts/mt7620a.dtsi
@@ -0,0 +1,58 @@
@@ -98,6 +105,9 @@ Patchwork: http://patchwork.linux-mips.org/patch/5190/
+ };
+ };
+};
+diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts
+new file mode 100644
+index 0000000..35eb874
--- /dev/null
+++ b/arch/mips/ralink/dts/mt7620a_eval.dts
@@ -0,0 +1,16 @@
@@ -117,3 +127,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5190/
+ bootargs = "console=ttyS0,57600";
+ };
+};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch b/target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch
index 8736e24..2f5626e 100644
--- a/target/linux/ramips/patches-3.8/0121-MIPS-add-detect_memory_region.patch
+++ b/target/linux/ramips/patches-3.8/0037-MIPS-add-detect_memory_region.patch
@@ -1,7 +1,7 @@
-From 9041c96ab5bd29d85ca95cffa44c755f68ae6bb1 Mon Sep 17 00:00:00 2001
+From 3350a0d29bc3f3d15b50835a20ffcc14a458e2d9 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()
+Subject: [PATCH 37/79] 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.
@@ -13,6 +13,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5178/
arch/mips/kernel/setup.c | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
+diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
+index 7a51d87..6d6cfac 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -104,6 +104,7 @@ struct boot_mem_map {
@@ -23,6 +25,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5178/
extern void prom_init(void);
extern void prom_free_prom_memory(void);
+diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
+index 8c41187..3937630 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -23,6 +23,7 @@
@@ -33,7 +37,7 @@ Patchwork: http://patchwork.linux-mips.org/patch/5178/
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
-@@ -122,6 +123,25 @@ void __init add_memory_region(phys_t sta
+@@ -122,6 +123,25 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
boot_mem_map.nr_map++;
}
@@ -59,3 +63,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5178/
static void __init print_memory_map(void)
{
int i;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch b/target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch
index 3454a5b..36fc72a 100644
--- a/target/linux/ramips/patches-3.8/0122-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch
+++ b/target/linux/ramips/patches-3.8/0038-MIPS-ralink-add-memory-definition-to-struct-ralink_s.patch
@@ -1,7 +1,7 @@
-From 5155790ed1f270379ea98325f01e1c72a36a37d0 Mon Sep 17 00:00:00 2001
+From cfad83f59816f2be69a22955a398906d749ab108 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
+Subject: [PATCH 38/79] 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
@@ -13,9 +13,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5179/
arch/mips/ralink/common.h | 5 +++++
1 file changed, 5 insertions(+)
+diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
+index 299119b..83144c3 100644
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
-@@ -33,6 +33,11 @@ extern struct ralink_pinmux rt_gpio_pinm
+@@ -33,6 +33,11 @@ extern struct ralink_pinmux rt_gpio_pinmux;
struct ralink_soc_info {
unsigned char sys_type[RAMIPS_SYS_TYPE_LEN];
unsigned char *compatible;
@@ -27,3 +29,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5179/
};
extern struct ralink_soc_info soc_info;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch b/target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch
index bf6d7f3..6738d9e 100644
--- a/target/linux/ramips/patches-3.8/0123-MIPS-ralink-add-memory-definition-for-RT305x.patch
+++ b/target/linux/ramips/patches-3.8/0039-MIPS-ralink-add-memory-definition-for-RT305x.patch
@@ -1,7 +1,7 @@
-From 016f1f659cf70cc78e72e12a2130d8f3e1a6e0d3 Mon Sep 17 00:00:00 2001
+From 7d0aa01494353532bbdc644469ef2a06ee089f3e 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
+Subject: [PATCH 39/79] MIPS: ralink: add memory definition for RT305x
Populate struct soc_info with the data that describes our RAM window.
@@ -15,6 +15,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5180/
arch/mips/ralink/rt305x.c | 45 ++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
+diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h
+index 80cda8a..069bf37 100644
--- 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)
@@ -28,6 +30,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5180/
+#define RT3352_MEM_SIZE_MAX 256
+
#endif
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+index 6aa3cb1..ca7ee3a 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -122,6 +122,40 @@ struct ralink_pinmux rt_gpio_pinmux = {
@@ -65,13 +69,13 @@ Patchwork: http://patchwork.linux-mips.org/patch/5180/
+ break;
+ }
+
-+ return ret * 1024 * 1024;
++ 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
+@@ -252,4 +286,15 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name,
(id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
(id & CHIP_ID_REV_MASK));
@@ -87,3 +91,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5180/
+ soc_info->mem_size_max = RT3352_MEM_SIZE_MAX;
+ }
}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch b/target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch
index 975fb48..e09d5b7 100644
--- a/target/linux/ramips/patches-3.8/0124-MIPS-ralink-add-memory-definition-for-RT2880.patch
+++ b/target/linux/ramips/patches-3.8/0040-MIPS-ralink-add-memory-definition-for-RT2880.patch
@@ -1,7 +1,7 @@
-From 0151f5f0dbf43b6b3718b0d1d403c87429ac0313 Mon Sep 17 00:00:00 2001
+From 1ca89d8a262f27f4ecd45d40b6774c415842421a 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
+Subject: [PATCH 40/79] MIPS: ralink: add memory definition for RT2880
Populate struct soc_info with the data that describes our RAM window.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5181/
arch/mips/ralink/rt288x.c | 4 ++++
2 files changed, 8 insertions(+)
+diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h
+index ad8b42d..03ad716 100644
--- a/arch/mips/include/asm/mach-ralink/rt288x.h
+++ b/arch/mips/include/asm/mach-ralink/rt288x.h
@@ -46,4 +46,8 @@
@@ -23,9 +25,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5181/
+#define RT2880_MEM_SIZE_MAX 128
+
#endif
+diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c
+index 1e0788e..f87de1a 100644
--- a/arch/mips/ralink/rt288x.c
+++ b/arch/mips/ralink/rt288x.c
-@@ -136,4 +136,8 @@ void prom_soc_init(struct ralink_soc_inf
+@@ -136,4 +136,8 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name,
(id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
(id & CHIP_ID_REV_MASK));
@@ -34,3 +38,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5181/
+ soc_info->mem_size_min = RT2880_MEM_SIZE_MIN;
+ soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch b/target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch
index 2c015ad..1160906 100644
--- a/target/linux/ramips/patches-3.8/0125-MIPS-ralink-add-memory-definition-for-RT3883.patch
+++ b/target/linux/ramips/patches-3.8/0041-MIPS-ralink-add-memory-definition-for-RT3883.patch
@@ -1,20 +1,30 @@
-From de85c6c3e2d5ed9c721a282d91af504a845e1fad Mon Sep 17 00:00:00 2001
+From 42a816a8312734e6b438e799378044365e229a07 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
+Subject: [PATCH 41/79] 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/include/asm/mach-ralink/rt3883.h | 5 +++++
arch/mips/ralink/rt3883.c | 4 ++++
- 2 files changed, 8 insertions(+)
+ 2 files changed, 9 insertions(+)
+diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h
+index b91c6c1..058382f 100644
--- a/arch/mips/include/asm/mach-ralink/rt3883.h
+++ b/arch/mips/include/asm/mach-ralink/rt3883.h
-@@ -245,4 +245,8 @@
+@@ -152,6 +152,7 @@
+ #define RT3883_GPIO_SPI_MISO 6
+ #define RT3883_GPIO_7 7
+ #define RT3883_GPIO_10 10
++#define RT3883_GPIO_11 11
+ #define RT3883_GPIO_14 14
+ #define RT3883_GPIO_UART1_TXD 15
+ #define RT3883_GPIO_UART1_RXD 16
+@@ -244,4 +245,8 @@
#define RT3883_FLASH_CFG_WIDTH_16BIT 0x1
#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2
@@ -23,9 +33,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5182/
+#define RT3883_MEM_SIZE_MAX 256
+
#endif /* _RT3883_REGS_H_ */
+diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c
+index 2d90aa9..afbf2ce 100644
--- a/arch/mips/ralink/rt3883.c
+++ b/arch/mips/ralink/rt3883.c
-@@ -239,4 +239,8 @@ void prom_soc_init(struct ralink_soc_inf
+@@ -239,4 +239,8 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name,
(id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK,
(id & RT3883_REVID_ECO_ID_MASK));
@@ -34,3 +46,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5182/
+ soc_info->mem_size_min = RT3883_MEM_SIZE_MIN;
+ soc_info->mem_size_max = RT3883_MEM_SIZE_MAX;
}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch b/target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch
index b36ab33..da2610c 100644
--- a/target/linux/ramips/patches-3.8/0126-MIPS-ralink-add-memory-definition-for-MT7620.patch
+++ b/target/linux/ramips/patches-3.8/0042-MIPS-ralink-add-memory-definition-for-MT7620.patch
@@ -1,7 +1,7 @@
-From c1d35c42d697e9c28c817921a79c5f814529a4c6 Mon Sep 17 00:00:00 2001
+From e7dfbb1eafed754442099a33492a9e90fa33d3fa 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
+Subject: [PATCH 42/79] MIPS: ralink: add memory definition for MT7620
Populate struct soc_info with the data that describes our RAM window.
@@ -12,6 +12,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5183/
arch/mips/ralink/mt7620.c | 20 ++++++++++++++++++++
2 files changed, 28 insertions(+)
+diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h
+index b272649..9809972 100644
--- a/arch/mips/include/asm/mach-ralink/mt7620.h
+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
@@ -50,6 +50,14 @@
@@ -29,9 +31,11 @@ Patchwork: http://patchwork.linux-mips.org/patch/5183/
#define MT7620_GPIO_MODE_I2C BIT(0)
#define MT7620_GPIO_MODE_UART0_SHIFT 2
#define MT7620_GPIO_MODE_UART0_MASK 0x7
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+index eb00ab8..98ddb93 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
-@@ -211,4 +211,24 @@ void prom_soc_init(struct ralink_soc_inf
+@@ -211,4 +211,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
@@ -56,3 +60,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5183/
+ }
+ soc_info->mem_base = MT7620_DRAM_BASE;
}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch b/target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch
index 59bdadd..1b6acf0 100644
--- a/target/linux/ramips/patches-3.8/0127-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch
+++ b/target/linux/ramips/patches-3.8/0043-MIPS-ralink-make-use-of-the-new-memory-detection-cod.patch
@@ -1,7 +1,7 @@
-From 1618a00f709817cbcdebf038d0b5e251c8d67237 Mon Sep 17 00:00:00 2001
+From 6142d0fa1c7ba6050664a27d7cca87043217b01f 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
+Subject: [PATCH 43/79] MIPS: ralink: make use of the new memory detection
code
Call detect_memory_region() from plat_mem_setup() unless the size was already
@@ -13,6 +13,8 @@ Patchwork: http://patchwork.linux-mips.org/patch/5184/
arch/mips/ralink/of.c | 9 +++++++++
1 file changed, 9 insertions(+)
+diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
+index 4165e70..fb15695 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -11,6 +11,7 @@
@@ -38,3 +40,6 @@ Patchwork: http://patchwork.linux-mips.org/patch/5184/
}
static int __init plat_of_setup(void)
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch b/target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch
new file mode 100644
index 0000000..0ebbfe5
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0044-MIPS-ralink-upstream-v3.10.patch
@@ -0,0 +1,23 @@
+From b6038567015683bc9541e2bee1b9bc0db50589a3 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 30 May 2013 16:16:13 +0200
+Subject: [PATCH 44/79] MIPS: ralink: upstream v3.10
+
+patches prior to this were sent upstream and accepted for v3.10
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ dummy | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 dummy
+
+diff --git a/dummy b/dummy
+new file mode 100644
+index 0000000..421376d
+--- /dev/null
++++ b/dummy
+@@ -0,0 +1 @@
++dummy
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch b/target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch
index f28115c..546719d 100644
--- a/target/linux/ramips/patches-3.8/0128-MIPS-ralink-add-pinmux-driver.patch
+++ b/target/linux/ramips/patches-3.8/0045-MIPS-ralink-add-pinmux-driver.patch
@@ -1,7 +1,7 @@
-From 5a2079532dfaf5762f658370ee7a0afb686f066e Mon Sep 17 00:00:00 2001
+From c7107291df4035794c67d7a904fe7419fedc5922 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
+Subject: [PATCH 45/79] 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
@@ -12,10 +12,12 @@ 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(-)
+ arch/mips/ralink/pinmux.c | 77 +++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 82 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/ralink/pinmux.c
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index 38cf1a8..341b4de 100644
--- a/arch/mips/ralink/Makefile
+++ b/arch/mips/ralink/Makefile
@@ -6,7 +6,7 @@
@@ -27,15 +29,19 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
obj-$(CONFIG_SOC_RT288X) += rt288x.o
obj-$(CONFIG_SOC_RT305X) += rt305x.o
+diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
+index 83144c3..f113fd6 100644
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
-@@ -50,4 +50,6 @@ extern void prom_soc_init(struct ralink_
+@@ -50,4 +50,6 @@ extern void prom_soc_init(struct ralink_soc_info *soc_info);
__iomem void *plat_of_remap_node(const char *node);
+void ralink_pinmux(void);
+
#endif /* _RALINK_COMMON_H__ */
+diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
+index fb15695..f916774 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -110,6 +110,8 @@ static int __init plat_of_setup(void)
@@ -47,6 +53,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
return 0;
}
+diff --git a/arch/mips/ralink/pinmux.c b/arch/mips/ralink/pinmux.c
+new file mode 100644
+index 0000000..1720216
--- /dev/null
+++ b/arch/mips/ralink/pinmux.c
@@ -0,0 +1,77 @@
@@ -127,3 +136,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+ rt_sysc_w32(mode, SYSC_REG_GPIO_MODE);
+}
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch b/target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch
index 6664e11..18e001c 100644
--- a/target/linux/ramips/patches-3.8/0129-MIPS-ralink-add-support-for-periodic-timer-irq.patch
+++ b/target/linux/ramips/patches-3.8/0046-MIPS-ralink-add-support-for-periodic-timer-irq.patch
@@ -1,7 +1,7 @@
-From 1f307fd0fdca585d5c7c32963e8a8a6f38d8a78c Mon Sep 17 00:00:00 2001
+From f14edca84cd854dac7dd429b1fbeb80ac76fca16 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
+Subject: [PATCH 46/79] MIPS: ralink: add support for periodic timer irq
Adds a driver for the periodic timer found on Ralink SoC.
@@ -12,6 +12,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
2 files changed, 193 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/ralink/timer.c
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index 341b4de..cae7d88 100644
--- a/arch/mips/ralink/Makefile
+++ b/arch/mips/ralink/Makefile
@@ -6,7 +6,7 @@
@@ -23,6 +25,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
obj-$(CONFIG_SOC_RT288X) += rt288x.o
obj-$(CONFIG_SOC_RT305X) += rt305x.o
+diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c
+new file mode 100644
+index 0000000..0a6856c
--- /dev/null
+++ b/arch/mips/ralink/timer.c
@@ -0,0 +1,192 @@
@@ -218,3 +223,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+MODULE_DESCRIPTION("Ralink RT2880 timer");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org");
+MODULE_LICENSE("GPL");
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0047-MIPS-ralink-add-rt_sysc_m32-helper.patch b/target/linux/ramips/patches-3.8/0047-MIPS-ralink-add-rt_sysc_m32-helper.patch
new file mode 100644
index 0000000..6afdb5a
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0047-MIPS-ralink-add-rt_sysc_m32-helper.patch
@@ -0,0 +1,31 @@
+From f7a5af8f5a3a4bc80a0c297c16c661d72ae356b4 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 19 May 2013 00:42:23 +0200
+Subject: [PATCH 47/79] MIPS: ralink: add rt_sysc_m32 helper
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/include/asm/mach-ralink/ralink_regs.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/mips/include/asm/mach-ralink/ralink_regs.h b/arch/mips/include/asm/mach-ralink/ralink_regs.h
+index 5a508f9..bd93014 100644
+--- a/arch/mips/include/asm/mach-ralink/ralink_regs.h
++++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h
+@@ -26,6 +26,13 @@ static inline u32 rt_sysc_r32(unsigned reg)
+ return __raw_readl(rt_sysc_membase + reg);
+ }
+
++static inline void rt_sysc_m32(u32 clr, u32 set, unsigned reg)
++{
++ u32 val = rt_sysc_r32(reg) & ~clr;
++
++ __raw_writel(val | set, rt_sysc_membase + reg);
++}
++
+ static inline void rt_memc_w32(u32 val, unsigned reg)
+ {
+ __raw_writel(val, rt_memc_membase + reg);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch b/target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch
new file mode 100644
index 0000000..d17c227
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0048-MIPS-ralink-make-mt7620-ram-detect-verbose.patch
@@ -0,0 +1,39 @@
+From 8c2015a6eed656d8578a78e392625869ba8f9bb4 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 20 May 2013 20:30:11 +0200
+Subject: [PATCH 48/79] MIPS: ralink: make mt7620 ram detect verbose
+
+Make the code print which of SDRAM, DDR1 or DDR2 was detected.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/mt7620.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+index 98ddb93..28350d0 100644
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -214,16 +214,19 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
+
+ switch (dram_type) {
+ case SYSCFG0_DRAM_TYPE_SDRAM:
++ pr_info("Board has SDRAM\n");
+ soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN;
+ soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX;
+ break;
+
+ case SYSCFG0_DRAM_TYPE_DDR1:
++ pr_info("Board has DDR1\n");
+ soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN;
+ soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX;
+ break;
+
+ case SYSCFG0_DRAM_TYPE_DDR2:
++ pr_info("Board has DDR2\n");
+ soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN;
+ soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX;
+ break;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch b/target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch
new file mode 100644
index 0000000..206e9d8
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0049-MIPS-ralink-add-verbose-pmu-info.patch
@@ -0,0 +1,64 @@
+From 1652cf71db797b249c0d384e6c3d31b312b7012e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 20 May 2013 20:57:09 +0200
+Subject: [PATCH 49/79] MIPS: ralink: add verbose pmu info
+
+Print the PMU and LDO settings on boot.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/mt7620.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+index 28350d0..69729a5 100644
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -20,6 +20,22 @@
+
+ #include "common.h"
+
++/* analog */
++#define PMU0_CFG 0x88
++#define PMU_SW_SET BIT(28)
++#define A_DCDC_EN BIT(24)
++#define A_SSC_PERI BIT(19)
++#define A_SSC_GEN BIT(18)
++#define A_SSC_M 0x3
++#define A_SSC_S 16
++#define A_DLY_M 0x7
++#define A_DLY_S 8
++#define A_VTUNE_M 0xff
++
++/* digital */
++#define PMU1_CFG 0x8C
++#define DIG_SW_SEL BIT(25)
++
+ /* does the board have sdram or ddram */
+ static int dram_type;
+
+@@ -187,6 +203,8 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
+ u32 n1;
+ u32 rev;
+ u32 cfg0;
++ u32 pmu0;
++ u32 pmu1;
+
+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
+@@ -234,4 +252,12 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
+ BUG();
+ }
+ soc_info->mem_base = MT7620_DRAM_BASE;
++
++ pmu0 = __raw_readl(sysc + PMU0_CFG);
++ pmu1 = __raw_readl(sysc + PMU1_CFG);
++
++ pr_info("Analog PMU set to %s control\n",
++ (pmu0 & PMU_SW_SET) ? ("sw") : ("hw"));
++ pr_info("Digital PMU set to %s control\n",
++ (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw"));
+ }
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch b/target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch
new file mode 100644
index 0000000..893a408
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0050-MIPS-ralink-adds-a-bootrom-dumper-module.patch
@@ -0,0 +1,83 @@
+From d0d5dff525d921a7200d4919ea46c51fce27b7fb Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 21 May 2013 15:50:31 +0200
+Subject: [PATCH 50/79] MIPS: ralink: adds a bootrom dumper module
+
+This patch adds a trivial driver that allows userland to extract the bootrom of
+a SoC via debugfs.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Makefile | 2 ++
+ arch/mips/ralink/bootrom.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+)
+ create mode 100644 arch/mips/ralink/bootrom.c
+
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index cae7d88..5fa6129 100644
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -15,4 +15,6 @@ obj-$(CONFIG_SOC_MT7620) += mt7620.o
+
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
++obj-$(CONFIG_DEBUG_FS) += bootrom.o
++
+ obj-y += dts/
+diff --git a/arch/mips/ralink/bootrom.c b/arch/mips/ralink/bootrom.c
+new file mode 100644
+index 0000000..f926f6f
+--- /dev/null
++++ b/arch/mips/ralink/bootrom.c
+@@ -0,0 +1,48 @@
++/*
++ * 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/debugfs.h>
++#include <linux/seq_file.h>
++
++#define BOOTROM_OFFSET 0x10118000
++#define BOOTROM_SIZE 0x8000
++
++static void __iomem *membase = (void __iomem*) KSEG1ADDR(BOOTROM_OFFSET);
++
++static int bootrom_show(struct seq_file *s, void *unused)
++{
++ seq_write(s, membase, BOOTROM_SIZE);
++
++ return 0;
++}
++
++static int bootrom_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, bootrom_show, NULL);
++}
++
++static const struct file_operations bootrom_file_ops = {
++ .open = bootrom_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int bootrom_setup(void)
++{
++ if (!debugfs_create_file("bootrom", 0444,
++ NULL, NULL, &bootrom_file_ops)) {
++ pr_err("Failed to create bootrom debugfs file\n");
++
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++postcore_initcall(bootrom_setup);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch b/target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch
new file mode 100644
index 0000000..161674e
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0051-MIPS-ralink-add-missing-SZ_1M-multiplier.patch
@@ -0,0 +1,29 @@
+From 1996ffa03b1c6e0ab7db35dfd910923f4ab54b26 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 21 May 2013 17:15:54 +0200
+Subject: [PATCH 51/79] MIPS: ralink: add missing SZ_1M multiplier
+
+On RT5350 the memory size is set to Bytes and not MegaBytes due to a missing
+multiplier.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/of.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
+index f916774..b25c1f2 100644
+--- a/arch/mips/ralink/of.c
++++ b/arch/mips/ralink/of.c
+@@ -88,7 +88,7 @@ void __init plat_mem_setup(void)
+ __dt_setup_arch(&__dtb_start);
+
+ if (soc_info.mem_size)
+- add_memory_region(soc_info.mem_base, soc_info.mem_size,
++ add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M,
+ BOOT_MEM_RAM);
+ else
+ detect_memory_region(soc_info.mem_base,
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch
new file mode 100644
index 0000000..0a6ecc4
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0052-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch
@@ -0,0 +1,78 @@
+From b9afea3f5cf6c2da3b88f2902c4377e9c5b22a6d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 May 2013 00:04:58 +0200
+Subject: [PATCH 52/79] MIPS: use set_mode() to enable/disable the cevt-r4k
+ irq
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/kernel/cevt-r4k.c | 39 ++++++++++++++++++++++++++-------------
+ 1 file changed, 26 insertions(+), 13 deletions(-)
+
+diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
+index 7532392..afc08e4 100644
+--- a/arch/mips/kernel/cevt-r4k.c
++++ b/arch/mips/kernel/cevt-r4k.c
+@@ -39,12 +39,6 @@ static int mips_next_event(unsigned long delta,
+
+ #endif /* CONFIG_MIPS_MT_SMTC */
+
+-void mips_set_clock_mode(enum clock_event_mode mode,
+- struct clock_event_device *evt)
+-{
+- /* Nothing to do ... */
+-}
+-
+ DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
+ int cp0_timer_irq_installed;
+
+@@ -89,6 +83,32 @@ struct irqaction c0_compare_irqaction = {
+ .name = "timer",
+ };
+
++void mips_set_clock_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ switch (mode) {
++ case CLOCK_EVT_MODE_ONESHOT:
++ if (cp0_timer_irq_installed)
++ break;
++
++ cp0_timer_irq_installed = 1;
++
++ setup_irq(evt->irq, &c0_compare_irqaction);
++ break;
++
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ if (!cp0_timer_irq_installed)
++ break;
++
++ cp0_timer_irq_installed = 0;
++ free_irq(evt->irq, &c0_compare_irqaction);
++ break;
++
++ default:
++ pr_err("Unhandeled mips clock_mode\n");
++ break;
++ }
++}
+
+ void mips_event_handler(struct clock_event_device *dev)
+ {
+@@ -208,13 +228,6 @@ int __cpuinit r4k_clockevent_init(void)
+
+ clockevents_register_device(cd);
+
+- if (cp0_timer_irq_installed)
+- return 0;
+-
+- cp0_timer_irq_installed = 1;
+-
+- setup_irq(irq, &c0_compare_irqaction);
+-
+ return 0;
+ }
+
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch b/target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch
new file mode 100644
index 0000000..ef2fdb9
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0053-MIPS-ralink-add-illegal-access-driver.patch
@@ -0,0 +1,121 @@
+From 69a5834d0a90588578df9689530fc8f3ab8ef59a Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 16 May 2013 23:28:23 +0200
+Subject: [PATCH 53/79] MIPS: ralink: add illegal access driver
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Makefile | 2 +-
+ arch/mips/ralink/ill_acc.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 88 insertions(+), 1 deletion(-)
+ create mode 100644 arch/mips/ralink/ill_acc.c
+
+diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
+index 5fa6129..55a5bfc 100644
+--- 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 ill_acc.o
+
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+diff --git a/arch/mips/ralink/ill_acc.c b/arch/mips/ralink/ill_acc.c
+new file mode 100644
+index 0000000..4a3f696
+--- /dev/null
++++ b/arch/mips/ralink/ill_acc.c
+@@ -0,0 +1,87 @@
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/interrupt.h>
++#include <linux/of_platform.h>
++#include <linux/of_irq.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define REG_ILL_ACC_ADDR 0x10
++#define REG_ILL_ACC_TYPE 0x14
++
++#define ILL_INT_STATUS BIT(31)
++#define ILL_ACC_WRITE BIT(30)
++#define ILL_ACC_LEN_M 0xff
++#define ILL_ACC_OFF_M 0xf
++#define ILL_ACC_OFF_S 16
++#define ILL_ACC_ID_M 0x7
++#define ILL_ACC_ID_S 8
++
++#define DRV_NAME "ill_acc"
++
++static const char *ill_acc_ids[] = {
++ "cpu", "dma", "ppe", "pdma rx","pdma tx", "pci/e", "wmac", "usb",
++};
++
++static irqreturn_t ill_acc_irq_handler(int irq, void *_priv)
++{
++ struct device *dev = (struct device *) _priv;
++ u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR);
++ u32 type = rt_memc_r32(REG_ILL_ACC_TYPE);
++
++ dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n",
++ (type & ILL_ACC_WRITE) ? ("write") : ("read"),
++ ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M],
++ addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
++ type & ILL_ACC_LEN_M);
++
++ rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE);
++
++ return IRQ_HANDLED;
++}
++
++static int __init ill_acc_of_setup(void)
++{
++ struct platform_device *pdev;
++ struct device_node *np;
++ int irq;
++
++ /* somehow this driver breaks on RT5350 */
++ if (of_machine_is_compatible("ralink,rt5350-soc"))
++ return -EINVAL;
++
++ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc");
++ if (!np)
++ return -EINVAL;
++
++ pdev = of_find_device_by_node(np);
++ if (!pdev) {
++ pr_err("%s: failed to lookup pdev\n", np->name);
++ return -EINVAL;
++ }
++
++ irq = irq_of_parse_and_map(np, 0);
++ if (!irq) {
++ dev_err(&pdev->dev, "failed to get irq\n");
++ return -EINVAL;
++ }
++
++ if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) {
++ dev_err(&pdev->dev, "failed to request irq\n");
++ return -EINVAL;
++ }
++
++ rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
++
++ dev_info(&pdev->dev, "irq registered\n");
++
++ return 0;
++}
++
++arch_initcall(ill_acc_of_setup);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch b/target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch
new file mode 100644
index 0000000..1a550ab
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0054-MIPS-ralink-workaround-DTB-memory-issue.patch
@@ -0,0 +1,29 @@
+From 9b6da5fa57a40647f6d69ee1fcdabc5e5f7010dc Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 23 May 2013 18:50:56 +0200
+Subject: [PATCH 54/79] MIPS: ralink: workaround DTB memory issue
+
+If the DTB is too big a bug happens on boot when init ram is freed.
+This is a temporary fix until the real cause is found.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/of.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
+index b25c1f2..8efb02b 100644
+--- a/arch/mips/ralink/of.c
++++ b/arch/mips/ralink/of.c
+@@ -74,7 +74,7 @@ void __init device_tree_init(void)
+ unflatten_device_tree();
+
+ /* free the space reserved for the dt blob */
+- free_bootmem(base, size);
++ //free_bootmem(base, size);
+ }
+
+ void __init plat_mem_setup(void)
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch b/target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch
new file mode 100644
index 0000000..b6d91eb
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0055-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch
@@ -0,0 +1,25 @@
+From 148d428995c21cc95350937d42ffd3b13e36daa5 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 23 May 2013 18:46:25 +0200
+Subject: [PATCH 55/79] MIPS: ralink: add spi clock definition to mt7620a
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/mt7620.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+index 69729a5..08c96db6 100644
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -183,6 +183,7 @@ void __init ralink_clk_init(void)
+ ralink_clk_add("cpu", cpu_rate);
+ ralink_clk_add("10000100.timer", 40000000);
+ ralink_clk_add("10000500.uart", 40000000);
++ ralink_clk_add("10000b00.spi", 40000000);
+ ralink_clk_add("10000c00.uartlite", 40000000);
+ }
+
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch b/target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch
new file mode 100644
index 0000000..7081622
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0056-MIPS-ralink-DTS-file-updates.patch
@@ -0,0 +1,1006 @@
+From 4f3d8fafc176d5d95957a4267c253d0c6ea5182d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 30 Apr 2013 17:27:46 +0200
+Subject: [PATCH 56/79] MIPS: ralink DTS file updates
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Kconfig | 8 +
+ arch/mips/ralink/dts/Makefile | 2 +
+ arch/mips/ralink/dts/mt7620a.dtsi | 238 ++++++++++++++++++++++++-
+ arch/mips/ralink/dts/mt7620a_eval.dts | 111 ++++++++++++
+ arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts | 99 ++++++++++
+ arch/mips/ralink/dts/rt2880.dtsi | 17 ++
+ arch/mips/ralink/dts/rt2880_eval.dts | 6 +
+ arch/mips/ralink/dts/rt3050.dtsi | 31 +++-
+ arch/mips/ralink/dts/rt3052_eval.dts | 19 +-
+ arch/mips/ralink/dts/rt5350.dtsi | 227 +++++++++++++++++++++++
+ arch/mips/ralink/dts/rt5350_eval.dts | 69 +++++++
+ 11 files changed, 824 insertions(+), 3 deletions(-)
+ create mode 100644 arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts
+ create mode 100644 arch/mips/ralink/dts/rt5350.dtsi
+ create mode 100644 arch/mips/ralink/dts/rt5350_eval.dts
+
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 026e823..38540a4 100644
+--- 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_RT5350_EVAL
++ bool "RT5350 eval kit"
++ depends on SOC_RT305X
++
+ config DTB_RT3883_EVAL
+ bool "RT3883 eval kit"
+ depends on SOC_RT3883
+@@ -50,6 +54,10 @@ choice
+ bool "MT7620A eval kit"
+ depends on SOC_MT7620
+
++ config DTB_MT7620A_MT7610E_EVAL
++ bool "MT7620A + MT7610E eval kit"
++ depends on SOC_MT7620
++
+ endchoice
+
+ endif
+diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile
+index 18194fa..0bd12b5 100644
+--- a/arch/mips/ralink/dts/Makefile
++++ b/arch/mips/ralink/dts/Makefile
+@@ -1,4 +1,6 @@
+ obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o
+ obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
++obj-$(CONFIG_DTB_RT5350_EVAL) := rt5350_eval.dtb.o
+ obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o
+ obj-$(CONFIG_DTB_MT7620A_EVAL) := mt7620a_eval.dtb.o
++obj-$(CONFIG_DTB_MT7620A_MT7610E_EVAL) := mt7620a_mt7610e_eval.dtb.o
+diff --git a/arch/mips/ralink/dts/mt7620a.dtsi b/arch/mips/ralink/dts/mt7620a.dtsi
+index 08bf24f..104abfb 100644
+--- a/arch/mips/ralink/dts/mt7620a.dtsi
++++ b/arch/mips/ralink/dts/mt7620a.dtsi
+@@ -25,14 +25,36 @@
+ #size-cells = <1>;
+
+ sysc@0 {
+- compatible = "ralink,mt7620a-sysc";
++ compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc";
+ reg = <0x0 0x100>;
+ };
+
++ timer@100 {
++ compatible = "ralink,mt7620a-timer", "ralink,rt2880-timer";
++ reg = <0x100 0x20>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <1>;
++ };
++
++ watchdog@120 {
++ compatible = "ralink,mt7620a-wdt", "ralink,rt2880-wdt";
++ reg = <0x120 0x10>;
++
++ resets = <&rstctrl 8>;
++ reset-names = "wdt";
++
++ interrupt-parent = <&intc>;
++ interrupts = <1>;
++ };
++
+ intc: intc@200 {
+ compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc";
+ reg = <0x200 0x100>;
+
++ resets = <&rstctrl 19>;
++ reset-names = "intc";
++
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+@@ -43,16 +65,230 @@
+ memc@300 {
+ compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc";
+ reg = <0x300 0x100>;
++
++ resets = <&rstctrl 20>;
++ reset-names = "mc";
++
++ interrupt-parent = <&intc>;
++ interrupts = <3>;
++ };
++
++ uart@500 {
++ compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
++ reg = <0x500 0x100>;
++
++ resets = <&rstctrl 12>;
++ reset-names = "uart";
++
++ interrupt-parent = <&intc>;
++ interrupts = <5>;
++
++ reg-shift = <2>;
++
++ status = "disabled";
++ };
++
++ gpio0: gpio@600 {
++ compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
++ reg = <0x600 0x34>;
++
++ resets = <&rstctrl 13>;
++ reset-names = "pio";
++
++ interrupt-parent = <&intc>;
++ interrupts = <6>;
++
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ ralink,gpio-base = <0>;
++ ralink,num-gpios = <24>;
++ ralink,register-map = [ 00 04 08 0c
++ 20 24 28 2c
++ 30 34 ];
++
++ status = "disabled";
++ };
++
++ gpio1: gpio@638 {
++ compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
++ reg = <0x638 0x24>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <6>;
++
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ ralink,gpio-base = <24>;
++ ralink,num-gpios = <16>;
++ ralink,register-map = [ 00 04 08 0c
++ 10 14 18 1c
++ 20 24 ];
++
++ status = "disabled";
++ };
++
++ gpio2: gpio@660 {
++ compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio";
++ reg = <0x660 0x24>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <6>;
++
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ ralink,gpio-base = <40>;
++ ralink,num-gpios = <32>;
++ ralink,register-map = [ 00 04 08 0c
++ 10 14 18 1c
++ 20 24 ];
++
++ status = "disabled";
++ };
++
++ i2c@900 {
++ compatible = "link,mt7620a-i2c", "ralink,rt2880-i2c";
++ reg = <0x900 0x100>;
++
++ resets = <&rstctrl 16>;
++ reset-names = "i2c";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "disabled";
++ };
++
++ spi@b00 {
++ compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi";
++ reg = <0xb00 0x100>;
++
++ resets = <&rstctrl 18>;
++ reset-names = "spi";
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ status = "disabled";
+ };
+
+ uartlite@c00 {
+ compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a";
+ reg = <0xc00 0x100>;
+
++ resets = <&rstctrl 19>;
++ reset-names = "uartl";
++
+ interrupt-parent = <&intc>;
+ interrupts = <12>;
+
+ reg-shift = <2>;
+ };
++
++ systick@d00 {
++ compatible = "ralink,mt7620a-systick", "ralink,cevt-systick";
++ reg = <0xd00 0x10>;
++
++ resets = <&rstctrl 28>;
++ reset-names = "intc";
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <7>;
++ };
++
++ gdma@2800 {
++ compatible = "ralink,mt7620a-gdma", "ralink,rt2880-gdma";
++ reg = <0x2800 0x800>;
++
++ resets = <&rstctrl 14>;
++ reset-names = "dma";
++
++ interrupt-parent = <&intc>;
++ interrupts = <7>;
++ };
++ };
++
++ rstctrl: rstctrl {
++ compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset";
++ #reset-cells = <1>;
++ };
++
++ ubsphy {
++ compatible = "ralink,mt7620a-usbphy";
++
++ resets = <&rstctrl 22 &rstctrl 25>;
++ reset-names = "host", "device";
++ };
++
++ ethernet@10100000 {
++ compatible = "ralink,mt7620a-eth";
++ reg = <0x10100000 10000>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <5>;
++
++ status = "disabled";
++
++ mdio-bus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "disabled";
++ };
++ };
++
++ gsw@10110000 {
++ compatible = "ralink,mt7620a-gsw";
++ reg = <0x10110000 8000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <17>;
++
++ status = "disabled";
++ };
++
++ sdhci@10130000 {
++ compatible = "ralink,mt7620a-sdhci";
++ reg = <0x10130000 4000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <14>;
++
++ status = "disabled";
++ };
++
++ ehci@101c0000 {
++ compatible = "ralink,rt3xxx-ehci";
++ reg = <0x101c0000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <18>;
++ };
++
++ ohci@101c1000 {
++ compatible = "ralink,rt3xxx-ohci";
++ reg = <0x101c1000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <18>;
++ };
++
++ pcie@10140000 {
++ compatible = "ralink,mt7620a-pci";
++ reg = <0x10140000 0x100
++ 0x10142000 0x100>;
++
++ resets = <&rstctrl 26>;
++ reset-names = "pcie0";
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <4>;
++
++ status = "disabled";
+ };
+ };
+diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts
+index 35eb874..b56f449 100644
+--- a/arch/mips/ralink/dts/mt7620a_eval.dts
++++ b/arch/mips/ralink/dts/mt7620a_eval.dts
+@@ -13,4 +13,115 @@
+ chosen {
+ bootargs = "console=ttyS0,57600";
+ };
++
++ palmbus@10000000 {
++ sysc@0 {
++ ralink,pinmux = "spi", "uartlite", "mdio", "wled", "ephy", "rgmii1", "rgmii2";
++ ralink,gpiomux = "i2c", "jtag";
++ ralink,uartmux = "gpio";
++ ralink,wdtmux = <1>;
++ };
++
++ gpio0: gpio@600 {
++ status = "okay";
++ };
++
++ spi@b00 {
++ status = "okay";
++
++ m25p80@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "en25q64";
++ reg = <0 0>;
++ linux,modalias = "m25p80", "en25q64";
++ spi-max-frequency = <10000000>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-boot-env";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ factory: partition@40000 {
++ label = "factory";
++ reg = <0x40000 0x10000>;
++ read-only;
++ };
++
++ partition@50000 {
++ label = "firmware";
++ reg = <0x50000 0x7b0000>;
++ };
++ };
++ };
++ };
++
++ ethernet@10100000 {
++ status = "okay";
++
++ port@4 {
++ compatible = "lantiq,mt7620a-gsw-port", "ralink,eth-port";
++ reg = <4>;
++ phy-mode = "rgmii";
++ phy-handle = <&phy4>;
++ };
++
++ port@5 {
++ compatible = "lantiq,mt7620a-gsw-port", "ralink,eth-port";
++ reg = <5>;
++ phy-mode = "rgmii";
++ phy-handle = <&phy5>;
++ };
++
++ mdio-bus {
++ status = "okay";
++
++ phy4: ethernet-phy@4 {
++ reg = <4>;
++ phy-mode = "rgmii";
++ };
++
++ phy5: ethernet-phy@5 {
++ reg = <5>;
++ phy-mode = "rgmii";
++ };
++ };
++ };
++
++ gsw@10110000 {
++ status = "okay";
++ ralink,port4 = "gmac";
++ };
++
++ sdhci@10130000 {
++ status = "okay";
++ };
++
++ pcie@10140000 {
++ status = "okay";
++ };
++
++ gpio-keys-polled {
++ compatible = "gpio-keys";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ poll-interval = <20>;
++ s2 {
++ label = "S2";
++ gpios = <&gpio0 1 1>;
++ linux,code = <0x100>;
++ };
++ s3 {
++ label = "S3";
++ gpios = <&gpio0 2 1>;
++ linux,code = <0x101>;
++ };
++ };
+ };
+diff --git a/arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts b/arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts
+new file mode 100644
+index 0000000..0d7755b
+--- /dev/null
++++ b/arch/mips/ralink/dts/mt7620a_mt7610e_eval.dts
+@@ -0,0 +1,99 @@
++/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";
++ };
++
++ palmbus@10000000 {
++ sysc@0 {
++ ralink,pinmux = "spi", "uartlite", "mdio", "wled", "ephy", "rgmii1", "rgmii2";
++ ralink,gpiomux = "i2c", "jtag";
++ ralink,uartmux = "gpio";
++ ralink,wdtmux = <1>;
++ };
++
++ gpio0: gpio@600 {
++ status = "okay";
++ };
++
++ spi@b00 {
++ status = "okay";
++
++ m25p80@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "en25q64";
++ reg = <0 0>;
++ linux,modalias = "m25p80", "en25q64";
++ spi-max-frequency = <10000000>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-boot-env";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ factory: partition@40000 {
++ label = "factory";
++ reg = <0x40000 0x10000>;
++ read-only;
++ };
++
++ partition@50000 {
++ label = "firmware";
++ reg = <0x50000 0x7b0000>;
++ };
++ };
++ };
++ };
++
++ ethernet@10100000 {
++ status = "okay";
++ };
++
++ gsw@10110000 {
++ status = "okay";
++ ralink,port4 = "ephy";
++ };
++
++ sdhci@10130000 {
++ status = "okay";
++ };
++
++ pcie@10140000 {
++ status = "okay";
++ };
++
++ gpio-keys-polled {
++ compatible = "gpio-keys";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ poll-interval = <20>;
++ wps {
++ label = "wps";
++ gpios = <&gpio0 12 1>;
++ linux,code = <0x100>;
++ };
++ reset {
++ label = "reset";
++ gpios = <&gpio0 13 1>;
++ linux,code = <0x101>;
++ };
++ };
++};
+diff --git a/arch/mips/ralink/dts/rt2880.dtsi b/arch/mips/ralink/dts/rt2880.dtsi
+index 182afde..2a34b8d 100644
+--- a/arch/mips/ralink/dts/rt2880.dtsi
++++ b/arch/mips/ralink/dts/rt2880.dtsi
+@@ -55,4 +55,21 @@
+ reg-shift = <2>;
+ };
+ };
++
++ ethernet@400000 {
++ compatible = "ralink,rt2880-eth";
++ reg = <0x00400000 10000>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <5>;
++
++ status = "disabled";
++
++ mdio-bus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "disabled";
++ };
++ };
+ };
+diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts
+index 322d700..58a1edf 100644
+--- a/arch/mips/ralink/dts/rt2880_eval.dts
++++ b/arch/mips/ralink/dts/rt2880_eval.dts
+@@ -43,4 +43,10 @@
+ reg = <0x50000 0x3b0000>;
+ };
+ };
++
++ ethernet@400000 {
++ status = "okay";
++
++ ralink,fixed-link = <1000 1 1 1>;
++ };
+ };
+diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi
+index ef7da1e..b1ac940 100644
+--- 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", "ralink,rt3350-soc";
++ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc";
+
+ cpus {
+ cpu@0 {
+@@ -45,6 +45,15 @@
+ reg = <0x300 0x100>;
+ };
+
++ i2c@900 {
++ compatible = "link,rt3052-i2c", "ralink,rt2880-i2c";
++ reg = <0x900 0x100>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "disabled";
++ };
++
+ uartlite@c00 {
+ compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a";
+ reg = <0xc00 0x100>;
+@@ -55,4 +64,24 @@
+ 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";
++ };
+ };
+diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
+index df17f5f..df02957 100644
+--- a/arch/mips/ralink/dts/rt3052_eval.dts
++++ b/arch/mips/ralink/dts/rt3052_eval.dts
+@@ -3,7 +3,7 @@
+ /include/ "rt3050.dtsi"
+
+ / {
+- compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc";
++ compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc", "ralink,rt5350-soc";
+ model = "Ralink RT3052 evaluation board";
+
+ memory@0 {
+@@ -14,6 +14,14 @@
+ bootargs = "console=ttyS0,57600";
+ };
+
++ palmbus@10000000 {
++ sysc@0 {
++ ralink,pinmux = "i2c", "spi", "uartlite", "jtag", "mdio", "sdram", "rgmii";
++ ralink,uartmux = "gpio";
++ ralink,wdtmux = <1>;
++ };
++ };
++
+ cfi@1f000000 {
+ compatible = "cfi-flash";
+ reg = <0x1f000000 0x800000>;
+@@ -43,4 +51,13 @@
+ reg = <0x50000 0x7b0000>;
+ };
+ };
++
++ ethernet@10100000 {
++ status = "okay";
++ };
++
++ esw@10110000 {
++ status = "okay";
++ ralink,portmap = <0x2f>;
++ };
+ };
+diff --git a/arch/mips/ralink/dts/rt5350.dtsi b/arch/mips/ralink/dts/rt5350.dtsi
+new file mode 100644
+index 0000000..3d6b3bc
+--- /dev/null
++++ b/arch/mips/ralink/dts/rt5350.dtsi
+@@ -0,0 +1,227 @@
++/ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "ralink,rt5350-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,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>;
++ };
++
++ watchdog@120 {
++ compatible = "ralink,rt5350-wdt", "ralink,rt2880-wdt";
++ reg = <0x120 0x10>;
++
++ resets = <&rstctrl 8>;
++ reset-names = "wdt";
++
++ interrupt-parent = <&intc>;
++ interrupts = <1>;
++ };
++
++ intc: intc@200 {
++ compatible = "ralink,rt5350-intc", "ralink,rt2880-intc";
++ reg = <0x200 0x100>;
++
++ resets = <&rstctrl 19>;
++ reset-names = "intc";
++
++ interrupt-controller;
++ #interrupt-cells = <1>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <2>;
++ };
++
++ memc@300 {
++ compatible = "ralink,rt5350-memc", "ralink,rt3050-memc";
++ reg = <0x300 0x100>;
++
++ resets = <&rstctrl 20>;
++ reset-names = "mc";
++
++ interrupt-parent = <&intc>;
++ interrupts = <3>;
++ };
++
++ uart@500 {
++ compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a";
++ reg = <0x500 0x100>;
++
++ resets = <&rstctrl 12>;
++ reset-names = "uart";
++
++ interrupt-parent = <&intc>;
++ interrupts = <5>;
++
++ reg-shift = <2>;
++
++ status = "disabled";
++ };
++
++ gpio0: gpio@600 {
++ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio";
++ reg = <0x600 0x34>;
++
++ resets = <&rstctrl 13>;
++ reset-names = "pio";
++
++ interrupt-parent = <&intc>;
++ interrupts = <6>;
++
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ ralink,gpio-base = <0>;
++ 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>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <6>;
++
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ ralink,gpio-base = <24>;
++ ralink,num-gpios = <16>;
++ ralink,register-map = [ 00 04 08 0c
++ 10 14 18 1c
++ 20 24 ];
++
++ status = "disabled";
++ };
++
++ i2c@900 {
++ compatible = "link,rt5350-i2c", "ralink,rt2880-i2c";
++ reg = <0x900 0x100>;
++
++ resets = <&rstctrl 16>;
++ reset-names = "i2c";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "disabled";
++ };
++
++ spi@b00 {
++ compatible = "ralink,rt5350-spi", "ralink,rt2880-spi";
++ reg = <0xb00 0x100>;
++
++ resets = <&rstctrl 18>;
++ reset-names = "spi";
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ status = "disabled";
++ };
++
++ uartlite@c00 {
++ compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a";
++ reg = <0xc00 0x100>;
++
++ resets = <&rstctrl 19>;
++ reset-names = "uartl";
++
++ interrupt-parent = <&intc>;
++ interrupts = <12>;
++
++ reg-shift = <2>;
++ };
++
++ systick@d00 {
++ compatible = "ralink,rt5350-systick", "ralink,cevt-systick";
++ reg = <0xd00 0x10>;
++
++ interrupt-parent = <&cpuintc>;
++ interrupts = <7>;
++ };
++ };
++
++ rstctrl: rstctrl {
++ compatible = "ralink,rt5350-reset", "ralink,rt2880-reset";
++ #reset-cells = <1>;
++ };
++
++ ubsphy {
++ compatible = "ralink,rt3xxx-usbphy";
++
++ resets = <&rstctrl 22 &rstctrl 25>;
++ reset-names = "host", "device";
++ };
++
++ ethernet@10100000 {
++ compatible = "ralink,rt5350-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";
++ };
++
++ ehci@101c0000 {
++ compatible = "ralink,rt3xxx-ehci";
++ reg = <0x101c0000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <18>;
++ };
++
++ ohci@101c1000 {
++ compatible = "ralink,rt3xxx-ohci";
++ reg = <0x101c1000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <18>;
++ };
++};
+diff --git a/arch/mips/ralink/dts/rt5350_eval.dts b/arch/mips/ralink/dts/rt5350_eval.dts
+new file mode 100644
+index 0000000..ab92043
+--- /dev/null
++++ b/arch/mips/ralink/dts/rt5350_eval.dts
+@@ -0,0 +1,69 @@
++/dts-v1/;
++
++/include/ "rt5350.dtsi"
++
++/ {
++ compatible = "ralink,rt5350-eval-board", "ralink,rt5350-soc";
++ model = "Ralink RT5350 evaluation board";
++
++ chosen {
++ bootargs = "console=ttyS0,57600";
++ };
++
++ palmbus@10000000 {
++ sysc@0 {
++ ralink,pinmux = "i2c", "spi", "uartlite", "jtag", "mdio", "sdram", "rgmii";
++ ralink,uartmux = "gpio";
++ ralink,wdtmux = <1>;
++ };
++
++ gpio0: gpio@600 {
++ status = "okay";
++ };
++
++ spi@b00 {
++ status = "okay";
++
++ m25p80@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "en25q64";
++ reg = <0 0>;
++ linux,modalias = "m25p80", "mx25l3205d";
++ spi-max-frequency = <10000000>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-boot-env";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ factory: partition@40000 {
++ label = "factory";
++ reg = <0x40000 0x10000>;
++ read-only;
++ };
++
++ partition@50000 {
++ label = "firmware";
++ reg = <0x50000 0x3b0000>;
++ };
++ };
++ };
++ };
++
++ ethernet@10100000 {
++ status = "okay";
++ };
++
++ esw@10110000 {
++ status = "okay";
++ ralink,portmap = <0x2f>;
++ };
++};
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0130-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch b/target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch
index cdff431..3149ac2 100644
--- a/target/linux/ramips/patches-3.8/0130-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch
+++ b/target/linux/ramips/patches-3.8/0057-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch
@@ -1,7 +1,7 @@
-From 007ab7fe49bfcaa220372260eedeb4eed51f1631 Mon Sep 17 00:00:00 2001
+From de5e1cd11d62d2e1a00210b757dad35e1372963b 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
+Subject: [PATCH 57/79] 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.
@@ -9,14 +9,16 @@ 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 ++++
+ 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(+)
+ drivers/gpio/gpio-ralink.c | 326 ++++++++++++++++++++++++++++++
+ 5 files changed, 358 insertions(+)
create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h
create mode 100644 drivers/gpio/gpio-ralink.c
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index b5fd476..2498972 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -449,6 +449,7 @@ config RALINK
@@ -27,6 +29,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
config SGI_IP22
bool "SGI IP22 (Indy/Indigo2)"
+diff --git a/arch/mips/include/asm/mach-ralink/gpio.h b/arch/mips/include/asm/mach-ralink/gpio.h
+new file mode 100644
+index 0000000..f68ee16
--- /dev/null
+++ b/arch/mips/include/asm/mach-ralink/gpio.h
@@ -0,0 +1,24 @@
@@ -54,6 +59,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+#define gpio_to_irq __gpio_to_irq
+
+#endif /* __ASM_MACH_RALINK_GPIO_H */
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 682de75..2e6e81c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -201,6 +201,12 @@ config GPIO_PXA
@@ -69,9 +76,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
config GPIO_SPEAR_SPICS
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
depends on PLAT_SPEAR
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index c5aebd0..a00adfc 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf85
+@@ -54,6 +54,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
@@ -79,9 +88,12 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
+diff --git a/drivers/gpio/gpio-ralink.c b/drivers/gpio/gpio-ralink.c
+new file mode 100644
+index 0000000..12984f1
--- /dev/null
+++ b/drivers/gpio/gpio-ralink.c
-@@ -0,0 +1,182 @@
+@@ -0,0 +1,326 @@
+/*
+ * 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
@@ -96,6 +108,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
++#include <linux/of_irq.h>
++#include <linux/irqdomain.h>
++#include <linux/interrupt.h>
+
+enum ralink_gpio_reg {
+ GPIO_REG_INT = 0,
@@ -117,13 +132,24 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+ spinlock_t lock;
+ void __iomem *membase;
++ struct irq_domain *domain;
++ int irq;
++
++ u32 rising;
++ u32 falling;
+};
+
++#define MAP_MAX 4
++static struct irq_domain *irq_map[MAP_MAX];
++static int irq_map_count;
++static atomic_t irq_refcount = ATOMIC_INIT(0);
++
+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;
+}
+
@@ -183,32 +209,158 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ return 0;
+}
+
++static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
++{
++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++
++ if (rg->irq < 1)
++ return -1;
++
++ ralink_gpio_direction_input(chip, pin);
++
++ return irq_create_mapping(rg->domain, pin);
++}
++
++static void ralink_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
++{
++ int i;
++
++ for (i = 0; i < irq_map_count; i++) {
++ struct irq_domain *domain = irq_map[i];
++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) domain->host_data;
++ unsigned long pending = rt_gpio_r32(rg, GPIO_REG_INT);
++ int bit;
++
++ for_each_set_bit(bit, &pending, rg->chip.ngpio) {
++ u32 map = irq_find_mapping(domain, bit);
++ generic_handle_irq(map);
++ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit));
++ }
++ }
++}
++
++static void ralink_gpio_irq_unmask(struct irq_data *d)
++{
++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) d->domain->host_data;
++ u32 val = rt_gpio_r32(rg, GPIO_REG_RENA);
++ unsigned long flags;
++
++ spin_lock_irqsave(&rg->lock, flags);
++ rt_gpio_w32(rg, GPIO_REG_RENA, val | (BIT(d->hwirq) & rg->rising));
++ rt_gpio_w32(rg, GPIO_REG_FENA, val | (BIT(d->hwirq) & rg->falling));
++ spin_unlock_irqrestore(&rg->lock, flags);
++}
++
++static void ralink_gpio_irq_mask(struct irq_data *d)
++{
++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) d->domain->host_data;
++ u32 val = rt_gpio_r32(rg, GPIO_REG_RENA);
++ unsigned long flags;
++
++ spin_lock_irqsave(&rg->lock, flags);
++ rt_gpio_w32(rg, GPIO_REG_FENA, val & ~BIT(d->hwirq));
++ rt_gpio_w32(rg, GPIO_REG_RENA, val & ~BIT(d->hwirq));
++ spin_unlock_irqrestore(&rg->lock, flags);
++}
++
++static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type)
++{
++ struct ralink_gpio_chip *rg = (struct ralink_gpio_chip *) d->domain->host_data;
++ u32 mask = BIT(d->hwirq);
++
++ if (type == IRQ_TYPE_PROBE) {
++ if ((rg->rising | rg->falling) & mask)
++ return 0;
++
++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_RISING;
++ }
++
++ if (type & IRQ_TYPE_EDGE_RISING)
++ rg->rising |= mask;
++ else
++ rg->rising &= mask;
++
++ if (type & IRQ_TYPE_EDGE_RISING)
++ rg->falling |= mask;
++ else
++ rg->falling &= mask;
++
++ return 0;
++}
++
++static struct irq_chip ralink_gpio_irq_chip = {
++ .name = "GPIO",
++ .irq_unmask = ralink_gpio_irq_unmask,
++ .irq_mask = ralink_gpio_irq_mask,
++ .irq_mask_ack = ralink_gpio_irq_mask,
++ .irq_set_type = ralink_gpio_irq_type,
++};
++
++static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
++{
++ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq);
++ irq_set_handler_data(irq, d);
++
++ return 0;
++}
++
++static const struct irq_domain_ops irq_domain_ops = {
++ .xlate = irq_domain_xlate_onecell,
++ .map = gpio_map,
++};
++
++static void ralink_gpio_irq_init(struct device_node *np, struct ralink_gpio_chip *rg)
++{
++ if (irq_map_count >= MAP_MAX)
++ return;
++
++ rg->irq = irq_of_parse_and_map(np, 0);
++ if (!rg->irq)
++ return;
++
++ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, &irq_domain_ops, rg);
++ if (!rg->domain) {
++ dev_err(rg->chip.dev, "irq_domain_add_linear failed\n");
++ return;
++ }
++
++ irq_map[irq_map_count++] = rg->domain;
++
++ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0);
++ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0);
++
++ if (!atomic_read(&irq_refcount))
++ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler);
++ atomic_inc(&irq_refcount);
++
++ dev_info(rg->chip.dev, "registering %d irq handlers\n", rg->chip.ngpio);
++}
++
+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;
-+ const __be32 *gpiobase;
++ struct ralink_gpio_chip *rg;
++ const __be32 *ngpio, *gpiobase;
+
+ 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)
++ rg = devm_kzalloc(&pdev->dev,
++ sizeof(struct ralink_gpio_chip), GFP_KERNEL);
++ if (!rg)
+ return -ENOMEM;
+
-+ gc->membase = devm_request_and_ioremap(&pdev->dev, res);
-+ if (!gc->membase) {
++ rg->membase = devm_request_and_ioremap(&pdev->dev, res);
++ if (!rg->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)) {
++ rg->regs, GPIO_REG_MAX)) {
+ dev_err(&pdev->dev, "failed to read register definition\n");
+ return -EINVAL;
+ }
@@ -221,26 +373,30 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+ gpiobase = of_get_property(np, "ralink,gpio-base", NULL);
+ if (gpiobase)
-+ gc->chip.base = be32_to_cpu(*gpiobase);
++ rg->chip.base = be32_to_cpu(*gpiobase);
+ else
-+ gc->chip.base = -1;
++ rg->chip.base = -1;
+
-+ gc->chip.label = dev_name(&pdev->dev);
-+ gc->chip.of_node = np;
-+ 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;
++ spin_lock_init(&rg->lock);
+
-+ spin_lock_init(&gc->lock);
++ rg->chip.dev = &pdev->dev;
++ rg->chip.label = dev_name(&pdev->dev);
++ rg->chip.of_node = np;
++ rg->chip.ngpio = be32_to_cpu(*ngpio);
++ rg->chip.direction_input = ralink_gpio_direction_input;
++ rg->chip.direction_output = ralink_gpio_direction_output;
++ rg->chip.get = ralink_gpio_get;
++ rg->chip.set = ralink_gpio_set;
++ rg->chip.to_irq = ralink_gpio_to_irq;
+
+ /* set polarity to low for all lines */
-+ rt_gpio_w32(gc, GPIO_REG_POL, 0);
++ rt_gpio_w32(rg, GPIO_REG_POL, 0);
++
++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio);
+
-+ dev_info(&pdev->dev, "registering %d gpios\n", gc->chip.ngpio);
++ ralink_gpio_irq_init(np, rg);
+
-+ return gpiochip_add(&gc->chip);
++ return gpiochip_add(&rg->chip);
+}
+
+static const struct of_device_id ralink_gpio_match[] = {
@@ -264,3 +420,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+}
+
+subsys_initcall(ralink_gpio_init);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch
index 8217b48..f1706f5 100644
--- a/target/linux/ramips/patches-3.8/0131-SPI-ralink-add-Ralink-SoC-spi-driver.patch
+++ b/target/linux/ramips/patches-3.8/0058-SPI-ralink-add-Ralink-SoC-spi-driver.patch
@@ -1,7 +1,7 @@
-From 32c1cff4c75925a0bbd305e85ed4adb30140cd42 Mon Sep 17 00:00:00 2001
+From cfb23fbd5be0276507a8af15be0738a7834555b5 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
+Subject: [PATCH 58/79] SPI: ralink: add Ralink SoC spi driver
Add the driver needed to make SPI work on Ralink SoC.
@@ -9,28 +9,32 @@ 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(+)
+ drivers/spi/spi-ralink.c | 475 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 482 insertions(+)
create mode 100644 drivers/spi/spi-ralink.c
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 2e188e1..76c489a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
-@@ -324,6 +324,12 @@ config SPI_RSPI
+@@ -315,6 +315,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)
++ depends on (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620)
+ 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
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 64e970b..5b73cf8 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
-@@ -51,6 +51,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.
+@@ -50,6 +50,7 @@ obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
@@ -38,9 +42,12 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
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
+diff --git a/drivers/spi/spi-ralink.c b/drivers/spi/spi-ralink.c
+new file mode 100644
+index 0000000..b07cbaa
--- /dev/null
+++ b/drivers/spi/spi-ralink.c
-@@ -0,0 +1,472 @@
+@@ -0,0 +1,475 @@
+/*
+ * spi-ralink.c -- Ralink RT288x/RT305x SPI controller driver
+ *
@@ -61,9 +68,10 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
-+#include <linux/platform_device.h>
+#include <linux/io.h>
++#include <linux/reset.h>
+#include <linux/spi/spi.h>
++#include <linux/platform_device.h>
+
+#define DRIVER_NAME "spi-ralink"
+#define RALINK_NUM_CHIPSELECTS 1 /* only one slave is supported*/
@@ -457,6 +465,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ goto out_disable_clk;
+ }
+
++ device_reset(&pdev->dev);
++
+ ralink_spi_reset(rs);
+
+ status = spi_register_master(master);
@@ -513,3 +523,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+MODULE_AUTHOR("Sergiy <piratfm@gmail.com>");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL");
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch b/target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch
index bff0799..16a82ca 100644
--- a/target/linux/ramips/patches-3.8/0132-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch
+++ b/target/linux/ramips/patches-3.8/0059-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch
@@ -1,7 +1,7 @@
-From 15bcdbd78abacbe0986a1904d2e2b5dcfe780b5b Mon Sep 17 00:00:00 2001
+From 15a3839fa080feec3b4ce6d92b08893bf1eefe56 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
+Subject: [PATCH 59/79] 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.
@@ -11,9 +11,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
drivers/tty/serial/of_serial.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
+diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
+index e7cae1c..026e5d6 100644
--- 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
+@@ -97,7 +97,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
port->regshift = prop;
port->irq = irq_of_parse_and_map(np, 0);
@@ -25,3 +27,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
switch (prop) {
case 1:
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch b/target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch
index 1fce223..c935a5a 100644
--- a/target/linux/ramips/patches-3.8/0133-serial-ralink-adds-mt7620-serial.patch
+++ b/target/linux/ramips/patches-3.8/0060-serial-ralink-adds-mt7620-serial.patch
@@ -1,7 +1,7 @@
-From 6471ee7bbf3f8b70267ba1dc93f067e18803c246 Mon Sep 17 00:00:00 2001
+From d76f99c928f0cd6e6cd3d99c916d890ae9a1e073 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
+Subject: [PATCH 60/79] serial: ralink: adds mt7620 serial
Add the config symbol for Mediatek7620 SoC to SERIAL_8250_RT288X
@@ -10,6 +10,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
drivers/tty/serial/8250/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+index 9e4febd..d1ec3a1 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -280,7 +280,7 @@ config SERIAL_8250_EM
@@ -21,3 +23,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
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
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch b/target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch
new file mode 100644
index 0000000..a2f8f09
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0061-DMA-MIPS-ralink-add-dmaengine-driver.patch
@@ -0,0 +1,341 @@
+From 1db0d19afe5830f7d020c7c5386be8cc20cf0f15 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 23 May 2013 18:45:29 +0200
+Subject: [PATCH 61/79] DMA: MIPS: ralink: add dmaengine driver
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/dma/Kconfig | 7 ++
+ drivers/dma/Makefile | 1 +
+ drivers/dma/ralink_gdma.c | 229 +++++++++++++++++++++++++++++++++++++++++++++
+ drivers/dma/ralink_gdma.h | 55 +++++++++++
+ 4 files changed, 292 insertions(+)
+ create mode 100644 drivers/dma/ralink_gdma.c
+ create mode 100644 drivers/dma/ralink_gdma.h
+
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index d4c1218..323f684 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -320,6 +320,13 @@ config MMP_PDMA
+ help
+ Support the MMP PDMA engine for PXA and MMP platfrom.
+
++config RALINK_GDMA
++ bool "Ralink Generic DMA support"
++ depends on RALINK
++ select DMA_ENGINE
++ help
++ Support the GDMA engine for MIPS based Ralink SoC.
++
+ config DMA_ENGINE
+ bool
+
+diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
+index 7428fea..a981e2c 100644
+--- a/drivers/dma/Makefile
++++ b/drivers/dma/Makefile
+@@ -34,3 +34,4 @@ obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
+ obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
+ obj-$(CONFIG_DMA_OMAP) += omap-dma.o
+ obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
++obj-$(CONFIG_RALINK_GDMA) += ralink_gdma.o
+diff --git a/drivers/dma/ralink_gdma.c b/drivers/dma/ralink_gdma.c
+new file mode 100644
+index 0000000..be7c317
+--- /dev/null
++++ b/drivers/dma/ralink_gdma.c
+@@ -0,0 +1,229 @@
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/of_platform.h>
++#include <linux/memory.h>
++
++#include "ralink_gdma.h"
++
++#define SURFBOARDINT_DMA 10
++#define MEMCPY_DMA_CH 8
++#define to_rt2880_dma_chan(chan) \
++ container_of(chan, struct rt2880_dma_chan, common)
++
++static dma_cookie_t rt2880_dma_tx_submit(struct dma_async_tx_descriptor *tx)
++{
++ dma_cookie_t cookie;
++
++ cookie = tx->chan->cookie;
++
++ return cookie;
++}
++
++#define MIN_RTDMA_PKT_LEN 128
++static struct dma_async_tx_descriptor *
++rt2880_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
++ size_t len, unsigned long flags)
++{
++ struct rt2880_dma_chan *rt_chan = to_rt2880_dma_chan(chan);
++ unsigned long mid_offset;
++
++ spin_lock_bh(&rt_chan->lock);
++
++ if(len < MIN_RTDMA_PKT_LEN) {
++ memcpy(phys_to_virt(dest), phys_to_virt(src), len);
++ } else {
++ mid_offset = len/2;
++
++ /* Lower parts are transferred by GDMA.
++ * Upper parts are transferred by CPU.
++ */
++ RT_DMA_WRITE_REG(RT_DMA_SRC_REG(MEMCPY_DMA_CH), src);
++ RT_DMA_WRITE_REG(RT_DMA_DST_REG(MEMCPY_DMA_CH), dest);
++ RT_DMA_WRITE_REG(RT_DMA_CTRL_REG(MEMCPY_DMA_CH), (mid_offset << 16) | (3 << 3) | (3 << 0));
++
++ memcpy(phys_to_virt(dest)+mid_offset, phys_to_virt(src)+mid_offset, len-mid_offset);
++
++ dma_async_tx_descriptor_init(&rt_chan->txd, chan);
++
++ while((RT_DMA_READ_REG(RT_DMA_DONEINT) & (0x1<<MEMCPY_DMA_CH))==0);
++ RT_DMA_WRITE_REG(RT_DMA_DONEINT, (1<<MEMCPY_DMA_CH));
++ }
++
++ spin_unlock_bh(&rt_chan->lock);
++
++ return &rt_chan->txd;
++}
++
++/**
++ * rt2880_dma_status - poll the status of an XOR transaction
++ * @chan: XOR channel handle
++ * @cookie: XOR transaction identifier
++ * @txstate: XOR transactions state holder (or NULL)
++ */
++static enum dma_status rt2880_dma_status(struct dma_chan *chan,
++ dma_cookie_t cookie,
++ struct dma_tx_state *txstate)
++{
++ return 0;
++}
++
++static irqreturn_t rt2880_dma_interrupt_handler(int irq, void *data)
++{
++
++ printk("%s\n",__FUNCTION__);
++
++ return IRQ_HANDLED;
++}
++
++static void rt2880_dma_issue_pending(struct dma_chan *chan)
++{
++}
++
++static int rt2880_dma_alloc_chan_resources(struct dma_chan *chan)
++{
++// printk("%s\n",__FUNCTION__);
++
++ return 0;
++}
++
++static void rt2880_dma_free_chan_resources(struct dma_chan *chan)
++{
++// printk("%s\n",__FUNCTION__);
++
++}
++
++static int rt2880_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
++{
++ switch (cmd) {
++ case DMA_TERMINATE_ALL:
++ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
++ break;
++ case DMA_SLAVE_CONFIG:
++ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
++ break;
++ default:
++ return -ENXIO;
++ }
++
++ return 0;
++}
++
++static int rt2880_dma_probe(struct platform_device *pdev)
++{
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ __iomem void *membase;
++ struct dma_device *dma_dev;
++ struct rt2880_dma_chan *rt_chan;
++ int err;
++ int ret;
++ int reg;
++ int irq;
++
++ membase = devm_request_and_ioremap(&pdev->dev, res);
++ if (IS_ERR(membase))
++ return PTR_ERR(membase);
++
++ dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev), GFP_KERNEL);
++ if (!dma_dev)
++ return -ENOMEM;
++
++ irq = platform_get_irq(pdev, 0);
++ if (!irq) {
++ dev_err(&pdev->dev, "failed to load irq\n");
++ return -ENOENT;
++ }
++
++
++ INIT_LIST_HEAD(&dma_dev->channels);
++ dma_cap_zero(dma_dev->cap_mask);
++ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
++ dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
++ dma_dev->device_alloc_chan_resources = rt2880_dma_alloc_chan_resources;
++ dma_dev->device_free_chan_resources = rt2880_dma_free_chan_resources;
++ dma_dev->device_tx_status = rt2880_dma_status;
++ dma_dev->device_issue_pending = rt2880_dma_issue_pending;
++ dma_dev->device_prep_dma_memcpy = rt2880_dma_prep_dma_memcpy;
++ dma_dev->device_control = rt2880_dma_control;
++ dma_dev->dev = &pdev->dev;
++
++ rt_chan = devm_kzalloc(&pdev->dev, sizeof(*rt_chan), GFP_KERNEL);
++ if (!rt_chan) {
++ return -ENOMEM;
++ }
++
++ spin_lock_init(&rt_chan->lock);
++ INIT_LIST_HEAD(&rt_chan->chain);
++ INIT_LIST_HEAD(&rt_chan->completed_slots);
++ INIT_LIST_HEAD(&rt_chan->all_slots);
++ rt_chan->common.device = dma_dev;
++ rt_chan->txd.tx_submit = rt2880_dma_tx_submit;
++
++ list_add_tail(&rt_chan->common.device_node, &dma_dev->channels);
++
++ err = dma_async_device_register(dma_dev);
++ if (0 != err) {
++ pr_err("ERR_MDMA:device_register failed: %d\n", err);
++ return 1;
++ }
++
++ ret = request_irq(irq, rt2880_dma_interrupt_handler, 0, dev_name(&pdev->dev), NULL);
++ if(ret){
++ pr_err("IRQ %d is not free.\n", SURFBOARDINT_DMA);
++ return 1;
++ }
++
++ //set GDMA register in advance.
++ reg = (32 << 16) | (32 << 8) | (MEMCPY_DMA_CH << 3);
++ RT_DMA_WRITE_REG(RT_DMA_CTRL_REG1(MEMCPY_DMA_CH), reg);
++
++ dev_info(&pdev->dev, "running\n");
++
++ return 0;
++}
++
++static int rt2880_dma_remove(struct platform_device *dev)
++{
++ struct dma_device *dma_dev = platform_get_drvdata(dev);
++
++ printk("%s\n",__FUNCTION__);
++
++ dma_async_device_unregister(dma_dev);
++
++ return 0;
++}
++
++static const struct of_device_id rt2880_dma_match[] = {
++ { .compatible = "ralink,rt2880-gdma" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt2880_wdt_match);
++
++static struct platform_driver rt2880_dma_driver = {
++ .probe = rt2880_dma_probe,
++ .remove = rt2880_dma_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = RT_DMA_NAME,
++ .of_match_table = rt2880_dma_match,
++ },
++};
++
++static int __init rt2880_dma_init(void)
++{
++ int rc;
++
++ rc = platform_driver_register(&rt2880_dma_driver);
++ return rc;
++}
++module_init(rt2880_dma_init);
++
++MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
++MODULE_DESCRIPTION("DMA engine driver for Ralink DMA engine");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/dma/ralink_gdma.h b/drivers/dma/ralink_gdma.h
+new file mode 100644
+index 0000000..73e1948
+--- /dev/null
++++ b/drivers/dma/ralink_gdma.h
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (C) 2007, 2008, Marvell International Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#ifndef RT_DMA_H
++#define RT_DMA_H
++
++#include <linux/types.h>
++#include <linux/io.h>
++#include <linux/dmaengine.h>
++#include <linux/interrupt.h>
++
++#define RT_DMA_NAME "rt2880_dma"
++
++#define RALINK_GDMA_BASE 0xB0002800
++
++struct rt2880_dma_chan {
++ int pending;
++ dma_cookie_t completed_cookie;
++ spinlock_t lock; /* protects the descriptor slot pool */
++ void __iomem *mmr_base;
++ unsigned int idx;
++ enum dma_transaction_type current_type;
++ struct dma_async_tx_descriptor txd;
++ struct list_head chain;
++ struct list_head completed_slots;
++ struct dma_chan common;
++ struct list_head all_slots;
++ int slots_allocated;
++ struct tasklet_struct irq_tasklet;
++};
++
++#define RT_DMA_READ_REG(addr) le32_to_cpu(*(volatile u32 *)(addr))
++#define RT_DMA_WRITE_REG(addr, val) *((volatile uint32_t *)(addr)) = cpu_to_le32(val)
++
++#define RT_DMA_SRC_REG(ch) (RALINK_GDMA_BASE + ch*16)
++#define RT_DMA_DST_REG(ch) (RT_DMA_SRC_REG(ch) + 4)
++#define RT_DMA_CTRL_REG(ch) (RT_DMA_DST_REG(ch) + 4)
++#define RT_DMA_CTRL_REG1(ch) (RT_DMA_CTRL_REG(ch) + 4)
++#define RT_DMA_DONEINT (RALINK_GDMA_BASE + 0x204)
++
++#endif
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch b/target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch
index 70758f1..108455d 100644
--- a/target/linux/ramips/patches-3.8/0134-PCI-MIPS-adds-rt2880-pci-support.patch
+++ b/target/linux/ramips/patches-3.8/0062-PCI-MIPS-adds-rt2880-pci-support.patch
@@ -1,7 +1,7 @@
-From 55e9ae6a23cb799b7c1d402e1cfda11a6bd1e86e Mon Sep 17 00:00:00 2001
+From ac237657b04e464f28e8fe428d032386ca8b0b31 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
+Subject: [PATCH 62/79] PCI: MIPS: adds rt2880 pci support
Add support for the pci found on the rt2880 SoC.
@@ -13,9 +13,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
3 files changed, 283 insertions(+)
create mode 100644 arch/mips/pci/pci-rt2880.c
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index ce995d3..c7c18ce 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
-@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1
+@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
@@ -23,6 +25,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c
+new file mode 100644
+index 0000000..e2c4730
--- /dev/null
+++ b/arch/mips/pci/pci-rt2880.c
@@ -0,0 +1,281 @@
@@ -307,6 +312,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+}
+
+arch_initcall(pcibios_init);
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 38540a4..2d39329 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -8,6 +8,7 @@ choice
@@ -317,3 +324,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
config SOC_RT305X
bool "RT305x"
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch b/target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch
index 9c4ca82..c1c8f75 100644
--- a/target/linux/ramips/patches-3.8/0135-PCI-MIPS-adds-rt3883-pci-support.patch
+++ b/target/linux/ramips/patches-3.8/0063-PCI-MIPS-adds-rt3883-pci-support.patch
@@ -1,7 +1,7 @@
-From 2a5dccdb00d85a6ad6111d7a2b13f9f4fae35838 Mon Sep 17 00:00:00 2001
+From 5b942b64c01b57cbde0dff2185728d5a8facea76 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
+Subject: [PATCH 63/79] PCI: MIPS: adds rt3883 pci support
Add support for the pcie found on the rt3883 SoC.
@@ -13,9 +13,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
3 files changed, 642 insertions(+)
create mode 100644 arch/mips/pci/pci-rt3883.c
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index c7c18ce..a238158 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
-@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops
+@@ -43,6 +43,7 @@ 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
@@ -23,6 +25,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c
+new file mode 100644
+index 0000000..212c90b
--- /dev/null
+++ b/arch/mips/pci/pci-rt3883.c
@@ -0,0 +1,640 @@
@@ -666,6 +671,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+}
+
+postcore_initcall(rt3883_pci_init);
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index 2d39329..f2f20ec 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -20,6 +20,7 @@ choice
@@ -676,3 +683,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
config SOC_MT7620
bool "MT7620"
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch b/target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch
new file mode 100644
index 0000000..b3b0ad4
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0064-PCI-MIPS-adds-mt7620a-pcie-driver.patch
@@ -0,0 +1,409 @@
+From 44712deb87f994f837796a55f670bf4c0d0d5b51 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 18:48:58 +0200
+Subject: [PATCH 64/79] PCI: MIPS: adds mt7620a pcie driver
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/pci/Makefile | 1 +
+ arch/mips/pci/pci-mt7620a.c | 363 +++++++++++++++++++++++++++++++++++++++++++
+ arch/mips/ralink/Kconfig | 1 +
+ 3 files changed, 365 insertions(+)
+ create mode 100644 arch/mips/pci/pci-mt7620a.c
+
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index a238158..168d477 100644
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -44,6 +44,7 @@ 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_SOC_MT7620) += pci-mt7620a.o
+ obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
+ obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+diff --git a/arch/mips/pci/pci-mt7620a.c b/arch/mips/pci/pci-mt7620a.c
+new file mode 100644
+index 0000000..271763c
+--- /dev/null
++++ b/arch/mips/pci/pci-mt7620a.c
+@@ -0,0 +1,363 @@
++/*
++ * Ralink MT7620A SoC PCI support
++ *
++ * Copyright (C) 2007-2013 Bruce Chang
++ * Copyright (C) 2013 John Crispin <blogic@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/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/reset.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define RALINK_PCI_MM_MAP_BASE 0x20000000
++#define RALINK_PCI_IO_MAP_BASE 0x10160000
++
++#define RALINK_INT_PCIE0 4
++#define RALINK_SYSTEM_CONTROL_BASE 0xb0000000
++#define RALINK_SYSCFG1 0x14
++#define RALINK_CLKCFG1 0x30
++#define RALINK_GPIOMODE 0x60
++#define RALINK_PCIE_CLK_GEN 0x7c
++#define RALINK_PCIE_CLK_GEN1 0x80
++#define PCIEPHY0_CFG 0x90
++#define PPLL_CFG1 0x9c
++#define PPLL_DRV 0xa0
++#define RALINK_PCI_HOST_MODE_EN (1<<7)
++#define RALINK_PCIE_RC_MODE_EN (1<<8)
++#define RALINK_PCIE_RST (1<<23)
++#define RALINK_PCI_RST (1<<24)
++#define RALINK_PCI_CLK_EN (1<<19)
++#define RALINK_PCIE_CLK_EN (1<<21)
++#define PCI_SLOTx2 (1<<11)
++#define PCI_SLOTx1 (2<<11)
++#define PDRV_SW_SET (1<<31)
++#define LC_CKDRVPD_ (1<<19)
++
++#define RALINK_PCI_CONFIG_ADDR 0x20
++#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24
++#define MEMORY_BASE 0x0
++#define RALINK_PCIE0_RST (1<<26)
++#define RALINK_PCI_BASE 0xB0140000
++#define RALINK_PCI_MEMBASE 0x28
++#define RALINK_PCI_IOBASE 0x2C
++
++#define RT6855_PCIE0_OFFSET 0x2000
++
++#define RALINK_PCI_PCICFG_ADDR 0x00
++#define RALINK_PCI0_BAR0SETUP_ADDR 0x10
++#define RALINK_PCI0_IMBASEBAR0_ADDR 0x18
++#define RALINK_PCI0_ID 0x30
++#define RALINK_PCI0_CLASS 0x34
++#define RALINK_PCI0_SUBID 0x38
++#define RALINK_PCI0_STATUS 0x50
++#define RALINK_PCI_PCIMSK_ADDR 0x0C
++
++#define RALINK_PCIE0_CLK_EN (1 << 26)
++
++#define BUSY 0x80000000
++#define WAITRETRY_MAX 10
++#define WRITE_MODE (1UL << 23)
++#define DATA_SHIFT 0
++#define ADDR_SHIFT 8
++
++
++static void __iomem *bridge_base;
++static void __iomem *pcie_base;
++
++static struct reset_control *rstpcie0;
++
++static inline void bridge_w32(u32 val, unsigned reg)
++{
++ iowrite32(val, bridge_base + reg);
++}
++
++static inline u32 bridge_r32(unsigned reg)
++{
++ return ioread32(bridge_base + reg);
++}
++
++static inline void pcie_w32(u32 val, unsigned reg)
++{
++ iowrite32(val, pcie_base + reg);
++}
++
++static inline u32 pcie_r32(unsigned reg)
++{
++ return ioread32(pcie_base + reg);
++}
++
++static inline void pcie_m32(u32 clr, u32 set, unsigned reg)
++{
++ u32 val = pcie_r32(reg);
++ val &= ~clr;
++ val |= set;
++ pcie_w32(val, reg);
++}
++
++int wait_pciephy_busy(void)
++{
++ unsigned long reg_value = 0x0, retry = 0;
++
++ while (1) {
++ //reg_value = rareg(READMODE, PCIEPHY0_CFG, 0);
++ reg_value = pcie_r32(PCIEPHY0_CFG);
++
++ if (reg_value & BUSY)
++ mdelay(100);
++ else
++ break;
++ if (retry++ > WAITRETRY_MAX){
++ printk("PCIE-PHY retry failed.\n");
++ return -1;
++ }
++ }
++ return 0;
++}
++
++static void pcie_phy(unsigned long addr, unsigned long val)
++{
++ wait_pciephy_busy();
++ pcie_w32(WRITE_MODE | (val << DATA_SHIFT) | (addr << ADDR_SHIFT), PCIEPHY0_CFG);
++ mdelay(1);
++ wait_pciephy_busy();
++}
++
++static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
++{
++ unsigned int slot = PCI_SLOT(devfn);
++ u8 func = PCI_FUNC(devfn);
++ u32 address;
++ u32 data;
++
++ address = (((where & 0xF00) >> 8) << 24) | (bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000;
++ bridge_w32(address, RALINK_PCI_CONFIG_ADDR);
++ data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRTUAL_REG);
++
++ 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 pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
++{
++ unsigned int slot = PCI_SLOT(devfn);
++ u8 func = PCI_FUNC(devfn);
++ u32 address;
++ u32 data;
++
++ address = (((where & 0xF00) >> 8) << 24) | (bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000;
++ bridge_w32(address, RALINK_PCI_CONFIG_ADDR);
++ data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRTUAL_REG);
++
++ 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;
++ }
++
++ bridge_w32(data, RALINK_PCI_CONFIG_DATA_VIRTUAL_REG);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++struct pci_ops mt7620a_pci_ops= {
++ .read = pci_config_read,
++ .write = pci_config_write,
++};
++
++static struct resource mt7620a_res_pci_mem1 = {
++ .name = "pci memory",
++ .start = RALINK_PCI_MM_MAP_BASE,
++ .end = (u32) ((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)),
++ .flags = IORESOURCE_MEM,
++};
++static struct resource mt7620a_res_pci_io1 = {
++ .name = "pci io",
++ .start = RALINK_PCI_IO_MAP_BASE,
++ .end = (u32) ((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)),
++ .flags = IORESOURCE_IO,
++};
++
++struct pci_controller mt7620a_controller = {
++ .pci_ops = &mt7620a_pci_ops,
++ .mem_resource = &mt7620a_res_pci_mem1,
++ .io_resource = &mt7620a_res_pci_io1,
++ .mem_offset = 0x00000000UL,
++ .io_offset = 0x00000000UL,
++ .io_map_base = 0xa0000000,
++};
++
++static int mt7620a_pci_probe(struct platform_device *pdev)
++{
++ struct resource *bridge_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ struct resource *pcie_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++
++ rstpcie0 = devm_reset_control_get(&pdev->dev, "pcie0");
++ if (IS_ERR(rstpcie0))
++ return PTR_ERR(rstpcie0);
++
++ bridge_base = devm_request_and_ioremap(&pdev->dev, bridge_res);
++ if (!bridge_base)
++ return -ENOMEM;
++
++ pcie_base = devm_request_and_ioremap(&pdev->dev, pcie_res);
++ if (!pcie_base)
++ return -ENOMEM;
++
++ iomem_resource.start = 0;
++ iomem_resource.end= ~0;
++ ioport_resource.start= 0;
++ ioport_resource.end = ~0;
++
++ /* PCIE: bypass PCIe DLL */
++ pcie_phy(0x0, 0x80);
++ pcie_phy(0x1, 0x04);
++ /* PCIE: Elastic buffer control */
++ pcie_phy(0x68, 0xB4);
++
++ reset_control_assert(rstpcie0);
++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
++ rt_sysc_m32(1<<19, 1<<31, PPLL_DRV);
++ rt_sysc_m32(0x3 << 16, 0, RALINK_GPIOMODE);
++
++ reset_control_deassert(rstpcie0);
++ rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
++
++ mdelay(100);
++
++ if (!(rt_sysc_r32(PPLL_CFG1) & 1<<23)) {
++ printk("MT7620 PPLL unlock\n");
++ reset_control_assert(rstpcie0);
++ rt_sysc_m32(BIT(26), 0, RALINK_CLKCFG1);
++ return 0;
++ }
++ rt_sysc_m32((0x1<<18) | (0x1<<17), (0x1 << 19) | (0x1 << 31), PPLL_DRV);
++
++ mdelay(100);
++ reset_control_assert(rstpcie0);
++ rt_sysc_m32(0x30, 2 << 4, RALINK_SYSCFG1);
++
++ rt_sysc_m32(~0x7fffffff, 0x80000000, RALINK_PCIE_CLK_GEN);
++ rt_sysc_m32(~0x80ffffff, 0xa << 24, RALINK_PCIE_CLK_GEN1);
++
++ mdelay(50);
++ reset_control_deassert(rstpcie0);
++ pcie_m32(BIT(1), 0, RALINK_PCI_PCICFG_ADDR);
++ mdelay(100);
++
++ if (( pcie_r32(RALINK_PCI0_STATUS) & 0x1) == 0) {
++ reset_control_assert(rstpcie0);
++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
++ rt_sysc_m32(LC_CKDRVPD_, PDRV_SW_SET, PPLL_DRV);
++ printk("PCIE0 no card, disable it(RST&CLK)\n");
++ }
++
++ bridge_w32(0xffffffff, RALINK_PCI_MEMBASE);
++ bridge_w32(RALINK_PCI_IO_MAP_BASE, RALINK_PCI_IOBASE);
++
++ pcie_w32(0x7FFF0000, RALINK_PCI0_BAR0SETUP_ADDR);
++ pcie_w32(MEMORY_BASE, RALINK_PCI0_IMBASEBAR0_ADDR);
++ pcie_w32(0x08021814, RALINK_PCI0_ID);
++ pcie_w32(0x06040001, RALINK_PCI0_CLASS);
++ pcie_w32(0x28801814, RALINK_PCI0_SUBID);
++ pcie_m32(0, BIT(20), RALINK_PCI_PCIMSK_ADDR);
++
++ register_pci_controller(&mt7620a_controller);
++
++ return 0;
++}
++
++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ const struct resource *res;
++ u16 cmd;
++ u32 val;
++ int i, irq = 0;
++
++ if ((dev->bus->number == 0) && (slot == 0)) {
++ pcie_w32(0x7FFF0001, RALINK_PCI0_BAR0SETUP_ADDR); //open 7FFF:2G; ENABLE
++ pci_config_write(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, MEMORY_BASE);
++ pci_config_read(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, &val);
++ } else if ((dev->bus->number == 1) && (slot == 0x0)) {
++ irq = RALINK_INT_PCIE0;
++ } else {
++ printk("bus=0x%x, slot = 0x%x\n", dev->bus->number, slot);
++ return 0;
++ }
++
++ for (i = 0; i < 6; i++) {
++ res = &dev->resource[i];
++ }
++
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++
++ // FIXME
++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++ //pci_write_config_byte(dev, PCI_INTERRUPT_PIN, dev->irq);
++
++ return irq;
++}
++
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ return 0;
++}
++
++static const struct of_device_id mt7620a_pci_ids[] = {
++ { .compatible = "ralink,mt7620a-pci" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, mt7620a_pci_ids);
++
++static struct platform_driver mt7620a_pci_driver = {
++ .probe = mt7620a_pci_probe,
++ .driver = {
++ .name = "mt7620a-pci",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(mt7620a_pci_ids),
++ },
++};
++
++static int __init mt7620a_pci_init(void)
++{
++ return platform_driver_register(&mt7620a_pci_driver);
++}
++
++arch_initcall(mt7620a_pci_init);
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index f2f20ec..f89fdf8 100644
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -24,6 +24,7 @@ choice
+
+ config SOC_MT7620
+ bool "MT7620"
++ select HW_HAS_PCI
+
+ endchoice
+
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch b/target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch
new file mode 100644
index 0000000..5d446ee
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0065-watchdog-adds-ralink-wdt.patch
@@ -0,0 +1,275 @@
+From 8eaa4bef40d38a4954389a2552504ea2d1c4a68a Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Apr 2013 23:23:07 +0200
+Subject: [PATCH 65/79] watchdog: adds ralink wdt
+
+Adds the watchdog driver for ralink SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/mt7620.c | 1 +
+ drivers/watchdog/Kconfig | 7 ++
+ drivers/watchdog/Makefile | 1 +
+ drivers/watchdog/rt2880_wdt.c | 208 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 217 insertions(+)
+ create mode 100644 drivers/watchdog/rt2880_wdt.c
+
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+index 08c96db6..4956d96 100644
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -182,6 +182,7 @@ void __init ralink_clk_init(void)
+
+ ralink_clk_add("cpu", cpu_rate);
+ ralink_clk_add("10000100.timer", 40000000);
++ ralink_clk_add("10000120.watchdog", 40000000);
+ ralink_clk_add("10000500.uart", 40000000);
+ ralink_clk_add("10000b00.spi", 40000000);
+ ralink_clk_add("10000c00.uartlite", 40000000);
+diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
+index 7f809fd..c8c7454 100644
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -1076,6 +1076,13 @@ config LANTIQ_WDT
+ help
+ Hardware driver for the Lantiq SoC Watchdog Timer.
+
++config RALINK_WDT
++ tristate "Ralink SoC watchdog"
++ select WATCHDOG_CORE
++ depends on RALINK
++ help
++ Hardware driver for the Ralink SoC Watchdog Timer.
++
+ # PARISC Architecture
+
+ # POWERPC Architecture
+diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
+index 97bbdb3a..0203784 100644
+--- 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) += rt2880_wdt.o
+
+ # PARISC Architecture
+
+diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c
+new file mode 100644
+index 0000000..3df65a4
+--- /dev/null
++++ b/drivers/watchdog/rt2880_wdt.c
+@@ -0,0 +1,208 @@
++/*
++ * Ralink RT288x/RT3xxx/MT76xx built-in hardware watchdog timer
++ *
++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ *
++ * This driver was based on: drivers/watchdog/softdog.c
++ *
++ * 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/clk.h>
++#include <linux/reset.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/watchdog.h>
++#include <linux/miscdevice.h>
++#include <linux/moduleparam.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define SYSC_RSTSTAT 0x38
++#define WDT_RST_CAUSE BIT(1)
++
++#define RALINK_WDT_TIMEOUT 30
++#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 struct clk *rt288x_wdt_clk;
++static unsigned long rt288x_wdt_freq;
++static void __iomem *rt288x_wdt_base;
++
++static bool nowayout = WATCHDOG_NOWAYOUT;
++module_param(nowayout, bool, 0);
++MODULE_PARM_DESC(nowayout,
++ "Watchdog cannot be stopped once started (default="
++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
++
++static inline void rt_wdt_w32(unsigned reg, u32 val)
++{
++ iowrite32(val, rt288x_wdt_base + reg);
++}
++
++static inline u32 rt_wdt_r32(unsigned reg)
++{
++ return ioread32(rt288x_wdt_base + reg);
++}
++
++static int rt288x_wdt_ping(struct watchdog_device *w)
++{
++ rt_wdt_w32(TIMER_REG_TMR1LOAD, w->timeout * rt288x_wdt_freq);
++
++ return 0;
++}
++
++static int rt288x_wdt_start(struct watchdog_device *w)
++{
++ u32 t;
++
++ 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);
++
++ rt288x_wdt_ping(w);
++
++ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
++ t |= TMR1CTL_ENABLE;
++ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
++
++ return 0;
++}
++
++static int rt288x_wdt_stop(struct watchdog_device *w)
++{
++ u32 t;
++
++ rt288x_wdt_ping(w);
++
++ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
++ t &= ~TMR1CTL_ENABLE;
++ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
++
++ return 0;
++}
++
++static int rt288x_wdt_set_timeout(struct watchdog_device *w, unsigned int t)
++{
++ w->timeout = t;
++ rt288x_wdt_ping(w);
++
++ return 0;
++}
++
++static int rt288x_wdt_bootcause(void)
++{
++ if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE)
++ return WDIOF_CARDRESET;
++
++ return 0;
++}
++
++static struct watchdog_info rt288x_wdt_info = {
++ .identity = "Ralink Watchdog",
++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
++};
++
++static struct watchdog_ops rt288x_wdt_ops = {
++ .owner = THIS_MODULE,
++ .start = rt288x_wdt_start,
++ .stop = rt288x_wdt_stop,
++ .ping = rt288x_wdt_ping,
++ .set_timeout = rt288x_wdt_set_timeout,
++};
++
++static struct watchdog_device rt288x_wdt_dev = {
++ .info = &rt288x_wdt_info,
++ .ops = &rt288x_wdt_ops,
++ .min_timeout = 1,
++};
++
++static int rt288x_wdt_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int ret;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ rt288x_wdt_base = devm_request_and_ioremap(&pdev->dev, res);
++ if (IS_ERR(rt288x_wdt_base))
++ return PTR_ERR(rt288x_wdt_base);
++
++ rt288x_wdt_clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(rt288x_wdt_clk))
++ return PTR_ERR(rt288x_wdt_clk);
++
++ device_reset(&pdev->dev);
++
++ rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE;
++
++ rt288x_wdt_dev.dev = &pdev->dev;
++ rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause();
++
++ rt288x_wdt_dev.timeout = RALINK_WDT_TIMEOUT;
++ rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq);
++
++ watchdog_set_nowayout(&rt288x_wdt_dev, nowayout);
++
++ ret = watchdog_register_device(&rt288x_wdt_dev);
++ if (!ret)
++ dev_info(&pdev->dev, "Initialized\n");
++
++ return 0;
++}
++
++static int rt288x_wdt_remove(struct platform_device *pdev)
++{
++ watchdog_unregister_device(&rt288x_wdt_dev);
++
++ return 0;
++}
++
++static void rt288x_wdt_shutdown(struct platform_device *pdev)
++{
++ rt288x_wdt_stop(&rt288x_wdt_dev);
++}
++
++static const struct of_device_id rt288x_wdt_match[] = {
++ { .compatible = "ralink,rt2880-wdt" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt288x_wdt_match);
++
++static struct platform_driver rt288x_wdt_driver = {
++ .probe = rt288x_wdt_probe,
++ .remove = rt288x_wdt_remove,
++ .shutdown = rt288x_wdt_shutdown,
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .owner = THIS_MODULE,
++ .of_match_table = rt288x_wdt_match,
++ },
++};
++
++module_platform_driver(rt288x_wdt_driver);
++
++MODULE_DESCRIPTION("MediaTek/Ralink RT288x/RT3xxx hardware watchdog driver");
++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0066-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-3.8/0066-i2c-MIPS-adds-ralink-I2C-driver.patch
new file mode 100644
index 0000000..286020a
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0066-i2c-MIPS-adds-ralink-I2C-driver.patch
@@ -0,0 +1,358 @@
+From 68fc18202484e98861ef7eed2a78b64b16c73db9 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 29 Apr 2013 14:40:43 +0200
+Subject: [PATCH 66/79] i2c: MIPS: adds ralink I2C driver
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ .../devicetree/bindings/i2c/i2c-ralink.txt | 27 ++
+ drivers/i2c/busses/Kconfig | 4 +
+ drivers/i2c/busses/Makefile | 1 +
+ drivers/i2c/busses/i2c-ralink.c | 274 ++++++++++++++++++++
+ 4 files changed, 306 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt
+ create mode 100644 drivers/i2c/busses/i2c-ralink.c
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-ralink.txt b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt
+new file mode 100644
+index 0000000..8fa8ac3
+--- /dev/null
++++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt
+@@ -0,0 +1,27 @@
++I2C for Ralink platforms
++
++Required properties :
++- compatible : Must be "link,rt3052-i2c"
++- reg: physical base address of the controller and length of memory mapped
++ region.
++- #address-cells = <1>;
++- #size-cells = <0>;
++
++Optional properties:
++- Child nodes conforming to i2c bus binding
++
++Example :
++
++palmbus@10000000 {
++ i2c@900 {
++ compatible = "link,rt3052-i2c";
++ reg = <0x900 0x100>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ hwmon@4b {
++ compatible = "national,lm92";
++ reg = <0x4b>;
++ };
++ };
++};
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index bdca511..19b1105 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -604,6 +604,10 @@ config I2C_PXA_SLAVE
+ is necessary for systems where the PXA may be a target on the
+ I2C bus.
+
++config I2C_RALINK
++ tristate "Ralink I2C Controller"
++ select OF_I2C
++
+ config HAVE_S3C2410_I2C
+ bool
+ help
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index 6181f3f..4cf4a88 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
+ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
+ obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
+ obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
++obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o
+ obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
+ obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
+ obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
+diff --git a/drivers/i2c/busses/i2c-ralink.c b/drivers/i2c/busses/i2c-ralink.c
+new file mode 100644
+index 0000000..b5abf0f
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-ralink.c
+@@ -0,0 +1,274 @@
++/*
++ * drivers/i2c/busses/i2c-ralink.c
++ *
++ * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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.
++ *
++ */
++
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/reset.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <linux/io.h>
++#include <linux/of_i2c.h>
++#include <linux/err.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define REG_CONFIG_REG 0x00
++#define REG_CLKDIV_REG 0x04
++#define REG_DEVADDR_REG 0x08
++#define REG_ADDR_REG 0x0C
++#define REG_DATAOUT_REG 0x10
++#define REG_DATAIN_REG 0x14
++#define REG_STATUS_REG 0x18
++#define REG_STARTXFR_REG 0x1C
++#define REG_BYTECNT_REG 0x20
++
++#define I2C_STARTERR BIT(4)
++#define I2C_ACKERR BIT(3)
++#define I2C_DATARDY BIT(2)
++#define I2C_SDOEMPTY BIT(1)
++#define I2C_BUSY BIT(0)
++
++#define I2C_DEVADLEN_7 (6 << 2)
++#define I2C_ADDRDIS BIT(1)
++
++#define I2C_RETRY 0x400
++
++#define CLKDIV_VALUE 600
++
++#define READ_CMD 0x01
++#define WRITE_CMD 0x00
++#define READ_BLOCK 64
++
++static void __iomem *membase;
++static struct i2c_adapter *adapter;
++
++static void rt_i2c_w32(u32 val, unsigned reg)
++{
++ iowrite32(val, membase + reg);
++}
++
++static u32 rt_i2c_r32(unsigned reg)
++{
++ return ioread32(membase + reg);
++}
++
++static inline int rt_i2c_wait_rx_done(void)
++{
++ int retries = I2C_RETRY;
++
++ do {
++ if (!retries--)
++ break;
++ } while(!(rt_i2c_r32(REG_STATUS_REG) & I2C_DATARDY));
++
++ return (retries < 0);
++}
++
++static inline int rt_i2c_wait_idle(void)
++{
++ int retries = I2C_RETRY;
++
++ do {
++ if (!retries--)
++ break;
++ } while(rt_i2c_r32(REG_STATUS_REG) & I2C_BUSY);
++
++ return (retries < 0);
++}
++
++static inline int rt_i2c_wait_tx_done(void)
++{
++ int retries = I2C_RETRY;
++
++ do {
++ if (!retries--)
++ break;
++ } while(!(rt_i2c_r32(REG_STATUS_REG) & I2C_SDOEMPTY));
++
++ return (retries < 0);
++}
++
++static int rt_i2c_handle_msg(struct i2c_adapter *a, struct i2c_msg* msg)
++{
++ int i = 0, j = 0, pos = 0;
++ int nblock = msg->len / READ_BLOCK;
++ int rem = msg->len % READ_BLOCK;
++
++ if (msg->flags & I2C_M_TEN) {
++ printk("10 bits addr not supported\n");
++ return -EINVAL;
++ }
++
++ if (msg->flags & I2C_M_RD) {
++ for (i = 0; i < nblock; i++) {
++ rt_i2c_wait_idle();
++ rt_i2c_w32(READ_BLOCK - 1, REG_BYTECNT_REG);
++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG);
++ for (j = 0; j < READ_BLOCK; j++) {
++ if (rt_i2c_wait_rx_done())
++ return -1;
++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG);
++ }
++ }
++
++ rt_i2c_wait_idle();
++ rt_i2c_w32(rem - 1, REG_BYTECNT_REG);
++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG);
++ for (i = 0; i < rem; i++) {
++ if (rt_i2c_wait_rx_done())
++ return -1;
++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG);
++ }
++ } else {
++ rt_i2c_wait_idle();
++ rt_i2c_w32(msg->len - 1, REG_BYTECNT_REG);
++ rt_i2c_w32(msg->buf[0], REG_DATAOUT_REG);
++ rt_i2c_w32(WRITE_CMD, REG_STARTXFR_REG);
++ for (i = 1; i < msg->len; i++) {
++ rt_i2c_w32(msg->buf[i], REG_DATAOUT_REG);
++ if (rt_i2c_wait_tx_done())
++ return -1;
++ }
++ }
++
++ return msg->len;
++}
++
++static int rt_i2c_master_xfer(struct i2c_adapter *a, struct i2c_msg *m, int n)
++{
++ int i = 0;
++ int ret = 0;
++
++ if (rt_i2c_wait_idle()) {
++ printk("i2c transfer failed\n");
++ return 0;
++ }
++
++ device_reset(a->dev.parent);
++
++ rt_i2c_w32(m->addr, REG_DEVADDR_REG);
++ rt_i2c_w32(I2C_DEVADLEN_7 | I2C_ADDRDIS, REG_CONFIG_REG);
++ rt_i2c_w32(CLKDIV_VALUE, REG_CLKDIV_REG);
++
++ for (i = 0; i < n && !ret; i++)
++ ret = rt_i2c_handle_msg(a, &m[i]);
++
++ if (ret) {
++ printk("i2c transfer failed\n");
++ return 0;
++ }
++
++ return n;
++}
++
++static u32 rt_i2c_func(struct i2c_adapter *a)
++{
++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static const struct i2c_algorithm rt_i2c_algo = {
++ .master_xfer = rt_i2c_master_xfer,
++ .functionality = rt_i2c_func,
++};
++
++static int rt_i2c_probe(struct platform_device *pdev)
++{
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ int ret;
++
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource found\n");
++ return -ENODEV;
++ }
++
++ adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter), GFP_KERNEL);
++ if (!adapter) {
++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n");
++ return -ENOMEM;
++ }
++
++ membase = devm_request_and_ioremap(&pdev->dev, res);
++ if (IS_ERR(membase))
++ return PTR_ERR(membase);
++
++ strlcpy(adapter->name, dev_name(&pdev->dev), sizeof(adapter->name));
++ adapter->owner = THIS_MODULE;
++ adapter->nr = pdev->id;
++ adapter->timeout = HZ;
++ adapter->algo = &rt_i2c_algo;
++ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
++ adapter->dev.parent = &pdev->dev;
++ adapter->dev.of_node = pdev->dev.of_node;
++
++ ret = i2c_add_numbered_adapter(adapter);
++ if (ret)
++ return ret;
++
++ of_i2c_register_devices(adapter);
++
++ platform_set_drvdata(pdev, adapter);
++
++ dev_info(&pdev->dev, "loaded\n");
++
++ return 0;
++}
++
++static int rt_i2c_remove(struct platform_device *pdev)
++{
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++static const struct of_device_id i2c_rt_dt_ids[] = {
++ { .compatible = "ralink,rt2880-i2c", },
++ { /* sentinel */ }
++};
++
++MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids);
++
++static struct platform_driver rt_i2c_driver = {
++ .probe = rt_i2c_probe,
++ .remove = rt_i2c_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "i2c-ralink",
++ .of_match_table = i2c_rt_dt_ids,
++ },
++};
++
++static int __init i2c_rt_init (void)
++{
++ return platform_driver_register(&rt_i2c_driver);
++}
++subsys_initcall(i2c_rt_init);
++
++static void __exit i2c_rt_exit (void)
++{
++ platform_driver_unregister(&rt_i2c_driver);
++}
++
++module_exit (i2c_rt_exit);
++
++MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>");
++MODULE_DESCRIPTION("Ralink I2c host driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:Ralink-I2C");
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch b/target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch
new file mode 100644
index 0000000..55bbb56
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0067-reset-Add-reset-controller-API.patch
@@ -0,0 +1,554 @@
+From 8951e08252c6c254d68c350468c40f88a12bcc1d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 20 May 2013 15:42:01 +0200
+Subject: [PATCH 67/79] reset: Add reset controller API
+
+backport from v3.10-rc1
+61fc41317666be400802ac793f47de816ef7bd57
+6034bb22d8387708075c083385e5d2e1072a4f33
+4e11f848c65b1c87782cb232a6e3b47a9d4c1f98
+
+This adds a simple API for devices to request being reset
+by separate reset controller hardware and implements the
+reset signal device tree binding.
+
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Stephen Warren <swarren@nvidia.com>
+Reviewed-by: Shawn Guo <shawn.guo@linaro.org>
+Reviewed-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Pavel Machek <pavel@ucw.cz>
+---
+ Documentation/devicetree/bindings/reset/reset.txt | 75 ++++++
+ drivers/Kconfig | 2 +
+ drivers/Makefile | 3 +
+ drivers/reset/Kconfig | 13 +
+ drivers/reset/Makefile | 1 +
+ drivers/reset/core.c | 297 +++++++++++++++++++++
+ include/linux/reset-controller.h | 51 ++++
+ include/linux/reset.h | 17 ++
+ 8 files changed, 459 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/reset/reset.txt
+ create mode 100644 drivers/reset/Kconfig
+ create mode 100644 drivers/reset/Makefile
+ create mode 100644 drivers/reset/core.c
+ create mode 100644 include/linux/reset-controller.h
+ create mode 100644 include/linux/reset.h
+
+diff --git a/Documentation/devicetree/bindings/reset/reset.txt b/Documentation/devicetree/bindings/reset/reset.txt
+new file mode 100644
+index 0000000..31db6ff
+--- /dev/null
++++ b/Documentation/devicetree/bindings/reset/reset.txt
+@@ -0,0 +1,75 @@
++= Reset Signal Device Tree Bindings =
++
++This binding is intended to represent the hardware reset signals present
++internally in most IC (SoC, FPGA, ...) designs. Reset signals for whole
++standalone chips are most likely better represented as GPIOs, although there
++are likely to be exceptions to this rule.
++
++Hardware blocks typically receive a reset signal. This signal is generated by
++a reset provider (e.g. power management or clock module) and received by a
++reset consumer (the module being reset, or a module managing when a sub-
++ordinate module is reset). This binding exists to represent the provider and
++consumer, and provide a way to couple the two together.
++
++A reset signal is represented by the phandle of the provider, plus a reset
++specifier - a list of DT cells that represents the reset signal within the
++provider. The length (number of cells) and semantics of the reset specifier
++are dictated by the binding of the reset provider, although common schemes
++are described below.
++
++A word on where to place reset signal consumers in device tree: It is possible
++in hardware for a reset signal to affect multiple logically separate HW blocks
++at once. In this case, it would be unwise to represent this reset signal in
++the DT node of each affected HW block, since if activated, an unrelated block
++may be reset. Instead, reset signals should be represented in the DT node
++where it makes most sense to control it; this may be a bus node if all
++children of the bus are affected by the reset signal, or an individual HW
++block node for dedicated reset signals. The intent of this binding is to give
++appropriate software access to the reset signals in order to manage the HW,
++rather than to slavishly enumerate the reset signal that affects each HW
++block.
++
++= Reset providers =
++
++Required properties:
++#reset-cells: Number of cells in a reset specifier; Typically 0 for nodes
++ with a single reset output and 1 for nodes with multiple
++ reset outputs.
++
++For example:
++
++ rst: reset-controller {
++ #reset-cells = <1>;
++ };
++
++= Reset consumers =
++
++Required properties:
++resets: List of phandle and reset specifier pairs, one pair
++ for each reset signal that affects the device, or that the
++ device manages. Note: if the reset provider specifies '0' for
++ #reset-cells, then only the phandle portion of the pair will
++ appear.
++
++Optional properties:
++reset-names: List of reset signal name strings sorted in the same order as
++ the resets property. Consumers drivers will use reset-names to
++ match reset signal names with reset specifiers.
++
++For example:
++
++ device {
++ resets = <&rst 20>;
++ reset-names = "reset";
++ };
++
++This represents a device with a single reset signal named "reset".
++
++ bus {
++ resets = <&rst 10> <&rst 11> <&rst 12> <&rst 11>;
++ reset-names = "i2s1", "i2s2", "dma", "mixer";
++ };
++
++This represents a bus that controls the reset signal of each of four sub-
++ordinate devices. Consider for example a bus that fails to operate unless no
++child device has reset asserted.
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index f5fb072..51f73ae 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -158,4 +158,6 @@ source "drivers/irqchip/Kconfig"
+
+ source "drivers/ipack/Kconfig"
+
++source "drivers/reset/Kconfig"
++
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 7863b9f..2819ac0 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -37,6 +37,9 @@ obj-$(CONFIG_XEN) += xen/
+ # regulators early, since some subsystems rely on them to initialize
+ obj-$(CONFIG_REGULATOR) += regulator/
+
++# reset controllers early, since gpu drivers might rely on them to initialize
++obj-$(CONFIG_RESET_CONTROLLER) += reset/
++
+ # tty/ comes before char/ so that the VT console is the boot-time
+ # default.
+ obj-y += tty/
+diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
+new file mode 100644
+index 0000000..c9d04f7
+--- /dev/null
++++ b/drivers/reset/Kconfig
+@@ -0,0 +1,13 @@
++config ARCH_HAS_RESET_CONTROLLER
++ bool
++
++menuconfig RESET_CONTROLLER
++ bool "Reset Controller Support"
++ default y if ARCH_HAS_RESET_CONTROLLER
++ help
++ Generic Reset Controller support.
++
++ This framework is designed to abstract reset handling of devices
++ via GPIOs or SoC-internal reset controller modules.
++
++ If unsure, say no.
+diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
+new file mode 100644
+index 0000000..1e2d83f
+--- /dev/null
++++ b/drivers/reset/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_RESET_CONTROLLER) += core.o
+diff --git a/drivers/reset/core.c b/drivers/reset/core.c
+new file mode 100644
+index 0000000..d1b6089
+--- /dev/null
++++ b/drivers/reset/core.c
+@@ -0,0 +1,297 @@
++/*
++ * Reset Controller framework
++ *
++ * Copyright 2013 Philipp Zabel, Pengutronix
++ *
++ * 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; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/export.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/reset.h>
++#include <linux/reset-controller.h>
++#include <linux/slab.h>
++
++static DEFINE_MUTEX(reset_controller_list_mutex);
++static LIST_HEAD(reset_controller_list);
++
++/**
++ * struct reset_control - a reset control
++ * @rcdev: a pointer to the reset controller device
++ * this reset control belongs to
++ * @id: ID of the reset controller in the reset
++ * controller device
++ */
++struct reset_control {
++ struct reset_controller_dev *rcdev;
++ struct device *dev;
++ unsigned int id;
++};
++
++/**
++ * of_reset_simple_xlate - translate reset_spec to the reset line number
++ * @rcdev: a pointer to the reset controller device
++ * @reset_spec: reset line specifier as found in the device tree
++ * @flags: a flags pointer to fill in (optional)
++ *
++ * This simple translation function should be used for reset controllers
++ * with 1:1 mapping, where reset lines can be indexed by number without gaps.
++ */
++int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
++ const struct of_phandle_args *reset_spec)
++{
++ if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
++ return -EINVAL;
++
++ if (reset_spec->args[0] >= rcdev->nr_resets)
++ return -EINVAL;
++
++ return reset_spec->args[0];
++}
++EXPORT_SYMBOL_GPL(of_reset_simple_xlate);
++
++/**
++ * reset_controller_register - register a reset controller device
++ * @rcdev: a pointer to the initialized reset controller device
++ */
++int reset_controller_register(struct reset_controller_dev *rcdev)
++{
++ if (!rcdev->of_xlate) {
++ rcdev->of_reset_n_cells = 1;
++ rcdev->of_xlate = of_reset_simple_xlate;
++ }
++
++ mutex_lock(&reset_controller_list_mutex);
++ list_add(&rcdev->list, &reset_controller_list);
++ mutex_unlock(&reset_controller_list_mutex);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(reset_controller_register);
++
++/**
++ * reset_controller_unregister - unregister a reset controller device
++ * @rcdev: a pointer to the reset controller device
++ */
++void reset_controller_unregister(struct reset_controller_dev *rcdev)
++{
++ mutex_lock(&reset_controller_list_mutex);
++ list_del(&rcdev->list);
++ mutex_unlock(&reset_controller_list_mutex);
++}
++EXPORT_SYMBOL_GPL(reset_controller_unregister);
++
++/**
++ * reset_control_reset - reset the controlled device
++ * @rstc: reset controller
++ */
++int reset_control_reset(struct reset_control *rstc)
++{
++ if (rstc->rcdev->ops->reset)
++ return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
++
++ return -ENOSYS;
++}
++EXPORT_SYMBOL_GPL(reset_control_reset);
++
++/**
++ * reset_control_assert - asserts the reset line
++ * @rstc: reset controller
++ */
++int reset_control_assert(struct reset_control *rstc)
++{
++ if (rstc->rcdev->ops->assert)
++ return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
++
++ return -ENOSYS;
++}
++EXPORT_SYMBOL_GPL(reset_control_assert);
++
++/**
++ * reset_control_deassert - deasserts the reset line
++ * @rstc: reset controller
++ */
++int reset_control_deassert(struct reset_control *rstc)
++{
++ if (rstc->rcdev->ops->deassert)
++ return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
++
++ return -ENOSYS;
++}
++EXPORT_SYMBOL_GPL(reset_control_deassert);
++
++/**
++ * reset_control_get - Lookup and obtain a reference to a reset controller.
++ * @dev: device to be reset by the controller
++ * @id: reset line name
++ *
++ * Returns a struct reset_control or IS_ERR() condition containing errno.
++ *
++ * Use of id names is optional.
++ */
++struct reset_control *reset_control_get(struct device *dev, const char *id)
++{
++ struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER);
++ struct reset_controller_dev *r, *rcdev;
++ struct of_phandle_args args;
++ int index = 0;
++ int rstc_id;
++ int ret;
++
++ if (!dev)
++ return ERR_PTR(-EINVAL);
++
++ if (id)
++ index = of_property_match_string(dev->of_node,
++ "reset-names", id);
++ ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells",
++ index, &args);
++ if (ret)
++ return ERR_PTR(ret);
++
++ mutex_lock(&reset_controller_list_mutex);
++ rcdev = NULL;
++ list_for_each_entry(r, &reset_controller_list, list) {
++ if (args.np == r->of_node) {
++ rcdev = r;
++ break;
++ }
++ }
++ of_node_put(args.np);
++
++ if (!rcdev) {
++ mutex_unlock(&reset_controller_list_mutex);
++ return ERR_PTR(-ENODEV);
++ }
++
++ rstc_id = rcdev->of_xlate(rcdev, &args);
++ if (rstc_id < 0) {
++ mutex_unlock(&reset_controller_list_mutex);
++ return ERR_PTR(rstc_id);
++ }
++
++ try_module_get(rcdev->owner);
++ mutex_unlock(&reset_controller_list_mutex);
++
++ rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
++ if (!rstc) {
++ module_put(rcdev->owner);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ rstc->dev = dev;
++ rstc->rcdev = rcdev;
++ rstc->id = rstc_id;
++
++ return rstc;
++}
++EXPORT_SYMBOL_GPL(reset_control_get);
++
++/**
++ * reset_control_put - free the reset controller
++ * @rstc: reset controller
++ */
++
++void reset_control_put(struct reset_control *rstc)
++{
++ if (IS_ERR(rstc))
++ return;
++
++ module_put(rstc->rcdev->owner);
++ kfree(rstc);
++}
++EXPORT_SYMBOL_GPL(reset_control_put);
++
++static void devm_reset_control_release(struct device *dev, void *res)
++{
++ reset_control_put(*(struct reset_control **)res);
++}
++
++/**
++ * devm_reset_control_get - resource managed reset_control_get()
++ * @dev: device to be reset by the controller
++ * @id: reset line name
++ *
++ * Managed reset_control_get(). For reset controllers returned from this
++ * function, reset_control_put() is called automatically on driver detach.
++ * See reset_control_get() for more information.
++ */
++struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
++{
++ struct reset_control **ptr, *rstc;
++
++ ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr),
++ GFP_KERNEL);
++ if (!ptr)
++ return ERR_PTR(-ENOMEM);
++
++ rstc = reset_control_get(dev, id);
++ if (!IS_ERR(rstc)) {
++ *ptr = rstc;
++ devres_add(dev, ptr);
++ } else {
++ devres_free(ptr);
++ }
++
++ return rstc;
++}
++EXPORT_SYMBOL_GPL(devm_reset_control_get);
++
++static int devm_reset_control_match(struct device *dev, void *res, void *data)
++{
++ struct reset_control **rstc = res;
++ if (WARN_ON(!rstc || !*rstc))
++ return 0;
++ return *rstc == data;
++}
++
++/**
++ * devm_reset_control_put - resource managed reset_control_put()
++ * @rstc: reset controller to free
++ *
++ * Deallocate a reset control allocated withd devm_reset_control_get().
++ * This function will not need to be called normally, as devres will take
++ * care of freeing the resource.
++ */
++void devm_reset_control_put(struct reset_control *rstc)
++{
++ int ret;
++
++ ret = devres_release(rstc->dev, devm_reset_control_release,
++ devm_reset_control_match, rstc);
++ if (ret)
++ WARN_ON(ret);
++}
++EXPORT_SYMBOL_GPL(devm_reset_control_put);
++
++/**
++ * device_reset - find reset controller associated with the device
++ * and perform reset
++ * @dev: device to be reset by the controller
++ *
++ * Convenience wrapper for reset_control_get() and reset_control_reset().
++ * This is useful for the common case of devices with single, dedicated reset
++ * lines.
++ */
++int device_reset(struct device *dev)
++{
++ struct reset_control *rstc;
++ int ret;
++
++ rstc = reset_control_get(dev, NULL);
++ if (IS_ERR(rstc))
++ return PTR_ERR(rstc);
++
++ ret = reset_control_reset(rstc);
++
++ reset_control_put(rstc);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(device_reset);
+diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
+new file mode 100644
+index 0000000..2f61311
+--- /dev/null
++++ b/include/linux/reset-controller.h
+@@ -0,0 +1,51 @@
++#ifndef _LINUX_RESET_CONTROLLER_H_
++#define _LINUX_RESET_CONTROLLER_H_
++
++#include <linux/list.h>
++
++struct reset_controller_dev;
++
++/**
++ * struct reset_control_ops
++ *
++ * @reset: for self-deasserting resets, does all necessary
++ * things to reset the device
++ * @assert: manually assert the reset line, if supported
++ * @deassert: manually deassert the reset line, if supported
++ */
++struct reset_control_ops {
++ int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);
++ int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);
++ int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);
++};
++
++struct module;
++struct device_node;
++
++/**
++ * struct reset_controller_dev - reset controller entity that might
++ * provide multiple reset controls
++ * @ops: a pointer to device specific struct reset_control_ops
++ * @owner: kernel module of the reset controller driver
++ * @list: internal list of reset controller devices
++ * @of_node: corresponding device tree node as phandle target
++ * @of_reset_n_cells: number of cells in reset line specifiers
++ * @of_xlate: translation function to translate from specifier as found in the
++ * device tree to id as given to the reset control ops
++ * @nr_resets: number of reset controls in this reset controller device
++ */
++struct reset_controller_dev {
++ struct reset_control_ops *ops;
++ struct module *owner;
++ struct list_head list;
++ struct device_node *of_node;
++ int of_reset_n_cells;
++ int (*of_xlate)(struct reset_controller_dev *rcdev,
++ const struct of_phandle_args *reset_spec);
++ unsigned int nr_resets;
++};
++
++int reset_controller_register(struct reset_controller_dev *rcdev);
++void reset_controller_unregister(struct reset_controller_dev *rcdev);
++
++#endif
+diff --git a/include/linux/reset.h b/include/linux/reset.h
+new file mode 100644
+index 0000000..6082247
+--- /dev/null
++++ b/include/linux/reset.h
+@@ -0,0 +1,17 @@
++#ifndef _LINUX_RESET_H_
++#define _LINUX_RESET_H_
++
++struct device;
++struct reset_control;
++
++int reset_control_reset(struct reset_control *rstc);
++int reset_control_assert(struct reset_control *rstc);
++int reset_control_deassert(struct reset_control *rstc);
++
++struct reset_control *reset_control_get(struct device *dev, const char *id);
++void reset_control_put(struct reset_control *rstc);
++struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
++
++int device_reset(struct device *dev);
++
++#endif
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch b/target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch
new file mode 100644
index 0000000..29a0991
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0068-reset-MIPS-ralink-add-core-device-reset-wrapper.patch
@@ -0,0 +1,135 @@
+From 42c26796ae7bcfe0b33a4145de5a392e32bc9bac Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 8 May 2013 22:08:39 +0200
+Subject: [PATCH 68/79] reset: MIPS: ralink: add core/device reset wrapper
+
+Add a helper for reseting different devices ont he SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/Kconfig | 1 +
+ arch/mips/ralink/of.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++
+ arch/mips/ralink/reset.c | 1 +
+ 3 files changed, 61 insertions(+)
+
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 2498972..ef5272f 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -450,6 +450,7 @@ config RALINK
+ select HAVE_MACH_CLKDEV
+ select CLKDEV_LOOKUP
+ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_HAS_RESET_CONTROLLER
+
+ config SGI_IP22
+ bool "SGI IP22 (Indy/Indigo2)"
+diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
+index 8efb02b..2faf478 100644
+--- a/arch/mips/ralink/of.c
++++ b/arch/mips/ralink/of.c
+@@ -14,16 +14,22 @@
+ #include <linux/sizes.h>
+ #include <linux/of_fdt.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/bootmem.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_address.h>
++#include <linux/reset-controller.h>
+
+ #include <asm/reboot.h>
+ #include <asm/bootinfo.h>
+ #include <asm/addrspace.h>
+
++#include <asm/mach-ralink/ralink_regs.h>
++
+ #include "common.h"
+
++#define SYSC_REG_RESET_CTRL 0x034
++
+ __iomem void *rt_sysc_membase;
+ __iomem void *rt_memc_membase;
+
+@@ -96,6 +102,53 @@ void __init plat_mem_setup(void)
+ soc_info.mem_size_max * SZ_1M);
+ }
+
++static int ralink_assert_device(struct reset_controller_dev *rcdev, unsigned long id)
++{
++ u32 val;
++
++ if (id < 8)
++ return -1;
++
++ val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
++ val |= BIT(id);
++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
++
++ return 0;
++}
++
++static int ralink_deassert_device(struct reset_controller_dev *rcdev, unsigned long id)
++{
++ u32 val;
++
++ if (id < 8)
++ return -1;
++
++ val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
++ val &= ~BIT(id);
++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
++
++ return 0;
++}
++
++static int ralink_reset_device(struct reset_controller_dev *rcdev, unsigned long id)
++{
++ ralink_assert_device(rcdev, id);
++ return ralink_deassert_device(rcdev, id);
++}
++
++static struct reset_control_ops reset_ops = {
++ .reset = ralink_reset_device,
++ .assert = ralink_assert_device,
++ .deassert = ralink_deassert_device,
++};
++
++static struct reset_controller_dev reset_dev = {
++ .ops = &reset_ops,
++ .owner = THIS_MODULE,
++ .nr_resets = 32,
++ .of_reset_n_cells = 1,
++};
++
+ static int __init plat_of_setup(void)
+ {
+ static struct of_device_id of_ids[3];
+@@ -110,6 +163,12 @@ static int __init plat_of_setup(void)
+ if (of_platform_populate(NULL, of_ids, NULL, NULL))
+ panic("failed to populate DT\n");
+
++ reset_dev.of_node = of_find_compatible_node(NULL, NULL, "ralink,rt2880-reset");
++ if (!reset_dev.of_node)
++ panic("Failed to find reset controller node");
++
++ reset_controller_register(&reset_dev);
++
+ ralink_pinmux();
+
+ return 0;
+diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c
+index 22120e5..6c15f4f 100644
+--- a/arch/mips/ralink/reset.c
++++ b/arch/mips/ralink/reset.c
+@@ -10,6 +10,7 @@
+
+ #include <linux/pm.h>
+ #include <linux/io.h>
++#include <linux/module.h>
+
+ #include <asm/reboot.h>
+
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0201-owrt-OF-NET-add-of_get_mac_address_mtd.patch b/target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch
index b7c79ab..6efccf0 100644
--- a/target/linux/ramips/patches-3.8/0201-owrt-OF-NET-add-of_get_mac_address_mtd.patch
+++ b/target/linux/ramips/patches-3.8/0069-NET-add-of_get_mac_address_mtd.patch
@@ -1,7 +1,7 @@
-From 1809af0f73208ec67363347ddf5370e1f08222e8 Mon Sep 17 00:00:00 2001
+From d30d4c01d2b97eed1fc109819b9c8747343ff4d7 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 17 Mar 2013 09:29:15 +0100
-Subject: [PATCH 201/208] owrt: OF: NET: add of_get_mac_address_mtd()
+Subject: [PATCH 69/79] NET: add of_get_mac_address_mtd()
Many embedded devices have information such as mac addresses stored inside mtd
devices. This patch allows us to add a property inside a node describing a
@@ -14,6 +14,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
include/linux/of_net.h | 1 +
2 files changed, 38 insertions(+)
+diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
+index ffab033..15f4a71 100644
--- a/drivers/of/of_net.c
+++ b/drivers/of/of_net.c
@@ -10,6 +10,7 @@
@@ -24,7 +26,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
/**
* It maps 'enum phy_interface_t' found in include/linux/phy.h
-@@ -92,3 +93,39 @@ const void *of_get_mac_address(struct de
+@@ -92,3 +93,39 @@ const void *of_get_mac_address(struct device_node *np)
return NULL;
}
EXPORT_SYMBOL(of_get_mac_address);
@@ -64,6 +66,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_get_mac_address_mtd);
+diff --git a/include/linux/of_net.h b/include/linux/of_net.h
+index f474641..9d3304f 100644
--- a/include/linux/of_net.h
+++ b/include/linux/of_net.h
@@ -11,6 +11,7 @@
@@ -74,3 +78,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#endif
#endif /* __LINUX_OF_NET_H */
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch b/target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch
new file mode 100644
index 0000000..4e8fbda
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0070-NET-multi-phy-support.patch
@@ -0,0 +1,61 @@
+From c00adb2a1ac75eaef1e71cd9819636b86eabebd9 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 11 May 2013 23:40:19 +0200
+Subject: [PATCH 70/79] NET: multi phy support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/phy/phy.c | 9 ++++++---
+ include/linux/phy.h | 2 +-
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index ef9ea92..27f9b45 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -800,7 +800,8 @@ void phy_state_machine(struct work_struct *work)
+ * negotiation for now */
+ if (!phydev->link) {
+ phydev->state = PHY_NOLINK;
+- netif_carrier_off(phydev->attached_dev);
++ if (!phydev->no_auto_carrier_off)
++ netif_carrier_off(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ break;
+ }
+@@ -891,7 +892,8 @@ void phy_state_machine(struct work_struct *work)
+ netif_carrier_on(phydev->attached_dev);
+ } else {
+ phydev->state = PHY_NOLINK;
+- netif_carrier_off(phydev->attached_dev);
++ if (!phydev->no_auto_carrier_off)
++ netif_carrier_off(phydev->attached_dev);
+ }
+
+ phydev->adjust_link(phydev->attached_dev);
+@@ -903,7 +905,8 @@ void phy_state_machine(struct work_struct *work)
+ case PHY_HALTED:
+ if (phydev->link) {
+ phydev->link = 0;
+- netif_carrier_off(phydev->attached_dev);
++ if (!phydev->no_auto_carrier_off)
++ netif_carrier_off(phydev->attached_dev);
+ phydev->adjust_link(phydev->attached_dev);
+ }
+ break;
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 93b3cf7..c09b4ad 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -298,7 +298,7 @@ struct phy_device {
+
+ struct phy_c45_device_ids c45_ids;
+ bool is_c45;
+-
++ bool no_auto_carrier_off;
+ enum phy_state state;
+
+ u32 dev_flags;
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch
new file mode 100644
index 0000000..5e35b5b
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0072-NET-MIPS-add-ralink-SoC-ethernet-driver.patch
@@ -0,0 +1,4732 @@
+From 34564578e57bd2bffddbd5f463c55db4a220f2a0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 18:52:00 +0200
+Subject: [PATCH 72/79] 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/ralink/Kconfig | 31 +
+ drivers/net/ethernet/ralink/Makefile | 18 +
+ drivers/net/ethernet/ralink/esw_rt3052.c | 1463 ++++++++++++++++++++
+ drivers/net/ethernet/ralink/esw_rt3052.h | 32 +
+ drivers/net/ethernet/ralink/gsw_mt7620a.c | 1027 ++++++++++++++
+ drivers/net/ethernet/ralink/gsw_mt7620a.h | 29 +
+ drivers/net/ethernet/ralink/mdio.c | 245 ++++
+ drivers/net/ethernet/ralink/mdio.h | 29 +
+ drivers/net/ethernet/ralink/mdio_rt2880.c | 163 +++
+ drivers/net/ethernet/ralink/mdio_rt2880.h | 25 +
+ drivers/net/ethernet/ralink/ralink_soc_eth.c | 759 ++++++++++
+ drivers/net/ethernet/ralink/ralink_soc_eth.h | 372 +++++
+ drivers/net/ethernet/ralink/soc_mt7620.c | 111 ++
+ drivers/net/ethernet/ralink/soc_rt2880.c | 51 +
+ drivers/net/ethernet/ralink/soc_rt305x.c | 102 ++
+ drivers/net/ethernet/ralink/soc_rt3883.c | 59 +
+ 20 files changed, 4546 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
+ create mode 100644 drivers/net/ethernet/ralink/Kconfig
+ create mode 100644 drivers/net/ethernet/ralink/Makefile
+ create mode 100644 drivers/net/ethernet/ralink/esw_rt3052.c
+ create mode 100644 drivers/net/ethernet/ralink/esw_rt3052.h
+ create mode 100644 drivers/net/ethernet/ralink/gsw_mt7620a.c
+ create mode 100644 drivers/net/ethernet/ralink/gsw_mt7620a.h
+ create mode 100644 drivers/net/ethernet/ralink/mdio.c
+ create mode 100644 drivers/net/ethernet/ralink/mdio.h
+ create mode 100644 drivers/net/ethernet/ralink/mdio_rt2880.c
+ create mode 100644 drivers/net/ethernet/ralink/mdio_rt2880.h
+ create mode 100644 drivers/net/ethernet/ralink/ralink_soc_eth.c
+ create mode 100644 drivers/net/ethernet/ralink/ralink_soc_eth.h
+ create mode 100644 drivers/net/ethernet/ralink/soc_mt7620.c
+ create mode 100644 drivers/net/ethernet/ralink/soc_rt2880.c
+ create mode 100644 drivers/net/ethernet/ralink/soc_rt305x.c
+ create mode 100644 drivers/net/ethernet/ralink/soc_rt3883.c
+
+diff --git a/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h b/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h
+new file mode 100644
+index 0000000..2098c5c
+--- /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 */
+diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
+index ca7ee3a..1a6b458 100644
+--- 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);
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index e4ff389..08c3c93 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -137,6 +137,7 @@ source "drivers/net/ethernet/pasemi/Kconfig"
+ source "drivers/net/ethernet/qlogic/Kconfig"
+ source "drivers/net/ethernet/racal/Kconfig"
+ source "drivers/net/ethernet/realtek/Kconfig"
++source "drivers/net/ethernet/ralink/Kconfig"
+ source "drivers/net/ethernet/renesas/Kconfig"
+ source "drivers/net/ethernet/rdc/Kconfig"
+
+diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
+index d447307..f6bffb1 100644
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -55,6 +55,7 @@ obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
+ obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
+ obj-$(CONFIG_NET_VENDOR_RACAL) += racal/
+ obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
++obj-$(CONFIG_NET_RALINK) += ralink/
+ obj-$(CONFIG_SH_ETH) += renesas/
+ obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
+ obj-$(CONFIG_S6GMAC) += s6gmac.o
+diff --git a/drivers/net/ethernet/ralink/Kconfig b/drivers/net/ethernet/ralink/Kconfig
+new file mode 100644
+index 0000000..ca2c9ad
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/Kconfig
+@@ -0,0 +1,31 @@
++config NET_RALINK
++ tristate "Ralink RT288X/RT3X5X/RT3662/RT3883/MT7620 ethernet driver"
++ depends on RALINK
++ help
++ This driver supports the ethernet mac inside the ralink wisocs
++
++if NET_RALINK
++
++config NET_RALINK_MDIO
++ def_bool NET_RALINK
++ depends on (SOC_RT288X || SOC_RT3883 || SOC_MT7620)
++ select PHYLIB
++
++config NET_RALINK_MDIO_RT2880
++ def_bool NET_RALINK
++ depends on (SOC_RT288X || SOC_RT3883)
++ select NET_RALINK_MDIO
++
++config NET_RALINK_ESW_RT3052
++ def_bool NET_RALINK
++ depends on SOC_RT305X
++ select PHYLIB
++ select SWCONFIG
++
++config NET_RALINK_GSW_MT7620
++ def_bool NET_RALINK
++ depends on SOC_MT7620
++ select NET_RALINK_MDIO
++ select PHYLIB
++ select SWCONFIG
++endif
+diff --git a/drivers/net/ethernet/ralink/Makefile b/drivers/net/ethernet/ralink/Makefile
+new file mode 100644
+index 0000000..a38fa21
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/Makefile
+@@ -0,0 +1,18 @@
++#
++# Makefile for the Ralink SoCs built-in ethernet macs
++#
++
++ralink-eth-y += ralink_soc_eth.o
++
++ralink-eth-$(CONFIG_NET_RALINK_MDIO) += mdio.o
++ralink-eth-$(CONFIG_NET_RALINK_MDIO_RT2880) += mdio_rt2880.o
++
++ralink-eth-$(CONFIG_NET_RALINK_ESW_RT3052) += esw_rt3052.o
++ralink-eth-$(CONFIG_NET_RALINK_GSW_MT7620) += gsw_mt7620a.o
++
++ralink-eth-$(CONFIG_SOC_RT288X) += soc_rt2880.o
++ralink-eth-$(CONFIG_SOC_RT305X) += soc_rt305x.o
++ralink-eth-$(CONFIG_SOC_RT3883) += soc_rt3883.o
++ralink-eth-$(CONFIG_SOC_MT7620) += soc_mt7620.o
++
++obj-$(CONFIG_NET_RALINK) += ralink-eth.o
+diff --git a/drivers/net/ethernet/ralink/esw_rt3052.c b/drivers/net/ethernet/ralink/esw_rt3052.c
+new file mode 100644
+index 0000000..b937062
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/esw_rt3052.c
+@@ -0,0 +1,1463 @@
++/*
++ * 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-2013 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/of_device.h>
++#include <linux/clk.h>
++#include <linux/of_net.h>
++#include <linux/of_mdio.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++
++#include <linux/ioport.h>
++#include <linux/switch.h>
++#include <linux/mii.h>
++
++#include <ralink_regs.h>
++#include <asm/mach-ralink/rt305x.h>
++#include <asm/mach-ralink/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_PXPC(_x) (0xe8 + (4 * _x))
++#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_GSC_BC_STROM_MASK 0x3
++#define RT305X_ESW_GSC_BC_STROM_SHIFT 4
++
++#define RT305X_ESW_GSC_LED_FREQ_MASK 0x3
++#define RT305X_ESW_GSC_LED_FREQ_SHIFT 23
++
++#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
++
++#define RT5350_ESW_REG_PXTPC(_x) (0x150 + (4 * _x))
++#define RT5350_EWS_REG_LED_POLARITY 0x168
++#define RT5350_RESET_EPHY BIT(24)
++#define SYSC_REG_RESET_CTRL 0x34
++
++enum {
++ /* Global attributes. */
++ RT305X_ESW_ATTR_ENABLE_VLAN,
++ RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
++ RT305X_ESW_ATTR_BC_STATUS,
++ RT305X_ESW_ATTR_LED_FREQ,
++ /* 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,
++ RT5350_ESW_ATTR_PORT_TR_BAD,
++ RT5350_ESW_ATTR_PORT_TR_GOOD,
++};
++
++struct esw_port {
++ bool disable;
++ bool doubletag;
++ bool untag;
++ u8 led;
++ u16 pvid;
++};
++
++struct 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;
++ unsigned int reg_led_polarity;
++
++
++ struct switch_dev swdev;
++ bool global_vlan_enable;
++ bool alt_vlan_disable;
++ int bc_storm_protect;
++ int led_frequency;
++ struct esw_vlan vlans[RT305X_ESW_NUM_VLANS];
++ struct esw_port ports[RT305X_ESW_NUM_PORTS];
++
++};
++
++static inline void esw_w32(struct rt305x_esw *esw, u32 val, unsigned reg)
++{
++ __raw_writel(val, esw->base + reg);
++}
++
++static inline u32 esw_r32(struct rt305x_esw *esw, unsigned reg)
++{
++ return __raw_readl(esw->base + reg);
++}
++
++static inline void 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 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);
++ 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 (!(esw_r32(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;
++ esw_w32(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 (esw_r32(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 esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan)
++{
++ unsigned s;
++ unsigned val;
++
++ s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
++ val = esw_r32(esw, RT305X_ESW_REG_VLANI(vlan / 2));
++ val = (val >> s) & RT305X_ESW_VLANI_VID_M;
++
++ return val;
++}
++
++static void esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid)
++{
++ unsigned s;
++
++ s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
++ esw_rmw(esw,
++ RT305X_ESW_REG_VLANI(vlan / 2),
++ RT305X_ESW_VLANI_VID_M << s,
++ (vid & RT305X_ESW_VLANI_VID_M) << s);
++}
++
++static unsigned esw_get_pvid(struct rt305x_esw *esw, unsigned port)
++{
++ unsigned s, val;
++
++ s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
++ val = esw_r32(esw, RT305X_ESW_REG_PVIDC(port / 2));
++ return (val >> s) & RT305X_ESW_PVIDC_PVID_M;
++}
++
++static void esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid)
++{
++ unsigned s;
++
++ s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
++ esw_rmw(esw,
++ RT305X_ESW_REG_PVIDC(port / 2),
++ RT305X_ESW_PVIDC_PVID_M << s,
++ (pvid & RT305X_ESW_PVIDC_PVID_M) << s);
++}
++
++static unsigned esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan)
++{
++ unsigned s, val;
++
++ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
++ val = esw_r32(esw, RT305X_ESW_REG_VMSC(vlan / 4));
++ val = (val >> s) & RT305X_ESW_VMSC_MSC_M;
++
++ return val;
++}
++
++static void esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
++{
++ unsigned s;
++
++ s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
++ esw_rmw(esw,
++ RT305X_ESW_REG_VMSC(vlan / 4),
++ RT305X_ESW_VMSC_MSC_M << s,
++ (msc & RT305X_ESW_VMSC_MSC_M) << s);
++}
++
++static unsigned esw_get_port_disable(struct rt305x_esw *esw)
++{
++ unsigned reg;
++ reg = esw_r32(esw, RT305X_ESW_REG_POC0);
++ return (reg >> RT305X_ESW_POC0_DIS_PORT_S) &
++ RT305X_ESW_POC0_DIS_PORT_M;
++}
++
++static void esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask)
++{
++ unsigned old_mask;
++ unsigned enable_mask;
++ unsigned changed;
++ int i;
++
++ old_mask = esw_get_port_disable(esw);
++ changed = old_mask ^ disable_mask;
++ enable_mask = old_mask & disable_mask;
++
++ /* enable before writing to MII */
++ 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 */
++ 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 void esw_set_gsc(struct rt305x_esw *esw)
++{
++ esw_rmw(esw, RT305X_ESW_REG_SGC,
++ RT305X_ESW_GSC_BC_STROM_MASK << RT305X_ESW_GSC_BC_STROM_SHIFT,
++ esw->bc_storm_protect << RT305X_ESW_GSC_BC_STROM_SHIFT);
++ esw_rmw(esw, RT305X_ESW_REG_SGC,
++ RT305X_ESW_GSC_LED_FREQ_MASK << RT305X_ESW_GSC_LED_FREQ_SHIFT,
++ esw->led_frequency << RT305X_ESW_GSC_LED_FREQ_SHIFT);
++}
++
++static int esw_apply_config(struct switch_dev *dev);
++
++static void esw_hw_init(struct rt305x_esw *esw)
++{
++ int i;
++ u8 port_disable = 0;
++ u8 port_map = RT305X_ESW_PMAP_LLLLLL;
++
++ /* vodoo from original driver */
++ esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
++ esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2);
++ /* Port priority 1 for all ports, vlan enabled. */
++ esw_w32(esw, 0x00005555 |
++ (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S),
++ RT305X_ESW_REG_PFC1);
++
++ /* Enable Back Pressure, and Flow Control */
++ esw_w32(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 */
++ esw_w32(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)
++ esw_w32(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2);
++ else
++ esw_w32(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.
++ */
++ esw_w32(esw, 0x0008a301, RT305X_ESW_REG_SGC);
++
++ /* Setup SoC Port control register */
++ esw_w32(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)
++ esw_w32(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
++ else
++ esw_w32(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
++ esw_w32(esw, 0x00000000, RT305X_ESW_REG_FPA);
++
++ /* Force Link/Activity on ports */
++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P0LED);
++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P1LED);
++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P2LED);
++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P3LED);
++ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P4LED);
++
++ /* Copy disabled port configuration from bootloader setup */
++ port_disable = esw_get_port_disable(esw);
++ for (i = 0; i < 6; i++)
++ esw->ports[i].disable = (port_disable & (1 << i)) != 0;
++
++ if (soc_is_rt3352()) {
++ /* reset EPHY */
++ u32 val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(val | RT5350_RESET_EPHY, SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
++
++ 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 LSB=0 disable PHY */
++ rt305x_mii_write(esw, i, 26, 0x1601);
++ /* TX100/TX10 AD/DA current bias */
++ rt305x_mii_write(esw, i, 29, 0x7016);
++ /* TX100 slew rate control */
++ rt305x_mii_write(esw, i, 30, 0x0038);
++ }
++
++ /* select global register */
++ rt305x_mii_write(esw, 0, 31, 0x0);
++ /* enlarge agcsel threshold 3 and threshold 2 */
++ rt305x_mii_write(esw, 0, 1, 0x4a40);
++ /* enlarge agcsel threshold 5 and threshold 4 */
++ rt305x_mii_write(esw, 0, 2, 0x6254);
++ /* enlarge agcsel threshold */
++ rt305x_mii_write(esw, 0, 3, 0xa17f);
++ rt305x_mii_write(esw, 0,12, 0x7eaa);
++ /* longer TP_IDL tail length */
++ rt305x_mii_write(esw, 0, 14, 0x65);
++ /* increased squelch pulse count threshold. */
++ rt305x_mii_write(esw, 0, 16, 0x0684);
++ /* 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);
++ /* tune TP_IDL tail and head waveform, enable power down slew rate control */
++ rt305x_mii_write(esw, 0, 22, 0x253f);
++ /* set PLL/Receive bias current are calibrated */
++ rt305x_mii_write(esw, 0, 27, 0x2fda);
++ /* change PLL/Receive bias current to internal(RT3350) */
++ rt305x_mii_write(esw, 0, 28, 0xc410);
++ /* change PLL bias current to internal(RT3052_MP3) */
++ rt305x_mii_write(esw, 0, 29, 0x598b);
++ /* select local register */
++ rt305x_mii_write(esw, 0, 31, 0x8000);
++ } else if (soc_is_rt5350()) {
++ /* reset EPHY */
++ u32 val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(val | RT5350_RESET_EPHY, SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
++
++ /* set the led polarity */
++ esw_w32(esw, esw->reg_led_polarity & 0x1F, RT5350_EWS_REG_LED_POLARITY);
++
++ /* local registers */
++ 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 LSB=0 disable PHY */
++ rt305x_mii_write(esw, i, 26, 0x1601);
++ /* TX100/TX10 AD/DA current bias */
++ rt305x_mii_write(esw, i, 29, 0x7015);
++ /* TX100 slew rate control */
++ rt305x_mii_write(esw, i, 30, 0x0038);
++ }
++
++ /* global registers */
++ rt305x_mii_write(esw, 0, 31, 0x0);
++ /* enlarge agcsel threshold 3 and threshold 2 */
++ rt305x_mii_write(esw, 0, 1, 0x4a40);
++ /* enlarge agcsel threshold 5 and threshold 4 */
++ rt305x_mii_write(esw, 0, 2, 0x6254);
++ /* enlarge agcsel threshold 6 */
++ rt305x_mii_write(esw, 0, 3, 0xa17f);
++ rt305x_mii_write(esw, 0, 12, 0x7eaa);
++ /* longer TP_IDL tail length */
++ rt305x_mii_write(esw, 0, 14, 0x65);
++ /* increased squelch pulse count threshold. */
++ rt305x_mii_write(esw, 0, 16, 0x0684);
++ /* 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);
++ /* tune TP_IDL tail and head waveform, enable power down slew rate control */
++ rt305x_mii_write(esw, 0, 22, 0x253f);
++ /* set PLL/Receive bias current are calibrated */
++ rt305x_mii_write(esw, 0, 27, 0x2fda);
++ /* change PLL/Receive bias current to internal(RT3350) */
++ rt305x_mii_write(esw, 0, 28, 0xc410);
++ /* change PLL bias current to internal(RT3052_MP3) */
++ rt305x_mii_write(esw, 0, 29, 0x598b);
++ /* select local register */
++ rt305x_mii_write(esw, 0, 31, 0x8000);
++ } else {
++ 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.
++ */
++ 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. */
++ esw_apply_config(&esw->swdev);
++
++ /* Only unmask the port change interrupt */
++ esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
++}
++
++static irqreturn_t esw_interrupt(int irq, void *_esw)
++{
++ struct rt305x_esw *esw = (struct rt305x_esw *) _esw;
++ u32 status;
++
++ status = esw_r32(esw, RT305X_ESW_REG_ISR);
++ if (status & RT305X_ESW_PORT_ST_CHG) {
++ u32 link = esw_r32(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);
++ }
++ esw_w32(esw, status, RT305X_ESW_REG_ISR);
++
++ return IRQ_HANDLED;
++}
++
++static int 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;
++ }
++ esw_set_vlan_id(esw, i, vid);
++ 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;
++ }
++ esw_set_pvid(esw, i, pvid);
++ if (i < RT305X_ESW_NUM_LEDS)
++ esw_w32(esw, esw->ports[i].led,
++ RT305X_ESW_REG_P0LED + 4*i);
++ }
++
++ esw_set_gsc(esw);
++ esw_set_port_disable(esw, disable);
++ 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);
++ 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);
++ 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
++ */
++ esw_set_vlan_id(esw, 0, 0);
++ esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL);
++ }
++
++ return 0;
++}
++
++static int 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));
++ esw_hw_init(esw);
++
++ return 0;
++}
++
++static int 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 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 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 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_set_bc_status(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->bc_storm_protect = val->value.i & RT305X_ESW_GSC_BC_STROM_MASK;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_bc_status(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->bc_storm_protect;
++
++ return 0;
++}
++
++static int
++rt305x_esw_set_led_freq(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->led_frequency = val->value.i & RT305X_ESW_GSC_LED_FREQ_MASK;
++
++ return 0;
++}
++
++static int
++rt305x_esw_get_led_freq(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->led_frequency;
++
++ return 0;
++}
++
++static int 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 = esw_r32(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 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 = esw_r32(esw, reg);
++ val->value.i = (x >> (idx + shift)) & 1;
++
++ return 0;
++}
++
++static int 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 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 = esw_r32(esw, RT305X_ESW_REG_PXPC(idx));
++ val->value.i = (reg >> shift) & 0xffff;
++
++ return 0;
++}
++
++static int
++esw_get_port_tr_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 == RT5350_ESW_ATTR_PORT_TR_GOOD ? 0 : 16;
++ u32 reg;
++
++ if (!soc_is_rt5350())
++ return -EINVAL;
++
++ if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN)
++ return -EINVAL;
++
++ reg = esw_r32(esw, RT5350_ESW_REG_PXTPC(idx));
++ val->value.i = (reg >> shift) & 0xffff;
++
++ return 0;
++}
++
++static int 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 = esw_r32(esw, RT305X_ESW_REG_P0LED + 4*idx);
++
++ return 0;
++}
++
++static int 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 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 = esw_get_pvid(esw, port);
++
++ return 0;
++}
++
++static int 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 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 (esw_get_vlan_id(esw, i) == val->port_vlan &&
++ esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) {
++ vlan_idx = i;
++ break;
++ }
++ }
++
++ if (vlan_idx == -1)
++ return -EINVAL;
++
++ vmsc = esw_get_vmsc(esw, vlan_idx);
++ poc2 = esw_r32(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 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 esw_global[] = {
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "enable_vlan",
++ .description = "VLAN mode (1:enabled)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_ENABLE_VLAN,
++ .get = esw_get_vlan_enable,
++ .set = 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 = esw_get_alt_vlan_disable,
++ .set = esw_set_alt_vlan_disable,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "bc_storm_protect",
++ .description = "Global broadcast storm protection (0:Disable, 1:64 blocks, 2:96 blocks, 3:128 blocks)",
++ .max = 3,
++ .id = RT305X_ESW_ATTR_BC_STATUS,
++ .get = rt305x_esw_get_bc_status,
++ .set = rt305x_esw_set_bc_status,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "led_frequency",
++ .description = "LED Flash frequency (0:30mS, 1:60mS, 2:240mS, 3:480mS)",
++ .max = 3,
++ .id = RT305X_ESW_ATTR_LED_FREQ,
++ .get = rt305x_esw_get_led_freq,
++ .set = rt305x_esw_set_led_freq,
++ }
++};
++
++static const struct switch_attr esw_port[] = {
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "disable",
++ .description = "Port state (1:disabled)",
++ .max = 1,
++ .id = RT305X_ESW_ATTR_PORT_DISABLE,
++ .get = esw_get_port_bool,
++ .set = 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 = esw_get_port_bool,
++ .set = 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 = esw_get_port_bool,
++ .set = 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, 11:off, 12:on)",
++ .max = 15,
++ .id = RT305X_ESW_ATTR_PORT_LED,
++ .get = esw_get_port_led,
++ .set = 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 = esw_get_port_bool,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "recv_bad",
++ .description = "Receive bad packet counter",
++ .id = RT305X_ESW_ATTR_PORT_RECV_BAD,
++ .get = 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 = esw_get_port_recv_badgood,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "tr_bad",
++
++ .description = "Transmit bad packet counter. rt5350 only",
++ .id = RT5350_ESW_ATTR_PORT_TR_BAD,
++ .get = esw_get_port_tr_badgood,
++ },
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "tr_good",
++
++ .description = "Transmit good packet counter. rt5350 only",
++ .id = RT5350_ESW_ATTR_PORT_TR_GOOD,
++ .get = esw_get_port_tr_badgood,
++ },
++};
++
++static const struct switch_attr esw_vlan[] = {
++};
++
++static const struct switch_dev_ops esw_ops = {
++ .attr_global = {
++ .attr = esw_global,
++ .n_attr = ARRAY_SIZE(esw_global),
++ },
++ .attr_port = {
++ .attr = esw_port,
++ .n_attr = ARRAY_SIZE(esw_port),
++ },
++ .attr_vlan = {
++ .attr = esw_vlan,
++ .n_attr = ARRAY_SIZE(esw_vlan),
++ },
++ .get_vlan_ports = esw_get_vlan_ports,
++ .set_vlan_ports = esw_set_vlan_ports,
++ .get_port_pvid = esw_get_port_pvid,
++ .set_port_pvid = esw_set_port_pvid,
++ .get_port_link = esw_get_port_link,
++ .apply_config = esw_apply_config,
++ .reset_switch = 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 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);
++
++ reg_init = of_get_property(np, "ralink,led_polarity", NULL);
++ if (reg_init)
++ esw->reg_led_polarity = 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 = &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);
++
++ esw_hw_init(esw);
++
++ esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR);
++ esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
++ request_irq(esw->irq, esw_interrupt, 0, "esw", esw);
++
++ return 0;
++
++unmap_base:
++ iounmap(esw->base);
++free_esw:
++ kfree(esw);
++ return err;
++}
++
++static int 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 esw_driver = {
++ .probe = esw_probe,
++ .remove = esw_remove,
++ .driver = {
++ .name = "rt305x-esw",
++ .owner = THIS_MODULE,
++ .of_match_table = ralink_esw_match,
++ },
++};
++
++int __init rtesw_init(void)
++{
++ return platform_driver_register(&esw_driver);
++}
++
++void rtesw_exit(void)
++{
++ platform_driver_unregister(&esw_driver);
++}
+diff --git a/drivers/net/ethernet/ralink/esw_rt3052.h b/drivers/net/ethernet/ralink/esw_rt3052.h
+new file mode 100644
+index 0000000..2ced3dff
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/esw_rt3052.h
+@@ -0,0 +1,32 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _RALINK_ESW_RT3052_H__
++#define _RALINK_ESW_RT3052_H__
++
++#ifdef CONFIG_NET_RALINK_ESW_RT3052
++
++int __init rtesw_init(void);
++void rtesw_exit(void);
++
++#else
++
++static inline int __init rtesw_init(void) { return 0; }
++static inline void rtesw_exit(void) { }
++
++#endif
++#endif
+diff --git a/drivers/net/ethernet/ralink/gsw_mt7620a.c b/drivers/net/ethernet/ralink/gsw_mt7620a.c
+new file mode 100644
+index 0000000..9fa6a54
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/gsw_mt7620a.c
+@@ -0,0 +1,1027 @@
++/*
++ * 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-2013 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/of_device.h>
++#include <linux/clk.h>
++#include <linux/of_net.h>
++#include <linux/of_mdio.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/switch.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++
++#include <linux/ioport.h>
++#include <linux/switch.h>
++#include <linux/mii.h>
++
++#include <ralink_regs.h>
++#include <asm/mach-ralink/mt7620.h>
++
++#include "ralink_soc_eth.h"
++#include "gsw_mt7620a.h"
++#include "mdio.h"
++
++#define GSW_REG_PHY_TIMEOUT (5 * HZ)
++
++#define MT7620A_GSW_REG_PIAC 0x7004
++
++#define GSW_NUM_VLANS 16
++#define GSW_NUM_VIDS 4096
++#define GSW_NUM_PORTS 7
++#define GSW_PORT6 6
++
++#define GSW_MDIO_ACCESS BIT(31)
++#define GSW_MDIO_READ BIT(19)
++#define GSW_MDIO_WRITE BIT(18)
++#define GSW_MDIO_START BIT(16)
++#define GSW_MDIO_ADDR_SHIFT 20
++#define GSW_MDIO_REG_SHIFT 25
++
++#define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100))
++#define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100))
++#define GSW_REG_SMACCR0 0x3fE4
++#define GSW_REG_SMACCR1 0x3fE8
++#define GSW_REG_CKGCR 0x3ff0
++
++#define GSW_REG_IMR 0x7008
++#define GSW_REG_ISR 0x700c
++
++#define SYSC_REG_CFG1 0x14
++
++#define PORT_IRQ_ST_CHG 0x7f
++
++#define GSW_VLAN_VTCR 0x90
++#define GSW_VLAN_VTCR_VID_M 0xfff
++#define GSW_VLAN_ID(_x) (0x100 + (4 * (_x)))
++#define GSW_VLAN_ID_VID_S 12
++#define GSW_VLAN_ID_VID_M 0xfff
++
++#define GSW_VAWD1 0x94
++#define GSW_VAWD1_VTAG_EN BIT(28)
++#define GSW_VAWD1_PORTM_S 16
++#define GSW_VAWD1_PORTM_M 0xff
++
++#define GSW_VAWD2 0x98
++#define GSW_VAWD2_PORTT_S 16
++#define GSW_VAWD2_PORTT_M 0xff
++
++#define GSW_VTIM(_x) (0x100 + (4 * (_x)))
++#define GSW_VTIM_M 0xfff
++#define GSW_VTIM_S 12
++
++#define GSW_REG_PCR(x) (0x2004 + (x * 0x100))
++#define GSW_REG_PCR_EG_TAG_S 28
++#define GSW_REG_PCR_EG_TAG_M 0x3
++
++#define SYSCFG1 0x14
++
++#define ESW_PHY_POLLING 0x7000
++
++#define PMCR_IPG BIT(18)
++#define PMCR_MAC_MODE BIT(16)
++#define PMCR_FORCE BIT(15)
++#define PMCR_TX_EN BIT(14)
++#define PMCR_RX_EN BIT(13)
++#define PMCR_BACKOFF BIT(9)
++#define PMCR_BACKPRES BIT(8)
++#define PMCR_RX_FC BIT(5)
++#define PMCR_TX_FC BIT(4)
++#define PMCR_SPEED(_x) (_x << 2)
++#define PMCR_DUPLEX BIT(1)
++#define PMCR_LINK BIT(0)
++
++#define PHY_AN_EN BIT(31)
++#define PHY_PRE_EN BIT(30)
++#define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24)
++
++enum {
++ /* Global attributes. */
++ GSW_ATTR_ENABLE_VLAN,
++ /* Port attributes. */
++ GSW_ATTR_PORT_UNTAG,
++};
++
++enum {
++ PORT4_EPHY = 0,
++ PORT4_EXT,
++};
++
++struct gsw_port {
++ bool disable;
++ bool untag;
++ u16 pvid;
++};
++
++struct gsw_vlan {
++ u8 ports;
++ u16 vid;
++};
++
++struct mt7620_gsw {
++ struct device *dev;
++ void __iomem *base;
++ int irq;
++
++ struct switch_dev swdev;
++ bool global_vlan_enable;
++ struct gsw_vlan vlans[GSW_NUM_VLANS];
++ struct gsw_port ports[GSW_NUM_PORTS];
++ long unsigned int autopoll;
++ int port4;
++};
++
++static inline void gsw_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg)
++{
++ iowrite32(val, gsw->base + reg);
++}
++
++static inline u32 gsw_r32(struct mt7620_gsw *gsw, unsigned reg)
++{
++ return ioread32(gsw->base + reg);
++}
++
++static int mt7620_mii_busy_wait(struct mt7620_gsw *gsw)
++{
++ unsigned long t_start = jiffies;
++
++ while (1) {
++ if (!(gsw_r32(gsw, MT7620A_GSW_REG_PIAC) & GSW_MDIO_ACCESS))
++ return 0;
++ if (time_after(jiffies, t_start + GSW_REG_PHY_TIMEOUT)) {
++ break;
++ }
++ }
++
++ printk(KERN_ERR "mdio: MDIO timeout\n");
++ return -1;
++}
++
++static u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, u32 phy_register,
++ u32 write_data)
++{
++ if (mt7620_mii_busy_wait(gsw))
++ return -1;
++
++ write_data &= 0xffff;
++
++ gsw_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_WRITE |
++ (phy_register << GSW_MDIO_REG_SHIFT) |
++ (phy_addr << GSW_MDIO_ADDR_SHIFT) | write_data,
++ MT7620A_GSW_REG_PIAC);
++
++ if (mt7620_mii_busy_wait(gsw))
++ return -1;
++
++ return 0;
++}
++
++int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
++{
++ struct fe_priv *priv = bus->priv;
++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
++
++ return _mt7620_mii_write(gsw, phy_addr, phy_reg, val);
++}
++
++int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
++{
++ struct fe_priv *priv = bus->priv;
++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
++ u32 d;
++
++ if (mt7620_mii_busy_wait(gsw))
++ return 0xffff;
++
++ gsw_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_READ |
++ (phy_reg << GSW_MDIO_REG_SHIFT) |
++ (phy_addr << GSW_MDIO_ADDR_SHIFT),
++ MT7620A_GSW_REG_PIAC);
++
++ if (mt7620_mii_busy_wait(gsw))
++ return 0xffff;
++
++ d = gsw_r32(gsw, MT7620A_GSW_REG_PIAC) & 0xffff;
++
++ return d;
++}
++
++static unsigned char *fe_speed_str(int speed)
++{
++ switch (speed) {
++ case 2:
++ case SPEED_1000:
++ return "1000";
++ case 1:
++ case SPEED_100:
++ return "100";
++ case 0:
++ case SPEED_10:
++ return "10";
++ }
++
++ return "? ";
++}
++
++int mt7620a_has_carrier(struct fe_priv *priv)
++{
++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
++ int i;
++
++ for (i = 0; i < GSW_PORT6; i++)
++ if (gsw_r32(gsw, GSW_REG_PORT_STATUS(i)) & 0x1)
++ return 1;
++ return 0;
++}
++
++static void mt7620a_handle_carrier(struct fe_priv *priv)
++{
++ if (!priv->phy)
++ return;
++
++ if (mt7620a_has_carrier(priv))
++ netif_carrier_on(priv->netdev);
++ else
++ netif_carrier_off(priv->netdev);
++}
++
++void mt7620_mdio_link_adjust(struct fe_priv *priv, int port)
++{
++ if (priv->link[port])
++ netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n",
++ port, fe_speed_str(priv->phy->speed[port]),
++ (DUPLEX_FULL == priv->phy->duplex[port]) ? "Full" : "Half");
++ else
++ netdev_info(priv->netdev, "port %d link down\n", port);
++ mt7620a_handle_carrier(priv);
++}
++
++static irqreturn_t gsw_interrupt(int irq, void *_priv)
++{
++ struct fe_priv *priv = (struct fe_priv *) _priv;
++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
++ u32 status;
++ int i, max = (gsw->port4 == PORT4_EPHY) ? (4) : (3);
++
++ status = gsw_r32(gsw, GSW_REG_ISR);
++ if (status & PORT_IRQ_ST_CHG)
++ for (i = 0; i <= max; i++) {
++ u32 status = gsw_r32(gsw, GSW_REG_PORT_STATUS(i));
++ int link = status & 0x1;
++
++ if (link != priv->link[i]) {
++ if (link)
++ netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n",
++ i, fe_speed_str((status >> 2) & 3),
++ (status & 0x2) ? "Full" : "Half");
++ else
++ netdev_info(priv->netdev, "port %d link down\n", i);
++ }
++
++ priv->link[i] = link;
++ }
++ mt7620a_handle_carrier(priv);
++
++ gsw_w32(gsw, status, GSW_REG_ISR);
++
++ return IRQ_HANDLED;
++}
++
++static int mt7620_is_bga(void)
++{
++ u32 bga = rt_sysc_r32(0x0c);
++
++ return (bga >> 16) & 1;
++}
++
++static void gsw_auto_poll(struct mt7620_gsw *gsw)
++{
++ int phy;
++ int lsb = -1, msb = 0;
++
++ for_each_set_bit(phy, &gsw->autopoll, 32) {
++ if (lsb < 0)
++ lsb = phy;
++ msb = phy;
++ }
++
++ gsw_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | (msb << 8) | lsb, ESW_PHY_POLLING);
++}
++
++void mt7620_port_init(struct fe_priv *priv, struct device_node *np)
++{
++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
++ const __be32 *_id = of_get_property(np, "reg", NULL);
++ int phy_mode, size, id;
++ int shift = 12;
++ u32 val, mask = 0;
++ int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4);
++
++ if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) {
++ if (_id)
++ pr_err("%s: invalid port id %d\n", np->name, be32_to_cpu(*_id));
++ else
++ pr_err("%s: invalid port id\n", np->name);
++ return;
++ }
++
++ id = be32_to_cpu(*_id);
++
++ if (id == 4)
++ shift = 14;
++
++ priv->phy->phy_fixed[id] = of_get_property(np, "ralink,fixed-link", &size);
++ if (priv->phy->phy_fixed[id] && (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) {
++ pr_err("%s: invalid fixed link property\n", np->name);
++ priv->phy->phy_fixed[id] = NULL;
++ return;
++ }
++
++ phy_mode = of_get_phy_mode(np);
++ switch (phy_mode) {
++ case PHY_INTERFACE_MODE_RGMII:
++ mask = 0;
++ break;
++ case PHY_INTERFACE_MODE_MII:
++ mask = 1;
++ break;
++ case PHY_INTERFACE_MODE_RMII:
++ mask = 2;
++ break;
++ default:
++ dev_err(priv->device, "port %d - invalid phy mode\n", priv->phy->speed[id]);
++ return;
++ }
++
++ priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0);
++ if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id])
++ return;
++
++ val = rt_sysc_r32(SYSCFG1);
++ val &= ~(3 << shift);
++ val |= mask << shift;
++ rt_sysc_w32(val, SYSCFG1);
++
++ if (priv->phy->phy_fixed[id]) {
++ const __be32 *link = priv->phy->phy_fixed[id];
++ int tx_fc = be32_to_cpup(link++);
++ int rx_fc = be32_to_cpup(link++);
++ u32 val = 0;
++
++ priv->phy->speed[id] = be32_to_cpup(link++);
++ priv->phy->duplex[id] = be32_to_cpup(link++);
++ priv->link[id] = 1;
++
++ switch (priv->phy->speed[id]) {
++ case SPEED_10:
++ val = 0;
++ break;
++ case SPEED_100:
++ val = 1;
++ break;
++ case SPEED_1000:
++ val = 2;
++ break;
++ default:
++ dev_err(priv->device, "invalid link speed: %d\n", priv->phy->speed[id]);
++ priv->phy->phy_fixed[id] = 0;
++ return;
++ }
++ val = PMCR_SPEED(val);
++ val |= PMCR_LINK | PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN |
++ PMCR_TX_EN | PMCR_FORCE | PMCR_MAC_MODE | PMCR_IPG;
++ if (tx_fc)
++ val |= PMCR_TX_FC;
++ if (rx_fc)
++ val |= PMCR_RX_FC;
++ if (priv->phy->duplex[id])
++ val |= PMCR_DUPLEX;
++ gsw_w32(gsw, val, GSW_REG_PORT_PMCR(id));
++ dev_info(priv->device, "using fixed link parameters\n");
++ return;
++ }
++
++ if (priv->phy->phy_node[id] && priv->mii_bus->phy_map[id]) {
++ u32 val = PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN |
++ PMCR_TX_EN | PMCR_MAC_MODE | PMCR_IPG;
++
++ gsw_w32(gsw, val, GSW_REG_PORT_PMCR(id));
++ fe_connect_phy_node(priv, priv->phy->phy_node[id]);
++ gsw->autopoll |= BIT(id);
++ gsw_auto_poll(gsw);
++ return;
++ }
++}
++
++static void gsw_hw_init(struct mt7620_gsw *gsw)
++{
++ u32 is_BGA = mt7620_is_bga();
++
++ rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1);
++ gsw_w32(gsw, gsw_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR);
++
++ /*correct PHY setting L3.0 BGA*/
++ _mt7620_mii_write(gsw, 1, 31, 0x4000); //global, page 4
++
++ _mt7620_mii_write(gsw, 1, 17, 0x7444);
++ if (is_BGA)
++ _mt7620_mii_write(gsw, 1, 19, 0x0114);
++ else
++ _mt7620_mii_write(gsw, 1, 19, 0x0117);
++
++ _mt7620_mii_write(gsw, 1, 22, 0x10cf);
++ _mt7620_mii_write(gsw, 1, 25, 0x6212);
++ _mt7620_mii_write(gsw, 1, 26, 0x0777);
++ _mt7620_mii_write(gsw, 1, 29, 0x4000);
++ _mt7620_mii_write(gsw, 1, 28, 0xc077);
++ _mt7620_mii_write(gsw, 1, 24, 0x0000);
++
++ _mt7620_mii_write(gsw, 1, 31, 0x3000); //global, page 3
++ _mt7620_mii_write(gsw, 1, 17, 0x4838);
++
++ _mt7620_mii_write(gsw, 1, 31, 0x2000); //global, page 2
++ if (is_BGA) {
++ _mt7620_mii_write(gsw, 1, 21, 0x0515);
++ _mt7620_mii_write(gsw, 1, 22, 0x0053);
++ _mt7620_mii_write(gsw, 1, 23, 0x00bf);
++ _mt7620_mii_write(gsw, 1, 24, 0x0aaf);
++ _mt7620_mii_write(gsw, 1, 25, 0x0fad);
++ _mt7620_mii_write(gsw, 1, 26, 0x0fc1);
++ } else {
++ _mt7620_mii_write(gsw, 1, 21, 0x0517);
++ _mt7620_mii_write(gsw, 1, 22, 0x0fd2);
++ _mt7620_mii_write(gsw, 1, 23, 0x00bf);
++ _mt7620_mii_write(gsw, 1, 24, 0x0aab);
++ _mt7620_mii_write(gsw, 1, 25, 0x00ae);
++ _mt7620_mii_write(gsw, 1, 26, 0x0fff);
++ }
++ _mt7620_mii_write(gsw, 1, 31, 0x1000); //global, page 1
++ _mt7620_mii_write(gsw, 1, 17, 0xe7f8);
++
++ _mt7620_mii_write(gsw, 1, 31, 0x8000); //local, page 0
++ _mt7620_mii_write(gsw, 0, 30, 0xa000);
++ _mt7620_mii_write(gsw, 1, 30, 0xa000);
++ _mt7620_mii_write(gsw, 2, 30, 0xa000);
++ _mt7620_mii_write(gsw, 3, 30, 0xa000);
++
++ _mt7620_mii_write(gsw, 0, 4, 0x05e1);
++ _mt7620_mii_write(gsw, 1, 4, 0x05e1);
++ _mt7620_mii_write(gsw, 2, 4, 0x05e1);
++ _mt7620_mii_write(gsw, 3, 4, 0x05e1);
++ _mt7620_mii_write(gsw, 1, 31, 0xa000); //local, page 2
++ _mt7620_mii_write(gsw, 0, 16, 0x1111);
++ _mt7620_mii_write(gsw, 1, 16, 0x1010);
++ _mt7620_mii_write(gsw, 2, 16, 0x1515);
++ _mt7620_mii_write(gsw, 3, 16, 0x0f0f);
++
++ /* CPU Port6 Force Link 1G, FC ON */
++ gsw_w32(gsw, 0x5e33b, GSW_REG_PORT_PMCR(6));
++ /* Set Port6 CPU Port */
++ gsw_w32(gsw, 0x7f7f7fe0, 0x0010);
++
++// GSW_VAWD2
++
++ /* setup port 4 */
++ if (gsw->port4 == PORT4_EPHY) {
++ u32 val = rt_sysc_r32(SYSCFG1);
++ val |= 3 << 14;
++ rt_sysc_w32(val, SYSCFG1);
++ _mt7620_mii_write(gsw, 4, 30, 0xa000);
++ _mt7620_mii_write(gsw, 4, 4, 0x05e1);
++ _mt7620_mii_write(gsw, 4, 16, 0x1313);
++ pr_info("gsw: setting port4 to ephy mode\n");
++ }
++}
++
++static int gsw_reset_switch(struct switch_dev *dev)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++
++ gsw->global_vlan_enable = 0;
++ memset(gsw->ports, 0, sizeof(gsw->ports));
++ memset(gsw->vlans, 0, sizeof(gsw->vlans));
++ gsw_hw_init(gsw);
++
++ return 0;
++}
++
++static int gsw_get_vlan_enable(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++
++ val->value.i = gsw->global_vlan_enable;
++
++ return 0;
++}
++
++static int gsw_set_vlan_enable(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++
++ gsw->global_vlan_enable = val->value.i != 0;
++
++ return 0;
++}
++
++static unsigned gsw_get_pvid(struct mt7620_gsw *gsw, unsigned port)
++{
++ unsigned s, val;
++
++ s = GSW_VTIM_S * (port % 2);
++ val = gsw_r32(gsw, GSW_VTIM(port / 2));
++
++ return (val >> s) & GSW_VTIM_M;
++}
++
++static void gsw_set_pvid(struct mt7620_gsw *gsw, unsigned port, unsigned pvid)
++{
++ unsigned s, val;
++
++ s = GSW_VTIM_S * (port % 2);
++ val = gsw_r32(gsw, GSW_VTIM(port / 2));
++ val &= ~(GSW_VTIM_M << s);
++ val |= (pvid && GSW_VTIM_M) << s;
++ gsw_w32(gsw, val, GSW_VTIM(port / 2));
++}
++
++static int gsw_get_port_bool(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int idx = val->port_vlan;
++
++ if (idx < 0 || idx >= GSW_NUM_PORTS)
++ return -EINVAL;
++
++ switch (attr->id) {
++ case GSW_ATTR_PORT_UNTAG:
++ return gsw->ports[idx].untag;
++ }
++
++ return -EINVAL;
++}
++
++static int gsw_get_port_pvid(struct switch_dev *dev, int port, int *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++
++ if (port >= GSW_NUM_PORTS)
++ return -EINVAL;
++
++ *val = gsw_get_pvid(gsw, port);
++
++ return 0;
++}
++
++static int gsw_set_port_pvid(struct switch_dev *dev, int port, int val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++
++ if (port >= GSW_NUM_PORTS)
++ return -EINVAL;
++
++ gsw->ports[port].pvid = val;
++
++ return 0;
++}
++
++static void gsw_set_vtcr(struct switch_dev *dev, u32 vid)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int retry = 1000;
++
++ gsw_w32(gsw, 0x80000000 | (BIT(vid) & GSW_VLAN_VTCR_VID_M), GSW_VLAN_VTCR);
++ while (retry-- && (gsw_r32(gsw, GSW_VLAN_VTCR) & 0x80000000))
++ ;
++}
++
++static void gsw_apply_vtcr(struct switch_dev *dev, u32 vid)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int retry = 1000;
++
++ gsw_w32(gsw, 0x80001000 | (BIT(vid) & GSW_VLAN_VTCR_VID_M), GSW_VLAN_VTCR);
++ while (retry-- && (gsw_r32(gsw, GSW_VLAN_VTCR) & 0x80000000))
++ ;
++}
++
++static unsigned gsw_get_vlan_id(struct mt7620_gsw *gsw, unsigned vlan)
++{
++ unsigned s;
++ unsigned val;
++
++ s = GSW_VLAN_ID_VID_S * (vlan % 2);
++ val = gsw_r32(gsw, GSW_VLAN_ID(vlan / 2));
++ val = (val >> s) & GSW_VLAN_ID_VID_M;
++
++ return val;
++}
++
++static void gsw_set_vlan_id(struct mt7620_gsw *gsw, unsigned vlan, unsigned vid)
++{
++ unsigned s;
++ unsigned val;
++
++ s = GSW_VLAN_ID_VID_S * (vlan % 2);
++ val = gsw_r32(gsw, GSW_VLAN_ID(vlan / 2));
++ val &= ~(GSW_VLAN_ID_VID_M << s);
++ val |= (vid << s);
++ gsw_w32(gsw, val, GSW_VLAN_ID(vlan / 2));
++}
++
++static void gsw_vlan_tagging_enable(struct mt7620_gsw *gsw, unsigned vlan, unsigned enable)
++{
++ unsigned val;
++
++ val = gsw_r32(gsw, GSW_VAWD1);
++ if (enable)
++ val |= GSW_VAWD1_VTAG_EN;
++ else
++ val &= ~GSW_VAWD1_VTAG_EN;
++ gsw_w32(gsw, val, GSW_VAWD1);
++}
++
++static unsigned gsw_get_port_member(struct mt7620_gsw *gsw, unsigned vlan)
++{
++ unsigned val;
++
++ gsw_set_vtcr(&gsw->swdev, vlan);
++
++ val = gsw_r32(gsw, GSW_VAWD1);
++ val = (val >> GSW_VAWD1_PORTM_S) & GSW_VAWD1_PORTM_M;
++
++ return val;
++}
++
++static void gsw_set_port_member(struct mt7620_gsw *gsw, unsigned vlan, unsigned member)
++{
++ unsigned val;
++
++ val = gsw_r32(gsw, GSW_VAWD1);
++ val = ~(GSW_VAWD1_PORTM_M << GSW_VAWD1_PORTM_S);
++ val |= (member & GSW_VAWD1_PORTM_M) << GSW_VAWD1_PORTM_S;
++ gsw_w32(gsw, val, GSW_VAWD1);
++}
++
++static unsigned gsw_get_port_tag(struct mt7620_gsw *gsw, unsigned port)
++{
++ unsigned val;
++
++ val = gsw_r32(gsw, GSW_REG_PCR(port));
++ val >>= GSW_REG_PCR_EG_TAG_S;
++ val &= GSW_REG_PCR_EG_TAG_M;
++
++ return !!val;
++}
++
++static void gsw_set_port_untag(struct mt7620_gsw *gsw, unsigned port, unsigned untag)
++{
++ unsigned val;
++
++ val = gsw_r32(gsw, GSW_REG_PCR(port));
++ if (!untag)
++ untag = 0x2;
++ else
++ untag = 0;
++ val &= ~(GSW_REG_PCR_EG_TAG_M << GSW_REG_PCR_EG_TAG_S);
++ val |= (untag & GSW_REG_PCR_EG_TAG_M) << GSW_REG_PCR_EG_TAG_S;
++ gsw_w32(gsw, val, GSW_REG_PCR(port));
++}
++
++static int gsw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int vlan_idx = -1;
++ u32 member;
++ int i;
++
++ val->len = 0;
++
++ if (val->port_vlan < 0 || val->port_vlan >= GSW_NUM_VIDS)
++ return -EINVAL;
++
++ /* valid vlan? */
++ for (i = 0; i < GSW_NUM_VLANS; i++) {
++ if (gsw_get_vlan_id(gsw, i) != val->port_vlan)
++ continue;
++ member = gsw_get_port_member(gsw, i);
++ vlan_idx = i;
++ break;
++ }
++
++ if (vlan_idx == -1)
++ return -EINVAL;
++
++ for (i = 0; i < GSW_NUM_PORTS; i++) {
++ struct switch_port *p;
++ int port_mask = 1 << i;
++
++ if (!(member & port_mask))
++ continue;
++
++ p = &val->value.ports[val->len++];
++ p->id = i;
++ if (gsw_get_port_tag(gsw, i))
++ p->flags = 1 << SWITCH_PORT_FLAG_TAGGED;
++ else
++ p->flags = 0;
++ }
++
++ return 0;
++}
++
++static int gsw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int ports;
++ int vlan_idx = -1;
++ int i;
++
++ if (val->port_vlan < 0 || val->port_vlan >= GSW_NUM_VIDS ||
++ val->len > GSW_NUM_PORTS)
++ return -EINVAL;
++
++ /* one of the already defined vlans? */
++ for (i = 0; i < GSW_NUM_VLANS; i++) {
++ if (gsw->vlans[i].vid == val->port_vlan &&
++ gsw->vlans[i].ports) {
++ vlan_idx = i;
++ break;
++ }
++ }
++
++ /* select a free slot */
++ for (i = 0; vlan_idx == -1 && i < GSW_NUM_VLANS; i++) {
++ if (!gsw->vlans[i].ports)
++ vlan_idx = i;
++ }
++
++ /* bail if all slots are in use */
++ if (vlan_idx == -1)
++ return -EINVAL;
++
++ ports = 0;
++ 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 >= GSW_NUM_PORTS)
++ return -EINVAL;
++
++ ports |= port_mask;
++ gsw->ports[p->id].untag = untagged;
++ }
++ gsw->vlans[vlan_idx].ports = ports;
++ if (!ports)
++ gsw->vlans[vlan_idx].vid = 0xfff;
++ else
++ gsw->vlans[vlan_idx].vid = val->port_vlan;
++
++ return 0;
++}
++
++static int gsw_apply_config(struct switch_dev *dev)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int i;
++
++ for (i = 0; i < GSW_NUM_VLANS; i++) {
++ gsw_set_vtcr(&gsw->swdev, i);
++ if (gsw->global_vlan_enable) {
++ gsw_set_vlan_id(gsw, i, gsw->vlans[i].vid);
++ gsw_set_port_member(gsw, i, gsw->vlans[i].ports);
++ gsw_vlan_tagging_enable(gsw, i, 1);
++ } else {
++ gsw_set_vlan_id(gsw, i, 0xfff);
++ gsw_set_port_member(gsw, i, 0);
++ gsw_vlan_tagging_enable(gsw, i, 0);
++ }
++ gsw_apply_vtcr(&gsw->swdev, i);
++ }
++
++ for (i = 0; i < GSW_NUM_PORTS; i++) {
++ if (gsw->global_vlan_enable) {
++ gsw_set_port_untag(gsw, i, !gsw->ports[i].untag);
++ gsw_set_pvid(gsw, i, gsw->ports[i].pvid);
++ } else {
++ gsw_set_port_untag(gsw, i, 0);
++ gsw_set_pvid(gsw, i, 0);
++ }
++ }
++
++ if (!gsw->global_vlan_enable)
++ gsw_set_vlan_id(gsw, 0, 0);
++
++ return 0;
++}
++
++static int gsw_get_port_link(struct switch_dev *dev,
++ int port,
++ struct switch_port_link *link)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ u32 status;
++
++ if (port < 0 || port >= GSW_NUM_PORTS)
++ return -EINVAL;
++
++ status = gsw_r32(gsw, GSW_REG_PORT_STATUS(port));
++ link->link = status & 0x1;
++ link->duplex = (status >> 1) & 1;
++
++ switch ((status >> 2) & 0x3) {
++ 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;
++ }
++
++ return 0;
++}
++
++static int gsw_set_port_bool(struct switch_dev *dev,
++ const struct switch_attr *attr,
++ struct switch_val *val)
++{
++ struct mt7620_gsw *gsw = container_of(dev, struct mt7620_gsw, swdev);
++ int idx = val->port_vlan;
++
++ if (idx < 0 || idx >= GSW_NUM_PORTS ||
++ val->value.i < 0 || val->value.i > 1)
++ return -EINVAL;
++
++ switch (attr->id) {
++ case GSW_ATTR_PORT_UNTAG:
++ gsw->ports[idx].untag = val->value.i;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static const struct switch_attr gsw_global[] = {
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "enable_vlan",
++ .description = "VLAN mode (1:enabled)",
++ .max = 1,
++ .id = GSW_ATTR_ENABLE_VLAN,
++ .get = gsw_get_vlan_enable,
++ .set = gsw_set_vlan_enable,
++ },
++};
++
++static const struct switch_attr gsw_port[] = {
++ {
++ .type = SWITCH_TYPE_INT,
++ .name = "untag",
++ .description = "Untag (1:strip outgoing vlan tag)",
++ .max = 1,
++ .id = GSW_ATTR_PORT_UNTAG,
++ .get = gsw_get_port_bool,
++ .set = gsw_set_port_bool,
++ },
++};
++
++static const struct switch_attr gsw_vlan[] = {
++};
++
++static const struct switch_dev_ops gsw_ops = {
++ .attr_global = {
++ .attr = gsw_global,
++ .n_attr = ARRAY_SIZE(gsw_global),
++ },
++ .attr_port = {
++ .attr = gsw_port,
++ .n_attr = ARRAY_SIZE(gsw_port),
++ },
++ .attr_vlan = {
++ .attr = gsw_vlan,
++ .n_attr = ARRAY_SIZE(gsw_vlan),
++ },
++ .get_vlan_ports = gsw_get_vlan_ports,
++ .set_vlan_ports = gsw_set_vlan_ports,
++ .get_port_pvid = gsw_get_port_pvid,
++ .set_port_pvid = gsw_set_port_pvid,
++ .get_port_link = gsw_get_port_link,
++ .apply_config = gsw_apply_config,
++ .reset_switch = gsw_reset_switch,
++};
++
++void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac)
++{
++ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ gsw_w32(gsw, (mac[0] << 8) | mac[1], GSW_REG_SMACCR1);
++ gsw_w32(gsw, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
++ GSW_REG_SMACCR0);
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++}
++
++static struct of_device_id gsw_match[] = {
++ { .compatible = "ralink,mt7620a-gsw" },
++ {}
++};
++
++int mt7620_gsw_probe(struct fe_priv *priv)
++{
++ struct mt7620_gsw *gsw;
++ struct device_node *np;
++ struct switch_dev *swdev;
++ const char *port4 = NULL;
++
++ np = of_find_matching_node(NULL, gsw_match);
++ if (!np) {
++ dev_err(priv->device, "no gsw node found\n");
++ return -EINVAL;
++ }
++ np = of_node_get(np);
++
++ gsw = devm_kzalloc(priv->device, sizeof(struct mt7620_gsw), GFP_KERNEL);
++ if (!gsw) {
++ dev_err(priv->device, "no gsw memory for private data\n");
++ return -ENOMEM;
++ }
++
++ gsw->irq = irq_of_parse_and_map(np, 0);
++ if (!gsw->irq) {
++ dev_err(priv->device, "no gsw irq resource found\n");
++ return -ENOMEM;
++ }
++
++ gsw->base = of_iomap(np, 0);
++ if (!gsw->base) {
++ dev_err(priv->device, "gsw ioremap failed\n");
++ }
++
++ gsw->dev = priv->device;
++ priv->soc->swpriv = gsw;
++
++ swdev = &gsw->swdev;
++ swdev->of_node = np;
++ swdev->name = "mt7620a-gsw";
++ swdev->alias = "mt7620x";
++ swdev->cpu_port = GSW_PORT6;
++ swdev->ports = GSW_NUM_PORTS;
++ swdev->vlans = GSW_NUM_VLANS;
++ swdev->ops = &gsw_ops;
++
++ if (register_switch(swdev, NULL))
++ dev_err(priv->device, "register_switch failed\n");
++
++ of_property_read_string(np, "ralink,port4", &port4);
++ if (port4 && !strcmp(port4, "ephy"))
++ gsw->port4 = PORT4_EPHY;
++ else if (port4 && !strcmp(port4, "gmac"))
++ gsw->port4 = PORT4_EXT;
++ else
++ WARN_ON(port4);
++
++ gsw_hw_init(gsw);
++
++ gsw_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR);
++ request_irq(gsw->irq, gsw_interrupt, 0, "gsw", priv);
++
++ return 0;
++}
+diff --git a/drivers/net/ethernet/ralink/gsw_mt7620a.h b/drivers/net/ethernet/ralink/gsw_mt7620a.h
+new file mode 100644
+index 0000000..fd4add5
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/gsw_mt7620a.h
+@@ -0,0 +1,29 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _RALINK_GSW_MT7620_H__
++#define _RALINK_GSW_MT7620_H__
++
++extern int mt7620_gsw_probe(struct fe_priv *priv);
++extern void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac);
++extern int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val);
++extern int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg);
++extern void mt7620_mdio_link_adjust(struct fe_priv *priv, int port);
++extern void mt7620_port_init(struct fe_priv *priv, struct device_node *np);
++extern int mt7620a_has_carrier(struct fe_priv *priv);
++
++#endif
+diff --git a/drivers/net/ethernet/ralink/mdio.c b/drivers/net/ethernet/ralink/mdio.c
+new file mode 100644
+index 0000000..b265c75
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/mdio.c
+@@ -0,0 +1,245 @@
++/*
++ * 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-2013 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 "ralink_soc_eth.h"
++#include "mdio.h"
++
++static int fe_mdio_reset(struct mii_bus *bus)
++{
++ /* TODO */
++ return 0;
++}
++
++static void fe_phy_link_adjust(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ unsigned long flags;
++ int i;
++
++ spin_lock_irqsave(&priv->phy->lock, flags);
++ for (i = 0; i < 8; i++) {
++ if (priv->phy->phy_node[i]) {
++ struct phy_device *phydev = priv->phy->phy[i];
++ int status_change = 0;
++
++ if (phydev->link)
++ if (priv->phy->duplex[i] != phydev->duplex ||
++ priv->phy->speed[i] != phydev->speed)
++ status_change = 1;
++
++ if (phydev->link != priv->link[i])
++ status_change = 1;
++
++ switch (phydev->speed) {
++ case SPEED_1000:
++ case SPEED_100:
++ case SPEED_10:
++ priv->link[i] = phydev->link;
++ priv->phy->duplex[i] = phydev->duplex;
++ priv->phy->speed[i] = phydev->speed;
++
++ if (status_change && priv->soc->mdio_adjust_link)
++ priv->soc->mdio_adjust_link(priv, i);
++ break;
++ }
++ }
++ }
++ spin_unlock_irqrestore(&priv->phy->lock, flags);
++}
++
++int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node)
++{
++ const __be32 *_port = NULL;
++ struct phy_device *phydev;
++ int phy_mode, port;
++
++ _port = of_get_property(phy_node, "reg", NULL);
++
++ if (!_port || (be32_to_cpu(*_port) >= 8)) {
++ pr_err("%s: invalid port id\n", phy_node->name);
++ return -EINVAL;
++ }
++ port = be32_to_cpu(*_port);
++ phy_mode = of_get_phy_mode(phy_node);
++ if (phy_mode < 0) {
++ dev_err(priv->device, "incorrect phy-mode %d\n", phy_mode);
++ priv->phy->phy_node[port] = NULL;
++ return -EINVAL;
++ }
++
++ phydev = of_phy_connect(priv->netdev, phy_node, fe_phy_link_adjust,
++ 0, phy_mode);
++ if (IS_ERR(phydev)) {
++ dev_err(priv->device, "could not connect to PHY\n");
++ priv->phy->phy_node[port] = NULL;
++ return PTR_ERR(phydev);
++ }
++
++ phydev->supported &= PHY_GBIT_FEATURES;
++ phydev->advertising = phydev->supported;
++ phydev->no_auto_carrier_off = 1;
++
++ dev_info(priv->device,
++ "connected port %d to PHY at %s [uid=%08x, driver=%s]\n",
++ port, dev_name(&phydev->dev), phydev->phy_id,
++ phydev->drv->name);
++
++ priv->phy->phy[port] = phydev;
++ priv->link[port] = 0;
++
++ return 0;
++}
++
++static int fe_phy_connect(struct fe_priv *priv)
++{
++ return 0;
++}
++
++static void fe_phy_disconnect(struct fe_priv *priv)
++{
++ unsigned long flags;
++ int i;
++
++ for (i = 0; i < 8; i++)
++ if (priv->phy->phy_fixed[i]) {
++ spin_lock_irqsave(&priv->phy->lock, flags);
++ priv->link[i] = 0;
++ if (priv->soc->mdio_adjust_link)
++ priv->soc->mdio_adjust_link(priv, i);
++ spin_unlock_irqrestore(&priv->phy->lock, flags);
++ } else if (priv->phy->phy[i]) {
++ phy_disconnect(priv->phy->phy[i]);
++ }
++}
++
++static void fe_phy_start(struct fe_priv *priv)
++{
++ unsigned long flags;
++ int i;
++
++ for (i = 0; i < 8; i++) {
++ if (priv->phy->phy_fixed[i]) {
++ spin_lock_irqsave(&priv->phy->lock, flags);
++ priv->link[i] = 1;
++ if (priv->soc->mdio_adjust_link)
++ priv->soc->mdio_adjust_link(priv, i);
++ spin_unlock_irqrestore(&priv->phy->lock, flags);
++ } else if (priv->phy->phy[i]) {
++ phy_start(priv->phy->phy[i]);
++ }
++ }
++}
++
++static void fe_phy_stop(struct fe_priv *priv)
++{
++ unsigned long flags;
++ int i;
++
++ for (i = 0; i < 8; i++)
++ if (priv->phy->phy_fixed[i]) {
++ spin_lock_irqsave(&priv->phy->lock, flags);
++ priv->link[i] = 0;
++ if (priv->soc->mdio_adjust_link)
++ priv->soc->mdio_adjust_link(priv, i);
++ spin_unlock_irqrestore(&priv->phy->lock, flags);
++ } else if (priv->phy->phy[i]) {
++ phy_stop(priv->phy->phy[i]);
++ }
++}
++
++static struct fe_phy phy_ralink = {
++ .connect = fe_phy_connect,
++ .disconnect = fe_phy_disconnect,
++ .start = fe_phy_start,
++ .stop = fe_phy_stop,
++};
++
++int fe_mdio_init(struct fe_priv *priv)
++{
++ struct device_node *mii_np;
++ int err;
++
++ if (!priv->soc->mdio_read || !priv->soc->mdio_write)
++ return 0;
++
++ spin_lock_init(&phy_ralink.lock);
++ priv->phy = &phy_ralink;
++
++ mii_np = of_get_child_by_name(priv->device->of_node, "mdio-bus");
++ if (!mii_np) {
++ dev_err(priv->device, "no %s child node found", "mdio-bus");
++ return -ENODEV;
++ }
++
++ if (!of_device_is_available(mii_np)) {
++ err = 0;
++ goto err_put_node;
++ }
++
++ priv->mii_bus = mdiobus_alloc();
++ if (priv->mii_bus == NULL) {
++ err = -ENOMEM;
++ goto err_put_node;
++ }
++
++ priv->mii_bus->name = "mdio";
++ priv->mii_bus->read = priv->soc->mdio_read;
++ priv->mii_bus->write = priv->soc->mdio_write;
++ priv->mii_bus->reset = fe_mdio_reset;
++ priv->mii_bus->irq = priv->mii_irq;
++ priv->mii_bus->priv = priv;
++ priv->mii_bus->parent = priv->device;
++
++ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name);
++ err = of_mdiobus_register(priv->mii_bus, mii_np);
++ if (err)
++ goto err_free_bus;
++
++ return 0;
++
++err_free_bus:
++ kfree(priv->mii_bus);
++err_put_node:
++ of_node_put(mii_np);
++ priv->mii_bus = NULL;
++ return err;
++}
++
++void fe_mdio_cleanup(struct fe_priv *priv)
++{
++ if (!priv->mii_bus)
++ return;
++
++ mdiobus_unregister(priv->mii_bus);
++ of_node_put(priv->mii_bus->dev.of_node);
++ kfree(priv->mii_bus);
++}
+diff --git a/drivers/net/ethernet/ralink/mdio.h b/drivers/net/ethernet/ralink/mdio.h
+new file mode 100644
+index 0000000..c3910a0
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/mdio.h
+@@ -0,0 +1,29 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _RALINK_MDIO_H__
++#define _RALINK_MDIO_H__
++
++#ifdef CONFIG_NET_RALINK_MDIO
++extern int fe_mdio_init(struct fe_priv *priv);
++extern void fe_mdio_cleanup(struct fe_priv *priv);
++extern int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node);
++#else
++static inline int fe_mdio_init(struct fe_priv *priv) { return 0; }
++static inline void fe_mdio_cleanup(struct fe_priv *priv) {}
++#endif
++#endif
+diff --git a/drivers/net/ethernet/ralink/mdio_rt2880.c b/drivers/net/ethernet/ralink/mdio_rt2880.c
+new file mode 100644
+index 0000000..54dbc53
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/mdio_rt2880.c
+@@ -0,0 +1,163 @@
++/*
++ * 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-2013 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 "ralink_soc_eth.h"
++#include "mdio_rt2880.h"
++
++#define FE_MDIO_RETRY 1000
++
++static unsigned char *rt2880_speed_str(struct fe_priv *priv)
++{
++ switch (priv->phy->speed[0]) {
++ case SPEED_1000:
++ return "1000";
++ case SPEED_100:
++ return "100";
++ case SPEED_10:
++ return "10";
++ }
++
++ return "?";
++}
++
++void rt2880_mdio_link_adjust(struct fe_priv *priv)
++{
++ u32 mdio_cfg;
++
++ if (!priv->link[0]) {
++ netif_carrier_off(priv->netdev);
++ netdev_info(priv->netdev, "link down\n");
++ return;
++ }
++
++ mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 |
++ FE_MDIO_CFG_RX_CLK_SKEW_200 |
++ FE_MDIO_CFG_GP1_FRC_EN;
++
++ if (priv->phy->duplex[0] == DUPLEX_FULL)
++ mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX;
++
++ if (priv->phy->tx_fc)
++ mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX;
++
++ if (priv->phy->rx_fc)
++ mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX;
++
++ switch (priv->phy->speed[0]) {
++ case SPEED_10:
++ mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10;
++ break;
++ case SPEED_100:
++ mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100;
++ break;
++ case SPEED_1000:
++ mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000;
++ break;
++ default:
++ BUG();
++ }
++
++ fe_w32(mdio_cfg, FE_MDIO_CFG);
++
++ netif_carrier_on(priv->netdev);
++ netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n",
++ rt2880_speed_str(priv),
++ (DUPLEX_FULL == priv->phy->duplex[0]) ? "Full" : "Half");
++}
++
++static int rt2880_mdio_wait_ready(struct fe_priv *priv)
++{
++ int retries;
++
++ retries = FE_MDIO_RETRY;
++ while (1) {
++ u32 t;
++
++ t = fe_r32(FE_MDIO_ACCESS);
++ if ((t & (0x1 << 31)) == 0)
++ return 0;
++
++ if (retries-- == 0)
++ break;
++
++ udelay(1);
++ }
++
++ dev_err(priv->device, "MDIO operation timed out\n");
++ return -ETIMEDOUT;
++}
++
++int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
++{
++ struct fe_priv *priv = bus->priv;
++ int err;
++ u32 t;
++
++ err = rt2880_mdio_wait_ready(priv);
++ if (err)
++ return 0xffff;
++
++ t = (phy_addr << 24) | (phy_reg << 16);
++ fe_w32(t, FE_MDIO_ACCESS);
++ t |= (1 << 31);
++ fe_w32(t, FE_MDIO_ACCESS);
++
++ err = rt2880_mdio_wait_ready(priv);
++ if (err)
++ return 0xffff;
++
++ pr_info("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
++ phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff);
++
++ return fe_r32(FE_MDIO_ACCESS) & 0xffff;
++}
++
++int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
++{
++ struct fe_priv *priv = bus->priv;
++ int err;
++ u32 t;
++
++ pr_info("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
++ phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff);
++
++ err = rt2880_mdio_wait_ready(priv);
++ if (err)
++ return err;
++
++ t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val;
++ fe_w32(t, FE_MDIO_ACCESS);
++ t |= (1 << 31);
++ fe_w32(t, FE_MDIO_ACCESS);
++
++ return rt2880_mdio_wait_ready(priv);
++}
+diff --git a/drivers/net/ethernet/ralink/mdio_rt2880.h b/drivers/net/ethernet/ralink/mdio_rt2880.h
+new file mode 100644
+index 0000000..c9ac0fe
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/mdio_rt2880.h
+@@ -0,0 +1,25 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _RALINK_MDIO_RT2880_H__
++#define _RALINK_MDIO_RT2880_H__
++
++void rt2880_mdio_link_adjust(struct fe_priv *priv);
++int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg);
++int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val);
++
++#endif
+diff --git a/drivers/net/ethernet/ralink/ralink_soc_eth.c b/drivers/net/ethernet/ralink/ralink_soc_eth.c
+new file mode 100644
+index 0000000..04e82eb
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/ralink_soc_eth.c
+@@ -0,0 +1,759 @@
++/*
++ * 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-2013 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/of_device.h>
++#include <linux/clk.h>
++#include <linux/of_net.h>
++#include <linux/of_mdio.h>
++#include <linux/if_vlan.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++#include "esw_rt3052.h"
++#include "mdio.h"
++
++#define TX_TIMEOUT (20 * HZ / 100)
++#define MAX_RX_LENGTH 1536
++
++static const u32 fe_reg_table_default[FE_REG_COUNT] = {
++ [FE_REG_PDMA_GLO_CFG] = FE_PDMA_GLO_CFG,
++ [FE_REG_PDMA_RST_CFG] = FE_PDMA_RST_CFG,
++ [FE_REG_DLY_INT_CFG] = FE_DLY_INT_CFG,
++ [FE_REG_TX_BASE_PTR0] = FE_TX_BASE_PTR0,
++ [FE_REG_TX_MAX_CNT0] = FE_TX_MAX_CNT0,
++ [FE_REG_TX_CTX_IDX0] = FE_TX_CTX_IDX0,
++ [FE_REG_RX_BASE_PTR0] = FE_RX_BASE_PTR0,
++ [FE_REG_RX_MAX_CNT0] = FE_RX_MAX_CNT0,
++ [FE_REG_RX_CALC_IDX0] = FE_RX_CALC_IDX0,
++ [FE_REG_FE_INT_ENABLE] = FE_FE_INT_ENABLE,
++ [FE_REG_FE_INT_STATUS] = FE_FE_INT_STATUS,
++ [FE_REG_FE_DMA_VID_BASE] = FE_DMA_VID0,
++};
++
++static const u32 *fe_reg_table = fe_reg_table_default;
++
++static void __iomem *fe_base = 0;
++
++void fe_w32(u32 val, unsigned reg)
++{
++ __raw_writel(val, fe_base + reg);
++}
++
++u32 fe_r32(unsigned reg)
++{
++ return __raw_readl(fe_base + reg);
++}
++
++static inline void fe_reg_w32(u32 val, enum fe_reg reg)
++{
++ fe_w32(val, fe_reg_table[reg]);
++}
++
++static inline u32 fe_reg_r32(enum fe_reg reg)
++{
++ return fe_r32(fe_reg_table[reg]);
++}
++
++static inline void fe_int_disable(u32 mask)
++{
++ fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) & ~mask,
++ FE_REG_FE_INT_ENABLE);
++ /* flush write */
++ fe_reg_r32(FE_REG_FE_INT_ENABLE);
++}
++
++static inline void fe_int_enable(u32 mask)
++{
++ fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) | mask,
++ FE_REG_FE_INT_ENABLE);
++ /* flush write */
++ fe_reg_r32(FE_REG_FE_INT_ENABLE);
++}
++
++static inline void fe_hw_set_macaddr(struct fe_priv *priv, unsigned char *mac)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ fe_w32((mac[0] << 8) | mac[1], FE_GDMA1_MAC_ADRH);
++ fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
++ FE_GDMA1_MAC_ADRL);
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++}
++
++static int fe_set_mac_address(struct net_device *dev, void *p)
++{
++ int ret = eth_mac_addr(dev, p);
++
++ if (!ret) {
++ struct fe_priv *priv = netdev_priv(dev);
++
++ if (priv->soc->set_mac)
++ priv->soc->set_mac(priv, dev->dev_addr);
++ else
++ fe_hw_set_macaddr(priv, p);
++ }
++
++ return ret;
++}
++
++static struct sk_buff* fe_alloc_skb(struct fe_priv *priv)
++{
++ struct sk_buff *skb;
++
++ skb = netdev_alloc_skb(priv->netdev, MAX_RX_LENGTH + NET_IP_ALIGN);
++ if (!skb)
++ return NULL;
++
++ skb_reserve(skb, NET_IP_ALIGN);
++
++ return skb;
++}
++
++static int fe_alloc_rx(struct fe_priv *priv)
++{
++ int size = NUM_DMA_DESC * sizeof(struct fe_rx_dma);
++ int i;
++
++ priv->rx_dma = dma_alloc_coherent(&priv->netdev->dev, size,
++ &priv->rx_phys, GFP_ATOMIC);
++ if (!priv->rx_dma)
++ return -ENOMEM;
++
++ memset(priv->rx_dma, 0, size);
++
++ for (i = 0; i < NUM_DMA_DESC; i++) {
++ priv->rx_skb[i] = fe_alloc_skb(priv);
++ if (!priv->rx_skb[i])
++ return -ENOMEM;
++ }
++
++ for (i = 0; i < NUM_DMA_DESC; i++) {
++ dma_addr_t dma_addr = dma_map_single(&priv->netdev->dev,
++ priv->rx_skb[i]->data,
++ MAX_RX_LENGTH,
++ DMA_FROM_DEVICE);
++ priv->rx_dma[i].rxd1 = (unsigned int) dma_addr;
++
++ if (priv->soc->rx_dma)
++ priv->soc->rx_dma(priv, i, MAX_RX_LENGTH);
++ else
++ priv->rx_dma[i].rxd2 = RX_DMA_LSO;
++ }
++ wmb();
++
++ fe_reg_w32(priv->rx_phys, FE_REG_RX_BASE_PTR0);
++ fe_reg_w32(NUM_DMA_DESC, FE_REG_RX_MAX_CNT0);
++ fe_reg_w32((NUM_DMA_DESC - 1), FE_REG_RX_CALC_IDX0);
++ fe_reg_w32(FE_PST_DRX_IDX0, FE_REG_PDMA_RST_CFG);
++
++ return 0;
++}
++
++static int fe_alloc_tx(struct fe_priv *priv)
++{
++ int size = NUM_DMA_DESC * sizeof(struct fe_tx_dma);
++ int i;
++
++ priv->tx_free_idx = 0;
++
++ priv->tx_dma = dma_alloc_coherent(&priv->netdev->dev, size,
++ &priv->tx_phys, GFP_ATOMIC);
++ if (!priv->tx_dma)
++ return -ENOMEM;
++
++ memset(priv->tx_dma, 0, size);
++
++ for (i = 0; i < NUM_DMA_DESC; i++) {
++ if (priv->soc->tx_dma) {
++ priv->soc->tx_dma(priv, i, 0);
++ continue;
++ }
++
++ priv->tx_dma[i].txd2 = TX_DMA_LSO | TX_DMA_DONE;
++ priv->tx_dma[i].txd4 = TX_DMA_QN(3) | TX_DMA_PN(1);
++ }
++
++ fe_reg_w32(priv->tx_phys, FE_REG_TX_BASE_PTR0);
++ fe_reg_w32(NUM_DMA_DESC, FE_REG_TX_MAX_CNT0);
++ fe_reg_w32(0, FE_REG_TX_CTX_IDX0);
++ fe_reg_w32(FE_PST_DTX_IDX0, FE_REG_PDMA_RST_CFG);
++
++ return 0;
++}
++
++static void fe_free_dma(struct fe_priv *priv)
++{
++ int i;
++
++ for (i = 0; i < NUM_DMA_DESC; i++) {
++ if (priv->rx_skb[i]) {
++ dma_unmap_single(&priv->netdev->dev, priv->rx_dma[i].rxd1,
++ MAX_RX_LENGTH, DMA_FROM_DEVICE);
++ dev_kfree_skb_any(priv->rx_skb[i]);
++ priv->rx_skb[i] = NULL;
++ }
++
++ if (priv->tx_skb[i]) {
++ dev_kfree_skb_any(priv->tx_skb[i]);
++ priv->tx_skb[i] = NULL;
++ }
++ }
++
++ if (priv->rx_dma) {
++ int size = NUM_DMA_DESC * sizeof(struct fe_rx_dma);
++ dma_free_coherent(&priv->netdev->dev, size, priv->rx_dma,
++ priv->rx_phys);
++ }
++
++ if (priv->tx_dma) {
++ int size = NUM_DMA_DESC * sizeof(struct fe_tx_dma);
++ dma_free_coherent(&priv->netdev->dev, size, priv->tx_dma,
++ priv->tx_phys);
++ }
++
++ netdev_reset_queue(priv->netdev);
++}
++
++static int fe_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ dma_addr_t mapped_addr;
++ u32 tx_next;
++ u32 tx;
++
++ if (priv->soc->min_pkt_len) {
++ if (skb->len < priv->soc->min_pkt_len) {
++ if (skb_padto(skb, priv->soc->min_pkt_len)) {
++ printk(KERN_ERR
++ "fe_eth: skb_padto failed\n");
++ kfree_skb(skb);
++ return 0;
++ }
++ skb_put(skb, priv->soc->min_pkt_len - skb->len);
++ }
++ }
++
++ dev->trans_start = jiffies;
++ mapped_addr = dma_map_single(&priv->netdev->dev, skb->data,
++ skb->len, DMA_TO_DEVICE);
++
++ spin_lock(&priv->page_lock);
++
++ tx = fe_reg_r32(FE_REG_TX_CTX_IDX0);
++ tx_next = (tx + 1) % NUM_DMA_DESC;
++
++ if ((priv->tx_skb[tx]) || (priv->tx_skb[tx_next]) ||
++ !(priv->tx_dma[tx].txd2 & TX_DMA_DONE) ||
++ !(priv->tx_dma[tx_next].txd2 & TX_DMA_DONE))
++ {
++ spin_unlock(&priv->page_lock);
++ dev->stats.tx_dropped++;
++ kfree_skb(skb);
++
++ return NETDEV_TX_OK;
++ }
++
++ priv->tx_skb[tx] = skb;
++ priv->tx_dma[tx].txd1 = (unsigned int) mapped_addr;
++ wmb();
++ if (priv->soc->tx_dma)
++ priv->soc->tx_dma(priv, tx, skb->len);
++ else
++ priv->tx_dma[tx].txd2 = TX_DMA_LSO | TX_DMA_PLEN0(skb->len);
++
++ if (skb->ip_summed == CHECKSUM_PARTIAL)
++ priv->tx_dma[tx].txd4 |= TX_DMA_CHKSUM;
++ else
++ priv->tx_dma[tx].txd4 &= ~TX_DMA_CHKSUM;
++
++ if (fe_reg_table[FE_REG_FE_DMA_VID_BASE] && vlan_tx_tag_present(skb))
++ priv->tx_dma[tx].txd4 |= 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF);
++ else
++ priv->tx_dma[tx].txd4 &= ~0x80;
++
++ dev->stats.tx_packets++;
++ dev->stats.tx_bytes += skb->len;
++
++ fe_reg_w32(tx_next, FE_REG_TX_CTX_IDX0);
++ netdev_sent_queue(dev, skb->len);
++
++ spin_unlock(&priv->page_lock);
++
++ return NETDEV_TX_OK;
++}
++
++static int fe_poll_rx(struct napi_struct *napi, int budget)
++{
++ struct fe_priv *priv = container_of(napi, struct fe_priv, rx_napi);
++ int idx = fe_reg_r32(FE_REG_RX_CALC_IDX0);
++ unsigned long flags;
++ int complete = 0;
++ int rx = 0;
++
++ while ((rx < budget) && !complete) {
++
++ idx = (idx + 1) % NUM_DMA_DESC;
++
++ if (priv->rx_dma[idx].rxd2 & RX_DMA_DONE) {
++ struct sk_buff *new_skb = fe_alloc_skb(priv);
++
++ if (new_skb) {
++ int pktlen = RX_DMA_PLEN0(priv->rx_dma[idx].rxd2);
++ dma_addr_t dma_addr;
++
++ dma_unmap_single(&priv->netdev->dev, priv->rx_dma[idx].rxd1,
++ MAX_RX_LENGTH, DMA_FROM_DEVICE);
++
++ skb_put(priv->rx_skb[idx], pktlen);
++ priv->rx_skb[idx]->dev = priv->netdev;
++ priv->rx_skb[idx]->protocol = eth_type_trans(priv->rx_skb[idx], priv->netdev);
++ if (priv->rx_dma[idx].rxd4 & priv->soc->checksum_bit)
++ priv->rx_skb[idx]->ip_summed = CHECKSUM_UNNECESSARY;
++ else
++ priv->rx_skb[idx]->ip_summed = CHECKSUM_NONE;
++ priv->netdev->stats.rx_packets++;
++ priv->netdev->stats.rx_bytes += pktlen;
++ netif_rx(priv->rx_skb[idx]);
++
++ priv->rx_skb[idx] = new_skb;
++
++ dma_addr = dma_map_single(&priv->netdev->dev,
++ new_skb->data,
++ MAX_RX_LENGTH,
++ DMA_FROM_DEVICE);
++ priv->rx_dma[idx].rxd1 = (unsigned int) dma_addr;
++ wmb();
++ } else {
++ priv->netdev->stats.rx_dropped++;
++ }
++
++ if (priv->soc->rx_dma)
++ priv->soc->rx_dma(priv, idx, MAX_RX_LENGTH);
++ else
++ priv->rx_dma[idx].rxd2 = RX_DMA_LSO;
++ fe_reg_w32(idx, FE_REG_RX_CALC_IDX0);
++ rx++;
++ } else {
++ complete = 1;
++ }
++ }
++
++ if (complete || !rx) {
++ napi_complete(&priv->rx_napi);
++ spin_lock_irqsave(&priv->page_lock, flags);
++ fe_int_enable(priv->soc->rx_dly_int);
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++ }
++
++ return rx;
++}
++
++static int fe_poll_tx(struct napi_struct *napi, int budget)
++{
++ struct fe_priv *priv = container_of(napi, struct fe_priv, tx_napi);
++ unsigned int bytes_compl = 0;
++ unsigned int pkts_compl = 0;
++ struct netdev_queue *txq;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ while (pkts_compl < budget) {
++ struct fe_tx_dma *txd;
++
++ txd = &priv->tx_dma[priv->tx_free_idx];
++
++ if (!(txd->txd2 & TX_DMA_DONE) || !(priv->tx_skb[priv->tx_free_idx]))
++ break;
++
++ bytes_compl += priv->tx_skb[priv->tx_free_idx]->len;
++ pkts_compl++;
++
++ dev_kfree_skb_irq(priv->tx_skb[priv->tx_free_idx]);
++ priv->tx_skb[priv->tx_free_idx] = NULL;
++ priv->tx_free_idx++;
++ if (priv->tx_free_idx >= NUM_DMA_DESC)
++ priv->tx_free_idx = 0;
++ }
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++
++ txq = netdev_get_tx_queue(priv->netdev, 0);
++ if (netif_tx_queue_stopped(txq))
++ netif_tx_start_queue(txq);
++
++ napi_complete(napi);
++ netdev_completed_queue(priv->netdev, pkts_compl, bytes_compl);
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ fe_int_enable(priv->soc->tx_dly_int);
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++
++ return pkts_compl;
++}
++
++static void fe_tx_timeout(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++
++ priv->netdev->stats.tx_errors++;
++ netdev_err(dev, "transmit timed out, waking up the queue\n");
++ netif_wake_queue(dev);
++}
++
++static irqreturn_t fe_handle_irq(int irq, void *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ unsigned int status;
++ unsigned int mask;
++
++ status = fe_reg_r32(FE_REG_FE_INT_STATUS);
++ mask = fe_reg_r32(FE_REG_FE_INT_ENABLE);
++
++ if (!(status & mask))
++ return IRQ_NONE;
++
++ if (status & priv->soc->rx_dly_int) {
++ fe_int_disable(priv->soc->rx_dly_int);
++ napi_schedule(&priv->rx_napi);
++ }
++
++ if (status & priv->soc->tx_dly_int) {
++ fe_int_disable(priv->soc->tx_dly_int);
++ napi_schedule(&priv->tx_napi);
++ }
++
++ fe_reg_w32(status, FE_REG_FE_INT_STATUS);
++
++ return IRQ_HANDLED;
++}
++
++static int fe_hw_init(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ int err, i;
++
++ err = devm_request_irq(priv->device, dev->irq, fe_handle_irq, 0,
++ dev_name(priv->device), dev);
++ if (err)
++ return err;
++
++ err = fe_alloc_rx(priv);
++ if (!err)
++ err = fe_alloc_tx(priv);
++ if (err)
++ return err;
++
++ if (priv->soc->set_mac)
++ priv->soc->set_mac(priv, dev->dev_addr);
++ else
++ fe_hw_set_macaddr(priv, dev->dev_addr);
++
++ fe_reg_w32(FE_DELAY_INIT, FE_REG_DLY_INT_CFG);
++
++ fe_int_disable(priv->soc->tx_dly_int | priv->soc->rx_dly_int);
++
++
++ if (fe_reg_table[FE_REG_FE_DMA_VID_BASE])
++ for (i = 0; i < 16; i += 2)
++ fe_w32((i + 1) << 16 | i, fe_reg_table[FE_REG_FE_DMA_VID_BASE] + (i * 4));
++
++ if (priv->soc->fwd_config) {
++ priv->soc->fwd_config(priv);
++ } else {
++ unsigned long sysclk = priv->sysclk;
++
++ if (!sysclk) {
++ netdev_err(dev, "unable to get clock\n");
++ return -EINVAL;
++ }
++
++ sysclk /= FE_US_CYC_CNT_DIVISOR;
++ sysclk <<= FE_US_CYC_CNT_SHIFT;
++
++ fe_w32((fe_r32(FE_FE_GLO_CFG) &
++ ~(FE_US_CYC_CNT_MASK << FE_US_CYC_CNT_SHIFT)) | priv->sysclk,
++ FE_FE_GLO_CFG);
++
++ fe_w32(fe_r32(FE_GDMA1_FWD_CFG) & ~0xffff, FE_GDMA1_FWD_CFG);
++ fe_w32(fe_r32(FE_GDMA1_FWD_CFG) | (FE_GDM1_ICS_EN | FE_GDM1_TCS_EN | FE_GDM1_UCS_EN),
++ FE_GDMA1_FWD_CFG);
++ fe_w32(fe_r32(FE_CDMA_CSG_CFG) | (FE_ICS_GEN_EN | FE_TCS_GEN_EN | FE_UCS_GEN_EN),
++ FE_CDMA_CSG_CFG);
++ fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG);
++ }
++
++ fe_w32(1, FE_FE_RST_GL);
++ fe_w32(0, FE_FE_RST_GL);
++
++ return 0;
++}
++
++static int fe_open(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ unsigned long flags;
++ u32 val;
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ napi_enable(&priv->rx_napi);
++ napi_enable(&priv->tx_napi);
++
++ val = FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN;
++ val |= priv->soc->pdma_glo_cfg;
++ fe_reg_w32(val, FE_REG_PDMA_GLO_CFG);
++
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++
++ if (priv->phy)
++ priv->phy->start(priv);
++
++ if (priv->soc->has_carrier && priv->soc->has_carrier(priv))
++ netif_carrier_on(dev);
++
++ netif_start_queue(dev);
++ fe_int_enable(priv->soc->tx_dly_int | priv->soc->rx_dly_int);
++
++ return 0;
++}
++
++static int fe_stop(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ unsigned long flags;
++
++ fe_int_disable(priv->soc->tx_dly_int | priv->soc->rx_dly_int);
++
++ netif_stop_queue(dev);
++
++ if (priv->phy)
++ priv->phy->stop(priv);
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ napi_disable(&priv->rx_napi);
++ napi_disable(&priv->tx_napi);
++
++ fe_reg_w32(fe_reg_r32(FE_REG_PDMA_GLO_CFG) &
++ ~(FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN),
++ FE_REG_PDMA_GLO_CFG);
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++
++ return 0;
++}
++
++static int __init fe_init(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++ struct device_node *port;
++ int err;
++
++ BUG_ON(!priv->soc->reset_fe);
++ priv->soc->reset_fe();
++
++ if (priv->soc->switch_init)
++ priv->soc->switch_init(priv);
++
++ net_srandom(jiffies);
++ memcpy(dev->dev_addr, priv->soc->mac, ETH_ALEN);
++ of_get_mac_address_mtd(priv->device->of_node, dev->dev_addr);
++
++ err = fe_mdio_init(priv);
++ if (err)
++ return err;
++
++ if (priv->phy) {
++ err = priv->phy->connect(priv);
++ if (err)
++ goto err_mdio_cleanup;
++ }
++
++ if (priv->soc->port_init)
++ for_each_child_of_node(priv->device->of_node, port)
++ if (of_device_is_compatible(port, "ralink,eth-port"))
++ priv->soc->port_init(priv, port);
++
++ err = fe_hw_init(dev);
++ if (err)
++ goto err_phy_disconnect;
++
++ return 0;
++
++err_phy_disconnect:
++ if (priv->phy)
++ priv->phy->disconnect(priv);
++err_mdio_cleanup:
++ fe_mdio_cleanup(priv);
++
++ return err;
++}
++
++static void fe_uninit(struct net_device *dev)
++{
++ struct fe_priv *priv = netdev_priv(dev);
++
++ if (priv->phy)
++ priv->phy->disconnect(priv);
++ fe_mdio_cleanup(priv);
++
++ fe_reg_w32(0, FE_REG_FE_INT_ENABLE);
++ free_irq(dev->irq, dev);
++
++ fe_free_dma(priv);
++}
++
++static const struct net_device_ops fe_netdev_ops = {
++ .ndo_init = fe_init,
++ .ndo_uninit = fe_uninit,
++ .ndo_open = fe_open,
++ .ndo_stop = fe_stop,
++ .ndo_start_xmit = fe_start_xmit,
++ .ndo_tx_timeout = fe_tx_timeout,
++ .ndo_set_mac_address = fe_set_mac_address,
++ .ndo_change_mtu = eth_change_mtu,
++ .ndo_validate_addr = eth_validate_addr,
++};
++
++static int fe_probe(struct platform_device *pdev)
++{
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ const struct of_device_id *match;
++ struct fe_soc_data *soc = NULL;
++ struct net_device *netdev;
++ struct fe_priv *priv;
++ struct clk *sysclk;
++ int err;
++
++ match = of_match_device(of_fe_match, &pdev->dev);
++ soc = (struct fe_soc_data *) match->data;
++ if (soc->reg_table)
++ fe_reg_table = soc->reg_table;
++
++ fe_base = devm_request_and_ioremap(&pdev->dev, res);
++ if (!fe_base)
++ return -ENOMEM;
++
++ netdev = alloc_etherdev(sizeof(struct fe_priv));
++ if (!netdev) {
++ dev_err(&pdev->dev, "alloc_etherdev failed\n");
++ return -ENOMEM;
++ }
++
++ strcpy(netdev->name, "eth%d");
++ netdev->netdev_ops = &fe_netdev_ops;
++ netdev->base_addr = (unsigned long) fe_base;
++ netdev->watchdog_timeo = TX_TIMEOUT;
++ netdev->features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
++ if (fe_reg_table[FE_REG_FE_DMA_VID_BASE])
++ netdev->features |= NETIF_F_HW_VLAN_TX;
++
++ netdev->irq = platform_get_irq(pdev, 0);
++ if (netdev->irq < 0) {
++ dev_err(&pdev->dev, "no IRQ resource found\n");
++ kfree(netdev);
++ return -ENXIO;
++ }
++
++ priv = netdev_priv(netdev);
++ memset(priv, 0, sizeof(struct fe_priv));
++ spin_lock_init(&priv->page_lock);
++
++ sysclk = devm_clk_get(&pdev->dev, NULL);
++ if (!IS_ERR(sysclk))
++ priv->sysclk = clk_get_rate(sysclk);
++
++ priv->netdev = netdev;
++ priv->device = &pdev->dev;
++ priv->soc = soc;
++
++ err = register_netdev(netdev);
++ if (err) {
++ dev_err(&pdev->dev, "error bringing up device\n");
++ kfree(netdev);
++ return err;
++ }
++
++ netif_napi_add(netdev, &priv->rx_napi, fe_poll_rx, 32);
++ netif_napi_add(netdev, &priv->tx_napi, fe_poll_tx, 8);
++
++ platform_set_drvdata(pdev, netdev);
++
++ netdev_info(netdev, "done loading\n");
++
++ return 0;
++}
++
++static int fe_remove(struct platform_device *pdev)
++{
++ struct net_device *dev = platform_get_drvdata(pdev);
++ struct fe_priv *priv = netdev_priv(dev);
++
++ netif_stop_queue(dev);
++ netif_napi_del(&priv->rx_napi);
++ netif_napi_del(&priv->tx_napi);
++
++ unregister_netdev(dev);
++ free_netdev(dev);
++
++ return 0;
++}
++
++static struct platform_driver fe_driver = {
++ .probe = fe_probe,
++ .remove = fe_remove,
++ .driver = {
++ .name = "ralink_soc_eth",
++ .owner = THIS_MODULE,
++ .of_match_table = of_fe_match,
++ },
++};
++
++static int __init init_rtfe(void)
++{
++ int ret;
++
++ ret = rtesw_init();
++ if (ret)
++ return ret;
++
++ ret = platform_driver_register(&fe_driver);
++ if (ret)
++ rtesw_exit();
++
++ return ret;
++}
++
++static void __exit exit_rtfe(void)
++{
++ platform_driver_unregister(&fe_driver);
++ rtesw_exit();
++}
++
++module_init(init_rtfe);
++module_exit(exit_rtfe);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
++MODULE_DESCRIPTION("Ethernet driver for Ralink SoC");
+diff --git a/drivers/net/ethernet/ralink/ralink_soc_eth.h b/drivers/net/ethernet/ralink/ralink_soc_eth.h
+new file mode 100644
+index 0000000..0c769ef
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/ralink_soc_eth.h
+@@ -0,0 +1,372 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef FE_ETH_H
++#define FE_ETH_H
++
++#include <linux/mii.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <linux/dma-mapping.h>
++#include <linux/phy.h>
++
++
++enum fe_reg {
++ FE_REG_PDMA_GLO_CFG = 0,
++ FE_REG_PDMA_RST_CFG,
++ FE_REG_DLY_INT_CFG,
++ FE_REG_TX_BASE_PTR0,
++ FE_REG_TX_MAX_CNT0,
++ FE_REG_TX_CTX_IDX0,
++ FE_REG_RX_BASE_PTR0,
++ FE_REG_RX_MAX_CNT0,
++ FE_REG_RX_CALC_IDX0,
++ FE_REG_FE_INT_ENABLE,
++ FE_REG_FE_INT_STATUS,
++ FE_REG_FE_DMA_VID_BASE,
++ FE_REG_COUNT
++};
++
++#define NUM_DMA_DESC 0x100
++
++#define FE_DELAY_EN_INT 0x80
++#define FE_DELAY_MAX_INT 0x04
++#define FE_DELAY_MAX_TOUT 0x04
++#define FE_DELAY_CHAN (((FE_DELAY_EN_INT | FE_DELAY_MAX_INT) << 8) | FE_DELAY_MAX_TOUT)
++#define FE_DELAY_INIT ((FE_DELAY_CHAN << 16) | FE_DELAY_CHAN)
++#define FE_PSE_FQFC_CFG_INIT 0x80504000
++
++/* interrupt bits */
++#define FE_CNT_PPE_AF BIT(31)
++#define FE_CNT_GDM_AF BIT(29)
++#define FE_PSE_P2_FC BIT(26)
++#define FE_PSE_BUF_DROP BIT(24)
++#define FE_GDM_OTHER_DROP BIT(23)
++#define FE_PSE_P1_FC BIT(22)
++#define FE_PSE_P0_FC BIT(21)
++#define FE_PSE_FQ_EMPTY BIT(20)
++#define FE_GE1_STA_CHG BIT(18)
++#define FE_TX_COHERENT BIT(17)
++#define FE_RX_COHERENT BIT(16)
++#define FE_TX_DONE_INT3 BIT(11)
++#define FE_TX_DONE_INT2 BIT(10)
++#define FE_TX_DONE_INT1 BIT(9)
++#define FE_TX_DONE_INT0 BIT(8)
++#define FE_RX_DONE_INT0 BIT(2)
++#define FE_TX_DLY_INT BIT(1)
++#define FE_RX_DLY_INT BIT(0)
++
++#define RT5350_RX_DLY_INT BIT(30)
++#define RT5350_TX_DLY_INT BIT(28)
++
++/* registers */
++#define FE_FE_OFFSET 0x0000
++#define FE_GDMA_OFFSET 0x0020
++#define FE_PSE_OFFSET 0x0040
++#define FE_GDMA2_OFFSET 0x0060
++#define FE_CDMA_OFFSET 0x0080
++#define FE_DMA_VID0 0x00a8
++#define FE_PDMA_OFFSET 0x0100
++#define FE_PPE_OFFSET 0x0200
++#define FE_CMTABLE_OFFSET 0x0400
++#define FE_POLICYTABLE_OFFSET 0x1000
++
++#define RT5350_PDMA_OFFSET 0x0800
++#define RT5350_SDM_OFFSET 0x0c00
++
++#define FE_MDIO_ACCESS (FE_FE_OFFSET + 0x00)
++#define FE_MDIO_CFG (FE_FE_OFFSET + 0x04)
++#define FE_FE_GLO_CFG (FE_FE_OFFSET + 0x08)
++#define FE_FE_RST_GL (FE_FE_OFFSET + 0x0C)
++#define FE_FE_INT_STATUS (FE_FE_OFFSET + 0x10)
++#define FE_FE_INT_ENABLE (FE_FE_OFFSET + 0x14)
++#define FE_MDIO_CFG2 (FE_FE_OFFSET + 0x18)
++#define FE_FOC_TS_T (FE_FE_OFFSET + 0x1C)
++
++#define FE_GDMA1_FWD_CFG (FE_GDMA_OFFSET + 0x00)
++#define FE_GDMA1_SCH_CFG (FE_GDMA_OFFSET + 0x04)
++#define FE_GDMA1_SHPR_CFG (FE_GDMA_OFFSET + 0x08)
++#define FE_GDMA1_MAC_ADRL (FE_GDMA_OFFSET + 0x0C)
++#define FE_GDMA1_MAC_ADRH (FE_GDMA_OFFSET + 0x10)
++
++#define FE_GDMA2_FWD_CFG (FE_GDMA2_OFFSET + 0x00)
++#define FE_GDMA2_SCH_CFG (FE_GDMA2_OFFSET + 0x04)
++#define FE_GDMA2_SHPR_CFG (FE_GDMA2_OFFSET + 0x08)
++#define FE_GDMA2_MAC_ADRL (FE_GDMA2_OFFSET + 0x0C)
++#define FE_GDMA2_MAC_ADRH (FE_GDMA2_OFFSET + 0x10)
++
++#define FE_PSE_FQ_CFG (FE_PSE_OFFSET + 0x00)
++#define FE_CDMA_FC_CFG (FE_PSE_OFFSET + 0x04)
++#define FE_GDMA1_FC_CFG (FE_PSE_OFFSET + 0x08)
++#define FE_GDMA2_FC_CFG (FE_PSE_OFFSET + 0x0C)
++
++#define FE_CDMA_CSG_CFG (FE_CDMA_OFFSET + 0x00)
++#define FE_CDMA_SCH_CFG (FE_CDMA_OFFSET + 0x04)
++
++#define MT7620A_GDMA_OFFSET 0x0600
++#define MT7620A_GDMA1_FWD_CFG (MT7620A_GDMA_OFFSET + 0x00)
++#define MT7620A_FE_GDMA1_SCH_CFG (MT7620A_GDMA_OFFSET + 0x04)
++#define MT7620A_FE_GDMA1_SHPR_CFG (MT7620A_GDMA_OFFSET + 0x08)
++#define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C)
++#define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10)
++
++#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 FE_PDMA_GLO_CFG (FE_PDMA_OFFSET + 0x00)
++#define FE_PDMA_RST_CFG (FE_PDMA_OFFSET + 0x04)
++#define FE_PDMA_SCH_CFG (FE_PDMA_OFFSET + 0x08)
++#define FE_DLY_INT_CFG (FE_PDMA_OFFSET + 0x0C)
++#define FE_TX_BASE_PTR0 (FE_PDMA_OFFSET + 0x10)
++#define FE_TX_MAX_CNT0 (FE_PDMA_OFFSET + 0x14)
++#define FE_TX_CTX_IDX0 (FE_PDMA_OFFSET + 0x18)
++#define FE_TX_DTX_IDX0 (FE_PDMA_OFFSET + 0x1C)
++#define FE_TX_BASE_PTR1 (FE_PDMA_OFFSET + 0x20)
++#define FE_TX_MAX_CNT1 (FE_PDMA_OFFSET + 0x24)
++#define FE_TX_CTX_IDX1 (FE_PDMA_OFFSET + 0x28)
++#define FE_TX_DTX_IDX1 (FE_PDMA_OFFSET + 0x2C)
++#define FE_RX_BASE_PTR0 (FE_PDMA_OFFSET + 0x30)
++#define FE_RX_MAX_CNT0 (FE_PDMA_OFFSET + 0x34)
++#define FE_RX_CALC_IDX0 (FE_PDMA_OFFSET + 0x38)
++#define FE_RX_DRX_IDX0 (FE_PDMA_OFFSET + 0x3C)
++#define FE_TX_BASE_PTR2 (FE_PDMA_OFFSET + 0x40)
++#define FE_TX_MAX_CNT2 (FE_PDMA_OFFSET + 0x44)
++#define FE_TX_CTX_IDX2 (FE_PDMA_OFFSET + 0x48)
++#define FE_TX_DTX_IDX2 (FE_PDMA_OFFSET + 0x4C)
++#define FE_TX_BASE_PTR3 (FE_PDMA_OFFSET + 0x50)
++#define FE_TX_MAX_CNT3 (FE_PDMA_OFFSET + 0x54)
++#define FE_TX_CTX_IDX3 (FE_PDMA_OFFSET + 0x58)
++#define FE_TX_DTX_IDX3 (FE_PDMA_OFFSET + 0x5C)
++#define FE_RX_BASE_PTR1 (FE_PDMA_OFFSET + 0x60)
++#define FE_RX_MAX_CNT1 (FE_PDMA_OFFSET + 0x64)
++#define FE_RX_CALC_IDX1 (FE_PDMA_OFFSET + 0x68)
++#define FE_RX_DRX_IDX1 (FE_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 FE_MDIO_CFG_AUTO_POLL_EN BIT(29)
++#define FE_MDIO_CFG_GP1_BP_EN BIT(16)
++#define FE_MDIO_CFG_GP1_FRC_EN BIT(15)
++#define FE_MDIO_CFG_GP1_SPEED_10 (0 << 13)
++#define FE_MDIO_CFG_GP1_SPEED_100 (1 << 13)
++#define FE_MDIO_CFG_GP1_SPEED_1000 (2 << 13)
++#define FE_MDIO_CFG_GP1_DUPLEX BIT(12)
++#define FE_MDIO_CFG_GP1_FC_TX BIT(11)
++#define FE_MDIO_CFG_GP1_FC_RX BIT(10)
++#define FE_MDIO_CFG_GP1_LNK_DWN BIT(9)
++#define FE_MDIO_CFG_GP1_AN_FAIL BIT(8)
++#define FE_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6)
++#define FE_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6)
++#define FE_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6)
++#define FE_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6)
++#define FE_MDIO_CFG_TURBO_MII_FREQ BIT(5)
++#define FE_MDIO_CFG_TURBO_MII_MODE BIT(4)
++#define FE_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2)
++#define FE_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2)
++#define FE_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2)
++#define FE_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2)
++#define FE_MDIO_CFG_TX_CLK_SKEW_0 0
++#define FE_MDIO_CFG_TX_CLK_SKEW_200 1
++#define FE_MDIO_CFG_TX_CLK_SKEW_400 2
++#define FE_MDIO_CFG_TX_CLK_SKEW_INV 3
++
++/* uni-cast port */
++#define FE_GDM1_ICS_EN BIT(22)
++#define FE_GDM1_TCS_EN BIT(21)
++#define FE_GDM1_UCS_EN BIT(20)
++#define FE_GDM1_JMB_EN BIT(19)
++#define FE_GDM1_STRPCRC BIT(16)
++#define FE_GDM1_UFRC_P_CPU (0 << 12)
++#define FE_GDM1_UFRC_P_GDMA1 (1 << 12)
++#define FE_GDM1_UFRC_P_PPE (6 << 12)
++
++/* checksums */
++#define FE_ICS_GEN_EN BIT(2)
++#define FE_UCS_GEN_EN BIT(1)
++#define FE_TCS_GEN_EN BIT(0)
++
++/* dma ring */
++#define FE_PST_DRX_IDX0 BIT(16)
++#define FE_PST_DTX_IDX3 BIT(3)
++#define FE_PST_DTX_IDX2 BIT(2)
++#define FE_PST_DTX_IDX1 BIT(1)
++#define FE_PST_DTX_IDX0 BIT(0)
++
++#define FE_TX_WB_DDONE BIT(6)
++#define FE_RX_DMA_BUSY BIT(3)
++#define FE_TX_DMA_BUSY BIT(1)
++#define FE_RX_DMA_EN BIT(2)
++#define FE_TX_DMA_EN BIT(0)
++
++#define FE_PDMA_SIZE_4DWORDS (0 << 4)
++#define FE_PDMA_SIZE_8DWORDS (1 << 4)
++#define FE_PDMA_SIZE_16DWORDS (2 << 4)
++
++#define FE_US_CYC_CNT_MASK 0xff
++#define FE_US_CYC_CNT_SHIFT 0x8
++#define FE_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)
++#define RX_DMA_L4VALID BIT(30)
++
++struct fe_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)
++#define TX_DMA_CHKSUM (0x7 << 29)
++
++struct fe_tx_dma {
++ unsigned int txd1;
++ unsigned int txd2;
++ unsigned int txd3;
++ unsigned int txd4;
++} __packed __aligned(4);
++
++struct fe_priv;
++
++struct fe_phy {
++ struct phy_device *phy[8];
++ struct device_node *phy_node[8];
++ const __be32 *phy_fixed[8];
++ int duplex[8];
++ int speed[8];
++ spinlock_t lock;
++
++ int (*connect)(struct fe_priv *priv);
++ void (*disconnect)(struct fe_priv *priv);
++ void (*start)(struct fe_priv *priv);
++ void (*stop)(struct fe_priv *priv);
++};
++
++struct fe_soc_data
++{
++ unsigned char mac[6];
++ const u32 *reg_table;
++
++ void (*reset_fe)(void);
++ void (*set_mac)(struct fe_priv *priv, unsigned char *mac);
++ void (*fwd_config)(struct fe_priv *priv);
++ void (*tx_dma)(struct fe_priv *priv, int idx, int len);
++ void (*rx_dma)(struct fe_priv *priv, int idx, int len);
++ int (*switch_init)(struct fe_priv *priv);
++ void (*port_init)(struct fe_priv *priv, struct device_node *port);
++ int (*has_carrier)(struct fe_priv *priv);
++ int (*mdio_init)(struct fe_priv *priv);
++ void (*mdio_cleanup)(struct fe_priv *priv);
++ int (*mdio_write)(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val);
++ int (*mdio_read)(struct mii_bus *bus, int phy_addr, int phy_reg);
++ void (*mdio_adjust_link)(struct fe_priv *priv, int port);
++
++ void *swpriv;
++ u32 pdma_glo_cfg;
++ u32 rx_dly_int;
++ u32 tx_dly_int;
++ u32 checksum_bit;
++
++ int min_pkt_len;
++};
++
++struct fe_priv
++{
++ spinlock_t page_lock;
++
++ struct fe_soc_data *soc;
++ struct net_device *netdev;
++ struct device *device;
++ unsigned long sysclk;
++
++ struct fe_rx_dma *rx_dma;
++ struct sk_buff *rx_skb[NUM_DMA_DESC];
++ struct napi_struct rx_napi;
++ dma_addr_t rx_phys;
++
++ struct fe_tx_dma *tx_dma;
++ struct sk_buff *tx_skb[NUM_DMA_DESC];
++ struct napi_struct tx_napi;
++ dma_addr_t tx_phys;
++ unsigned int tx_free_idx;
++
++ struct fe_phy *phy;
++ struct mii_bus *mii_bus;
++ int mii_irq[PHY_MAX_ADDR];
++
++ int link[8];
++};
++
++extern const struct of_device_id of_fe_match[];
++
++void fe_w32(u32 val, unsigned reg);
++u32 fe_r32(unsigned reg);
++
++#endif /* FE_ETH_H */
+diff --git a/drivers/net/ethernet/ralink/soc_mt7620.c b/drivers/net/ethernet/ralink/soc_mt7620.c
+new file mode 100644
+index 0000000..55e303f
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/soc_mt7620.c
+@@ -0,0 +1,111 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++#include "gsw_mt7620a.h"
++
++#define MT7620A_CDMA_CSG_CFG 0x400
++#define MT7620_DMA_VID (MT7620A_CDMA_CSG_CFG | 0x30)
++#define MT7620A_DMA_2B_OFFSET BIT(31)
++#define MT7620A_RESET_FE BIT(21)
++#define MT7620A_RESET_ESW BIT(23)
++#define MT7620_L4_VALID BIT(23)
++
++#define SYSC_REG_RESET_CTRL 0x34
++#define MAX_RX_LENGTH 1536
++
++#define CDMA_ICS_EN BIT(2)
++#define CDMA_UCS_EN BIT(1)
++#define CDMA_TCS_EN BIT(0)
++
++#define GDMA_ICS_EN BIT(22)
++#define GDMA_TCS_EN BIT(21)
++#define GDMA_UCS_EN BIT(20)
++
++static const u32 rt5350_reg_table[FE_REG_COUNT] = {
++ [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG,
++ [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG,
++ [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG,
++ [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0,
++ [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0,
++ [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0,
++ [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0,
++ [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0,
++ [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0,
++ [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE,
++ [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS,
++ [FE_REG_FE_DMA_VID_BASE] = MT7620_DMA_VID,
++};
++
++static void mt7620_fe_reset(void)
++{
++ rt_sysc_w32(MT7620A_RESET_FE | MT7620A_RESET_ESW, SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL);
++}
++
++static void mt7620_fwd_config(struct fe_priv *priv)
++{
++ fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~7, MT7620A_GDMA1_FWD_CFG);
++ fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | GDMA_TCS_EN | GDMA_UCS_EN), MT7620A_GDMA1_FWD_CFG);
++ fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) | (CDMA_ICS_EN | CDMA_UCS_EN | CDMA_TCS_EN), MT7620A_CDMA_CSG_CFG);
++}
++
++static void mt7620_tx_dma(struct fe_priv *priv, int idx, int len)
++{
++ if (len)
++ priv->tx_dma[idx].txd2 = TX_DMA_LSO | TX_DMA_PLEN0(len);
++ else
++ priv->tx_dma[idx].txd2 = TX_DMA_LSO | TX_DMA_DONE;
++}
++
++static void mt7620_rx_dma(struct fe_priv *priv, int idx, int len)
++{
++ priv->rx_dma[idx].rxd2 = RX_DMA_PLEN0(len);
++}
++
++static struct fe_soc_data mt7620_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reset_fe = mt7620_fe_reset,
++ .set_mac = mt7620_set_mac,
++ .fwd_config = mt7620_fwd_config,
++ .tx_dma = mt7620_tx_dma,
++ .rx_dma = mt7620_rx_dma,
++ .switch_init = mt7620_gsw_probe,
++ .port_init = mt7620_port_init,
++ .min_pkt_len = 0,
++ .reg_table = rt5350_reg_table,
++ .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS | MT7620A_DMA_2B_OFFSET,
++ .rx_dly_int = RT5350_RX_DLY_INT,
++ .tx_dly_int = RT5350_TX_DLY_INT,
++ .checksum_bit = MT7620_L4_VALID,
++ .has_carrier = mt7620a_has_carrier,
++ .mdio_read = mt7620_mdio_read,
++ .mdio_write = mt7620_mdio_write,
++ .mdio_adjust_link = mt7620_mdio_link_adjust,
++};
++
++const struct of_device_id of_fe_match[] = {
++ { .compatible = "ralink,mt7620a-eth", .data = &mt7620_data },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, of_fe_match);
+diff --git a/drivers/net/ethernet/ralink/soc_rt2880.c b/drivers/net/ethernet/ralink/soc_rt2880.c
+new file mode 100644
+index 0000000..fdbd118
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/soc_rt2880.c
+@@ -0,0 +1,51 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++#include "mdio_rt2880.h"
++
++#define SYSC_REG_RESET_CTRL 0x034
++#define RT2880_RESET_FE BIT(18)
++
++void rt2880_fe_reset(void)
++{
++ rt_sysc_w32(RT2880_RESET_FE, SYSC_REG_RESET_CTRL);
++}
++
++struct fe_soc_data rt2880_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reset_fe = rt2880_fe_reset,
++ .min_pkt_len = 64,
++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS,
++ .checksum_bit = RX_DMA_L4VALID,
++ .rx_dly_int = FE_RX_DLY_INT,
++ .tx_dly_int = FE_TX_DLY_INT,
++ .mdio_read = rt2880_mdio_read,
++ .mdio_write = rt2880_mdio_write,
++ .mdio_link_adjust = rt2880_mdio_link_adjust,
++};
++
++const struct of_device_id of_fe_match[] = {
++ { .compatible = "ralink,rt2880-eth", .data = &rt2880_data },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, of_fe_match);
+diff --git a/drivers/net/ethernet/ralink/soc_rt305x.c b/drivers/net/ethernet/ralink/soc_rt305x.c
+new file mode 100644
+index 0000000..c43d3f9
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/soc_rt305x.c
+@@ -0,0 +1,102 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++
++#define RT305X_RESET_FE BIT(21)
++#define RT305X_RESET_ESW BIT(23)
++#define SYSC_REG_RESET_CTRL 0x034
++
++static const u32 rt5350_reg_table[FE_REG_COUNT] = {
++ [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG,
++ [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG,
++ [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG,
++ [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0,
++ [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0,
++ [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0,
++ [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0,
++ [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0,
++ [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0,
++ [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE,
++ [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS,
++ [FE_REG_FE_DMA_VID_BASE] = 0,
++};
++
++static void rt305x_fe_reset(void)
++{
++ rt_sysc_w32(RT305X_RESET_FE, SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL);
++}
++
++static void rt5350_set_mac(struct fe_priv *priv, unsigned char *mac)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->page_lock, flags);
++ fe_w32((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH);
++ fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5],
++ RT5350_SDM_MAC_ADRL);
++ spin_unlock_irqrestore(&priv->page_lock, flags);
++}
++
++static void rt5350_fwd_config(struct fe_priv *priv)
++{
++ fe_w32(fe_r32(RT5350_SDM_CFG) & ~0xffff, RT5350_SDM_CFG);
++ fe_w32(fe_r32(RT5350_SDM_CFG) | RT5350_SDM_ICS_EN | RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN,
++ RT5350_SDM_CFG);
++}
++
++static void rt5350_fe_reset(void)
++{
++ rt_sysc_w32(RT305X_RESET_FE | RT305X_RESET_ESW, SYSC_REG_RESET_CTRL);
++ rt_sysc_w32(0, SYSC_REG_RESET_CTRL);
++}
++
++static struct fe_soc_data rt3050_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reset_fe = rt305x_fe_reset,
++ .min_pkt_len = 64,
++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS,
++ .checksum_bit = RX_DMA_L4VALID,
++ .rx_dly_int = FE_RX_DLY_INT,
++ .tx_dly_int = FE_TX_DLY_INT,
++};
++
++static struct fe_soc_data rt5350_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reg_table = rt5350_reg_table,
++ .reset_fe = rt5350_fe_reset,
++ .set_mac = rt5350_set_mac,
++ .fwd_config = rt5350_fwd_config,
++ .min_pkt_len = 64,
++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS,
++ .checksum_bit = RX_DMA_L4VALID,
++ .rx_dly_int = RT5350_RX_DLY_INT,
++ .tx_dly_int = RT5350_TX_DLY_INT,
++};
++
++const struct of_device_id of_fe_match[] = {
++ { .compatible = "ralink,rt3050-eth", .data = &rt3050_data },
++ { .compatible = "ralink,rt5350-eth", .data = &rt5350_data },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, of_fe_match);
+diff --git a/drivers/net/ethernet/ralink/soc_rt3883.c b/drivers/net/ethernet/ralink/soc_rt3883.c
+new file mode 100644
+index 0000000..3886be1
+--- /dev/null
++++ b/drivers/net/ethernet/ralink/soc_rt3883.c
+@@ -0,0 +1,59 @@
++/*
++ * 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-2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#include "ralink_soc_eth.h"
++#include "mdio_rt2880.h"
++
++#define RT3883_SYSC_REG_RSTCTRL 0x34
++#define RT3883_RSTCTRL_FE BIT(21)
++
++static void rt3883_fe_reset(void)
++{
++ 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);
++}
++
++static struct fe_soc_data rt3883_data = {
++ .mac = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
++ .reset_fe = rt3883_fe_reset,
++ .min_pkt_len = 64,
++ .pdma_glo_cfg = FE_PDMA_SIZE_4DWORDS,
++ .rx_dly_int = FE_RX_DLY_INT,
++ .tx_dly_int = FE_TX_DLY_INT,
++ .checksum_bit = RX_DMA_L4VALID,
++ .mdio_read = rt2880_mdio_read,
++ .mdio_write = rt2880_mdio_write,
++ .mdio_link_adjust = rt2880_mdio_link_adjust,
++};
++
++const struct of_device_id of_fe_match[] = {
++ { .compatible = "ralink,rt3883-eth", .data = &rt3883_data },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, of_fe_match);
++
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch b/target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch
new file mode 100644
index 0000000..e6a63bd
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0073-USB-phy-add-ralink-SoC-driver.patch
@@ -0,0 +1,238 @@
+From 277c29fcf17b9e3ada6ddc3bda0f7780bb8a222a Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 19:06:09 +0200
+Subject: [PATCH 73/79] USB: phy: add ralink SoC driver
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/usb/phy/Kconfig | 8 ++
+ drivers/usb/phy/Makefile | 1 +
+ drivers/usb/phy/ralink-phy.c | 191 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 200 insertions(+)
+ create mode 100644 drivers/usb/phy/ralink-phy.c
+
+diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
+index 5de6e7f..9b899b0 100644
+--- a/drivers/usb/phy/Kconfig
++++ b/drivers/usb/phy/Kconfig
+@@ -45,3 +45,11 @@ config USB_RCAR_PHY
+
+ To compile this driver as a module, choose M here: the
+ module will be called rcar-phy.
++
++config RALINK_USBPHY
++ bool "Ralink USB PHY controller Driver"
++ depends on MIPS && RALINK
++ select USB_OTG_UTILS
++ help
++ Enable this to support ralink USB phy controller for ralink
++ SoCs.
+diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
+index 1a579a8..52ba41a 100644
+--- a/drivers/usb/phy/Makefile
++++ b/drivers/usb/phy/Makefile
+@@ -9,3 +9,4 @@ obj-$(CONFIG_USB_ISP1301) += isp1301.o
+ obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o
+ obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o
+ obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o
++obj-$(CONFIG_RALINK_USBPHY) += ralink-phy.o
+diff --git a/drivers/usb/phy/ralink-phy.c b/drivers/usb/phy/ralink-phy.c
+new file mode 100644
+index 0000000..3fbabea
+--- /dev/null
++++ b/drivers/usb/phy/ralink-phy.c
+@@ -0,0 +1,191 @@
++/*
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ *
++ * based on: Renesas R-Car USB phy driver
++ *
++ * 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/delay.h>
++#include <linux/io.h>
++#include <linux/usb/otg.h>
++#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++#include <linux/reset.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define RT_SYSC_REG_SYSCFG1 0x014
++#define RT_SYSC_REG_CLKCFG1 0x030
++#define RT_SYSC_REG_USB_PHY_CFG 0x05c
++
++#define RT_RSTCTRL_UDEV BIT(25)
++#define RT_RSTCTRL_UHST BIT(22)
++#define RT_SYSCFG1_USB0_HOST_MODE BIT(10)
++
++#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25)
++#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20)
++#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18)
++
++#define USB_PHY_UTMI_8B60M BIT(1)
++#define UDEV_WAKEUP BIT(0)
++
++static atomic_t usb_pwr_ref = ATOMIC_INIT(0);
++static struct reset_control *rstdev;
++static struct reset_control *rsthost;
++static u32 phy_clk;
++
++static void usb_phy_enable(int state)
++{
++ if (state)
++ rt_sysc_m32(0, phy_clk, RT_SYSC_REG_CLKCFG1);
++ else
++ rt_sysc_m32(phy_clk, 0, RT_SYSC_REG_CLKCFG1);
++ mdelay(100);
++}
++
++static int usb_power_on(struct usb_phy *phy)
++{
++ if (atomic_inc_return(&usb_pwr_ref) == 1) {
++ u32 t;
++
++ usb_phy_enable(1);
++
++ reset_control_assert(rstdev);
++ reset_control_assert(rsthost);
++
++ if (OTG_STATE_B_HOST) {
++ rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1);
++ reset_control_deassert(rsthost);
++ } else {
++ rt_sysc_m32(RT_SYSCFG1_USB0_HOST_MODE, 0, RT_SYSC_REG_SYSCFG1);
++ reset_control_deassert(rstdev);
++ }
++ mdelay(100);
++
++ t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG);
++ dev_info(phy->dev, "remote usb device wakeup %s\n",
++ (t & UDEV_WAKEUP) ? ("enabbled") : ("disabled"));
++ if (t & USB_PHY_UTMI_8B60M)
++ dev_info(phy->dev, "UTMI 8bit 60MHz\n");
++ else
++ dev_info(phy->dev, "UTMI 16bit 30MHz\n");
++ }
++
++ return 0;
++}
++
++static void usb_power_off(struct usb_phy *phy)
++{
++ if (atomic_dec_return(&usb_pwr_ref) == 0) {
++ usb_phy_enable(0);
++ reset_control_assert(rstdev);
++ reset_control_assert(rsthost);
++ }
++}
++
++static int usb_set_host(struct usb_otg *otg, struct usb_bus *host)
++{
++ otg->gadget = NULL;
++ otg->host = host;
++
++ return 0;
++}
++
++static int usb_set_peripheral(struct usb_otg *otg,
++ struct usb_gadget *gadget)
++{
++ otg->host = NULL;
++ otg->gadget = gadget;
++
++ return 0;
++}
++
++static const struct of_device_id ralink_usbphy_dt_match[] = {
++ { .compatible = "ralink,rt3xxx-usbphy", .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN | RT_CLKCFG1_UPHY0_CLK_EN) },
++ { .compatible = "ralink,mt7620a-usbphy", .data = (void *) MT7620_CLKCFG1_UPHY0_CLK_EN },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ralink_usbphy_dt_match);
++
++static int usb_phy_probe(struct platform_device *pdev)
++{
++ const struct of_device_id *match;
++ struct device *dev = &pdev->dev;
++ struct usb_otg *otg;
++ struct usb_phy *phy;
++ int ret;
++
++ match = of_match_device(ralink_usbphy_dt_match, &pdev->dev);
++ phy_clk = (int) match->data;
++
++ rsthost = devm_reset_control_get(&pdev->dev, "host");
++ if (IS_ERR(rsthost))
++ return PTR_ERR(rsthost);
++
++ rstdev = devm_reset_control_get(&pdev->dev, "device");
++ if (IS_ERR(rstdev))
++ return PTR_ERR(rstdev);
++
++ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
++ if (!phy) {
++ dev_err(&pdev->dev, "unable to allocate memory for USB PHY\n");
++ return -ENOMEM;
++ }
++
++ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
++ if (!otg) {
++ dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
++ return -ENOMEM;
++ }
++
++ phy->dev = dev;
++ phy->label = dev_name(dev);
++ phy->init = usb_power_on;
++ phy->shutdown = usb_power_off;
++ otg->set_host = usb_set_host;
++ otg->set_peripheral = usb_set_peripheral;
++ otg->phy = phy;
++ phy->otg = otg;
++ ret = usb_add_phy(phy, USB_PHY_TYPE_USB2);
++
++ if (ret < 0) {
++ dev_err(dev, "usb phy addition error\n");
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, phy);
++
++ dev_info(&pdev->dev, "loaded\n");
++
++ return ret;
++}
++
++static int usb_phy_remove(struct platform_device *pdev)
++{
++ struct usb_phy *phy = platform_get_drvdata(pdev);
++
++ usb_remove_phy(phy);
++
++ return 0;
++}
++
++static struct platform_driver usb_phy_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "rt3xxx-usbphy",
++ .of_match_table = of_match_ptr(ralink_usbphy_dt_match),
++ },
++ .probe = usb_phy_probe,
++ .remove = usb_phy_remove,
++};
++
++module_platform_driver(usb_phy_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("Ralink USB phy");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch b/target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch
new file mode 100644
index 0000000..ad8269c
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0074-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch
@@ -0,0 +1,48 @@
+From 93bb6d731e96dc373b88a910ca9db66c560c8f4e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 24 May 2013 21:28:08 +0200
+Subject: [PATCH 74/79] USB: MIPS: ralink: fix usb issue on mt7620
+
+USB fails when frequency scaling is enabled. Increase the idle cpu speed when
+scaled.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/include/asm/mach-ralink/mt7620.h | 1 +
+ arch/mips/ralink/mt7620.c | 8 ++++++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h
+index 9809972..d469c69 100644
+--- a/arch/mips/include/asm/mach-ralink/mt7620.h
++++ b/arch/mips/include/asm/mach-ralink/mt7620.h
+@@ -20,6 +20,7 @@
+ #define SYSC_REG_CHIP_REV 0x0c
+ #define SYSC_REG_SYSTEM_CONFIG0 0x10
+ #define SYSC_REG_SYSTEM_CONFIG1 0x14
++#define SYSC_REG_CPU_SYS_CLKCFG 0x3c
+ #define SYSC_REG_CPLL_CONFIG0 0x54
+ #define SYSC_REG_CPLL_CONFIG1 0x58
+
+diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
+index 4956d96..d76eb85 100644
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -186,6 +186,14 @@ void __init ralink_clk_init(void)
+ ralink_clk_add("10000500.uart", 40000000);
+ ralink_clk_add("10000b00.spi", 40000000);
+ ralink_clk_add("10000c00.uartlite", 40000000);
++
++#ifdef CONFIG_USB
++ /*
++ * When the CPU goes into sleep mode, the BUS clock will be too low for
++ * USB to function properly
++ */
++ rt_sysc_m32(0x1f1f, 0x303, SYSC_REG_CPU_SYS_CLKCFG);
++#endif
+ }
+
+ void __init ralink_of_remap(void)
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch b/target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch
new file mode 100644
index 0000000..b66bd85
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0075-Kbuild-add-missing-space.patch
@@ -0,0 +1,38 @@
+From 5d5c270635a50b82931bb32f6fe28b84d45bdb59 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 17 May 2013 01:03:45 +0200
+Subject: [PATCH 75/79] Kbuild: add missing space
+
+Currently the output looks like this:
+DTC arch/mips/ralink/dts/mt7620a_eval.dtb
+DTB arch/mips/ralink/dts/mt7620a_eval.dtb.S
+AS arch/mips/ralink/dts/mt7620a_eval.dtb.o
+
+Whitespace error was introduced by initial commit
+commit aab94339cd85d726abeae78fc02351fc1910e6a4
+Author: Dirk Brandewie <dirk.brandewie@gmail.com>
+Date: Wed Dec 22 11:57:26 2010 -0800
+
+of: Add support for linking device tree blobs into vmlinux
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ scripts/Makefile.lib | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
+index bdf42fd..21c1359 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -246,7 +246,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
+ # ---------------------------------------------------------------------------
+
+ # Generate an assembly file to wrap the output of the device tree compiler
+-quiet_cmd_dt_S_dtb= DTB $@
++quiet_cmd_dt_S_dtb= DTB $@
+ cmd_dt_S_dtb= \
+ ( \
+ echo '\#include <asm-generic/vmlinux.lds.h>'; \
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
new file mode 100644
index 0000000..c1fe6ad
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0076-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
@@ -0,0 +1,3446 @@
+From 3bebf4a4400ab70ccef98c069d240dbd17dd718f Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 19:13:25 +0200
+Subject: [PATCH 76/79] mmc: MIPS: ralink: add sdhci for mt7620a SoC
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mmc/host/Kconfig | 11 +
+ drivers/mmc/host/Makefile | 1 +
+ drivers/mmc/host/mt6575_sd.h | 1068 ++++++++++++++++++
+ drivers/mmc/host/sdhci-mt7620.c | 2314 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 3394 insertions(+)
+ create mode 100644 drivers/mmc/host/mt6575_sd.h
+ create mode 100644 drivers/mmc/host/sdhci-mt7620.c
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 8d13c65..04085b3 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -241,6 +241,17 @@ config MMC_SDHCI_S3C_DMA
+
+ YMMV.
+
++config MMC_SDHCI_MT7620
++ tristate "SDHCI platform support for the MT7620 SD/MMC Controller"
++ depends on SOC_MT7620
++ depends on MMC_SDHCI_PLTFM
++ select MMC_SDHCI_IO_ACCESSORS
++ help
++ This selects the BCM2835 SD/MMC controller. If you have a BCM2835
++ platform with SD or MMC devices, say Y or M here.
++
++ If unsure, say N.
++
+ config MMC_OMAP
+ tristate "TI OMAP Multimedia Card Interface support"
+ depends on ARCH_OMAP
+diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
+index e4e218c..be79804 100644
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -58,6 +58,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o
+ obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o
+ obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
+ obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
++obj-$(CONFIG_MMC_SDHCI_MT7620) += sdhci-mt7620.o
+
+ ifeq ($(CONFIG_CB710_DEBUG),y)
+ CFLAGS-cb710-mmc += -DDEBUG
+diff --git a/drivers/mmc/host/mt6575_sd.h b/drivers/mmc/host/mt6575_sd.h
+new file mode 100644
+index 0000000..406382c
+--- /dev/null
++++ b/drivers/mmc/host/mt6575_sd.h
+@@ -0,0 +1,1068 @@
++/* Copyright Statement:
++ *
++ * This software/firmware and related documentation ("MediaTek Software") are
++ * protected under relevant copyright laws. The information contained herein
++ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
++ * Without the prior written permission of MediaTek inc. and/or its licensors,
++ * any reproduction, modification, use or disclosure of MediaTek Software,
++ * and information contained herein, in whole or in part, shall be strictly prohibited.
++ */
++/* MediaTek Inc. (C) 2010. All rights reserved.
++ *
++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
++ *
++ * The following software/firmware and/or related documentation ("MediaTek Software")
++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
++ * applicable license agreements with MediaTek Inc.
++ */
++
++#ifndef MT6575_SD_H
++#define MT6575_SD_H
++
++#include <linux/bitops.h>
++#include <linux/mmc/host.h>
++
++// #include <mach/mt6575_reg_base.h> /* --- by chhung */
++
++typedef void (*sdio_irq_handler_t)(void*); /* external irq handler */
++typedef void (*pm_callback_t)(pm_message_t state, void *data);
++
++#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */
++#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */
++#define MSDC_RST_PIN_EN (1 << 2) /* emmc reset pin is wired */
++#define MSDC_SDIO_IRQ (1 << 3) /* use internal sdio irq (bus) */
++#define MSDC_EXT_SDIO_IRQ (1 << 4) /* use external sdio irq */
++#define MSDC_REMOVABLE (1 << 5) /* removable slot */
++#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */
++#define MSDC_HIGHSPEED (1 << 7) /* high-speed mode support */
++#define MSDC_UHS1 (1 << 8) /* uhs-1 mode support */
++#define MSDC_DDR (1 << 9) /* ddr mode support */
++#define MSDC_SPE (1 << 10) /* special support */
++#define MSDC_INTERNAL_CLK (1 << 11) /* Force Internal clock */
++#define MSDC_TABDRV (1 << 12) /* TABLET */
++
++
++#define MSDC_SMPL_RISING (0)
++#define MSDC_SMPL_FALLING (1)
++
++#define MSDC_CMD_PIN (0)
++#define MSDC_DAT_PIN (1)
++#define MSDC_CD_PIN (2)
++#define MSDC_WP_PIN (3)
++#define MSDC_RST_PIN (4)
++
++enum {
++ MSDC_CLKSRC_26MHZ = 0,
++ MSDC_CLKSRC_197MHZ = 1,
++ MSDC_CLKSRC_208MHZ = 2
++};
++
++struct msdc_hw {
++ unsigned char clk_src; /* host clock source */
++ unsigned char cmd_edge; /* command latch edge */
++ unsigned char data_edge; /* data latch edge */
++ unsigned char clk_drv; /* clock pad driving */
++ unsigned char cmd_drv; /* command pad driving */
++ unsigned char dat_drv; /* data pad driving */
++ unsigned long flags; /* hardware capability flags */
++ unsigned long data_pins; /* data pins */
++ unsigned long data_offset; /* data address offset */
++
++ /* config gpio pull mode */
++ void (*config_gpio_pin)(int type, int pull);
++
++ /* external power control for card */
++ void (*ext_power_on)(void);
++ void (*ext_power_off)(void);
++
++ /* external sdio irq operations */
++ void (*request_sdio_eirq)(sdio_irq_handler_t sdio_irq_handler, void *data);
++ void (*enable_sdio_eirq)(void);
++ void (*disable_sdio_eirq)(void);
++
++ /* external cd irq operations */
++ void (*request_cd_eirq)(sdio_irq_handler_t cd_irq_handler, void *data);
++ void (*enable_cd_eirq)(void);
++ void (*disable_cd_eirq)(void);
++ int (*get_cd_status)(void);
++
++ /* power management callback for external module */
++ void (*register_pm)(pm_callback_t pm_cb, void *data);
++};
++
++extern struct msdc_hw msdc0_hw;
++extern struct msdc_hw msdc1_hw;
++extern struct msdc_hw msdc2_hw;
++extern struct msdc_hw msdc3_hw;
++
++
++/*--------------------------------------------------------------------------*/
++/* Common Macro */
++/*--------------------------------------------------------------------------*/
++#define REG_ADDR(x) ((volatile u32*)(base + OFFSET_##x))
++
++/*--------------------------------------------------------------------------*/
++/* Common Definition */
++/*--------------------------------------------------------------------------*/
++#define MSDC_FIFO_SZ (128)
++#define MSDC_FIFO_THD (64) // (128)
++#define MSDC_NUM (4)
++
++#define MSDC_MS (0)
++#define MSDC_SDMMC (1)
++
++#define MSDC_MODE_UNKNOWN (0)
++#define MSDC_MODE_PIO (1)
++#define MSDC_MODE_DMA_BASIC (2)
++#define MSDC_MODE_DMA_DESC (3)
++#define MSDC_MODE_DMA_ENHANCED (4)
++#define MSDC_MODE_MMC_STREAM (5)
++
++#define MSDC_BUS_1BITS (0)
++#define MSDC_BUS_4BITS (1)
++#define MSDC_BUS_8BITS (2)
++
++#define MSDC_BRUST_8B (3)
++#define MSDC_BRUST_16B (4)
++#define MSDC_BRUST_32B (5)
++#define MSDC_BRUST_64B (6)
++
++#define MSDC_PIN_PULL_NONE (0)
++#define MSDC_PIN_PULL_DOWN (1)
++#define MSDC_PIN_PULL_UP (2)
++#define MSDC_PIN_KEEP (3)
++
++#define MSDC_MAX_SCLK (48000000) /* +/- by chhung */
++#define MSDC_MIN_SCLK (260000)
++
++#define MSDC_AUTOCMD12 (0x0001)
++#define MSDC_AUTOCMD23 (0x0002)
++#define MSDC_AUTOCMD19 (0x0003)
++
++#define MSDC_EMMC_BOOTMODE0 (0) /* Pull low CMD mode */
++#define MSDC_EMMC_BOOTMODE1 (1) /* Reset CMD mode */
++
++enum {
++ RESP_NONE = 0,
++ RESP_R1,
++ RESP_R2,
++ RESP_R3,
++ RESP_R4,
++ RESP_R5,
++ RESP_R6,
++ RESP_R7,
++ RESP_R1B
++};
++
++/*--------------------------------------------------------------------------*/
++/* Register Offset */
++/*--------------------------------------------------------------------------*/
++#define OFFSET_MSDC_CFG (0x0)
++#define OFFSET_MSDC_IOCON (0x04)
++#define OFFSET_MSDC_PS (0x08)
++#define OFFSET_MSDC_INT (0x0c)
++#define OFFSET_MSDC_INTEN (0x10)
++#define OFFSET_MSDC_FIFOCS (0x14)
++#define OFFSET_MSDC_TXDATA (0x18)
++#define OFFSET_MSDC_RXDATA (0x1c)
++#define OFFSET_SDC_CFG (0x30)
++#define OFFSET_SDC_CMD (0x34)
++#define OFFSET_SDC_ARG (0x38)
++#define OFFSET_SDC_STS (0x3c)
++#define OFFSET_SDC_RESP0 (0x40)
++#define OFFSET_SDC_RESP1 (0x44)
++#define OFFSET_SDC_RESP2 (0x48)
++#define OFFSET_SDC_RESP3 (0x4c)
++#define OFFSET_SDC_BLK_NUM (0x50)
++#define OFFSET_SDC_CSTS (0x58)
++#define OFFSET_SDC_CSTS_EN (0x5c)
++#define OFFSET_SDC_DCRC_STS (0x60)
++#define OFFSET_EMMC_CFG0 (0x70)
++#define OFFSET_EMMC_CFG1 (0x74)
++#define OFFSET_EMMC_STS (0x78)
++#define OFFSET_EMMC_IOCON (0x7c)
++#define OFFSET_SDC_ACMD_RESP (0x80)
++#define OFFSET_SDC_ACMD19_TRG (0x84)
++#define OFFSET_SDC_ACMD19_STS (0x88)
++#define OFFSET_MSDC_DMA_SA (0x90)
++#define OFFSET_MSDC_DMA_CA (0x94)
++#define OFFSET_MSDC_DMA_CTRL (0x98)
++#define OFFSET_MSDC_DMA_CFG (0x9c)
++#define OFFSET_MSDC_DBG_SEL (0xa0)
++#define OFFSET_MSDC_DBG_OUT (0xa4)
++#define OFFSET_MSDC_PATCH_BIT (0xb0)
++#define OFFSET_MSDC_PATCH_BIT1 (0xb4)
++#define OFFSET_MSDC_PAD_CTL0 (0xe0)
++#define OFFSET_MSDC_PAD_CTL1 (0xe4)
++#define OFFSET_MSDC_PAD_CTL2 (0xe8)
++#define OFFSET_MSDC_PAD_TUNE (0xec)
++#define OFFSET_MSDC_DAT_RDDLY0 (0xf0)
++#define OFFSET_MSDC_DAT_RDDLY1 (0xf4)
++#define OFFSET_MSDC_HW_DBG (0xf8)
++#define OFFSET_MSDC_VERSION (0x100)
++#define OFFSET_MSDC_ECO_VER (0x104)
++
++/*--------------------------------------------------------------------------*/
++/* Register Address */
++/*--------------------------------------------------------------------------*/
++
++/* common register */
++#define MSDC_CFG REG_ADDR(MSDC_CFG)
++#define MSDC_IOCON REG_ADDR(MSDC_IOCON)
++#define MSDC_PS REG_ADDR(MSDC_PS)
++#define MSDC_INT REG_ADDR(MSDC_INT)
++#define MSDC_INTEN REG_ADDR(MSDC_INTEN)
++#define MSDC_FIFOCS REG_ADDR(MSDC_FIFOCS)
++#define MSDC_TXDATA REG_ADDR(MSDC_TXDATA)
++#define MSDC_RXDATA REG_ADDR(MSDC_RXDATA)
++#define MSDC_PATCH_BIT0 REG_ADDR(MSDC_PATCH_BIT)
++
++/* sdmmc register */
++#define SDC_CFG REG_ADDR(SDC_CFG)
++#define SDC_CMD REG_ADDR(SDC_CMD)
++#define SDC_ARG REG_ADDR(SDC_ARG)
++#define SDC_STS REG_ADDR(SDC_STS)
++#define SDC_RESP0 REG_ADDR(SDC_RESP0)
++#define SDC_RESP1 REG_ADDR(SDC_RESP1)
++#define SDC_RESP2 REG_ADDR(SDC_RESP2)
++#define SDC_RESP3 REG_ADDR(SDC_RESP3)
++#define SDC_BLK_NUM REG_ADDR(SDC_BLK_NUM)
++#define SDC_CSTS REG_ADDR(SDC_CSTS)
++#define SDC_CSTS_EN REG_ADDR(SDC_CSTS_EN)
++#define SDC_DCRC_STS REG_ADDR(SDC_DCRC_STS)
++
++/* emmc register*/
++#define EMMC_CFG0 REG_ADDR(EMMC_CFG0)
++#define EMMC_CFG1 REG_ADDR(EMMC_CFG1)
++#define EMMC_STS REG_ADDR(EMMC_STS)
++#define EMMC_IOCON REG_ADDR(EMMC_IOCON)
++
++/* auto command register */
++#define SDC_ACMD_RESP REG_ADDR(SDC_ACMD_RESP)
++#define SDC_ACMD19_TRG REG_ADDR(SDC_ACMD19_TRG)
++#define SDC_ACMD19_STS REG_ADDR(SDC_ACMD19_STS)
++
++/* dma register */
++#define MSDC_DMA_SA REG_ADDR(MSDC_DMA_SA)
++#define MSDC_DMA_CA REG_ADDR(MSDC_DMA_CA)
++#define MSDC_DMA_CTRL REG_ADDR(MSDC_DMA_CTRL)
++#define MSDC_DMA_CFG REG_ADDR(MSDC_DMA_CFG)
++
++/* pad ctrl register */
++#define MSDC_PAD_CTL0 REG_ADDR(MSDC_PAD_CTL0)
++#define MSDC_PAD_CTL1 REG_ADDR(MSDC_PAD_CTL1)
++#define MSDC_PAD_CTL2 REG_ADDR(MSDC_PAD_CTL2)
++
++/* data read delay */
++#define MSDC_DAT_RDDLY0 REG_ADDR(MSDC_DAT_RDDLY0)
++#define MSDC_DAT_RDDLY1 REG_ADDR(MSDC_DAT_RDDLY1)
++
++/* debug register */
++#define MSDC_DBG_SEL REG_ADDR(MSDC_DBG_SEL)
++#define MSDC_DBG_OUT REG_ADDR(MSDC_DBG_OUT)
++
++/* misc register */
++#define MSDC_PATCH_BIT REG_ADDR(MSDC_PATCH_BIT)
++#define MSDC_PATCH_BIT1 REG_ADDR(MSDC_PATCH_BIT1)
++#define MSDC_PAD_TUNE REG_ADDR(MSDC_PAD_TUNE)
++#define MSDC_HW_DBG REG_ADDR(MSDC_HW_DBG)
++#define MSDC_VERSION REG_ADDR(MSDC_VERSION)
++#define MSDC_ECO_VER REG_ADDR(MSDC_ECO_VER) /* ECO Version */
++
++/*--------------------------------------------------------------------------*/
++/* Register Mask */
++/*--------------------------------------------------------------------------*/
++
++/* MSDC_CFG mask */
++#define MSDC_CFG_MODE (0x1 << 0) /* RW */
++#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */
++#define MSDC_CFG_RST (0x1 << 2) /* RW */
++#define MSDC_CFG_PIO (0x1 << 3) /* RW */
++#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */
++#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */
++#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */
++#define MSDC_CFG_CKSTB (0x1 << 7) /* R */
++#define MSDC_CFG_CKDIV (0xff << 8) /* RW */
++#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */
++
++/* MSDC_IOCON mask */
++#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */
++#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */
++#define MSDC_IOCON_DSPL (0x1 << 2) /* RW */
++#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */
++#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */
++#define MSDC_IOCON_DSPLSEL (0x1 << 5) /* RW */
++#define MSDC_IOCON_D0SPL (0x1 << 16) /* RW */
++#define MSDC_IOCON_D1SPL (0x1 << 17) /* RW */
++#define MSDC_IOCON_D2SPL (0x1 << 18) /* RW */
++#define MSDC_IOCON_D3SPL (0x1 << 19) /* RW */
++#define MSDC_IOCON_D4SPL (0x1 << 20) /* RW */
++#define MSDC_IOCON_D5SPL (0x1 << 21) /* RW */
++#define MSDC_IOCON_D6SPL (0x1 << 22) /* RW */
++#define MSDC_IOCON_D7SPL (0x1 << 23) /* RW */
++#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW */
++
++/* MSDC_PS mask */
++#define MSDC_PS_CDEN (0x1 << 0) /* RW */
++#define MSDC_PS_CDSTS (0x1 << 1) /* R */
++#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */
++#define MSDC_PS_DAT (0xff << 16) /* R */
++#define MSDC_PS_CMD (0x1 << 24) /* R */
++#define MSDC_PS_WP (0x1UL<< 31) /* R */
++
++/* MSDC_INT mask */
++#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */
++#define MSDC_INT_CDSC (0x1 << 1) /* W1C */
++#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */
++#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */
++#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */
++#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */
++#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */
++#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */
++#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */
++#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */
++#define MSDC_INT_CSTA (0x1 << 11) /* R */
++#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */
++#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */
++#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */
++#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */
++#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */
++
++/* MSDC_INTEN mask */
++#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */
++#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */
++#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */
++#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */
++#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */
++#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */
++#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */
++#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */
++#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */
++#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */
++#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */
++#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */
++#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */
++#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */
++#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */
++#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */
++
++/* MSDC_FIFOCS mask */
++#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */
++#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */
++#define MSDC_FIFOCS_CLR (0x1UL<< 31) /* RW */
++
++/* SDC_CFG mask */
++#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */
++#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */
++#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */
++#define SDC_CFG_SDIO (0x1 << 19) /* RW */
++#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */
++#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */
++#define SDC_CFG_DTOC (0xffUL << 24) /* RW */
++
++/* SDC_CMD mask */
++#define SDC_CMD_OPC (0x3f << 0) /* RW */
++#define SDC_CMD_BRK (0x1 << 6) /* RW */
++#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */
++#define SDC_CMD_DTYP (0x3 << 11) /* RW */
++#define SDC_CMD_DTYP (0x3 << 11) /* RW */
++#define SDC_CMD_RW (0x1 << 13) /* RW */
++#define SDC_CMD_STOP (0x1 << 14) /* RW */
++#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */
++#define SDC_CMD_BLKLEN (0xfff<< 16) /* RW */
++#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */
++#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */
++
++/* SDC_STS mask */
++#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */
++#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */
++#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */
++
++/* SDC_DCRC_STS mask */
++#define SDC_DCRC_STS_NEG (0xf << 8) /* RO */
++#define SDC_DCRC_STS_POS (0xff << 0) /* RO */
++
++/* EMMC_CFG0 mask */
++#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* W */
++#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* W */
++#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW */
++#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW */
++#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW */
++#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW */
++
++/* EMMC_CFG1 mask */
++#define EMMC_CFG1_BOOTDATTMC (0xfffff << 0) /* RW */
++#define EMMC_CFG1_BOOTACKTMC (0xfffUL << 20) /* RW */
++
++/* EMMC_STS mask */
++#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C */
++#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C */
++#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C */
++#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C */
++#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* R */
++#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C */
++#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* R */
++
++/* EMMC_IOCON mask */
++#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW */
++
++/* SDC_ACMD19_TRG mask */
++#define SDC_ACMD19_TRG_TUNESEL (0xf << 0) /* RW */
++
++/* MSDC_DMA_CTRL mask */
++#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */
++#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */
++#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */
++#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */
++#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */
++#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */
++#define MSDC_DMA_CTRL_XFERSZ (0xffffUL << 16)/* RW */
++
++/* MSDC_DMA_CFG mask */
++#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */
++#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */
++#define MSDC_DMA_CFG_BDCSERR (0x1 << 4) /* R */
++#define MSDC_DMA_CFG_GPDCSERR (0x1 << 5) /* R */
++
++/* MSDC_PATCH_BIT mask */
++#define MSDC_PATCH_BIT_WFLSMODE (0x1 << 0) /* RW */
++#define MSDC_PATCH_BIT_ODDSUPP (0x1 << 1) /* RW */
++#define MSDC_PATCH_BIT_CKGEN_CK (0x1 << 6) /* E2: Fixed to 1 */
++#define MSDC_PATCH_BIT_IODSSEL (0x1 << 16) /* RW */
++#define MSDC_PATCH_BIT_IOINTSEL (0x1 << 17) /* RW */
++#define MSDC_PATCH_BIT_BUSYDLY (0xf << 18) /* RW */
++#define MSDC_PATCH_BIT_WDOD (0xf << 22) /* RW */
++#define MSDC_PATCH_BIT_IDRTSEL (0x1 << 26) /* RW */
++#define MSDC_PATCH_BIT_CMDFSEL (0x1 << 27) /* RW */
++#define MSDC_PATCH_BIT_INTDLSEL (0x1 << 28) /* RW */
++#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */
++#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
++
++/* MSDC_PATCH_BIT1 mask */
++#define MSDC_PATCH_BIT1_WRDAT_CRCS (0x7 << 3)
++#define MSDC_PATCH_BIT1_CMD_RSP (0x7 << 0)
++
++/* MSDC_PAD_CTL0 mask */
++#define MSDC_PAD_CTL0_CLKDRVN (0x7 << 0) /* RW */
++#define MSDC_PAD_CTL0_CLKDRVP (0x7 << 4) /* RW */
++#define MSDC_PAD_CTL0_CLKSR (0x1 << 8) /* RW */
++#define MSDC_PAD_CTL0_CLKPD (0x1 << 16) /* RW */
++#define MSDC_PAD_CTL0_CLKPU (0x1 << 17) /* RW */
++#define MSDC_PAD_CTL0_CLKSMT (0x1 << 18) /* RW */
++#define MSDC_PAD_CTL0_CLKIES (0x1 << 19) /* RW */
++#define MSDC_PAD_CTL0_CLKTDSEL (0xf << 20) /* RW */
++#define MSDC_PAD_CTL0_CLKRDSEL (0xffUL<< 24) /* RW */
++
++/* MSDC_PAD_CTL1 mask */
++#define MSDC_PAD_CTL1_CMDDRVN (0x7 << 0) /* RW */
++#define MSDC_PAD_CTL1_CMDDRVP (0x7 << 4) /* RW */
++#define MSDC_PAD_CTL1_CMDSR (0x1 << 8) /* RW */
++#define MSDC_PAD_CTL1_CMDPD (0x1 << 16) /* RW */
++#define MSDC_PAD_CTL1_CMDPU (0x1 << 17) /* RW */
++#define MSDC_PAD_CTL1_CMDSMT (0x1 << 18) /* RW */
++#define MSDC_PAD_CTL1_CMDIES (0x1 << 19) /* RW */
++#define MSDC_PAD_CTL1_CMDTDSEL (0xf << 20) /* RW */
++#define MSDC_PAD_CTL1_CMDRDSEL (0xffUL<< 24) /* RW */
++
++/* MSDC_PAD_CTL2 mask */
++#define MSDC_PAD_CTL2_DATDRVN (0x7 << 0) /* RW */
++#define MSDC_PAD_CTL2_DATDRVP (0x7 << 4) /* RW */
++#define MSDC_PAD_CTL2_DATSR (0x1 << 8) /* RW */
++#define MSDC_PAD_CTL2_DATPD (0x1 << 16) /* RW */
++#define MSDC_PAD_CTL2_DATPU (0x1 << 17) /* RW */
++#define MSDC_PAD_CTL2_DATIES (0x1 << 19) /* RW */
++#define MSDC_PAD_CTL2_DATSMT (0x1 << 18) /* RW */
++#define MSDC_PAD_CTL2_DATTDSEL (0xf << 20) /* RW */
++#define MSDC_PAD_CTL2_DATRDSEL (0xffUL<< 24) /* RW */
++
++/* MSDC_PAD_TUNE mask */
++#define MSDC_PAD_TUNE_DATWRDLY (0x1F << 0) /* RW */
++#define MSDC_PAD_TUNE_DATRRDLY (0x1F << 8) /* RW */
++#define MSDC_PAD_TUNE_CMDRDLY (0x1F << 16) /* RW */
++#define MSDC_PAD_TUNE_CMDRRDLY (0x1FUL << 22) /* RW */
++#define MSDC_PAD_TUNE_CLKTXDLY (0x1FUL << 27) /* RW */
++
++/* MSDC_DAT_RDDLY0/1 mask */
++#define MSDC_DAT_RDDLY0_D0 (0x1F << 0) /* RW */
++#define MSDC_DAT_RDDLY0_D1 (0x1F << 8) /* RW */
++#define MSDC_DAT_RDDLY0_D2 (0x1F << 16) /* RW */
++#define MSDC_DAT_RDDLY0_D3 (0x1F << 24) /* RW */
++
++#define MSDC_DAT_RDDLY1_D4 (0x1F << 0) /* RW */
++#define MSDC_DAT_RDDLY1_D5 (0x1F << 8) /* RW */
++#define MSDC_DAT_RDDLY1_D6 (0x1F << 16) /* RW */
++#define MSDC_DAT_RDDLY1_D7 (0x1F << 24) /* RW */
++
++#define MSDC_CKGEN_MSDC_DLY_SEL (0x1F<<10)
++#define MSDC_INT_DAT_LATCH_CK_SEL (0x7<<7)
++#define MSDC_CKGEN_MSDC_CK_SEL (0x1<<6)
++#define CARD_READY_FOR_DATA (1<<8)
++#define CARD_CURRENT_STATE(x) ((x&0x00001E00)>>9)
++
++/*--------------------------------------------------------------------------*/
++/* Descriptor Structure */
++/*--------------------------------------------------------------------------*/
++typedef struct {
++ u32 hwo:1; /* could be changed by hw */
++ u32 bdp:1;
++ u32 rsv0:6;
++ u32 chksum:8;
++ u32 intr:1;
++ u32 rsv1:15;
++ void *next;
++ void *ptr;
++ u32 buflen:16;
++ u32 extlen:8;
++ u32 rsv2:8;
++ u32 arg;
++ u32 blknum;
++ u32 cmd;
++} gpd_t;
++
++typedef struct {
++ u32 eol:1;
++ u32 rsv0:7;
++ u32 chksum:8;
++ u32 rsv1:1;
++ u32 blkpad:1;
++ u32 dwpad:1;
++ u32 rsv2:13;
++ void *next;
++ void *ptr;
++ u32 buflen:16;
++ u32 rsv3:16;
++} bd_t;
++
++/*--------------------------------------------------------------------------*/
++/* Register Debugging Structure */
++/*--------------------------------------------------------------------------*/
++
++typedef struct {
++ u32 msdc:1;
++ u32 ckpwn:1;
++ u32 rst:1;
++ u32 pio:1;
++ u32 ckdrven:1;
++ u32 start18v:1;
++ u32 pass18v:1;
++ u32 ckstb:1;
++ u32 ckdiv:8;
++ u32 ckmod:2;
++ u32 pad:14;
++} msdc_cfg_reg;
++typedef struct {
++ u32 sdr104cksel:1;
++ u32 rsmpl:1;
++ u32 dsmpl:1;
++ u32 ddlysel:1;
++ u32 ddr50ckd:1;
++ u32 dsplsel:1;
++ u32 pad1:10;
++ u32 d0spl:1;
++ u32 d1spl:1;
++ u32 d2spl:1;
++ u32 d3spl:1;
++ u32 d4spl:1;
++ u32 d5spl:1;
++ u32 d6spl:1;
++ u32 d7spl:1;
++ u32 riscsz:1;
++ u32 pad2:7;
++} msdc_iocon_reg;
++typedef struct {
++ u32 cden:1;
++ u32 cdsts:1;
++ u32 pad1:10;
++ u32 cddebounce:4;
++ u32 dat:8;
++ u32 cmd:1;
++ u32 pad2:6;
++ u32 wp:1;
++} msdc_ps_reg;
++typedef struct {
++ u32 mmcirq:1;
++ u32 cdsc:1;
++ u32 pad1:1;
++ u32 atocmdrdy:1;
++ u32 atocmdtmo:1;
++ u32 atocmdcrc:1;
++ u32 dmaqempty:1;
++ u32 sdioirq:1;
++ u32 cmdrdy:1;
++ u32 cmdtmo:1;
++ u32 rspcrc:1;
++ u32 csta:1;
++ u32 xfercomp:1;
++ u32 dxferdone:1;
++ u32 dattmo:1;
++ u32 datcrc:1;
++ u32 atocmd19done:1;
++ u32 pad2:15;
++} msdc_int_reg;
++typedef struct {
++ u32 mmcirq:1;
++ u32 cdsc:1;
++ u32 pad1:1;
++ u32 atocmdrdy:1;
++ u32 atocmdtmo:1;
++ u32 atocmdcrc:1;
++ u32 dmaqempty:1;
++ u32 sdioirq:1;
++ u32 cmdrdy:1;
++ u32 cmdtmo:1;
++ u32 rspcrc:1;
++ u32 csta:1;
++ u32 xfercomp:1;
++ u32 dxferdone:1;
++ u32 dattmo:1;
++ u32 datcrc:1;
++ u32 atocmd19done:1;
++ u32 pad2:15;
++} msdc_inten_reg;
++typedef struct {
++ u32 rxcnt:8;
++ u32 pad1:8;
++ u32 txcnt:8;
++ u32 pad2:7;
++ u32 clr:1;
++} msdc_fifocs_reg;
++typedef struct {
++ u32 val;
++} msdc_txdat_reg;
++typedef struct {
++ u32 val;
++} msdc_rxdat_reg;
++typedef struct {
++ u32 sdiowkup:1;
++ u32 inswkup:1;
++ u32 pad1:14;
++ u32 buswidth:2;
++ u32 pad2:1;
++ u32 sdio:1;
++ u32 sdioide:1;
++ u32 intblkgap:1;
++ u32 pad4:2;
++ u32 dtoc:8;
++} sdc_cfg_reg;
++typedef struct {
++ u32 cmd:6;
++ u32 brk:1;
++ u32 rsptyp:3;
++ u32 pad1:1;
++ u32 dtype:2;
++ u32 rw:1;
++ u32 stop:1;
++ u32 goirq:1;
++ u32 blklen:12;
++ u32 atocmd:2;
++ u32 volswth:1;
++ u32 pad2:1;
++} sdc_cmd_reg;
++typedef struct {
++ u32 arg;
++} sdc_arg_reg;
++typedef struct {
++ u32 sdcbusy:1;
++ u32 cmdbusy:1;
++ u32 pad:29;
++ u32 swrcmpl:1;
++} sdc_sts_reg;
++typedef struct {
++ u32 val;
++} sdc_resp0_reg;
++typedef struct {
++ u32 val;
++} sdc_resp1_reg;
++typedef struct {
++ u32 val;
++} sdc_resp2_reg;
++typedef struct {
++ u32 val;
++} sdc_resp3_reg;
++typedef struct {
++ u32 num;
++} sdc_blknum_reg;
++typedef struct {
++ u32 sts;
++} sdc_csts_reg;
++typedef struct {
++ u32 sts;
++} sdc_cstsen_reg;
++typedef struct {
++ u32 datcrcsts:8;
++ u32 ddrcrcsts:4;
++ u32 pad:20;
++} sdc_datcrcsts_reg;
++typedef struct {
++ u32 bootstart:1;
++ u32 bootstop:1;
++ u32 bootmode:1;
++ u32 pad1:9;
++ u32 bootwaidly:3;
++ u32 bootsupp:1;
++ u32 pad2:16;
++} emmc_cfg0_reg;
++typedef struct {
++ u32 bootcrctmc:16;
++ u32 pad:4;
++ u32 bootacktmc:12;
++} emmc_cfg1_reg;
++typedef struct {
++ u32 bootcrcerr:1;
++ u32 bootackerr:1;
++ u32 bootdattmo:1;
++ u32 bootacktmo:1;
++ u32 bootupstate:1;
++ u32 bootackrcv:1;
++ u32 bootdatrcv:1;
++ u32 pad:25;
++} emmc_sts_reg;
++typedef struct {
++ u32 bootrst:1;
++ u32 pad:31;
++} emmc_iocon_reg;
++typedef struct {
++ u32 val;
++} msdc_acmd_resp_reg;
++typedef struct {
++ u32 tunesel:4;
++ u32 pad:28;
++} msdc_acmd19_trg_reg;
++typedef struct {
++ u32 val;
++} msdc_acmd19_sts_reg;
++typedef struct {
++ u32 addr;
++} msdc_dma_sa_reg;
++typedef struct {
++ u32 addr;
++} msdc_dma_ca_reg;
++typedef struct {
++ u32 start:1;
++ u32 stop:1;
++ u32 resume:1;
++ u32 pad1:5;
++ u32 mode:1;
++ u32 pad2:1;
++ u32 lastbuf:1;
++ u32 pad3:1;
++ u32 brustsz:3;
++ u32 pad4:1;
++ u32 xfersz:16;
++} msdc_dma_ctrl_reg;
++typedef struct {
++ u32 status:1;
++ u32 decsen:1;
++ u32 pad1:2;
++ u32 bdcsen:1;
++ u32 gpdcsen:1;
++ u32 pad2:26;
++} msdc_dma_cfg_reg;
++typedef struct {
++ u32 sel:16;
++ u32 pad2:16;
++} msdc_dbg_sel_reg;
++typedef struct {
++ u32 val;
++} msdc_dbg_out_reg;
++typedef struct {
++ u32 clkdrvn:3;
++ u32 rsv0:1;
++ u32 clkdrvp:3;
++ u32 rsv1:1;
++ u32 clksr:1;
++ u32 rsv2:7;
++ u32 clkpd:1;
++ u32 clkpu:1;
++ u32 clksmt:1;
++ u32 clkies:1;
++ u32 clktdsel:4;
++ u32 clkrdsel:8;
++} msdc_pad_ctl0_reg;
++typedef struct {
++ u32 cmddrvn:3;
++ u32 rsv0:1;
++ u32 cmddrvp:3;
++ u32 rsv1:1;
++ u32 cmdsr:1;
++ u32 rsv2:7;
++ u32 cmdpd:1;
++ u32 cmdpu:1;
++ u32 cmdsmt:1;
++ u32 cmdies:1;
++ u32 cmdtdsel:4;
++ u32 cmdrdsel:8;
++} msdc_pad_ctl1_reg;
++typedef struct {
++ u32 datdrvn:3;
++ u32 rsv0:1;
++ u32 datdrvp:3;
++ u32 rsv1:1;
++ u32 datsr:1;
++ u32 rsv2:7;
++ u32 datpd:1;
++ u32 datpu:1;
++ u32 datsmt:1;
++ u32 daties:1;
++ u32 dattdsel:4;
++ u32 datrdsel:8;
++} msdc_pad_ctl2_reg;
++typedef struct {
++ u32 wrrxdly:3;
++ u32 pad1:5;
++ u32 rdrxdly:8;
++ u32 pad2:16;
++} msdc_pad_tune_reg;
++typedef struct {
++ u32 dat0:5;
++ u32 rsv0:3;
++ u32 dat1:5;
++ u32 rsv1:3;
++ u32 dat2:5;
++ u32 rsv2:3;
++ u32 dat3:5;
++ u32 rsv3:3;
++} msdc_dat_rddly0;
++typedef struct {
++ u32 dat4:5;
++ u32 rsv4:3;
++ u32 dat5:5;
++ u32 rsv5:3;
++ u32 dat6:5;
++ u32 rsv6:3;
++ u32 dat7:5;
++ u32 rsv7:3;
++} msdc_dat_rddly1;
++typedef struct {
++ u32 dbg0sel:8;
++ u32 dbg1sel:6;
++ u32 pad1:2;
++ u32 dbg2sel:6;
++ u32 pad2:2;
++ u32 dbg3sel:6;
++ u32 pad3:2;
++} msdc_hw_dbg_reg;
++typedef struct {
++ u32 val;
++} msdc_version_reg;
++typedef struct {
++ u32 val;
++} msdc_eco_ver_reg;
++
++struct msdc_regs {
++ msdc_cfg_reg msdc_cfg; /* base+0x00h */
++ msdc_iocon_reg msdc_iocon; /* base+0x04h */
++ msdc_ps_reg msdc_ps; /* base+0x08h */
++ msdc_int_reg msdc_int; /* base+0x0ch */
++ msdc_inten_reg msdc_inten; /* base+0x10h */
++ msdc_fifocs_reg msdc_fifocs; /* base+0x14h */
++ msdc_txdat_reg msdc_txdat; /* base+0x18h */
++ msdc_rxdat_reg msdc_rxdat; /* base+0x1ch */
++ u32 rsv1[4];
++ sdc_cfg_reg sdc_cfg; /* base+0x30h */
++ sdc_cmd_reg sdc_cmd; /* base+0x34h */
++ sdc_arg_reg sdc_arg; /* base+0x38h */
++ sdc_sts_reg sdc_sts; /* base+0x3ch */
++ sdc_resp0_reg sdc_resp0; /* base+0x40h */
++ sdc_resp1_reg sdc_resp1; /* base+0x44h */
++ sdc_resp2_reg sdc_resp2; /* base+0x48h */
++ sdc_resp3_reg sdc_resp3; /* base+0x4ch */
++ sdc_blknum_reg sdc_blknum; /* base+0x50h */
++ u32 rsv2[1];
++ sdc_csts_reg sdc_csts; /* base+0x58h */
++ sdc_cstsen_reg sdc_cstsen; /* base+0x5ch */
++ sdc_datcrcsts_reg sdc_dcrcsta; /* base+0x60h */
++ u32 rsv3[3];
++ emmc_cfg0_reg emmc_cfg0; /* base+0x70h */
++ emmc_cfg1_reg emmc_cfg1; /* base+0x74h */
++ emmc_sts_reg emmc_sts; /* base+0x78h */
++ emmc_iocon_reg emmc_iocon; /* base+0x7ch */
++ msdc_acmd_resp_reg acmd_resp; /* base+0x80h */
++ msdc_acmd19_trg_reg acmd19_trg; /* base+0x84h */
++ msdc_acmd19_sts_reg acmd19_sts; /* base+0x88h */
++ u32 rsv4[1];
++ msdc_dma_sa_reg dma_sa; /* base+0x90h */
++ msdc_dma_ca_reg dma_ca; /* base+0x94h */
++ msdc_dma_ctrl_reg dma_ctrl; /* base+0x98h */
++ msdc_dma_cfg_reg dma_cfg; /* base+0x9ch */
++ msdc_dbg_sel_reg dbg_sel; /* base+0xa0h */
++ msdc_dbg_out_reg dbg_out; /* base+0xa4h */
++ u32 rsv5[2];
++ u32 patch0; /* base+0xb0h */
++ u32 patch1; /* base+0xb4h */
++ u32 rsv6[10];
++ msdc_pad_ctl0_reg pad_ctl0; /* base+0xe0h */
++ msdc_pad_ctl1_reg pad_ctl1; /* base+0xe4h */
++ msdc_pad_ctl2_reg pad_ctl2; /* base+0xe8h */
++ msdc_pad_tune_reg pad_tune; /* base+0xech */
++ msdc_dat_rddly0 dat_rddly0; /* base+0xf0h */
++ msdc_dat_rddly1 dat_rddly1; /* base+0xf4h */
++ msdc_hw_dbg_reg hw_dbg; /* base+0xf8h */
++ u32 rsv7[1];
++ msdc_version_reg version; /* base+0x100h */
++ msdc_eco_ver_reg eco_ver; /* base+0x104h */
++};
++
++struct scatterlist_ex {
++ u32 cmd;
++ u32 arg;
++ u32 sglen;
++ struct scatterlist *sg;
++};
++
++#define DMA_FLAG_NONE (0x00000000)
++#define DMA_FLAG_EN_CHKSUM (0x00000001)
++#define DMA_FLAG_PAD_BLOCK (0x00000002)
++#define DMA_FLAG_PAD_DWORD (0x00000004)
++
++struct msdc_dma {
++ u32 flags; /* flags */
++ u32 xfersz; /* xfer size in bytes */
++ u32 sglen; /* size of scatter list */
++ u32 blklen; /* block size */
++ struct scatterlist *sg; /* I/O scatter list */
++ struct scatterlist_ex *esg; /* extended I/O scatter list */
++ u8 mode; /* dma mode */
++ u8 burstsz; /* burst size */
++ u8 intr; /* dma done interrupt */
++ u8 padding; /* padding */
++ u32 cmd; /* enhanced mode command */
++ u32 arg; /* enhanced mode arg */
++ u32 rsp; /* enhanced mode command response */
++ u32 autorsp; /* auto command response */
++
++ gpd_t *gpd; /* pointer to gpd array */
++ bd_t *bd; /* pointer to bd array */
++ dma_addr_t gpd_addr; /* the physical address of gpd array */
++ dma_addr_t bd_addr; /* the physical address of bd array */
++ u32 used_gpd; /* the number of used gpd elements */
++ u32 used_bd; /* the number of used bd elements */
++};
++
++struct msdc_host
++{
++ struct msdc_hw *hw;
++
++ struct mmc_host *mmc; /* mmc structure */
++ struct mmc_command *cmd;
++ struct mmc_data *data;
++ struct mmc_request *mrq;
++ int cmd_rsp;
++ int cmd_rsp_done;
++ int cmd_r1b_done;
++
++ int error;
++ spinlock_t lock; /* mutex */
++ struct semaphore sem;
++
++ u32 blksz; /* host block size */
++ u32 base; /* host base address */
++ int id; /* host id */
++ int pwr_ref; /* core power reference count */
++
++ u32 xfer_size; /* total transferred size */
++
++ struct msdc_dma dma; /* dma channel */
++ u32 dma_addr; /* dma transfer address */
++ u32 dma_left_size; /* dma transfer left size */
++ u32 dma_xfer_size; /* dma transfer size in bytes */
++ int dma_xfer; /* dma transfer mode */
++
++ u32 timeout_ns; /* data timeout ns */
++ u32 timeout_clks; /* data timeout clks */
++
++ atomic_t abort; /* abort transfer */
++
++ int irq; /* host interrupt */
++
++ struct tasklet_struct card_tasklet;
++
++ struct completion cmd_done;
++ struct completion xfer_done;
++ struct pm_message pm_state;
++
++ u32 mclk; /* mmc subsystem clock */
++ u32 hclk; /* host clock speed */
++ u32 sclk; /* SD/MS clock speed */
++ u8 core_clkon; /* Host core clock on ? */
++ u8 card_clkon; /* Card clock on ? */
++ u8 core_power; /* core power */
++ u8 power_mode; /* host power mode */
++ u8 card_inserted; /* card inserted ? */
++ u8 suspend; /* host suspended ? */
++ u8 reserved;
++ u8 app_cmd; /* for app command */
++ u32 app_cmd_arg;
++ u64 starttime;
++};
++
++static inline unsigned int uffs(unsigned int x)
++{
++ unsigned int r = 1;
++
++ if (!x)
++ return 0;
++ if (!(x & 0xffff)) {
++ x >>= 16;
++ r += 16;
++ }
++ if (!(x & 0xff)) {
++ x >>= 8;
++ r += 8;
++ }
++ if (!(x & 0xf)) {
++ x >>= 4;
++ r += 4;
++ }
++ if (!(x & 3)) {
++ x >>= 2;
++ r += 2;
++ }
++ if (!(x & 1)) {
++ x >>= 1;
++ r += 1;
++ }
++ return r;
++}
++#define sdr_read8(reg) __raw_readb(reg)
++#define sdr_read16(reg) __raw_readw(reg)
++#define sdr_read32(reg) __raw_readl(reg)
++#define sdr_write8(reg,val) __raw_writeb(val,reg)
++#define sdr_write16(reg,val) __raw_writew(val,reg)
++#define sdr_write32(reg,val) __raw_writel(val,reg)
++
++#define sdr_set_bits(reg,bs) ((*(volatile u32*)(reg)) |= (u32)(bs))
++#define sdr_clr_bits(reg,bs) ((*(volatile u32*)(reg)) &= ~((u32)(bs)))
++
++#define sdr_set_field(reg,field,val) \
++ do { \
++ volatile unsigned int tv = sdr_read32(reg); \
++ tv &= ~(field); \
++ tv |= ((val) << (uffs((unsigned int)field) - 1)); \
++ sdr_write32(reg,tv); \
++ } while(0)
++#define sdr_get_field(reg,field,val) \
++ do { \
++ volatile unsigned int tv = sdr_read32(reg); \
++ val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \
++ } while(0)
++
++#endif
++
+diff --git a/drivers/mmc/host/sdhci-mt7620.c b/drivers/mmc/host/sdhci-mt7620.c
+new file mode 100644
+index 0000000..a3cb5e4
+--- /dev/null
++++ b/drivers/mmc/host/sdhci-mt7620.c
+@@ -0,0 +1,2314 @@
++/* Copyright Statement:
++ *
++ * This software/firmware and related documentation ("MediaTek Software") are
++ * protected under relevant copyright laws. The information contained herein
++ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
++ * Without the prior written permission of MediaTek inc. and/or its licensors,
++ * any reproduction, modification, use or disclosure of MediaTek Software,
++ * and information contained herein, in whole or in part, shall be strictly prohibited.
++ *
++ * MediaTek Inc. (C) 2010. All rights reserved.
++ *
++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
++ *
++ * The following software/firmware and/or related documentation ("MediaTek Software")
++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
++ * applicable license agreements with MediaTek Inc.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/timer.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/of_platform.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/blkdev.h>
++#include <linux/slab.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/card.h>
++#include <linux/mmc/core.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/sd.h>
++#include <linux/mmc/sdio.h>
++#include <linux/dma-mapping.h>
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/pm.h>
++
++#define MSDC_SMPL_FALLING (1)
++#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */
++#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */
++#define MSDC_REMOVABLE (1 << 5) /* removable slot */
++#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */
++#define MSDC_HIGHSPEED (1 << 7)
++
++#define IRQ_SDC 22
++
++#include <asm/dma.h>
++
++#include "mt6575_sd.h"
++
++#define DRV_NAME "mtk-sd"
++
++#define HOST_MAX_NUM (1) /* +/- by chhung */
++
++#define HOST_MAX_MCLK (48000000) /* +/- by chhung */
++#define HOST_MIN_MCLK (260000)
++
++#define HOST_MAX_BLKSZ (2048)
++
++#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33)
++
++#define GPIO_PULL_DOWN (0)
++#define GPIO_PULL_UP (1)
++
++#define DEFAULT_DEBOUNCE (8) /* 8 cycles */
++#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */
++
++#define CMD_TIMEOUT (HZ/10) /* 100ms */
++#define DAT_TIMEOUT (HZ/2 * 5) /* 500ms x5 */
++
++#define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/
++
++#define MAX_GPD_NUM (1 + 1) /* one null gpd */
++#define MAX_BD_NUM (1024)
++#define MAX_BD_PER_GPD (MAX_BD_NUM)
++
++#define MAX_HW_SGMTS (MAX_BD_NUM)
++#define MAX_PHY_SGMTS (MAX_BD_NUM)
++#define MAX_SGMT_SZ (MAX_DMA_CNT)
++#define MAX_REQ_SZ (MAX_SGMT_SZ * 8)
++
++#ifdef MT6575_SD_DEBUG
++static struct msdc_regs *msdc_reg[HOST_MAX_NUM];
++#endif
++
++//=================================
++#define PERI_MSDC0_PDN (15)
++//#define PERI_MSDC1_PDN (16)
++//#define PERI_MSDC2_PDN (17)
++//#define PERI_MSDC3_PDN (18)
++
++struct msdc_host *msdc_6575_host[] = {NULL,NULL,NULL,NULL};
++
++struct msdc_hw msdc0_hw = {
++ .clk_src = 0,
++ .cmd_edge = MSDC_SMPL_FALLING,
++ .data_edge = MSDC_SMPL_FALLING,
++ .clk_drv = 4,
++ .cmd_drv = 4,
++ .dat_drv = 4,
++ .data_pins = 4,
++ .data_offset = 0,
++ .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED,
++};
++
++static struct resource mtk_sd_resources[] = {
++ [0] = {
++ .start = 0xb0130000,
++ .end = 0xb0133fff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_SDC, /*FIXME*/
++ .end = IRQ_SDC, /*FIXME*/
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device mtk_sd_device = {
++ .name = "mtk-sd",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(mtk_sd_resources),
++ .resource = mtk_sd_resources,
++};
++/* end of +++ */
++
++static int msdc_rsp[] = {
++ 0, /* RESP_NONE */
++ 1, /* RESP_R1 */
++ 2, /* RESP_R2 */
++ 3, /* RESP_R3 */
++ 4, /* RESP_R4 */
++ 1, /* RESP_R5 */
++ 1, /* RESP_R6 */
++ 1, /* RESP_R7 */
++ 7, /* RESP_R1b */
++};
++
++/* For Inhanced DMA */
++#define msdc_init_gpd_ex(gpd,extlen,cmd,arg,blknum) \
++ do { \
++ ((gpd_t*)gpd)->extlen = extlen; \
++ ((gpd_t*)gpd)->cmd = cmd; \
++ ((gpd_t*)gpd)->arg = arg; \
++ ((gpd_t*)gpd)->blknum = blknum; \
++ }while(0)
++
++#define msdc_init_bd(bd, blkpad, dwpad, dptr, dlen) \
++ do { \
++ BUG_ON(dlen > 0xFFFFUL); \
++ ((bd_t*)bd)->blkpad = blkpad; \
++ ((bd_t*)bd)->dwpad = dwpad; \
++ ((bd_t*)bd)->ptr = (void*)dptr; \
++ ((bd_t*)bd)->buflen = dlen; \
++ }while(0)
++
++#define msdc_txfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16)
++#define msdc_rxfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0)
++#define msdc_fifo_write32(v) sdr_write32(MSDC_TXDATA, (v))
++#define msdc_fifo_write8(v) sdr_write8(MSDC_TXDATA, (v))
++#define msdc_fifo_read32() sdr_read32(MSDC_RXDATA)
++#define msdc_fifo_read8() sdr_read8(MSDC_RXDATA)
++
++
++#define msdc_dma_on() sdr_clr_bits(MSDC_CFG, MSDC_CFG_PIO)
++#define msdc_dma_off() sdr_set_bits(MSDC_CFG, MSDC_CFG_PIO)
++
++#define msdc_retry(expr,retry,cnt) \
++ do { \
++ int backup = cnt; \
++ while (retry) { \
++ if (!(expr)) break; \
++ if (cnt-- == 0) { \
++ retry--; mdelay(1); cnt = backup; \
++ } \
++ } \
++ WARN_ON(retry == 0); \
++ } while(0)
++
++#if 0 /* +/- chhung */
++#define msdc_reset() \
++ do { \
++ int retry = 3, cnt = 1000; \
++ sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \
++ dsb(); \
++ msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \
++ } while(0)
++#else
++#define msdc_reset() \
++ do { \
++ int retry = 3, cnt = 1000; \
++ sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \
++ msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \
++ } while(0)
++#endif /* end of +/- */
++
++#define msdc_clr_int() \
++ do { \
++ volatile u32 val = sdr_read32(MSDC_INT); \
++ sdr_write32(MSDC_INT, val); \
++ } while(0)
++
++#define msdc_clr_fifo() \
++ do { \
++ int retry = 3, cnt = 1000; \
++ sdr_set_bits(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \
++ msdc_retry(sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \
++ } while(0)
++
++#define msdc_irq_save(val) \
++ do { \
++ val = sdr_read32(MSDC_INTEN); \
++ sdr_clr_bits(MSDC_INTEN, val); \
++ } while(0)
++
++#define msdc_irq_restore(val) \
++ do { \
++ sdr_set_bits(MSDC_INTEN, val); \
++ } while(0)
++
++/* clock source for host: global */
++static u32 hclks[] = {48000000}; /* +/- by chhung */
++
++//============================================
++// the power for msdc host controller: global
++// always keep the VMC on.
++//============================================
++#define msdc_vcore_on(host) \
++ do { \
++ printk("[+]VMC ref. count<%d>\n", ++host->pwr_ref); \
++ (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \
++ } while (0)
++#define msdc_vcore_off(host) \
++ do { \
++ printk("[-]VMC ref. count<%d>\n", --host->pwr_ref); \
++ (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \
++ } while (0)
++
++//====================================
++// the vdd output for card: global
++// always keep the VMCH on.
++//====================================
++#define msdc_vdd_on(host) \
++ do { \
++ (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \
++ } while (0)
++#define msdc_vdd_off(host) \
++ do { \
++ (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \
++ } while (0)
++
++#define sdc_is_busy() (sdr_read32(SDC_STS) & SDC_STS_SDCBUSY)
++#define sdc_is_cmd_busy() (sdr_read32(SDC_STS) & SDC_STS_CMDBUSY)
++
++#define sdc_send_cmd(cmd,arg) \
++ do { \
++ sdr_write32(SDC_ARG, (arg)); \
++ sdr_write32(SDC_CMD, (cmd)); \
++ } while(0)
++
++// can modify to read h/w register.
++//#define is_card_present(h) ((sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1);
++#define is_card_present(h) (((struct msdc_host*)(h))->card_inserted)
++
++/* +++ chhung */
++#ifndef __ASSEMBLY__
++#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff)
++#else
++#define PHYSADDR(a) ((a) & 0x1fffffff)
++#endif
++/* end of +++ */
++static unsigned int msdc_do_command(struct msdc_host *host,
++ struct mmc_command *cmd,
++ int tune,
++ unsigned long timeout);
++
++static int msdc_tune_cmdrsp(struct msdc_host*host,struct mmc_command *cmd);
++
++#ifdef MT6575_SD_DEBUG
++static void msdc_dump_card_status(struct msdc_host *host, u32 status)
++{
++ static char *state[] = {
++ "Idle", /* 0 */
++ "Ready", /* 1 */
++ "Ident", /* 2 */
++ "Stby", /* 3 */
++ "Tran", /* 4 */
++ "Data", /* 5 */
++ "Rcv", /* 6 */
++ "Prg", /* 7 */
++ "Dis", /* 8 */
++ "Reserved", /* 9 */
++ "Reserved", /* 10 */
++ "Reserved", /* 11 */
++ "Reserved", /* 12 */
++ "Reserved", /* 13 */
++ "Reserved", /* 14 */
++ "I/O mode", /* 15 */
++ };
++ if (status & R1_OUT_OF_RANGE)
++ printk("[CARD_STATUS] Out of Range\n");
++ if (status & R1_ADDRESS_ERROR)
++ printk("[CARD_STATUS] Address Error\n");
++ if (status & R1_BLOCK_LEN_ERROR)
++ printk("[CARD_STATUS] Block Len Error\n");
++ if (status & R1_ERASE_SEQ_ERROR)
++ printk("[CARD_STATUS] Erase Seq Error\n");
++ if (status & R1_ERASE_PARAM)
++ printk("[CARD_STATUS] Erase Param\n");
++ if (status & R1_WP_VIOLATION)
++ printk("[CARD_STATUS] WP Violation\n");
++ if (status & R1_CARD_IS_LOCKED)
++ printk("[CARD_STATUS] Card is Locked\n");
++ if (status & R1_LOCK_UNLOCK_FAILED)
++ printk("[CARD_STATUS] Lock/Unlock Failed\n");
++ if (status & R1_COM_CRC_ERROR)
++ printk("[CARD_STATUS] Command CRC Error\n");
++ if (status & R1_ILLEGAL_COMMAND)
++ printk("[CARD_STATUS] Illegal Command\n");
++ if (status & R1_CARD_ECC_FAILED)
++ printk("[CARD_STATUS] Card ECC Failed\n");
++ if (status & R1_CC_ERROR)
++ printk("[CARD_STATUS] CC Error\n");
++ if (status & R1_ERROR)
++ printk("[CARD_STATUS] Error\n");
++ if (status & R1_UNDERRUN)
++ printk("[CARD_STATUS] Underrun\n");
++ if (status & R1_OVERRUN)
++ printk("[CARD_STATUS] Overrun\n");
++ if (status & R1_CID_CSD_OVERWRITE)
++ printk("[CARD_STATUS] CID/CSD Overwrite\n");
++ if (status & R1_WP_ERASE_SKIP)
++ printk("[CARD_STATUS] WP Eraser Skip\n");
++ if (status & R1_CARD_ECC_DISABLED)
++ printk("[CARD_STATUS] Card ECC Disabled\n");
++ if (status & R1_ERASE_RESET)
++ printk("[CARD_STATUS] Erase Reset\n");
++ if (status & R1_READY_FOR_DATA)
++ printk("[CARD_STATUS] Ready for Data\n");
++ if (status & R1_SWITCH_ERROR)
++ printk("[CARD_STATUS] Switch error\n");
++ if (status & R1_APP_CMD)
++ printk("[CARD_STATUS] App Command\n");
++
++ printk("[CARD_STATUS] '%s' State\n", state[R1_CURRENT_STATE(status)]);
++}
++
++static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp)
++{
++ if (resp & (1 << 7))
++ printk("[OCR] Low Voltage Range\n");
++ if (resp & (1 << 15))
++ printk("[OCR] 2.7-2.8 volt\n");
++ if (resp & (1 << 16))
++ printk("[OCR] 2.8-2.9 volt\n");
++ if (resp & (1 << 17))
++ printk("[OCR] 2.9-3.0 volt\n");
++ if (resp & (1 << 18))
++ printk("[OCR] 3.0-3.1 volt\n");
++ if (resp & (1 << 19))
++ printk("[OCR] 3.1-3.2 volt\n");
++ if (resp & (1 << 20))
++ printk("[OCR] 3.2-3.3 volt\n");
++ if (resp & (1 << 21))
++ printk("[OCR] 3.3-3.4 volt\n");
++ if (resp & (1 << 22))
++ printk("[OCR] 3.4-3.5 volt\n");
++ if (resp & (1 << 23))
++ printk("[OCR] 3.5-3.6 volt\n");
++ if (resp & (1 << 24))
++ printk("[OCR] Switching to 1.8V Accepted (S18A)\n");
++ if (resp & (1 << 30))
++ printk("[OCR] Card Capacity Status (CCS)\n");
++ if (resp & (1 << 31))
++ printk("[OCR] Card Power Up Status (Idle)\n");
++ else
++ printk("[OCR] Card Power Up Status (Busy)\n");
++}
++
++static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp)
++{
++ u32 status = (((resp >> 15) & 0x1) << 23) |
++ (((resp >> 14) & 0x1) << 22) |
++ (((resp >> 13) & 0x1) << 19) |
++ (resp & 0x1fff);
++
++ printk("[RCA] 0x%.4x\n", resp >> 16);
++
++ msdc_dump_card_status(host, status);
++}
++
++static void msdc_dump_io_resp(struct msdc_host *host, u32 resp)
++{
++ u32 flags = (resp >> 8) & 0xFF;
++ char *state[] = {"DIS", "CMD", "TRN", "RFU"};
++
++ if (flags & (1 << 7))
++ printk("[IO] COM_CRC_ERR\n");
++ if (flags & (1 << 6))
++ printk("[IO] Illgal command\n");
++ if (flags & (1 << 3))
++ printk("[IO] Error\n");
++ if (flags & (1 << 2))
++ printk("[IO] RFU\n");
++ if (flags & (1 << 1))
++ printk("[IO] Function number error\n");
++ if (flags & (1 << 0))
++ printk("[IO] Out of range\n");
++
++ printk("[IO] State: %s, Data:0x%x\n", state[(resp >> 12) & 0x3], resp & 0xFF);
++}
++#endif
++
++static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
++{
++ u32 base = host->base;
++ u32 timeout, clk_ns;
++
++ host->timeout_ns = ns;
++ host->timeout_clks = clks;
++
++ clk_ns = 1000000000UL / host->sclk;
++ timeout = ns / clk_ns + clks;
++ timeout = timeout >> 16; /* in 65536 sclk cycle unit */
++ timeout = timeout > 1 ? timeout - 1 : 0;
++ timeout = timeout > 255 ? 255 : timeout;
++
++ sdr_set_field(SDC_CFG, SDC_CFG_DTOC, timeout);
++
++/* printk("Set read data timeout: %dns %dclks -> %d x 65536 cycles\n",
++ ns, clks, timeout + 1);*/
++}
++
++static void msdc_eirq_sdio(void *data)
++{
++ struct msdc_host *host = (struct msdc_host *)data;
++
++// printk("SDIO EINT\n");
++
++ mmc_signal_sdio_irq(host->mmc);
++}
++
++static void msdc_eirq_cd(void *data)
++{
++ struct msdc_host *host = (struct msdc_host *)data;
++
++// printk("CD EINT\n");
++
++ tasklet_hi_schedule(&host->card_tasklet);
++}
++
++static void msdc_tasklet_card(unsigned long arg)
++{
++ struct msdc_host *host = (struct msdc_host *)arg;
++ struct msdc_hw *hw = host->hw;
++ u32 base = host->base;
++ u32 inserted;
++ u32 status = 0;
++
++ spin_lock(&host->lock);
++
++ if (hw->get_cd_status) {
++ inserted = hw->get_cd_status();
++ } else {
++ status = sdr_read32(MSDC_PS);
++ inserted = (status & MSDC_PS_CDSTS) ? 0 : 1;
++ }
++
++ host->card_inserted = inserted;
++
++ if (!host->suspend) {
++ host->mmc->f_max = HOST_MAX_MCLK;
++ mmc_detect_change(host->mmc, msecs_to_jiffies(20));
++ }
++
++// printk("card found<%s>\n", inserted ? "inserted" : "removed");
++
++ spin_unlock(&host->lock);
++}
++
++static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz)
++{
++ u32 base = host->base;
++ u32 hclk = host->hclk;
++ u32 mode, flags, div, sclk;
++
++ if (!hz) {
++// printk("set mclk to 0!!!\n");
++ msdc_reset();
++ return;
++ }
++
++ msdc_irq_save(flags);
++
++ if (ddr) {
++ mode = 0x2;
++ if (hz >= (hclk >> 2)) {
++ div = 1;
++ sclk = hclk >> 2;
++ } else {
++ div = (hclk + ((hz << 2) - 1)) / (hz << 2);
++ sclk = (hclk >> 2) / div;
++ }
++ } else if (hz >= hclk) {
++ mode = 0x1;
++ div = 0;
++ sclk = hclk;
++ } else {
++ mode = 0x0;
++ if (hz >= (hclk >> 1)) {
++ div = 0;
++ sclk = hclk >> 1;
++ } else {
++ div = (hclk + ((hz << 2) - 1)) / (hz << 2);
++ sclk = (hclk >> 2) / div;
++ }
++ }
++
++ sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode);
++ sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div);
++
++ while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB));
++
++ host->sclk = sclk;
++ host->mclk = hz;
++ msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
++
++/* printk("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>\n",
++ hz / 1000, hclk / 1000, sclk / 1000);
++*/
++ msdc_irq_restore(flags);
++}
++
++static void msdc_abort_data(struct msdc_host *host)
++{
++ u32 base = host->base;
++ struct mmc_command *stop = host->mrq->stop;
++
++// printk("Need to Abort. dma<%d>\n", host->dma_xfer);
++
++ msdc_reset();
++ msdc_clr_fifo();
++ msdc_clr_int();
++
++ if (stop) {
++// printk("stop when abort CMD<%d>\n", stop->opcode);
++ msdc_do_command(host, stop, 0, CMD_TIMEOUT);
++ }
++}
++
++static unsigned int msdc_command_start(struct msdc_host *host,
++ struct mmc_command *cmd, int tune, unsigned long timeout)
++{
++ u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO |
++ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO |
++ MSDC_INT_ACMD19_DONE;
++ u32 base = host->base;
++ u32 opcode = cmd->opcode;
++ u32 rawcmd;
++ u32 resp;
++ unsigned long tmo;
++
++ if (opcode == MMC_SEND_OP_COND || opcode == SD_APP_OP_COND)
++ resp = RESP_R3;
++ else if (opcode == MMC_SET_RELATIVE_ADDR || opcode == SD_SEND_RELATIVE_ADDR)
++ resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1;
++ else if (opcode == MMC_FAST_IO)
++ resp = RESP_R4;
++ else if (opcode == MMC_GO_IRQ_STATE)
++ resp = RESP_R5;
++ else if (opcode == MMC_SELECT_CARD)
++ resp = (cmd->arg != 0) ? RESP_R1B : RESP_NONE;
++ else if (opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED)
++ resp = RESP_R1;
++ else if (opcode == SD_SEND_IF_COND && (mmc_cmd_type(cmd) == MMC_CMD_BCR))
++ resp = RESP_R1;
++ else {
++ switch (mmc_resp_type(cmd)) {
++ case MMC_RSP_R1:
++ resp = RESP_R1;
++ break;
++ case MMC_RSP_R1B:
++ resp = RESP_R1B;
++ break;
++ case MMC_RSP_R2:
++ resp = RESP_R2;
++ break;
++ case MMC_RSP_R3:
++ resp = RESP_R3;
++ break;
++ case MMC_RSP_NONE:
++ default:
++ resp = RESP_NONE;
++ break;
++ }
++ }
++
++ cmd->error = 0;
++ rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16;
++
++ if (opcode == MMC_READ_MULTIPLE_BLOCK) {
++ rawcmd |= (2 << 11);
++ } else if (opcode == MMC_READ_SINGLE_BLOCK) {
++ rawcmd |= (1 << 11);
++ } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) {
++ rawcmd |= ((2 << 11) | (1 << 13));
++ } else if (opcode == MMC_WRITE_BLOCK) {
++ rawcmd |= ((1 << 11) | (1 << 13));
++ } else if (opcode == SD_IO_RW_EXTENDED) {
++ if (cmd->data->flags & MMC_DATA_WRITE)
++ rawcmd |= (1 << 13);
++ if (cmd->data->blocks > 1)
++ rawcmd |= (2 << 11);
++ else
++ rawcmd |= (1 << 11);
++ } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) {
++ rawcmd |= (1 << 14);
++ } else if ((opcode == SD_APP_SEND_SCR) ||
++ (opcode == SD_APP_SEND_NUM_WR_BLKS) ||
++ (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) ||
++ (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) ||
++ (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) {
++ rawcmd |= (1 << 11);
++ } else if (opcode == MMC_STOP_TRANSMISSION) {
++ rawcmd |= (1 << 14);
++ rawcmd &= ~(0x0FFF << 16);
++ }
++
++// printk("CMD<%d><0x%.8x> Arg<0x%.8x>\n", opcode , rawcmd, cmd->arg);
++
++ tmo = jiffies + timeout;
++
++ if (opcode == MMC_SEND_STATUS) {
++ for (;;) {
++ if (!sdc_is_cmd_busy())
++ break;
++
++ if (time_after(jiffies, tmo)) {
++ //printk("XXX cmd_busy timeout: before CMD<%d>\n", opcode);
++ cmd->error = (unsigned int)-ETIMEDOUT;
++ msdc_reset();
++ goto end;
++ }
++ }
++ } else {
++ for (;;) {
++ if (!sdc_is_busy())
++ break;
++ if (time_after(jiffies, tmo)) {
++ //printk("XXX sdc_busy timeout: before CMD<%d>\n", opcode);
++ cmd->error = (unsigned int)-ETIMEDOUT;
++ msdc_reset();
++ goto end;
++ }
++ }
++ }
++
++ //BUG_ON(in_interrupt());
++ host->cmd = cmd;
++ host->cmd_rsp = resp;
++ init_completion(&host->cmd_done);
++ sdr_set_bits(MSDC_INTEN, wints);
++ sdc_send_cmd(rawcmd, cmd->arg);
++
++end:
++ return cmd->error;
++}
++
++static unsigned int msdc_command_resp(struct msdc_host *host, struct mmc_command *cmd,
++ int tune, unsigned long timeout)
++{
++ u32 base = host->base;
++ //u32 opcode = cmd->opcode;
++ u32 resp;
++ u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO |
++ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO |
++ MSDC_INT_ACMD19_DONE;
++
++ resp = host->cmd_rsp;
++
++ BUG_ON(in_interrupt());
++ spin_unlock(&host->lock);
++ if (!wait_for_completion_timeout(&host->cmd_done, 10*timeout)) {
++ //printk("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>\n", opcode, cmd->arg);
++ cmd->error = (unsigned int)-ETIMEDOUT;
++ msdc_reset();
++ }
++ spin_lock(&host->lock);
++
++ sdr_clr_bits(MSDC_INTEN, wints);
++ host->cmd = NULL;
++
++ if (!tune)
++ return cmd->error;
++
++ /* memory card CRC */
++ if (host->hw->flags & MSDC_REMOVABLE && cmd->error == (unsigned int)(-EIO) ) {
++ if (sdr_read32(SDC_CMD) & 0x1800) {
++ msdc_abort_data(host);
++ } else {
++ msdc_reset();
++ msdc_clr_fifo();
++ msdc_clr_int();
++ }
++ cmd->error = msdc_tune_cmdrsp(host,cmd);
++ }
++
++ return cmd->error;
++}
++
++static unsigned int msdc_do_command(struct msdc_host *host, struct mmc_command *cmd,
++ int tune, unsigned long timeout)
++{
++ if (!msdc_command_start(host, cmd, tune, timeout))
++ msdc_command_resp(host, cmd, tune, timeout);
++
++ //printk(" return<%d> resp<0x%.8x>\n", cmd->error, cmd->resp[0]);
++ return cmd->error;
++}
++
++static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, unsigned long tmo)
++{
++ u32 base = host->base;
++ int ret = 0;
++
++ if (atomic_read(&host->abort))
++ ret = 1;
++
++ if (time_after(jiffies, tmo)) {
++ data->error = (unsigned int)-ETIMEDOUT;
++ //printk("XXX PIO Data Timeout: CMD<%d>\n", host->mrq->cmd->opcode);
++ ret = 1;
++ }
++
++ if (ret) {
++ msdc_reset();
++ msdc_clr_fifo();
++ msdc_clr_int();
++ //printk("msdc pio find abort\n");
++ }
++
++ return ret;
++}
++
++static int msdc_pio_read(struct msdc_host *host, struct mmc_data *data)
++{
++ struct scatterlist *sg = data->sg;
++ u32 base = host->base;
++ u32 num = data->sg_len;
++ u32 *ptr;
++ u8 *u8ptr;
++ u32 left;
++ u32 count, size = 0;
++ u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR;
++ unsigned long tmo = jiffies + DAT_TIMEOUT;
++
++ sdr_set_bits(MSDC_INTEN, wints);
++ while (num) {
++ left = sg_dma_len(sg);
++ ptr = sg_virt(sg);
++ while (left) {
++ if ((left >= MSDC_FIFO_THD) && (msdc_rxfifocnt() >= MSDC_FIFO_THD)) {
++ count = MSDC_FIFO_THD >> 2;
++ do {
++ *ptr++ = msdc_fifo_read32();
++ } while (--count);
++ left -= MSDC_FIFO_THD;
++ } else if ((left < MSDC_FIFO_THD) && msdc_rxfifocnt() >= left) {
++ while (left > 3) {
++ *ptr++ = msdc_fifo_read32();
++ left -= 4;
++ }
++
++ u8ptr = (u8 *)ptr;
++ while(left) {
++ * u8ptr++ = msdc_fifo_read8();
++ left--;
++ }
++ }
++
++ if (msdc_pio_abort(host, data, tmo))
++ goto end;
++ }
++ size += sg_dma_len(sg);
++ sg = sg_next(sg); num--;
++ }
++end:
++ data->bytes_xfered += size;
++ //printk(" PIO Read<%d>bytes\n", size);
++
++ sdr_clr_bits(MSDC_INTEN, wints);
++ if(data->error)
++ printk("read pio data->error<%d> left<%d> size<%d>\n", data->error, left, size);
++
++ return data->error;
++}
++
++static int msdc_pio_write(struct msdc_host* host, struct mmc_data *data)
++{
++ u32 base = host->base;
++ struct scatterlist *sg = data->sg;
++ u32 num = data->sg_len;
++ u32 *ptr;
++ u8 *u8ptr;
++ u32 left;
++ u32 count, size = 0;
++ u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR;
++ unsigned long tmo = jiffies + DAT_TIMEOUT;
++
++ sdr_set_bits(MSDC_INTEN, wints);
++ while (num) {
++ left = sg_dma_len(sg);
++ ptr = sg_virt(sg);
++
++ while (left) {
++ if (left >= MSDC_FIFO_SZ && msdc_txfifocnt() == 0) {
++ count = MSDC_FIFO_SZ >> 2;
++ do {
++ msdc_fifo_write32(*ptr); ptr++;
++ } while (--count);
++ left -= MSDC_FIFO_SZ;
++ } else if (left < MSDC_FIFO_SZ && msdc_txfifocnt() == 0) {
++ while (left > 3) {
++ msdc_fifo_write32(*ptr); ptr++;
++ left -= 4;
++ }
++
++ u8ptr = (u8*)ptr;
++ while( left) {
++ msdc_fifo_write8(*u8ptr);
++ u8ptr++;
++ left--;
++ }
++ }
++
++ if (msdc_pio_abort(host, data, tmo))
++ goto end;
++ }
++ size += sg_dma_len(sg);
++ sg = sg_next(sg); num--;
++ }
++end:
++ data->bytes_xfered += size;
++ //printk(" PIO Write<%d>bytes\n", size);
++ if(data->error)
++ printk("write pio data->error<%d>\n", data->error);
++
++ sdr_clr_bits(MSDC_INTEN, wints);
++
++ return data->error;
++}
++
++static void msdc_dma_start(struct msdc_host *host)
++{
++ u32 base = host->base;
++ u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR;
++
++ sdr_set_bits(MSDC_INTEN, wints);
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
++
++ //printk("DMA start\n");
++}
++
++static void msdc_dma_stop(struct msdc_host *host)
++{
++ u32 base = host->base;
++ u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR;
++
++ //printk("DMA status: 0x%.8x\n",sdr_read32(MSDC_DMA_CFG));
++
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1);
++ while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS);
++ sdr_clr_bits(MSDC_INTEN, wints); /* Not just xfer_comp */
++
++ //printk("DMA stop\n");
++}
++
++static u8 msdc_dma_calcs(u8 *buf, u32 len)
++{
++ u32 i, sum = 0;
++
++ for (i = 0; i < len; i++)
++ sum += buf[i];
++
++ return 0xFF - (u8)sum;
++}
++
++static int msdc_dma_config(struct msdc_host *host, struct msdc_dma *dma)
++{
++ u32 base = host->base;
++ u32 sglen = dma->sglen;
++ u32 j, num, bdlen;
++ u8 blkpad, dwpad, chksum;
++ struct scatterlist *sg = dma->sg;
++ gpd_t *gpd;
++ bd_t *bd;
++
++ switch (dma->mode) {
++ case MSDC_MODE_DMA_BASIC:
++ BUG_ON(dma->xfersz > 65535);
++ BUG_ON(dma->sglen != 1);
++ sdr_write32(MSDC_DMA_SA, PHYSADDR(sg_dma_address(sg)));
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_LASTBUF, 1);
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_XFERSZ, sg_dma_len(sg));
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz);
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 0);
++ break;
++
++ case MSDC_MODE_DMA_DESC:
++ blkpad = (dma->flags & DMA_FLAG_PAD_BLOCK) ? 1 : 0;
++ dwpad = (dma->flags & DMA_FLAG_PAD_DWORD) ? 1 : 0;
++ chksum = (dma->flags & DMA_FLAG_EN_CHKSUM) ? 1 : 0;
++
++ num = (sglen + MAX_BD_PER_GPD - 1) / MAX_BD_PER_GPD;
++ BUG_ON(num !=1 );
++
++ gpd = dma->gpd;
++ bd = dma->bd;
++ bdlen = sglen;
++
++ gpd->hwo = 1; /* hw will clear it */
++ gpd->bdp = 1;
++ gpd->chksum = 0; /* need to clear first. */
++ gpd->chksum = (chksum ? msdc_dma_calcs((u8 *)gpd, 16) : 0);
++
++ for (j = 0; j < bdlen; j++) {
++ msdc_init_bd(&bd[j], blkpad, dwpad, sg_dma_address(sg), sg_dma_len(sg));
++ if( j == bdlen - 1)
++ bd[j].eol = 1;
++ else
++ bd[j].eol = 0;
++ bd[j].chksum = 0; /* checksume need to clear first */
++ bd[j].chksum = (chksum ? msdc_dma_calcs((u8 *)(&bd[j]), 16) : 0);
++ sg++;
++ }
++
++ dma->used_gpd += 2;
++ dma->used_bd += bdlen;
++
++ sdr_set_field(MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, chksum);
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz);
++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1);
++ sdr_write32(MSDC_DMA_SA, PHYSADDR((u32)dma->gpd_addr));
++ break;
++ }
++
++// printk("DMA_CTRL = 0x%x\n", sdr_read32(MSDC_DMA_CTRL));
++// printk("DMA_CFG = 0x%x\n", sdr_read32(MSDC_DMA_CFG));
++// printk("DMA_SA = 0x%x\n", sdr_read32(MSDC_DMA_SA));
++
++ return 0;
++}
++
++static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
++ struct scatterlist *sg, unsigned int sglen)
++{
++ BUG_ON(sglen > MAX_BD_NUM);
++
++ dma->sg = sg;
++ dma->flags = DMA_FLAG_EN_CHKSUM;
++ dma->sglen = sglen;
++ dma->xfersz = host->xfer_size;
++ dma->burstsz = MSDC_BRUST_64B;
++
++ if (sglen == 1 && sg_dma_len(sg) <= MAX_DMA_CNT)
++ dma->mode = MSDC_MODE_DMA_BASIC;
++ else
++ dma->mode = MSDC_MODE_DMA_DESC;
++
++// printk("DMA mode<%d> sglen<%d> xfersz<%d>\n", dma->mode, dma->sglen, dma->xfersz);
++
++ msdc_dma_config(host, dma);
++}
++
++static void msdc_set_blknum(struct msdc_host *host, u32 blknum)
++{
++ u32 base = host->base;
++
++ sdr_write32(SDC_BLK_NUM, blknum);
++}
++
++static int msdc_do_request(struct mmc_host*mmc, struct mmc_request*mrq)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ struct mmc_command *cmd;
++ struct mmc_data *data;
++ u32 base = host->base;
++ unsigned int left=0;
++ int dma = 0, read = 1, dir = DMA_FROM_DEVICE, send_type=0;
++
++#define SND_DAT 0
++#define SND_CMD 1
++
++ BUG_ON(mmc == NULL);
++ BUG_ON(mrq == NULL);
++
++ host->error = 0;
++ atomic_set(&host->abort, 0);
++
++ cmd = mrq->cmd;
++ data = mrq->cmd->data;
++
++ if (!data) {
++ send_type = SND_CMD;
++ if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0)
++ goto done;
++ } else {
++ BUG_ON(data->blksz > HOST_MAX_BLKSZ);
++ send_type=SND_DAT;
++
++ data->error = 0;
++ read = data->flags & MMC_DATA_READ ? 1 : 0;
++ host->data = data;
++ host->xfer_size = data->blocks * data->blksz;
++ host->blksz = data->blksz;
++
++ host->dma_xfer = dma = ((host->xfer_size >= 512) ? 1 : 0);
++
++ if (read)
++ if ((host->timeout_ns != data->timeout_ns) ||
++ (host->timeout_clks != data->timeout_clks))
++ msdc_set_timeout(host, data->timeout_ns, data->timeout_clks);
++
++ msdc_set_blknum(host, data->blocks);
++
++ if (dma) {
++ msdc_dma_on();
++ init_completion(&host->xfer_done);
++
++ if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0)
++ goto done;
++
++ dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
++ dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir);
++ msdc_dma_setup(host, &host->dma, data->sg, data->sg_len);
++
++ if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0)
++ goto done;
++
++ msdc_dma_start(host);
++
++ spin_unlock(&host->lock);
++ if (!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)) {
++ /*printk("XXX CMD<%d> wait xfer_done<%d> timeout!!\n", cmd->opcode, data->blocks * data->blksz);
++ printk(" DMA_SA = 0x%x\n", sdr_read32(MSDC_DMA_SA));
++ printk(" DMA_CA = 0x%x\n", sdr_read32(MSDC_DMA_CA));
++ printk(" DMA_CTRL = 0x%x\n", sdr_read32(MSDC_DMA_CTRL));
++ printk(" DMA_CFG = 0x%x\n", sdr_read32(MSDC_DMA_CFG));*/
++ data->error = (unsigned int)-ETIMEDOUT;
++
++ msdc_reset();
++ msdc_clr_fifo();
++ msdc_clr_int();
++ }
++ spin_lock(&host->lock);
++ msdc_dma_stop(host);
++ } else {
++ if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0)
++ goto done;
++
++ if (read) {
++ if (msdc_pio_read(host, data))
++ goto done;
++ } else {
++ if (msdc_pio_write(host, data))
++ goto done;
++ }
++
++ if (!read) {
++ while (1) {
++ left = msdc_txfifocnt();
++ if (left == 0) {
++ break;
++ }
++ if (msdc_pio_abort(host, data, jiffies + DAT_TIMEOUT)) {
++ break;
++ /* Fix me: what about if data error, when stop ? how to? */
++ }
++ }
++ } else {
++ /* Fix me: read case: need to check CRC error */
++ }
++
++ /* For write case: SDCBUSY and Xfer_Comp will assert when DAT0 not busy.
++ For read case : SDCBUSY and Xfer_Comp will assert when last byte read out from FIFO.
++ */
++
++ /* try not to wait xfer_comp interrupt.
++ the next command will check SDC_BUSY.
++ SDC_BUSY means xfer_comp assert
++ */
++
++ } // PIO mode
++
++ /* Last: stop transfer */
++ if (data->stop){
++ if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) {
++ goto done;
++ }
++ }
++ }
++
++done:
++ if (data != NULL) {
++ host->data = NULL;
++ host->dma_xfer = 0;
++ if (dma != 0) {
++ msdc_dma_off();
++ host->dma.used_bd = 0;
++ host->dma.used_gpd = 0;
++ dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, dir);
++ }
++ host->blksz = 0;
++
++ // printk("CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>",cmd->opcode, (dma? "dma":"pio\n"),
++ // (read ? "read ":"write") ,data->blksz, data->blocks, data->error);
++ }
++
++ if (mrq->cmd->error) host->error = 0x001;
++ if (mrq->data && mrq->data->error) host->error |= 0x010;
++ if (mrq->stop && mrq->stop->error) host->error |= 0x100;
++
++ //if (host->error) printk("host->error<%d>\n", host->error);
++
++ return host->error;
++}
++
++static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host)
++{
++ struct mmc_command cmd;
++ struct mmc_request mrq;
++ u32 err;
++
++ memset(&cmd, 0, sizeof(struct mmc_command));
++ cmd.opcode = MMC_APP_CMD;
++#if 0 /* bug: we meet mmc->card is null when ACMD6 */
++ cmd.arg = mmc->card->rca << 16;
++#else
++ cmd.arg = host->app_cmd_arg;
++#endif
++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
++
++ memset(&mrq, 0, sizeof(struct mmc_request));
++ mrq.cmd = &cmd; cmd.mrq = &mrq;
++ cmd.data = NULL;
++
++ err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT);
++ return err;
++}
++
++static int msdc_tune_cmdrsp(struct msdc_host*host, struct mmc_command *cmd)
++{
++ int result = -1;
++ u32 base = host->base;
++ u32 rsmpl, cur_rsmpl, orig_rsmpl;
++ u32 rrdly, cur_rrdly = 0, orig_rrdly;
++ u32 skip = 1;
++
++ /* ==== don't support 3.0 now ====
++ 1: R_SMPL[1]
++ 2: PAD_CMD_RESP_RXDLY[26:22]
++ ==========================*/
++
++ // save the previous tune result
++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_RSPL, orig_rsmpl);
++ sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, orig_rrdly);
++
++ rrdly = 0;
++ do {
++ for (rsmpl = 0; rsmpl < 2; rsmpl++) {
++ /* Lv1: R_SMPL[1] */
++ cur_rsmpl = (orig_rsmpl + rsmpl) % 2;
++ if (skip == 1) {
++ skip = 0;
++ continue;
++ }
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl);
++
++ if (host->app_cmd) {
++ result = msdc_app_cmd(host->mmc, host);
++ if (result) {
++ //printk("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>\n",
++ // host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl);
++ continue;
++ }
++ }
++ result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune.
++ //printk("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>\n", cmd->opcode,
++// (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl);
++
++ if (result == 0) {
++ return 0;
++ }
++ if (result != (unsigned int)(-EIO)) {
++ // printk("TUNE_CMD<%d> Error<%d> not -EIO\n", cmd->opcode, result);
++ return result;
++ }
++
++ /* should be EIO */
++ if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */
++ msdc_abort_data(host);
++ }
++ }
++
++ /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */
++ cur_rrdly = (orig_rrdly + rrdly + 1) % 32;
++ sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly);
++ }while (++rrdly < 32);
++
++ return result;
++}
++
++/* Support SD2.0 Only */
++static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ u32 base = host->base;
++ u32 ddr=0;
++ u32 dcrc = 0;
++ u32 rxdly, cur_rxdly0, cur_rxdly1;
++ u32 dsmpl, cur_dsmpl, orig_dsmpl;
++ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3;
++ u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7;
++ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3;
++ u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7;
++ int result = -1;
++ u32 skip = 1;
++
++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl);
++
++ /* Tune Method 2. */
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
++
++ rxdly = 0;
++ do {
++ for (dsmpl = 0; dsmpl < 2; dsmpl++) {
++ cur_dsmpl = (orig_dsmpl + dsmpl) % 2;
++ if (skip == 1) {
++ skip = 0;
++ continue;
++ }
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl);
++
++ if (host->app_cmd) {
++ result = msdc_app_cmd(host->mmc, host);
++ if (result) {
++ //printk("TUNE_BREAD app_cmd<%d> failed\n", host->mrq->cmd->opcode);
++ continue;
++ }
++ }
++ result = msdc_do_request(mmc,mrq);
++
++ sdr_get_field(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc); /* RO */
++ if (!ddr) dcrc &= ~SDC_DCRC_STS_NEG;
++ //printk("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>\n",
++ // (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc,
++ // sdr_read32(MSDC_DAT_RDDLY0), sdr_read32(MSDC_DAT_RDDLY1), cur_dsmpl);
++
++ /* Fix me: result is 0, but dcrc is still exist */
++ if (result == 0 && dcrc == 0) {
++ goto done;
++ } else {
++ /* there is a case: command timeout, and data phase not processed */
++ if (mrq->data->error != 0 && mrq->data->error != (unsigned int)(-EIO)) {
++ //printk("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>\n",
++ // result, mrq->cmd->error, mrq->data->error);
++ goto done;
++ }
++ }
++ }
++
++ cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0);
++ cur_rxdly1 = sdr_read32(MSDC_DAT_RDDLY1);
++
++ /* E1 ECO. YD: Reverse */
++ if (sdr_read32(MSDC_ECO_VER) >= 4) {
++ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
++ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
++ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
++ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
++ orig_dat4 = (cur_rxdly1 >> 24) & 0x1F;
++ orig_dat5 = (cur_rxdly1 >> 16) & 0x1F;
++ orig_dat6 = (cur_rxdly1 >> 8) & 0x1F;
++ orig_dat7 = (cur_rxdly1 >> 0) & 0x1F;
++ } else {
++ orig_dat0 = (cur_rxdly0 >> 0) & 0x1F;
++ orig_dat1 = (cur_rxdly0 >> 8) & 0x1F;
++ orig_dat2 = (cur_rxdly0 >> 16) & 0x1F;
++ orig_dat3 = (cur_rxdly0 >> 24) & 0x1F;
++ orig_dat4 = (cur_rxdly1 >> 0) & 0x1F;
++ orig_dat5 = (cur_rxdly1 >> 8) & 0x1F;
++ orig_dat6 = (cur_rxdly1 >> 16) & 0x1F;
++ orig_dat7 = (cur_rxdly1 >> 24) & 0x1F;
++ }
++
++ if (ddr) {
++ cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0;
++ cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1;
++ cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2;
++ cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3;
++ } else {
++ cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0;
++ cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1;
++ cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2;
++ cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3;
++ }
++ cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4;
++ cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5;
++ cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6;
++ cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7;
++
++ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0);
++ cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0);
++
++ sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0);
++ sdr_write32(MSDC_DAT_RDDLY1, cur_rxdly1);
++
++ } while (++rxdly < 32);
++
++done:
++ return result;
++}
++
++static int msdc_tune_bwrite(struct mmc_host *mmc,struct mmc_request *mrq)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ u32 base = host->base;
++
++ u32 wrrdly, cur_wrrdly = 0, orig_wrrdly;
++ u32 dsmpl, cur_dsmpl, orig_dsmpl;
++ u32 rxdly, cur_rxdly0;
++ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3;
++ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3;
++ int result = -1;
++ u32 skip = 1;
++
++ // MSDC_IOCON_DDR50CKD need to check. [Fix me]
++
++ sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, orig_wrrdly);
++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl );
++
++ /* Tune Method 2. just DAT0 */
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
++ cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0);
++
++ /* E1 ECO. YD: Reverse */
++ if (sdr_read32(MSDC_ECO_VER) >= 4) {
++ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F;
++ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F;
++ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F;
++ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F;
++ } else {
++ orig_dat0 = (cur_rxdly0 >> 0) & 0x1F;
++ orig_dat1 = (cur_rxdly0 >> 8) & 0x1F;
++ orig_dat2 = (cur_rxdly0 >> 16) & 0x1F;
++ orig_dat3 = (cur_rxdly0 >> 24) & 0x1F;
++ }
++
++ rxdly = 0;
++ do {
++ wrrdly = 0;
++ do {
++ for (dsmpl = 0; dsmpl < 2; dsmpl++) {
++ cur_dsmpl = (orig_dsmpl + dsmpl) % 2;
++ if (skip == 1) {
++ skip = 0;
++ continue;
++ }
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl);
++
++ if (host->app_cmd) {
++ result = msdc_app_cmd(host->mmc, host);
++ if (result) {
++ //printk("TUNE_BWRITE app_cmd<%d> failed\n", host->mrq->cmd->opcode);
++ continue;
++ }
++ }
++ result = msdc_do_request(mmc,mrq);
++
++ //printk("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>\n",
++ // result == 0 ? "PASS" : "FAIL",
++ // cur_dsmpl, cur_wrrdly, cur_rxdly0);
++
++ if (result == 0) {
++ goto done;
++ }
++ else {
++ /* there is a case: command timeout, and data phase not processed */
++ if (mrq->data->error != (unsigned int)(-EIO)) {
++ //printk("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>\n",
++ // && result, mrq->cmd->error, mrq->data->error);
++ goto done;
++ }
++ }
++ }
++ cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32;
++ sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly);
++ } while (++wrrdly < 32);
++
++ cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */
++ cur_dat1 = orig_dat1;
++ cur_dat2 = orig_dat2;
++ cur_dat3 = orig_dat3;
++
++ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0);
++ sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0);
++ } while (++rxdly < 32);
++
++done:
++ return result;
++}
++
++static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status)
++{
++ struct mmc_command cmd;
++ struct mmc_request mrq;
++ u32 err;
++
++ memset(&cmd, 0, sizeof(struct mmc_command));
++ cmd.opcode = MMC_SEND_STATUS;
++ if (mmc->card) {
++ cmd.arg = mmc->card->rca << 16;
++ } else {
++ //printk("cmd13 mmc card is null\n");
++ cmd.arg = host->app_cmd_arg;
++ }
++ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
++
++ memset(&mrq, 0, sizeof(struct mmc_request));
++ mrq.cmd = &cmd; cmd.mrq = &mrq;
++ cmd.data = NULL;
++
++ err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT);
++
++ if (status)
++ *status = cmd.resp[0];
++
++ return err;
++}
++
++static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host)
++{
++ u32 err = 0;
++ u32 status = 0;
++
++ do {
++ err = msdc_get_card_status(mmc, host, &status);
++ if (err)
++ return err;
++ /* need cmd12? */
++ //printk("cmd<13> resp<0x%x>\n", status);
++ } while (R1_CURRENT_STATE(status) == 7);
++
++ return err;
++}
++
++static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ struct mmc_command *cmd;
++ struct mmc_data *data;
++ int ret=0, read;
++
++ cmd = mrq->cmd;
++ data = mrq->cmd->data;
++
++ read = data->flags & MMC_DATA_READ ? 1 : 0;
++
++ if (read) {
++ if (data->error == (unsigned int)(-EIO))
++ ret = msdc_tune_bread(mmc,mrq);
++ } else {
++ ret = msdc_check_busy(mmc, host);
++ if (ret){
++ //printk("XXX cmd13 wait program done failed\n");
++ return ret;
++ }
++ /* CRC and TO */
++ /* Fix me: don't care card status? */
++ ret = msdc_tune_bwrite(mmc,mrq);
++ }
++
++ return ret;
++}
++
++static void msdc_ops_request(struct mmc_host *mmc,struct mmc_request *mrq)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++
++ if (host->mrq) {
++ //printk("XXX host->mrq<0x%.8x>\n", (int)host->mrq);
++ BUG();
++ }
++ if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) {
++ //printk("cmd<%d> card<%d> power<%d>\n", mrq->cmd->opcode, is_card_present(host), host->power_mode);
++ mrq->cmd->error = (unsigned int)-ENOMEDIUM;
++ mrq->done(mrq);
++ return;
++ }
++ spin_lock(&host->lock);
++
++ host->mrq = mrq;
++
++ if (msdc_do_request(mmc,mrq))
++ if(host->hw->flags & MSDC_REMOVABLE && mrq->data && mrq->data->error)
++ msdc_tune_request(mmc,mrq);
++
++ if (mrq->cmd->opcode == MMC_APP_CMD) {
++ host->app_cmd = 1;
++ host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */
++ } else {
++ host->app_cmd = 0;
++ }
++
++ host->mrq = NULL;
++
++ spin_unlock(&host->lock);
++
++ mmc_request_done(mmc, mrq);
++}
++
++/* called by ops.set_ios */
++static void msdc_set_buswidth(struct msdc_host *host, u32 width)
++{
++ u32 base = host->base;
++ u32 val = sdr_read32(SDC_CFG);
++
++ val &= ~SDC_CFG_BUSWIDTH;
++
++ switch (width) {
++ default:
++ case MMC_BUS_WIDTH_1:
++ width = 1;
++ val |= (MSDC_BUS_1BITS << 16);
++ break;
++ case MMC_BUS_WIDTH_4:
++ val |= (MSDC_BUS_4BITS << 16);
++ break;
++ case MMC_BUS_WIDTH_8:
++ val |= (MSDC_BUS_8BITS << 16);
++ break;
++ }
++
++ sdr_write32(SDC_CFG, val);
++
++ //printk("Bus Width = %d\n", width);
++}
++
++/* ops.set_ios */
++static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ struct msdc_hw *hw=host->hw;
++ u32 base = host->base;
++ u32 ddr = 0;
++
++#ifdef MT6575_SD_DEBUG
++ static char *vdd[] = {
++ "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v",
++ "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v",
++ "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v",
++ "3.40v", "3.50v", "3.60v"
++ };
++ static char *power_mode[] = {
++ "OFF", "UP", "ON"
++ };
++ static char *bus_mode[] = {
++ "UNKNOWN", "OPENDRAIN", "PUSHPULL"
++ };
++ static char *timing[] = {
++ "LEGACY", "MMC_HS", "SD_HS"
++ };
++
++ /*printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)\n",
++ ios->clock / 1000, bus_mode[ios->bus_mode],
++ (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1,
++ power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]);*/
++#endif
++
++ msdc_set_buswidth(host, ios->bus_width);
++
++ /* Power control ??? */
++ switch (ios->power_mode) {
++ case MMC_POWER_OFF:
++ case MMC_POWER_UP:
++ // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */
++ break;
++ case MMC_POWER_ON:
++ host->power_mode = MMC_POWER_ON;
++ break;
++ default:
++ break;
++ }
++
++ /* Clock control */
++ if (host->mclk != ios->clock) {
++ if(ios->clock > 25000000) {
++ //printk("SD data latch edge<%d>\n", hw->data_edge);
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, hw->cmd_edge);
++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, hw->data_edge);
++ } else {
++ sdr_write32(MSDC_IOCON, 0x00000000);
++ sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward
++ sdr_write32(MSDC_DAT_RDDLY1, 0x00000000);
++ sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward
++ }
++ msdc_set_mclk(host, ddr, ios->clock);
++ }
++}
++
++/* ops.get_ro */
++static int msdc_ops_get_ro(struct mmc_host *mmc)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ u32 base = host->base;
++ unsigned long flags;
++ int ro = 0;
++
++ if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */
++ spin_lock_irqsave(&host->lock, flags);
++ ro = (sdr_read32(MSDC_PS) >> 31);
++ spin_unlock_irqrestore(&host->lock, flags);
++ }
++ return ro;
++}
++
++/* ops.get_cd */
++static int msdc_ops_get_cd(struct mmc_host *mmc)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ u32 base = host->base;
++ unsigned long flags;
++ int present = 1;
++
++ /* for sdio, MSDC_REMOVABLE not set, always return 1 */
++ if (!(host->hw->flags & MSDC_REMOVABLE)) {
++ /* For sdio, read H/W always get<1>, but may timeout some times */
++#if 1
++ host->card_inserted = 1;
++ return 1;
++#else
++ host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0;
++ printk("sdio ops_get_cd<%d>\n", host->card_inserted);
++ return host->card_inserted;
++#endif
++ }
++
++ /* MSDC_CD_PIN_EN set for card */
++ if (host->hw->flags & MSDC_CD_PIN_EN) {
++ spin_lock_irqsave(&host->lock, flags);
++#if 0
++ present = host->card_inserted; /* why not read from H/W: Fix me*/
++#else
++ present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1;
++ host->card_inserted = present;
++#endif
++ spin_unlock_irqrestore(&host->lock, flags);
++ } else {
++ present = 0; /* TODO? Check DAT3 pins for card detection */
++ }
++
++ //printk("ops_get_cd return<%d>\n", present);
++ return present;
++}
++
++/* ops.enable_sdio_irq */
++static void msdc_ops_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++ struct msdc_host *host = mmc_priv(mmc);
++ struct msdc_hw *hw = host->hw;
++ u32 base = host->base;
++ u32 tmp;
++
++ if (hw->flags & MSDC_EXT_SDIO_IRQ) { /* yes for sdio */
++ if (enable) {
++ hw->enable_sdio_eirq(); /* combo_sdio_enable_eirq */
++ } else {
++ hw->disable_sdio_eirq(); /* combo_sdio_disable_eirq */
++ }
++ } else {
++ //printk("XXX \n"); /* so never enter here */
++ tmp = sdr_read32(SDC_CFG);
++ /* FIXME. Need to interrupt gap detection */
++ if (enable) {
++ tmp |= (SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP);
++ } else {
++ tmp &= ~(SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP);
++ }
++ sdr_write32(SDC_CFG, tmp);
++ }
++}
++
++static struct mmc_host_ops mt_msdc_ops = {
++ .request = msdc_ops_request,
++ .set_ios = msdc_ops_set_ios,
++ .get_ro = msdc_ops_get_ro,
++ .get_cd = msdc_ops_get_cd,
++ .enable_sdio_irq = msdc_ops_enable_sdio_irq,
++};
++
++/*--------------------------------------------------------------------------*/
++/* interrupt handler */
++/*--------------------------------------------------------------------------*/
++static irqreturn_t msdc_irq(int irq, void *dev_id)
++{
++ struct msdc_host *host = (struct msdc_host *)dev_id;
++ struct mmc_data *data = host->data;
++ struct mmc_command *cmd = host->cmd;
++ u32 base = host->base;
++
++ u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY |
++ MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY |
++ MSDC_INT_ACMD19_DONE;
++ u32 datsts = MSDC_INT_DATCRCERR |MSDC_INT_DATTMO;
++
++ u32 intsts = sdr_read32(MSDC_INT);
++ u32 inten = sdr_read32(MSDC_INTEN); inten &= intsts;
++
++ sdr_write32(MSDC_INT, intsts); /* clear interrupts */
++ /* MSG will cause fatal error */
++
++ /* card change interrupt */
++ if (intsts & MSDC_INT_CDSC){
++ //printk("MSDC_INT_CDSC irq<0x%.8x>\n", intsts);
++ tasklet_hi_schedule(&host->card_tasklet);
++ /* tuning when plug card ? */
++ }
++
++ /* sdio interrupt */
++ if (intsts & MSDC_INT_SDIOIRQ){
++ //printk("XXX MSDC_INT_SDIOIRQ\n"); /* seems not sdio irq */
++ //mmc_signal_sdio_irq(host->mmc);
++ }
++
++ /* transfer complete interrupt */
++ if (data != NULL) {
++ if (inten & MSDC_INT_XFER_COMPL) {
++ data->bytes_xfered = host->dma.xfersz;
++ complete(&host->xfer_done);
++ }
++
++ if (intsts & datsts) {
++ /* do basic reset, or stop command will sdc_busy */
++ msdc_reset();
++ msdc_clr_fifo();
++ msdc_clr_int();
++ atomic_set(&host->abort, 1); /* For PIO mode exit */
++
++ if (intsts & MSDC_INT_DATTMO){
++ //printk("XXX CMD<%d> MSDC_INT_DATTMO\n", host->mrq->cmd->opcode);
++ data->error = (unsigned int)-ETIMEDOUT;
++ }
++ else if (intsts & MSDC_INT_DATCRCERR){
++ //printk("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>\n", host->mrq->cmd->opcode, sdr_read32(SDC_DCRC_STS));
++ data->error = (unsigned int)-EIO;
++ }
++
++ //if(sdr_read32(MSDC_INTEN) & MSDC_INT_XFER_COMPL) {
++ if (host->dma_xfer) {
++ complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */
++ } /* PIO mode can't do complete, because not init */
++ }
++ }
++
++ /* command interrupts */
++ if ((cmd != NULL) && (intsts & cmdsts)) {
++ if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) ||
++ (intsts & MSDC_INT_ACMD19_DONE)) {
++ u32 *rsp = &cmd->resp[0];
++
++ switch (host->cmd_rsp) {
++ case RESP_NONE:
++ break;
++ case RESP_R2:
++ *rsp++ = sdr_read32(SDC_RESP3); *rsp++ = sdr_read32(SDC_RESP2);
++ *rsp++ = sdr_read32(SDC_RESP1); *rsp++ = sdr_read32(SDC_RESP0);
++ break;
++ default: /* Response types 1, 3, 4, 5, 6, 7(1b) */
++ if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) {
++ *rsp = sdr_read32(SDC_ACMD_RESP);
++ } else {
++ *rsp = sdr_read32(SDC_RESP0);
++ }
++ break;
++ }
++ } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) {
++ if(intsts & MSDC_INT_ACMDCRCERR){
++ //printk("XXX CMD<%d> MSDC_INT_ACMDCRCERR\n",cmd->opcode);
++ }
++ else {
++ //printk("XXX CMD<%d> MSDC_INT_RSPCRCERR\n",cmd->opcode);
++ }
++ cmd->error = (unsigned int)-EIO;
++ } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) {
++ if(intsts & MSDC_INT_ACMDTMO){
++ //printk("XXX CMD<%d> MSDC_INT_ACMDTMO\n",cmd->opcode);
++ }
++ else {
++ //printk("XXX CMD<%d> MSDC_INT_CMDTMO\n",cmd->opcode);
++ }
++ cmd->error = (unsigned int)-ETIMEDOUT;
++ msdc_reset();
++ msdc_clr_fifo();
++ msdc_clr_int();
++ }
++ complete(&host->cmd_done);
++ }
++
++ /* mmc irq interrupts */
++ if (intsts & MSDC_INT_MMCIRQ) {
++ //printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", host->id, sdr_read32(SDC_CSTS));
++ }
++
++#ifdef MT6575_SD_DEBUG
++ {
++ msdc_int_reg *int_reg = (msdc_int_reg*)&intsts;
++ /*printk("IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)\n",
++ intsts,
++ int_reg->mmcirq,
++ int_reg->cdsc,
++ int_reg->atocmdrdy,
++ int_reg->atocmdtmo,
++ int_reg->atocmdcrc,
++ int_reg->atocmd19done);
++ printk("IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)\n",
++ intsts,
++ int_reg->sdioirq,
++ int_reg->cmdrdy,
++ int_reg->cmdtmo,
++ int_reg->rspcrc,
++ int_reg->csta);
++ printk("IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)\n",
++ intsts,
++ int_reg->xfercomp,
++ int_reg->dxferdone,
++ int_reg->dattmo,
++ int_reg->datcrc,
++ int_reg->dmaqempty);*/
++
++ }
++#endif
++
++ return IRQ_HANDLED;
++}
++
++/*--------------------------------------------------------------------------*/
++/* platform_driver members */
++/*--------------------------------------------------------------------------*/
++/* called by msdc_drv_probe/remove */
++static void msdc_enable_cd_irq(struct msdc_host *host, int enable)
++{
++ struct msdc_hw *hw = host->hw;
++ u32 base = host->base;
++
++ /* for sdio, not set */
++ if ((hw->flags & MSDC_CD_PIN_EN) == 0) {
++ /* Pull down card detection pin since it is not avaiable */
++ /*
++ if (hw->config_gpio_pin)
++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN);
++ */
++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN);
++ sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC);
++ sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP);
++ return;
++ }
++
++ //printk("CD IRQ Eanable(%d)\n", enable);
++
++ if (enable) {
++ if (hw->enable_cd_eirq) { /* not set, never enter */
++ hw->enable_cd_eirq();
++ } else {
++ /* card detection circuit relies on the core power so that the core power
++ * shouldn't be turned off. Here adds a reference count to keep
++ * the core power alive.
++ */
++ //msdc_vcore_on(host); //did in msdc_init_hw()
++
++ if (hw->config_gpio_pin) /* NULL */
++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP);
++
++ sdr_set_field(MSDC_PS, MSDC_PS_CDDEBOUNCE, DEFAULT_DEBOUNCE);
++ sdr_set_bits(MSDC_PS, MSDC_PS_CDEN);
++ sdr_set_bits(MSDC_INTEN, MSDC_INTEN_CDSC);
++ sdr_set_bits(SDC_CFG, SDC_CFG_INSWKUP); /* not in document! Fix me */
++ }
++ } else {
++ if (hw->disable_cd_eirq) {
++ hw->disable_cd_eirq();
++ } else {
++ if (hw->config_gpio_pin) /* NULL */
++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN);
++
++ sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP);
++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN);
++ sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC);
++
++ /* Here decreases a reference count to core power since card
++ * detection circuit is shutdown.
++ */
++ //msdc_vcore_off(host);
++ }
++ }
++}
++
++/* called by msdc_drv_probe */
++static void msdc_init_hw(struct msdc_host *host)
++{
++ u32 base = host->base;
++ struct msdc_hw *hw = host->hw;
++
++#ifdef MT6575_SD_DEBUG
++ msdc_reg[host->id] = (struct msdc_regs *)host->base;
++#endif
++
++ /* Power on */
++#if 0 /* --- chhung */
++ msdc_vcore_on(host);
++ msdc_pin_reset(host, MSDC_PIN_PULL_UP);
++ msdc_select_clksrc(host, hw->clk_src);
++ enable_clock(PERI_MSDC0_PDN + host->id, "SD");
++ msdc_vdd_on(host);
++#endif /* end of --- */
++ /* Configure to MMC/SD mode */
++ sdr_set_field(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC);
++
++ /* Reset */
++ msdc_reset();
++ msdc_clr_fifo();
++
++ /* Disable card detection */
++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN);
++
++ /* Disable and clear all interrupts */
++ sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN));
++ sdr_write32(MSDC_INT, sdr_read32(MSDC_INT));
++
++#if 1
++ /* reset tuning parameter */
++ sdr_write32(MSDC_PAD_CTL0, 0x00090000);
++ sdr_write32(MSDC_PAD_CTL1, 0x000A0000);
++ sdr_write32(MSDC_PAD_CTL2, 0x000A0000);
++ // sdr_write32(MSDC_PAD_TUNE, 0x00000000);
++ sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward
++ // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000);
++ sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward
++ sdr_write32(MSDC_DAT_RDDLY1, 0x00000000);
++ sdr_write32(MSDC_IOCON, 0x00000000);
++#if 0 // use MT7620 default value: 0x403c004f
++ sdr_write32(MSDC_PATCH_BIT0, 0x003C000F); /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/
++#endif
++
++ if (sdr_read32(MSDC_ECO_VER) >= 4) {
++ if (host->id == 1) {
++ sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, 1);
++ sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, 1);
++
++ /* internal clock: latch read data */
++ sdr_set_bits(MSDC_PATCH_BIT0, MSDC_PATCH_BIT_CKGEN_CK);
++ }
++ }
++#endif
++
++ /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in
++ pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only
++ set when kernel driver wants to use SDIO bus interrupt */
++ /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */
++ sdr_set_bits(SDC_CFG, SDC_CFG_SDIO);
++
++ /* disable detect SDIO device interupt function */
++ sdr_clr_bits(SDC_CFG, SDC_CFG_SDIOIDE);
++
++ /* eneable SMT for glitch filter */
++ sdr_set_bits(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT);
++ sdr_set_bits(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT);
++ sdr_set_bits(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT);
++
++#if 1
++ /* set clk, cmd, dat pad driving */
++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, hw->clk_drv);
++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, hw->clk_drv);
++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, hw->cmd_drv);
++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, hw->cmd_drv);
++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, hw->dat_drv);
++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, hw->dat_drv);
++#else
++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0);
++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0);
++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0);
++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0);
++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0);
++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0);
++#endif
++
++ /* set sampling edge */
++
++ /* write crc timeout detection */
++ sdr_set_field(MSDC_PATCH_BIT0, 1 << 30, 1);
++
++ /* Configure to default data timeout */
++ sdr_set_field(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC);
++
++ msdc_set_buswidth(host, MMC_BUS_WIDTH_1);
++
++ //printk("init hardware done!\n");
++}
++
++/* called by msdc_drv_remove */
++static void msdc_deinit_hw(struct msdc_host *host)
++{
++ u32 base = host->base;
++
++ /* Disable and clear all interrupts */
++ sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN));
++ sdr_write32(MSDC_INT, sdr_read32(MSDC_INT));
++
++ /* Disable card detection */
++ msdc_enable_cd_irq(host, 0);
++ // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */
++}
++
++/* init gpd and bd list in msdc_drv_probe */
++static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma)
++{
++ gpd_t *gpd = dma->gpd;
++ bd_t *bd = dma->bd;
++ bd_t *ptr, *prev;
++
++ /* we just support one gpd */
++ int bdlen = MAX_BD_PER_GPD;
++
++ /* init the 2 gpd */
++ memset(gpd, 0, sizeof(gpd_t) * 2);
++ //gpd->next = (void *)virt_to_phys(gpd + 1); /* pointer to a null gpd, bug! kmalloc <-> virt_to_phys */
++ //gpd->next = (dma->gpd_addr + 1); /* bug */
++ gpd->next = (void *)((u32)dma->gpd_addr + sizeof(gpd_t));
++
++ //gpd->intr = 0;
++ gpd->bdp = 1; /* hwo, cs, bd pointer */
++ //gpd->ptr = (void*)virt_to_phys(bd);
++ gpd->ptr = (void *)dma->bd_addr; /* physical address */
++
++ memset(bd, 0, sizeof(bd_t) * bdlen);
++ ptr = bd + bdlen - 1;
++ //ptr->eol = 1; /* 0 or 1 [Fix me]*/
++ //ptr->next = 0;
++
++ while (ptr != bd) {
++ prev = ptr - 1;
++ prev->next = (void *)(dma->bd_addr + sizeof(bd_t) *(ptr - bd));
++ ptr = prev;
++ }
++}
++
++static int msdc_drv_probe(struct platform_device *pdev)
++{
++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ __iomem void *base;
++ struct mmc_host *mmc;
++ struct resource *mem;
++ struct msdc_host *host;
++ struct msdc_hw *hw;
++ int ret, irq;
++ pdev->dev.platform_data = &msdc0_hw;
++
++ /* Allocate MMC host for this device */
++ mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
++ if (!mmc) return -ENOMEM;
++
++ hw = (struct msdc_hw*)pdev->dev.platform_data;
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq = platform_get_irq(pdev, 0);
++
++ //BUG_ON((!hw) || (!mem) || (irq < 0)); /* --- by chhung */
++
++ base = devm_request_and_ioremap(&pdev->dev, res);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++/* mem = request_mem_region(mem->start - 0xa0000000, (mem->end - mem->start + 1) - 0xa0000000, dev_name(&pdev->dev));
++ if (mem == NULL) {
++ mmc_free_host(mmc);
++ return -EBUSY;
++ }
++*/
++ /* Set host parameters to mmc */
++ mmc->ops = &mt_msdc_ops;
++ mmc->f_min = HOST_MIN_MCLK;
++ mmc->f_max = HOST_MAX_MCLK;
++ mmc->ocr_avail = MSDC_OCR_AVAIL;
++
++ /* For sd card: MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED,
++ For sdio : MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED */
++ if (hw->flags & MSDC_HIGHSPEED) {
++ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
++ }
++ if (hw->data_pins == 4) { /* current data_pins are all 4*/
++ mmc->caps |= MMC_CAP_4_BIT_DATA;
++ } else if (hw->data_pins == 8) {
++ mmc->caps |= MMC_CAP_8_BIT_DATA;
++ }
++ if ((hw->flags & MSDC_SDIO_IRQ) || (hw->flags & MSDC_EXT_SDIO_IRQ))
++ mmc->caps |= MMC_CAP_SDIO_IRQ; /* yes for sdio */
++
++ /* MMC core transfer sizes tunable parameters */
++ // mmc->max_hw_segs = MAX_HW_SGMTS;
++// mmc->max_phys_segs = MAX_PHY_SGMTS;
++ mmc->max_seg_size = MAX_SGMT_SZ;
++ mmc->max_blk_size = HOST_MAX_BLKSZ;
++ mmc->max_req_size = MAX_REQ_SZ;
++ mmc->max_blk_count = mmc->max_req_size;
++
++ host = mmc_priv(mmc);
++ host->hw = hw;
++ host->mmc = mmc;
++ host->id = pdev->id;
++ host->error = 0;
++ host->irq = irq;
++ host->base = (unsigned long) base;
++ host->mclk = 0; /* mclk: the request clock of mmc sub-system */
++ host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */
++ host->sclk = 0; /* sclk: the really clock after divition */
++ host->pm_state = PMSG_RESUME;
++ host->suspend = 0;
++ host->core_clkon = 0;
++ host->card_clkon = 0;
++ host->core_power = 0;
++ host->power_mode = MMC_POWER_OFF;
++// host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1;
++ host->timeout_ns = 0;
++ host->timeout_clks = DEFAULT_DTOC * 65536;
++
++ host->mrq = NULL;
++ //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */
++
++ host->dma.used_gpd = 0;
++ host->dma.used_bd = 0;
++
++ /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */
++ host->dma.gpd = dma_alloc_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), &host->dma.gpd_addr, GFP_KERNEL);
++ host->dma.bd = dma_alloc_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), &host->dma.bd_addr, GFP_KERNEL);
++ BUG_ON((!host->dma.gpd) || (!host->dma.bd));
++ msdc_init_gpd_bd(host, &host->dma);
++ /*for emmc*/
++ msdc_6575_host[pdev->id] = host;
++
++ tasklet_init(&host->card_tasklet, msdc_tasklet_card, (ulong)host);
++ spin_lock_init(&host->lock);
++ msdc_init_hw(host);
++
++ ret = request_irq((unsigned int)irq, msdc_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), host);
++ if (ret) goto release;
++ // mt65xx_irq_unmask(irq); /* --- by chhung */
++
++ if (hw->flags & MSDC_CD_PIN_EN) { /* not set for sdio */
++ if (hw->request_cd_eirq) { /* not set for MT6575 */
++ hw->request_cd_eirq(msdc_eirq_cd, (void*)host); /* msdc_eirq_cd will not be used! */
++ }
++ }
++
++ if (hw->request_sdio_eirq) /* set to combo_sdio_request_eirq() for WIFI */
++ hw->request_sdio_eirq(msdc_eirq_sdio, (void*)host); /* msdc_eirq_sdio() will be called when EIRQ */
++
++ if (hw->register_pm) {/* yes for sdio */
++ if(hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */
++ //printk("MSDC_SYS_SUSPEND and register_pm both set\n");
++ }
++ //mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* pm not controlled by system but by client. */ /* --- by chhung */
++ }
++
++ platform_set_drvdata(pdev, mmc);
++
++ ret = mmc_add_host(mmc);
++ if (ret) goto free_irq;
++
++ /* Config card detection pin and enable interrupts */
++ if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */
++ msdc_enable_cd_irq(host, 1);
++ } else {
++ msdc_enable_cd_irq(host, 0);
++ }
++
++ return 0;
++
++free_irq:
++ free_irq(irq, host);
++release:
++ platform_set_drvdata(pdev, NULL);
++ msdc_deinit_hw(host);
++
++ tasklet_kill(&host->card_tasklet);
++
++/* if (mem)
++ release_mem_region(mem->start, mem->end - mem->start + 1);
++*/
++ mmc_free_host(mmc);
++
++ return ret;
++}
++
++/* 4 device share one driver, using "drvdata" to show difference */
++static int msdc_drv_remove(struct platform_device *pdev)
++{
++ struct mmc_host *mmc;
++ struct msdc_host *host;
++ struct resource *mem;
++
++
++ mmc = platform_get_drvdata(pdev);
++ BUG_ON(!mmc);
++
++ host = mmc_priv(mmc);
++ BUG_ON(!host);
++
++ //printk("removed !!!\n");
++
++ platform_set_drvdata(pdev, NULL);
++ mmc_remove_host(host->mmc);
++ msdc_deinit_hw(host);
++
++ tasklet_kill(&host->card_tasklet);
++ free_irq(host->irq, host);
++
++ dma_free_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), host->dma.gpd, host->dma.gpd_addr);
++ dma_free_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), host->dma.bd, host->dma.bd_addr);
++
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++ if (mem)
++ release_mem_region(mem->start, mem->end - mem->start + 1);
++
++ mmc_free_host(host->mmc);
++
++ return 0;
++}
++
++static const struct of_device_id mt7620a_sdhci_match[] = {
++ { .compatible = "ralink,mt7620a-sdhci" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt288x_wdt_match);
++
++/* Fix me: Power Flow */
++static struct platform_driver mt_msdc_driver = {
++ .probe = msdc_drv_probe,
++ .remove = msdc_drv_remove,
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = mt7620a_sdhci_match,
++
++ },
++};
++
++static int __init mt_msdc_init(void)
++{
++ int ret;
++/* +++ chhung */
++ unsigned int reg;
++
++ mtk_sd_device.dev.platform_data = &msdc0_hw;
++ printk("MTK MSDC device init.\n");
++ reg = sdr_read32((__iomem void *) 0xb0000060) & ~(0x3<<18);
++ reg |= 0x1 << 18;
++ sdr_write32((__iomem void *) 0xb0000060, reg);
++/* end of +++ */
++ ret = platform_driver_register(&mt_msdc_driver);
++ if (ret) {
++ printk(KERN_ERR DRV_NAME ": Can't register driver");
++ return ret;
++ }
++ printk(KERN_INFO DRV_NAME ": MediaTek MT6575 MSDC Driver\n");
++
++ //msdc_debug_proc_init();
++ return 0;
++}
++
++static void __exit mt_msdc_exit(void)
++{
++ platform_driver_unregister(&mt_msdc_driver);
++}
++
++module_init(mt_msdc_init);
++module_exit(mt_msdc_exit);
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("MediaTek MT6575 SD/MMC Card Driver");
++MODULE_AUTHOR("Infinity Chen <infinity.chen@mediatek.com>");
++
++EXPORT_SYMBOL(msdc_6575_host);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch b/target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch
new file mode 100644
index 0000000..62f043a
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0077-clocksource-add-common-of_clksrc_init-function.patch
@@ -0,0 +1,132 @@
+From 517d8e6ba345620c6704ec3db5b23c56fde06392 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 19:16:03 +0200
+Subject: [PATCH 77/79] clocksource: add common of_clksrc_init() function
+
+It is desirable to move all clocksource drivers to drivers/clocksource,
+yet each requires its own initialization function. We'd rather not
+pollute <linux/> with a header for each function. Instead, create a
+single of_clksrc_init() function which will determine which clocksource
+driver to initialize based on device tree.
+
+Based on a similar patch for drivers/irqchip by Thomas Petazzoni.
+
+Signed-off-by: Stephen Warren <swarren@nvidia.com>
+---
+ drivers/clocksource/Kconfig | 3 +++
+ drivers/clocksource/Makefile | 1 +
+ drivers/clocksource/clksrc-of.c | 35 +++++++++++++++++++++++++++++++++++
+ include/asm-generic/vmlinux.lds.h | 9 +++++++++
+ include/linux/clocksource.h | 9 +++++++++
+ 5 files changed, 57 insertions(+)
+ create mode 100644 drivers/clocksource/clksrc-of.c
+
+diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
+index 7fdcbd3..a32b7a9 100644
+--- a/drivers/clocksource/Kconfig
++++ b/drivers/clocksource/Kconfig
+@@ -1,3 +1,6 @@
++config CLKSRC_OF
++ bool
++
+ config CLKSRC_I8253
+ bool
+
+diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
+index f93453d..a33f792 100644
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -1,3 +1,4 @@
++obj-$(CONFIG_CLKSRC_OF) += clksrc-of.o
+ obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
+ obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o
+ obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o
+diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
+new file mode 100644
+index 0000000..bdabdaa
+--- /dev/null
++++ b/drivers/clocksource/clksrc-of.c
+@@ -0,0 +1,35 @@
++/*
++ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/init.h>
++#include <linux/of.h>
++
++extern struct of_device_id __clksrc_of_table[];
++
++static const struct of_device_id __clksrc_of_table_sentinel
++ __used __section(__clksrc_of_table_end);
++
++void __init clocksource_of_init(void)
++{
++ struct device_node *np;
++ const struct of_device_id *match;
++ void (*init_func)(void);
++
++ for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
++ init_func = match->data;
++ init_func();
++ }
++}
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index d1ea7ce..1e744c5 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -149,6 +149,14 @@
+ #define TRACE_SYSCALLS()
+ #endif
+
++#ifdef CONFIG_CLKSRC_OF
++#define CLKSRC_OF_TABLES() . = ALIGN(8); \
++ VMLINUX_SYMBOL(__clksrc_of_table) = .; \
++ *(__clksrc_of_table) \
++ *(__clksrc_of_table_end)
++#else
++#define CLKSRC_OF_TABLES()
++#endif
+
+ #define KERNEL_DTB() \
+ STRUCT_ALIGN(); \
+@@ -493,6 +501,7 @@
+ DEV_DISCARD(init.rodata) \
+ CPU_DISCARD(init.rodata) \
+ MEM_DISCARD(init.rodata) \
++ CLKSRC_OF_TABLES() \
+ KERNEL_DTB()
+
+ #define INIT_TEXT \
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index 4dceaf8..7944f14 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -332,4 +332,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
+
+ extern int clocksource_i8253_init(void);
+
++#ifdef CONFIG_CLKSRC_OF
++extern void clocksource_of_init(void);
++
++#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
++ static const struct of_device_id __clksrc_of_table_##name \
++ __used __section(__clksrc_of_table) \
++ = { .compatible = compat, .data = fn };
++#endif
++
+ #endif /* _LINUX_CLOCKSOURCE_H */
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch b/target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch
new file mode 100644
index 0000000..218dfc3
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0078-clocksource-make-clocksource_of_init-pass-a-device_n.patch
@@ -0,0 +1,36 @@
+From 0e00abf87d50e80b1ce5bda65a4d89adc530ba10 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 23 May 2013 16:58:12 +0200
+Subject: [PATCH 78/79] clocksource: make clocksource_of_init() pass a
+ device_node pointer
+
+If we look at the clocksources that are OF enabled we will notice, that they
+all do a of_find_matching_node() when being called. This patch changes
+clocksource_of_init() to always pass the struct device_node pointer to the
+init function.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/clocksource/clksrc-of.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
+index bdabdaa..3ef11fb 100644
+--- a/drivers/clocksource/clksrc-of.c
++++ b/drivers/clocksource/clksrc-of.c
+@@ -26,10 +26,10 @@ void __init clocksource_of_init(void)
+ {
+ struct device_node *np;
+ const struct of_device_id *match;
+- void (*init_func)(void);
++ void (*init_func)(struct device_node *);
+
+ for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
+ init_func = match->data;
+- init_func();
++ init_func(np);
+ }
+ }
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch b/target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch
new file mode 100644
index 0000000..32c96ec
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0079-clocksource-MIPS-ralink-add-support-for-systick-time.patch
@@ -0,0 +1,282 @@
+From 4f3ae2a7ee1b1c9b9cab287c828f2ed7b1858495 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 19:21:52 +0200
+Subject: [PATCH 79/79] clocksource: MIPS: ralink: add support for systick
+ timer found on newer ralink SoC
+
+Signed-off-by: John Crispin <blogic@openwrt.org
+---
+ arch/mips/pci/Makefile.rej | 10 +++
+ arch/mips/ralink/Kconfig | 2 +
+ arch/mips/ralink/Kconfig.rej | 10 +++
+ arch/mips/ralink/clk.c | 1 +
+ drivers/clocksource/Kconfig | 6 ++
+ drivers/clocksource/Makefile | 1 +
+ drivers/clocksource/cevt-rt3352.c | 162 +++++++++++++++++++++++++++++++++++++
+ 7 files changed, 192 insertions(+)
+ create mode 100644 arch/mips/pci/Makefile.rej
+ create mode 100644 arch/mips/ralink/Kconfig.rej
+ create mode 100644 drivers/clocksource/cevt-rt3352.c
+
+diff --git a/arch/mips/pci/Makefile.rej b/arch/mips/pci/Makefile.rej
+new file mode 100644
+index 0000000..c5761e8
+--- /dev/null
++++ b/arch/mips/pci/Makefile.rej
+@@ -0,0 +1,10 @@
++--- arch/mips/pci/Makefile
+++++ arch/mips/pci/Makefile
++@@ -43,6 +43,7 @@
++ 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_SOC_MT7620) += pci-mt7620a.o
++ obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
++ obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
++ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index f89fdf8..c8d5b6c 100644
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -15,6 +15,7 @@ choice
+ select USB_ARCH_HAS_HCD
+ select USB_ARCH_HAS_OHCI
+ select USB_ARCH_HAS_EHCI
++ select CLKEVT_RT3352
+
+ config SOC_RT3883
+ bool "RT3883"
+@@ -24,6 +25,7 @@ choice
+
+ config SOC_MT7620
+ bool "MT7620"
++ select CLKEVT_RT3352
+ select HW_HAS_PCI
+
+ endchoice
+diff --git a/arch/mips/ralink/Kconfig.rej b/arch/mips/ralink/Kconfig.rej
+new file mode 100644
+index 0000000..d3a804f
+--- /dev/null
++++ b/arch/mips/ralink/Kconfig.rej
+@@ -0,0 +1,10 @@
++--- arch/mips/ralink/Kconfig
+++++ arch/mips/ralink/Kconfig
++@@ -23,6 +24,7 @@
++
++ config SOC_MT7620
++ bool "MT7620"
+++ select CLKEVT_RT3352
++
++ endchoice
++
+diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c
+index 8dfa22f..bba0cdf 100644
+--- a/arch/mips/ralink/clk.c
++++ b/arch/mips/ralink/clk.c
+@@ -69,4 +69,5 @@ void __init plat_time_init(void)
+ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+ clk_put(clk);
++ clocksource_of_init();
+ }
+diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
+index a32b7a9..90bed1a 100644
+--- a/drivers/clocksource/Kconfig
++++ b/drivers/clocksource/Kconfig
+@@ -7,6 +7,12 @@ config CLKSRC_I8253
+ config CLKEVT_I8253
+ bool
+
++config CLKEVT_RT3352
++ bool
++ depends on MIPS && RALINK
++ select CLKSRC_OF
++ select CLKSRC_MMIO
++
+ config I8253_LOCK
+ bool
+
+diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
+index a33f792..5031f82 100644
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
+ obj-$(CONFIG_EM_TIMER_STI) += em_sti.o
+ obj-$(CONFIG_CLKBLD_I8253) += i8253.o
+ obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
++obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
+ obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
+ obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
+ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o
+diff --git a/drivers/clocksource/cevt-rt3352.c b/drivers/clocksource/cevt-rt3352.c
+new file mode 100644
+index 0000000..bd50edd
+--- /dev/null
++++ b/drivers/clocksource/cevt-rt3352.c
+@@ -0,0 +1,162 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2013 by John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/clockchips.h>
++#include <linux/clocksource.h>
++#include <linux/interrupt.h>
++#include <linux/reset.h>
++#include <linux/init.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++#include <asm/time.h>
++
++#define SYSTICK_FREQ (50 * 1000)
++
++#define SYSTICK_CONFIG 0x00
++#define SYSTICK_COMPARE 0x04
++#define SYSTICK_COUNT 0x08
++
++/* route systick irq to mips irq 7 instead of the r4k-timer */
++#define CFG_EXT_STK_EN 0x2
++/* enable the counter */
++#define CFG_CNT_EN 0x1
++
++struct systick_device {
++ void __iomem *membase;
++ struct clock_event_device dev;
++ int irq_requested;
++ int freq_scale;
++};
++
++static void systick_set_clock_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt);
++
++static int systick_next_event(unsigned long delta,
++ struct clock_event_device *evt)
++{
++ struct systick_device *sdev = container_of(evt, struct systick_device, dev);
++ u32 count;
++
++ count = ioread32(sdev->membase + SYSTICK_COUNT);
++ count = (count + delta) % SYSTICK_FREQ;
++ iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE);
++
++ return 0;
++}
++
++static void systick_event_handler(struct clock_event_device *dev)
++{
++ /* noting to do here */
++}
++
++static irqreturn_t systick_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *dev = (struct clock_event_device *) dev_id;
++
++ dev->event_handler(dev);
++
++ return IRQ_HANDLED;
++}
++
++static struct systick_device systick = {
++ .dev = {
++ /* cevt-r4k uses 300, make sure systick gets used if available */
++ .rating = 310,
++ .features = CLOCK_EVT_FEAT_ONESHOT,
++ .set_next_event = systick_next_event,
++ .set_mode = systick_set_clock_mode,
++ .event_handler = systick_event_handler,
++ },
++};
++
++static struct irqaction systick_irqaction = {
++ .handler = systick_interrupt,
++ .flags = IRQF_PERCPU | IRQF_TIMER,
++ .dev_id = &systick.dev,
++};
++
++/* ugly hack */
++#ifdef CONFIG_SOC_MT7620
++
++#define CLK_LUT_CFG 0x40
++#define SLEEP_EN BIT(31)
++
++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status)
++{
++ if (sdev->freq_scale == status)
++ return;
++
++ sdev->freq_scale = status;
++
++ pr_info("%s: %s autosleep mode\n", systick.dev.name, (status) ? ("enable") : ("disable"));
++ if (status)
++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG);
++ else
++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG);
++}
++#else
++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) {}
++#endif
++
++static void systick_set_clock_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ struct systick_device *sdev = container_of(evt, struct systick_device, dev);
++
++ switch (mode) {
++ case CLOCK_EVT_MODE_ONESHOT:
++ if (!sdev->irq_requested)
++ setup_irq(systick.dev.irq, &systick_irqaction);
++ mt7620_freq_scaling(sdev, 1);
++ sdev->irq_requested = 1;
++ iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN, systick.membase + SYSTICK_CONFIG);
++ break;
++
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ if (sdev->irq_requested)
++ free_irq(systick.dev.irq, &systick_irqaction);
++ mt7620_freq_scaling(sdev, 0);
++ sdev->irq_requested = 0;
++ iowrite32(0, systick.membase + SYSTICK_CONFIG);
++ break;
++
++ default:
++ pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name);
++ break;
++ }
++}
++
++static void __init ralink_systick_init(struct device_node *np)
++{
++ systick.membase = of_iomap(np, 0);
++ if (!systick.membase) {
++ pr_err("%s: of_iomap failed", np->name);
++ return;
++ }
++
++ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
++ SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up);
++
++ systick_irqaction.name = np->name;
++ systick.dev.name = np->name;
++ clockevent_set_clock(&systick.dev, SYSTICK_FREQ);
++ systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
++ systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
++ systick.dev.irq = irq_of_parse_and_map(np, 0);
++ if (!systick.dev.irq)
++ panic("%s: request_irq failed", np->name);
++
++ clockevents_register_device(&systick.dev);
++
++ pr_info("%s: runing - mult: %d, shift: %d\n", np->name, systick.dev.mult, systick.dev.shift);
++}
++
++CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch b/target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch
new file mode 100644
index 0000000..0726ac8
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0080-MIPS-add-ohci-ehci-support.patch
@@ -0,0 +1,227 @@
+From ec6f3aa022ef6e61f6ca80c6e30610d879654466 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 20 Jun 2013 23:33:05 +0200
+Subject: [PATCH] MIPS: add ohci/ehci support
+
+Signed-off-by: John Crsipin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Kconfig | 2 ++
+ drivers/usb/Makefile | 3 ++-
+ drivers/usb/host/ehci-platform.c | 43 ++++++++++++++++++++++++++++++++------
+ drivers/usb/host/ohci-platform.c | 37 +++++++++++++++++++++++++++-----
+ 4 files changed, 73 insertions(+), 12 deletions(-)
+
+diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
+index c8d5b6c..7cd1188 100644
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -27,6 +27,8 @@ choice
+ bool "MT7620"
+ select CLKEVT_RT3352
+ select HW_HAS_PCI
++ select USB_ARCH_HAS_OHCI
++ select USB_ARCH_HAS_EHCI
+
+ endchoice
+
+diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
+index f5ed3d7..41a4741 100644
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -12,6 +12,8 @@ obj-$(CONFIG_USB_DWC3) += dwc3/
+
+ obj-$(CONFIG_USB_MON) += mon/
+
++obj-$(CONFIG_USB_COMMON) += phy/
++
+ obj-$(CONFIG_PCI) += host/
+ obj-$(CONFIG_USB_EHCI_HCD) += host/
+ obj-$(CONFIG_USB_ISP116X_HCD) += host/
+@@ -46,7 +48,6 @@ obj-$(CONFIG_USB_MICROTEK) += image/
+ obj-$(CONFIG_USB_SERIAL) += serial/
+
+ obj-$(CONFIG_USB) += misc/
+-obj-$(CONFIG_USB_COMMON) += phy/
+ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
+
+ obj-$(CONFIG_USB_ATM) += atm/
+diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
+index 58fa0c9..0050df7 100644
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -23,6 +23,10 @@
+ #include <linux/io.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/of.h>
++#include <linux/usb/otg.h>
++#include <linux/usb/phy.h>
+ #include <linux/usb.h>
+ #include <linux/usb/hcd.h>
+ #include <linux/usb/ehci_pdriver.h>
+@@ -61,22 +65,40 @@ static const struct ehci_driver_overrides platform_overrides __initdata = {
+ .reset = ehci_platform_reset,
+ };
+
++static struct usb_ehci_pdata ehci_platform_defaults;
++
+ static int ehci_platform_probe(struct platform_device *dev)
+ {
+ struct usb_hcd *hcd;
+ struct resource *res_mem;
+- struct usb_ehci_pdata *pdata = dev->dev.platform_data;
++ struct usb_ehci_pdata *pdata;
+ int irq;
+ int err = -ENOMEM;
+
+- if (!pdata) {
+- WARN_ON(1);
+- return -ENODEV;
+- }
+-
+ if (usb_disabled())
+ return -ENODEV;
+
++ /*
++ * use reasonable defaults so platforms don't have to provide these.
++ * with DT probing on ARM, none of these are set.
++ */
++ if (!dev->dev.platform_data)
++ dev->dev.platform_data = &ehci_platform_defaults;
++ if (!dev->dev.dma_mask)
++ dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
++ if (!dev->dev.coherent_dma_mask)
++ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
++
++ pdata = dev->dev.platform_data;
++
++#ifdef CONFIG_USB_COMMON
++ hcd->phy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2);
++ if (!IS_ERR_OR_NULL(hcd->phy)) {
++ otg_set_host(hcd->phy->otg,
++ &hcd->self);
++ usb_phy_init(hcd->phy);
++ }
++#endif
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0) {
+ dev_err(&dev->dev, "no irq provided");
+@@ -138,6 +160,9 @@ static int ehci_platform_remove(struct platform_device *dev)
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
++ if (pdata == &ehci_platform_defaults)
++ dev->dev.platform_data = NULL;
++
+ return 0;
+ }
+
+@@ -182,6 +207,11 @@ static int ehci_platform_resume(struct device *dev)
+ #define ehci_platform_resume NULL
+ #endif /* CONFIG_PM */
+
++static const struct of_device_id ralink_ehci_ids[] = {
++ { .compatible = "ralink,rt3xxx-ehci", },
++ {}
++};
++
+ static const struct platform_device_id ehci_platform_table[] = {
+ { "ehci-platform", 0 },
+ { }
+@@ -202,6 +232,7 @@ static struct platform_driver ehci_platform_driver = {
+ .owner = THIS_MODULE,
+ .name = "ehci-platform",
+ .pm = &ehci_platform_pm_ops,
++ .of_match_table = of_match_ptr(ralink_ehci_ids),
+ }
+ };
+
+diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
+index 084503b..3a60f96 100644
+--- a/drivers/usb/host/ohci-platform.c
++++ b/drivers/usb/host/ohci-platform.c
+@@ -15,6 +15,10 @@
+ */
+ #include <linux/platform_device.h>
+ #include <linux/usb/ohci_pdriver.h>
++#include <linux/dma-mapping.h>
++#include <linux/of.h>
++
++static struct usb_ohci_pdata ohci_platform_defaults;
+
+ static int ohci_platform_reset(struct usb_hcd *hcd)
+ {
+@@ -87,14 +91,22 @@ static int ohci_platform_probe(struct platform_device *dev)
+ {
+ struct usb_hcd *hcd;
+ struct resource *res_mem;
+- struct usb_ohci_pdata *pdata = dev->dev.platform_data;
++ struct usb_ohci_pdata *pdata;
+ int irq;
+ int err = -ENOMEM;
+
+- if (!pdata) {
+- WARN_ON(1);
+- return -ENODEV;
+- }
++ /*
++ * use reasonable defaults so platforms don't have to provide these.
++ * with DT probing on ARM, none of these are set.
++ */
++ if (!dev->dev.platform_data)
++ dev->dev.platform_data = &ohci_platform_defaults;
++ if (!dev->dev.dma_mask)
++ dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
++ if (!dev->dev.coherent_dma_mask)
++ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
++
++ pdata = dev->dev.platform_data;
+
+ if (usb_disabled())
+ return -ENODEV;
+@@ -124,6 +136,12 @@ static int ohci_platform_probe(struct platform_device *dev)
+ goto err_power;
+ }
+
++#ifdef CONFIG_USB_COMMON
++ hcd->phy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2);
++ if (!IS_ERR_OR_NULL(hcd->phy))
++ usb_phy_init(hcd->phy);
++#endif
++
+ hcd->rsrc_start = res_mem->start;
+ hcd->rsrc_len = resource_size(res_mem);
+
+@@ -161,6 +179,9 @@ static int ohci_platform_remove(struct platform_device *dev)
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
++ if (pdata == &ohci_platform_defaults)
++ dev->dev.platform_data = NULL;
++
+ return 0;
+ }
+
+@@ -200,6 +221,11 @@ static int ohci_platform_resume(struct device *dev)
+ #define ohci_platform_resume NULL
+ #endif /* CONFIG_PM */
+
++static const struct of_device_id ralink_ohci_ids[] = {
++ { .compatible = "ralink,rt3xxx-ohci", },
++ {}
++};
++
+ static const struct platform_device_id ohci_platform_table[] = {
+ { "ohci-platform", 0 },
+ { }
+@@ -220,5 +246,6 @@ static struct platform_driver ohci_platform_driver = {
+ .owner = THIS_MODULE,
+ .name = "ohci-platform",
+ .pm = &ohci_platform_pm_ops,
++ .of_match_table = of_match_ptr(ralink_ohci_ids),
+ }
+ };
+--
+1.7.10.4
+
diff --git a/target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch
deleted file mode 100644
index 9bb9b5f..0000000
--- a/target/linux/ramips/patches-3.8/0136-NET-MIPS-add-ralink-SoC-ethernet-driver.patch
+++ /dev/null
@@ -1,3137 +0,0 @@
-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_RX_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");
diff --git a/target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch b/target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch
deleted file mode 100644
index 3b7246f..0000000
--- a/target/linux/ramips/patches-3.8/0137-watchdog-adds-ralink-wdt.patch
+++ /dev/null
@@ -1,395 +0,0 @@
-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);
diff --git a/target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch b/target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch
deleted file mode 100644
index 13a45b2..0000000
--- a/target/linux/ramips/patches-3.8/0203-owrt-OF-USB-add-OF-binding-for-ehci-and-ohci-platfor.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From 3c99a50d689cb4811b13b9810d18c9316587216f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 18 Mar 2013 20:51:21 +0100
-Subject: [PATCH 203/208] owrt: OF: USB: add OF binding for ehci and ohci
- platform driver
-
-Make ohci-platform and ehci-platform loadable from OF.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/usb/host/ehci-platform.c | 7 +++++++
- drivers/usb/host/ohci-platform.c | 7 +++++++
- 2 files changed, 14 insertions(+)
-
---- a/drivers/usb/host/ehci-platform.c
-+++ b/drivers/usb/host/ehci-platform.c
-@@ -183,6 +183,12 @@ static int ehci_platform_resume(struct d
- #define ehci_platform_resume NULL
- #endif /* CONFIG_PM */
-
-+static const struct of_device_id ehci_match_table[] = {
-+ { .compatible = "ehci-platform" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ehci_match_table);
-+
- static const struct platform_device_id ehci_platform_table[] = {
- { "ehci-platform", 0 },
- { }
-@@ -203,6 +209,7 @@ static struct platform_driver ehci_platf
- .owner = THIS_MODULE,
- .name = "ehci-platform",
- .pm = &ehci_platform_pm_ops,
-+ .of_match_table = ehci_match_table,
- }
- };
-
---- a/drivers/usb/host/ohci-platform.c
-+++ b/drivers/usb/host/ohci-platform.c
-@@ -200,6 +200,12 @@ static int ohci_platform_resume(struct d
- #define ohci_platform_resume NULL
- #endif /* CONFIG_PM */
-
-+static const struct of_device_id ohci_match_table[] = {
-+ { .compatible = "ohci-platform" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ohci_match_table);
-+
- static const struct platform_device_id ohci_platform_table[] = {
- { "ohci-platform", 0 },
- { }
-@@ -220,5 +226,6 @@ static struct platform_driver ohci_platf
- .owner = THIS_MODULE,
- .name = "ohci-platform",
- .pm = &ohci_platform_pm_ops,
-+ .of_match_table = ohci_match_table,
- }
- };
diff --git a/target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch b/target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch
deleted file mode 100644
index 0fedc91..0000000
--- a/target/linux/ramips/patches-3.8/0204-owrt-MIPS-ralink-add-usb-platform-support.patch
+++ /dev/null
@@ -1,325 +0,0 @@
-From d7e679017ec92824145b275572f6ef83d461f076 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 19 Mar 2013 09:26:22 +0100
-Subject: [PATCH 204/208] owrt: MIPS: ralink: add usb platform support
-
-Add code to load the platform ehci/ohci driver on Ralink SoC. For the usb core
-to work we need to populate the platform_data during boot, prior to the usb
-driver being loaded.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Makefile | 4 +-
- arch/mips/ralink/common.h | 1 +
- arch/mips/ralink/mt7620.c | 5 ++
- arch/mips/ralink/of.c | 1 +
- arch/mips/ralink/rt305x-usb.c | 120 +++++++++++++++++++++++++++++++++++++++++
- arch/mips/ralink/rt3883-usb.c | 118 ++++++++++++++++++++++++++++++++++++++++
- 6 files changed, 247 insertions(+), 2 deletions(-)
- create mode 100644 arch/mips/ralink/rt305x-usb.c
- create mode 100644 arch/mips/ralink/rt3883-usb.c
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -9,8 +9,8 @@
- 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
--obj-$(CONFIG_SOC_RT3883) += rt3883.o
-+obj-$(CONFIG_SOC_RT305X) += rt305x.o rt305x-usb.o
-+obj-$(CONFIG_SOC_RT3883) += rt3883.o rt3883-usb.o
- obj-$(CONFIG_SOC_MT7620) += mt7620.o
-
- obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
---- a/arch/mips/ralink/common.h
-+++ b/arch/mips/ralink/common.h
-@@ -51,5 +51,6 @@ extern void prom_soc_init(struct ralink_
- __iomem void *plat_of_remap_node(const char *node);
-
- void ralink_pinmux(void);
-+void ralink_usb_platform(void);
-
- #endif /* _RALINK_COMMON_H__ */
---- a/arch/mips/ralink/mt7620.c
-+++ b/arch/mips/ralink/mt7620.c
-@@ -140,6 +140,11 @@ struct ralink_pinmux rt_gpio_pinmux = {
- .uart_mask = MT7620_GPIO_MODE_GPIO,
- };
-
-+void ralink_usb_platform(void)
-+{
-+
-+}
-+
- void __init ralink_clk_init(void)
- {
- unsigned long cpu_rate, sys_rate;
---- a/arch/mips/ralink/of.c
-+++ b/arch/mips/ralink/of.c
-@@ -111,6 +111,7 @@ static int __init plat_of_setup(void)
- panic("failed to populate DT\n");
-
- ralink_pinmux();
-+ ralink_usb_platform();
-
- return 0;
- }
---- /dev/null
-+++ b/arch/mips/ralink/rt305x-usb.c
-@@ -0,0 +1,120 @@
-+/*
-+ * 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) 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 <linux/delay.h>
-+#include <linux/of_platform.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/usb/ehci_pdriver.h>
-+#include <linux/usb/ohci_pdriver.h>
-+
-+#include <asm/mach-ralink/ralink_regs.h>
-+#include <asm/mach-ralink/rt305x.h>
-+
-+static atomic_t rt3352_usb_pwr_ref = ATOMIC_INIT(0);
-+
-+static int rt3352_usb_power_on(struct platform_device *pdev)
-+{
-+
-+ if (atomic_inc_return(&rt3352_usb_pwr_ref) == 1) {
-+ u32 t;
-+
-+ t = rt_sysc_r32(RT3352_SYSC_REG_USB_PS);
-+
-+ /* enable clock for port0's and port1's phys */
-+ t = rt_sysc_r32(RT3352_SYSC_REG_CLKCFG1);
-+ t |= RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN;
-+ rt_sysc_w32(t, RT3352_SYSC_REG_CLKCFG1);
-+ mdelay(500);
-+
-+ /* pull USBHOST and USBDEV out from reset */
-+ t = rt_sysc_r32(RT3352_SYSC_REG_RSTCTRL);
-+ t &= ~(RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV);
-+ rt_sysc_w32(t, RT3352_SYSC_REG_RSTCTRL);
-+ mdelay(500);
-+
-+ /* enable host mode */
-+ t = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG1);
-+ t |= RT3352_SYSCFG1_USB0_HOST_MODE;
-+ rt_sysc_w32(t, RT3352_SYSC_REG_SYSCFG1);
-+
-+ t = rt_sysc_r32(RT3352_SYSC_REG_USB_PS);
-+ }
-+
-+ return 0;
-+}
-+
-+static void rt3352_usb_power_off(struct platform_device *pdev)
-+{
-+ if (atomic_dec_return(&rt3352_usb_pwr_ref) == 0) {
-+ u32 t;
-+
-+ /* put USBHOST and USBDEV into reset */
-+ t = rt_sysc_r32(RT3352_SYSC_REG_RSTCTRL);
-+ t |= RT3352_RSTCTRL_UHST | RT3352_RSTCTRL_UDEV;
-+ rt_sysc_w32(t, RT3352_SYSC_REG_RSTCTRL);
-+ udelay(10000);
-+
-+ /* disable clock for port0's and port1's phys*/
-+ t = rt_sysc_r32(RT3352_SYSC_REG_CLKCFG1);
-+ t &= ~(RT3352_CLKCFG1_UPHY0_CLK_EN | RT3352_CLKCFG1_UPHY1_CLK_EN);
-+ rt_sysc_w32(t, RT3352_SYSC_REG_CLKCFG1);
-+ udelay(10000);
-+ }
-+}
-+
-+static struct usb_ehci_pdata rt3352_ehci_data = {
-+ .power_on = rt3352_usb_power_on,
-+ .power_off = rt3352_usb_power_off,
-+};
-+
-+static struct usb_ohci_pdata rt3352_ohci_data = {
-+ .power_on = rt3352_usb_power_on,
-+ .power_off = rt3352_usb_power_off,
-+};
-+
-+static void ralink_add_usb(char *name, void *pdata, u64 *mask)
-+{
-+ struct device_node *node;
-+ struct platform_device *pdev;
-+
-+ node = of_find_compatible_node(NULL, NULL, name);
-+ if (!node)
-+ return;
-+
-+ pdev = of_find_device_by_node(node);
-+ if (!pdev)
-+ goto error_out;
-+
-+ if (pdata)
-+ pdev->dev.platform_data = pdata;
-+ if (mask) {
-+ pdev->dev.dma_mask = mask;
-+ pdev->dev.coherent_dma_mask = *mask;
-+ }
-+
-+error_out:
-+ of_node_put(node);
-+}
-+
-+static u64 rt3352_ohci_dmamask = DMA_BIT_MASK(32);
-+static u64 rt3352_ehci_dmamask = DMA_BIT_MASK(32);
-+
-+void ralink_usb_platform(void)
-+{
-+ if (soc_is_rt3352() || soc_is_rt5350()) {
-+ ralink_add_usb("ohci-platform",
-+ &rt3352_ohci_data, &rt3352_ohci_dmamask);
-+ ralink_add_usb("ehci-platform",
-+ &rt3352_ehci_data, &rt3352_ehci_dmamask);
-+ }
-+}
---- /dev/null
-+++ b/arch/mips/ralink/rt3883-usb.c
-@@ -0,0 +1,118 @@
-+/*
-+ * 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) 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 <linux/delay.h>
-+#include <linux/of_platform.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/usb/ehci_pdriver.h>
-+#include <linux/usb/ohci_pdriver.h>
-+
-+#include <asm/mach-ralink/ralink_regs.h>
-+#include <asm/mach-ralink/rt3883.h>
-+
-+static atomic_t rt3883_usb_pwr_ref = ATOMIC_INIT(0);
-+
-+static int rt3883_usb_power_on(struct platform_device *pdev)
-+{
-+ if (atomic_inc_return(&rt3883_usb_pwr_ref) == 1) {
-+ u32 t;
-+
-+ t = rt_sysc_r32(RT3883_SYSC_REG_USB_PS);
-+
-+ /* enable clock for port0's and port1's phys */
-+ t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1);
-+ t |= RT3883_CLKCFG1_UPHY0_CLK_EN | RT3883_CLKCFG1_UPHY1_CLK_EN;
-+ rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1);
-+ mdelay(500);
-+
-+ /* pull USBHOST and USBDEV out from reset */
-+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
-+ t &= ~(RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV);
-+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
-+ mdelay(500);
-+
-+ /* enable host mode */
-+ t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1);
-+ t |= RT3883_SYSCFG1_USB0_HOST_MODE;
-+ rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1);
-+
-+ t = rt_sysc_r32(RT3883_SYSC_REG_USB_PS);
-+ }
-+
-+ return 0;
-+}
-+
-+static void rt3883_usb_power_off(struct platform_device *pdev)
-+{
-+ if (atomic_dec_return(&rt3883_usb_pwr_ref) == 0) {
-+ u32 t;
-+
-+ /* put USBHOST and USBDEV into reset */
-+ t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
-+ t |= RT3883_RSTCTRL_UHST | RT3883_RSTCTRL_UDEV;
-+ rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
-+ udelay(10000);
-+
-+ /* disable clock for port0's and port1's phys*/
-+ t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1);
-+ t &= ~(RT3883_CLKCFG1_UPHY0_CLK_EN |
-+ RT3883_CLKCFG1_UPHY1_CLK_EN);
-+ rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1);
-+ udelay(10000);
-+ }
-+}
-+
-+static struct usb_ohci_pdata rt3883_ohci_data = {
-+ .power_on = rt3883_usb_power_on,
-+ .power_off = rt3883_usb_power_off,
-+};
-+
-+static struct usb_ehci_pdata rt3883_ehci_data = {
-+ .power_on = rt3883_usb_power_on,
-+ .power_off = rt3883_usb_power_off,
-+};
-+
-+static void ralink_add_usb(char *name, void *pdata, u64 *mask)
-+{
-+ struct device_node *node;
-+ struct platform_device *pdev;
-+
-+ node = of_find_compatible_node(NULL, NULL, name);
-+ if (!node)
-+ return;
-+
-+ pdev = of_find_device_by_node(node);
-+ if (!pdev)
-+ goto error_out;
-+
-+ if (pdata)
-+ pdev->dev.platform_data = pdata;
-+ if (mask) {
-+ pdev->dev.dma_mask = mask;
-+ pdev->dev.coherent_dma_mask = *mask;
-+ }
-+
-+error_out:
-+ of_node_put(node);
-+}
-+
-+static u64 rt3883_ohci_dmamask = DMA_BIT_MASK(32);
-+static u64 rt3883_ehci_dmamask = DMA_BIT_MASK(32);
-+
-+void ralink_usb_platform(void)
-+{
-+ ralink_add_usb("ohci-platform",
-+ &rt3883_ohci_data, &rt3883_ohci_dmamask);
-+ ralink_add_usb("ehci-platform",
-+ &rt3883_ehci_data, &rt3883_ehci_dmamask);
-+}
---- a/arch/mips/ralink/rt288x.c
-+++ b/arch/mips/ralink/rt288x.c
-@@ -74,6 +74,11 @@ struct ralink_pinmux rt_gpio_pinmux = {
- .wdt_reset = rt288x_wdt_reset,
- };
-
-+void ralink_usb_platform(void)
-+{
-+
-+}
-+
- void __init ralink_clk_init(void)
- {
- unsigned long cpu_rate;