ramips: update v3.10 patches
authorblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Wed, 14 Aug 2013 18:15:15 +0000 (18:15 +0000)
committerblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Wed, 14 Aug 2013 18:15:15 +0000 (18:15 +0000)
Sync the patches with those sent upstream for v3.12.

Signed-off-by: John Crispin <blogic@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@37778 3c298f89-4303-0410-b956-a3cf2f4a3e73

92 files changed:
target/linux/ramips/mt7620a/config-3.10
target/linux/ramips/mt7620a/config-3.9 [deleted file]
target/linux/ramips/patches-3.10/0001-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch [deleted file]
target/linux/ramips/patches-3.10/0001-MTD-m25p80-allow-loading-mtd-name-from-OF.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0002-MIPS-ralink-add-pinmux-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0002-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0003-DT-Add-documentation-for-rt2880-wdt.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0003-MIPS-ralink-add-support-for-periodic-timer-irq.patch [deleted file]
target/linux/ramips/patches-3.10/0004-MIPS-ralink-add-rt_sysc_m32-helper.patch [deleted file]
target/linux/ramips/patches-3.10/0004-watchdog-MIPS-add-ralink-watchdog-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0005-DT-Add-documentation-for-gpio-ralink.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0005-MIPS-ralink-make-mt7620-ram-detect-verbose.patch [deleted file]
target/linux/ramips/patches-3.10/0006-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0006-MIPS-ralink-add-verbose-pmu-info.patch [deleted file]
target/linux/ramips/patches-3.10/0007-MIPS-ralink-adds-a-bootrom-dumper-module.patch [deleted file]
target/linux/ramips/patches-3.10/0007-serial-MIPS-lantiq-add-clk_enable-call-to-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0008-MIPS-ralink-add-illegal-access-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0008-serial-MIPS-lantiq-fix-clock-error-check.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0009-MIPS-ralink-add-support-for-reset-controller-API.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0009-MIPS-ralink-workaround-DTB-memory-issue.patch [deleted file]
target/linux/ramips/patches-3.10/0010-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch [deleted file]
target/linux/ramips/patches-3.10/0010-MIPS-ralink-add-support-for-periodic-timer-irq.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0011-MIPS-ralink-add-support-for-systick-timer-found-on-n.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0011-PCI-MIPS-adds-rt2880-pci-support.patch [deleted file]
target/linux/ramips/patches-3.10/0012-MIPS-ralink-probe-clocksources-from-OF.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0012-PCI-MIPS-adds-rt3883-pci-support.patch [deleted file]
target/linux/ramips/patches-3.10/0013-MIPS-ralink-mt7620-add-verbose-ram-info.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0013-PCI-MIPS-adds-mt7620a-pcie-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0014-MIPS-ralink-mt7620-add-spi-clock-definition.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0014-NET-multi-phy-support.patch [deleted file]
target/linux/ramips/patches-3.10/0015-MIPS-ralink-mt7620-add-wdt-clock-definition.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0015-NET-add-of_get_mac_address_mtd.patch [deleted file]
target/linux/ramips/patches-3.10/0016-MIPS-ralink-mt7620-fix-usb-issue-during-frequency-sc.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0016-NET-MIPS-add-ralink-SoC-ethernet-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0017-MIPS-ralink-mt7620-this-SoC-has-ehci-and-ohci-hosts.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0017-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch [deleted file]
target/linux/ramips/patches-3.10/0018-DT-Add-documentation-for-spi-rt2880.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0018-USB-phy-add-ralink-SoC-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0019-SPI-ralink-add-Ralink-SoC-spi-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0019-USB-add-OHCI-EHCI-OF-binding.patch [deleted file]
target/linux/ramips/patches-3.10/0020-MIPS-ralink-update-dts-files.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0020-serial-ralink-adds-mt7620-serial.patch [deleted file]
target/linux/ramips/patches-3.10/0021-MIPS-ralink-add-cpu-frequency-scaling.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0021-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch [deleted file]
target/linux/ramips/patches-3.10/0022-MIPS-add-driver-for-the-built-in-PCI-controller-of-the-RT3883-SoC.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0022-clocksource-MIPS-ralink-add-support-for-systick-time.patch [deleted file]
target/linux/ramips/patches-3.10/0023-GPIO-MIPS-ralink-adds-ralink-gpio-support.patch [deleted file]
target/linux/ramips/patches-3.10/0024-SPI-ralink-add-Ralink-SoC-spi-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0025-watchdog-adds-ralink-wdt.patch [deleted file]
target/linux/ramips/patches-3.10/0026-i2c-MIPS-adds-ralink-I2C-driver.patch [deleted file]
target/linux/ramips/patches-3.10/0027-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch [deleted file]
target/linux/ramips/patches-3.10/0028-reset-MIPS-ralink-add-core-device-reset-wrapper.patch [deleted file]
target/linux/ramips/patches-3.10/0029-owrt-GPIO-add-gpio_export_with_name.patch [deleted file]
target/linux/ramips/patches-3.10/0030-owrt-MIPS-ralink-add-pseudo-pwm-led-trigger-based-on.patch [deleted file]
target/linux/ramips/patches-3.10/0031-owrt-MIPS-add-OWRTDTB-secion.patch [deleted file]
target/linux/ramips/patches-3.10/0032-mtd-fix-cfi-cmdset-0002-erase-status-check.patch [deleted file]
target/linux/ramips/patches-3.10/0033-mtd-cfi-cmdset-0002-force-word-write.patch [deleted file]
target/linux/ramips/patches-3.10/0034-mtd-split-remove-padding.patch [deleted file]
target/linux/ramips/patches-3.10/0035-USB-dwc2.patch [deleted file]
target/linux/ramips/patches-3.10/0100-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0101-MIPS-ralink-add-pinmux-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0102-MIPS-ralink-add-verbose-pmu-info.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0103-MIPS-ralink-adds-a-bootrom-dumper-module.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0104-MIPS-ralink-add-illegal-access-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0105-MIPS-ralink-workaround-DTB-memory-issue.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0106-USB-dwc2.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0107-PCI-MIPS-adds-rt2880-pci-support.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0108-PCI-MIPS-adds-mt7620a-pcie-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0109-NET-multi-phy-support.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0110-NET-add-of_get_mac_address_mtd.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0111-NET-MIPS-add-ralink-SoC-ethernet-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0112-USB-phy-add-ralink-SoC-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0113-USB-add-OHCI-EHCI-OF-binding.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0114-serial-ralink-adds-mt7620-serial.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0115-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0116-i2c-MIPS-adds-ralink-I2C-driver.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0117-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0118-mtd-fix-cfi-cmdset-0002-erase-status-check.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0119-mtd-cfi-cmdset-0002-force-word-write.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0120-spi-introduce-macros-to-set-bits_per_word_mask.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0121-MIPS-ralink-add-rt_sysc_m32-helper.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0200-owrt-GPIO-add-gpio_export_with_name.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0201-owrt-MIPS-ralink-add-pseudo-pwm-led-trigger-based-on.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0202-owrt-USB-adds-dwc_otg.patch [deleted file]
target/linux/ramips/patches-3.10/0203-owrt-MIPS-add-OWRTDTB-secion.patch [new file with mode: 0644]
target/linux/ramips/patches-3.10/0204-owrt-mtd-split-remove-padding.patch [new file with mode: 0644]
target/linux/ramips/rt288x/config-3.10
target/linux/ramips/rt288x/config-3.9 [deleted file]
target/linux/ramips/rt305x/config-3.10
target/linux/ramips/rt305x/config-3.9 [deleted file]
target/linux/ramips/rt3883/config-3.10
target/linux/ramips/rt3883/config-3.9 [deleted file]

index 17596b1..fe54475 100644 (file)
@@ -155,7 +155,7 @@ CONFIG_SOC_MT7620=y
 # CONFIG_SOC_RT3883 is not set
 CONFIG_SPI=y
 CONFIG_SPI_MASTER=y
-CONFIG_SPI_RALINK=y
+CONFIG_SPI_RT2880=y
 CONFIG_SWCONFIG=y
 CONFIG_SYS_HAS_CPU_MIPS32_R1=y
 CONFIG_SYS_HAS_CPU_MIPS32_R2=y
diff --git a/target/linux/ramips/mt7620a/config-3.9 b/target/linux/ramips/mt7620a/config-3.9
deleted file mode 100644 (file)
index de16bf0..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
-CONFIG_ARCH_DISCARD_MEMBLOCK=y
-CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
-CONFIG_ARCH_HAS_RESET_CONTROLLER=y
-CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_REQUIRE_GPIOLIB=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_CEVT_R4K=y
-CONFIG_CLKDEV_LOOKUP=y
-CONFIG_CLKEVT_RT3352=y
-CONFIG_CLKSRC_MMIO=y
-CONFIG_CLKSRC_OF=y
-CONFIG_CLONE_BACKWARDS=y
-CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
-CONFIG_CMDLINE_BOOL=y
-# CONFIG_CMDLINE_OVERRIDE is not set
-CONFIG_CPU_GENERIC_DUMP_TLB=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_CPU_MIPS32=y
-# CONFIG_CPU_MIPS32_R1 is not set
-CONFIG_CPU_MIPS32_R2=y
-CONFIG_CPU_MIPSR2=y
-CONFIG_CPU_R4K_CACHE_TLB=y
-CONFIG_CPU_R4K_FPU=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_CSRC_R4K=y
-CONFIG_DECOMPRESS_LZMA=y
-CONFIG_DMA_NONCOHERENT=y
-# CONFIG_DTB_MT7620A_EVAL is not set
-# CONFIG_DTB_MT7620A_MT7610E_EVAL is not set
-CONFIG_DTB_RT_NONE=y
-CONFIG_DTC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_ATOMIC64=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_GENERIC_GPIO=y
-CONFIG_GENERIC_IO=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_PCI_IOMAP=y
-CONFIG_GENERIC_SMP_IDLE_THREAD=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_DEVRES=y
-CONFIG_GPIO_RALINK=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_HARDWARE_WATCHPOINTS=y
-CONFIG_HAS_DMA=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-CONFIG_HAVE_DMA_API_DEBUG=y
-CONFIG_HAVE_DMA_ATTRS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_HAVE_GENERIC_HARDIRQS=y
-CONFIG_HAVE_IDE=y
-CONFIG_HAVE_MACH_CLKDEV=y
-CONFIG_HAVE_MEMBLOCK=y
-CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_HAVE_NET_DSA=y
-CONFIG_HAVE_OPROFILE=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_HW_HAS_PCI=y
-CONFIG_HW_RANDOM=m
-CONFIG_IMAGE_CMDLINE_HACK=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_IRQCHIP=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_DOMAIN=y
-CONFIG_IRQ_FORCED_THREADING=y
-CONFIG_IRQ_WORK=y
-CONFIG_M25PXX_USE_FAST_READ=y
-CONFIG_MDIO_BOARDINFO=y
-# CONFIG_MII is not set
-CONFIG_MIPS=y
-# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-# CONFIG_MIPS_MACHINE is not set
-CONFIG_MIPS_MT_DISABLED=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_IO_ACCESSORS=y
-CONFIG_MMC_SDHCI_MT7620=y
-# CONFIG_MMC_SDHCI_PCI is not set
-CONFIG_MMC_SDHCI_PLTFM=y
-# CONFIG_MMC_TIFM_SD is not set
-CONFIG_MODULES_USE_ELF_REL=y
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_OF_PARTS=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_UIMAGE_SPLIT=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEED_PER_CPU_KM=y
-CONFIG_NET_RALINK=y
-CONFIG_NET_RALINK_GSW_MT7620=y
-CONFIG_NET_RALINK_MDIO=y
-CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
-CONFIG_OF=y
-CONFIG_OF_ADDRESS=y
-CONFIG_OF_DEVICE=y
-# CONFIG_OF_DISPLAY_TIMING is not set
-CONFIG_OF_EARLY_FLATTREE=y
-CONFIG_OF_FLATTREE=y
-CONFIG_OF_GPIO=y
-CONFIG_OF_IRQ=y
-CONFIG_OF_MDIO=y
-CONFIG_OF_MTD=y
-CONFIG_OF_NET=y
-CONFIG_OF_PCI=y
-CONFIG_OF_PCI_IRQ=y
-# CONFIG_OF_VIDEOMODE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PERF_USE_VMALLOC=y
-CONFIG_PHYLIB=y
-# CONFIG_PREEMPT_RCU is not set
-CONFIG_RALINK=y
-# CONFIG_RALINK_ILL_ACC is not set
-CONFIG_RALINK_USBPHY=y
-CONFIG_RALINK_WDT=y
-# CONFIG_RCU_STALL_COMMON is not set
-CONFIG_RESET_CONTROLLER=y
-# CONFIG_SCSI_DMA is not set
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RT288X=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-CONFIG_SOC_MT7620=y
-# CONFIG_SOC_RT288X is not set
-# CONFIG_SOC_RT305X is not set
-# CONFIG_SOC_RT3883 is not set
-CONFIG_SPI=y
-CONFIG_SPI_MASTER=y
-CONFIG_SPI_RALINK=y
-CONFIG_SWCONFIG=y
-CONFIG_SYS_HAS_CPU_MIPS32_R1=y
-CONFIG_SYS_HAS_CPU_MIPS32_R2=y
-CONFIG_SYS_HAS_EARLY_PRINTK=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
-CONFIG_TICK_CPU_ACCOUNTING=y
-CONFIG_UIDGID_CONVERTED=y
-CONFIG_USB_ARCH_HAS_XHCI=y
-CONFIG_USB_OTG_UTILS=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USE_OF=y
-CONFIG_WATCHDOG_CORE=y
-CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/ramips/patches-3.10/0001-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-3.10/0001-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch
deleted file mode 100644 (file)
index f6ff898..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-From a1f29e15505226c6bc3a714daf91edccfc3a9e13 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 14 Jul 2013 23:08:11 +0200
-Subject: [PATCH 01/33] 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(-)
-
---- a/arch/mips/kernel/cevt-r4k.c
-+++ b/arch/mips/kernel/cevt-r4k.c
-@@ -38,12 +38,6 @@ static int mips_next_event(unsigned long
- #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;
-@@ -90,6 +84,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)
- {
-@@ -215,13 +235,6 @@ int __cpuinit r4k_clockevent_init(void)
- #endif
-       clockevents_register_device(cd);
--      if (cp0_timer_irq_installed)
--              return 0;
--
--      cp0_timer_irq_installed = 1;
--
--      setup_irq(irq, &c0_compare_irqaction);
--
-       return 0;
- }
diff --git a/target/linux/ramips/patches-3.10/0001-MTD-m25p80-allow-loading-mtd-name-from-OF.patch b/target/linux/ramips/patches-3.10/0001-MTD-m25p80-allow-loading-mtd-name-from-OF.patch
new file mode 100644 (file)
index 0000000..b48023d
--- /dev/null
@@ -0,0 +1,39 @@
+From d11f6e47eb748f27ba325bd843cc88bae3ad0e8a Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 29 Jan 2013 21:11:55 +0100
+Subject: [PATCH 01/25] MTD: m25p80: allow loading mtd name from OF
+
+In accordance with the physmap flash we should honour the linux,mtd-name
+property when deciding what name the mtd device has.
+
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mtd/devices/m25p80.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -926,10 +926,13 @@ static int m25p_probe(struct spi_device
+       unsigned                        i;
+       struct mtd_part_parser_data     ppdata;
+       struct device_node __maybe_unused *np = spi->dev.of_node;
++      const char __maybe_unused       *of_mtd_name = NULL;
+ #ifdef CONFIG_MTD_OF_PARTS
+       if (!of_device_is_available(np))
+               return -ENODEV;
++      of_property_read_string(spi->dev.of_node,
++                                      "linux,mtd-name", &of_mtd_name);
+ #endif
+       /* Platform data helps sort out which chip type we have, as
+@@ -1005,6 +1008,8 @@ static int m25p_probe(struct spi_device
+       if (data && data->name)
+               flash->mtd.name = data->name;
++      else if (of_mtd_name)
++              flash->mtd.name = of_mtd_name;
+       else
+               flash->mtd.name = dev_name(&spi->dev);
diff --git a/target/linux/ramips/patches-3.10/0002-MIPS-ralink-add-pinmux-driver.patch b/target/linux/ramips/patches-3.10/0002-MIPS-ralink-add-pinmux-driver.patch
deleted file mode 100644 (file)
index 67dd69d..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-From 9a3055dad80db43aeb22b247512e18e8f06bf54c Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 22 Apr 2013 23:11:42 +0200
-Subject: [PATCH 02/33] MIPS: ralink: add pinmux driver
-
-Add code to setup the pinmux on ralonk SoC. The SoC has a single 32 bit register
-for this functionality with simple on/off bits. Building a full featured pinctrl
-driver would be overkill.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Makefile |    2 +-
- arch/mips/ralink/common.h |    2 ++
- arch/mips/ralink/of.c     |    2 ++
- arch/mips/ralink/pinmux.c |   77 +++++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 82 insertions(+), 1 deletion(-)
- create mode 100644 arch/mips/ralink/pinmux.c
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -6,7 +6,7 @@
- # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
- # Copyright (C) 2013 John Crispin <blogic@openwrt.org>
--obj-y := prom.o of.o reset.o clk.o irq.o
-+obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
---- a/arch/mips/ralink/common.h
-+++ b/arch/mips/ralink/common.h
-@@ -50,4 +50,6 @@ extern void prom_soc_init(struct ralink_
- __iomem void *plat_of_remap_node(const char *node);
-+void ralink_pinmux(void);
-+
- #endif /* _RALINK_COMMON_H__ */
---- a/arch/mips/ralink/of.c
-+++ b/arch/mips/ralink/of.c
-@@ -110,6 +110,8 @@ static int __init plat_of_setup(void)
-       if (of_platform_populate(NULL, of_ids, NULL, NULL))
-               panic("failed to populate DT\n");
-+      ralink_pinmux();
-+
-       return 0;
- }
---- /dev/null
-+++ b/arch/mips/ralink/pinmux.c
-@@ -0,0 +1,92 @@
-+/*
-+ *  This program is free software; you can redistribute it and/or modify it
-+ *  under the terms of the GNU General Public License version 2 as published
-+ *  by the Free Software Foundation.
-+ *
-+ *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/of.h>
-+
-+#include <asm/mach-ralink/ralink_regs.h>
-+
-+#include "common.h"
-+
-+#define SYSC_REG_GPIO_MODE    0x60
-+
-+static int ralink_mux_mask(const char *name, struct ralink_pinmux_grp *grps, u32* mask)
-+{
-+      for (; grps && grps->name; grps++)
-+              if (!strcmp(grps->name, name)) {
-+                      *mask = grps->mask;
-+                      return 0;
-+              }
-+
-+      return -1;
-+}
-+
-+void ralink_pinmux(void)
-+{
-+      const __be32 *wdt;
-+      struct device_node *np;
-+      struct property *prop;
-+      const char *uart, *pci, *pin;
-+      u32 mode = 0;
-+      int m;
-+
-+      np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-sysc");
-+      if (!np)
-+              return;
-+
-+      of_property_for_each_string(np, "ralink,gpiomux", prop, pin) {
-+              if (!ralink_mux_mask(pin, rt_gpio_pinmux.mode, &m)) {
-+                      mode |= m;
-+                      pr_debug("pinmux: registered gpiomux \"%s\"\n", pin);
-+              } else {
-+                      pr_err("pinmux: failed to load \"%s\"\n", pin);
-+              }
-+      }
-+
-+      of_property_for_each_string(np, "ralink,pinmux", prop, pin) {
-+              if (!ralink_mux_mask(pin, rt_gpio_pinmux.mode, &m)) {
-+                      mode &= ~m;
-+                      pr_debug("pinmux: registered pinmux \"%s\"\n", pin);
-+              } else {
-+                      pr_err("pinmux: failed to load group \"%s\"\n", pin);
-+              }
-+      }
-+
-+      of_property_read_string(np, "ralink,uartmux", &uart);
-+      if (uart) {
-+              mode &= ~(rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift);
-+              if (ralink_mux_mask(uart, rt_gpio_pinmux.uart, &m)) {
-+                      pr_err("pinmux: failed to load uartmux \"%s\"\n", uart);
-+                      mode |= rt_gpio_pinmux.uart_mask << rt_gpio_pinmux.uart_shift;
-+              } else {
-+                      mode |= m << rt_gpio_pinmux.uart_shift;
-+                      pr_debug("pinmux: registered uartmux \"%s\"\n", uart);
-+              }
-+      }
-+
-+      wdt = of_get_property(np, "ralink,wdtmux", NULL);
-+      if (wdt && *wdt && rt_gpio_pinmux.wdt_reset)
-+              rt_gpio_pinmux.wdt_reset();
-+
-+      pci = NULL;
-+      if (rt_gpio_pinmux.pci)
-+              of_property_read_string(np, "ralink,pcimux", &pci);
-+
-+      if (pci) {
-+              mode &= ~(rt_gpio_pinmux.pci_mask << rt_gpio_pinmux.pci_shift);
-+              if (ralink_mux_mask(pci, rt_gpio_pinmux.pci, &m)) {
-+                      mode |= rt_gpio_pinmux.pci_mask << rt_gpio_pinmux.pci_shift;
-+                      pr_debug("pinmux: failed to load pcimux \"%s\"\n", pci);
-+              } else {
-+                      mode |= m << rt_gpio_pinmux.pci_shift;
-+                      pr_debug("pinmux: registered pcimux \"%s\"\n", pci);
-+              }
-+      }
-+
-+      rt_sysc_w32(mode, SYSC_REG_GPIO_MODE);
-+}
diff --git a/target/linux/ramips/patches-3.10/0002-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch b/target/linux/ramips/patches-3.10/0002-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch
new file mode 100644 (file)
index 0000000..6b0c143
--- /dev/null
@@ -0,0 +1,105 @@
+From 080f1a0c539180a88066fb004a8c31eefdf74161 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 9 Aug 2013 18:47:27 +0200
+Subject: [PATCH 02/25] reset: Fix compile when reset RESET_CONTROLLER is not
+ selected
+
+Drivers need to protect their reset api calls with #ifdef to avoid compile
+errors.
+
+This patch adds dummy wrappers in the same way that linux/of.h does it.
+
+Cc: linux-kernel@vger.kernel.org
+Cc: Philipp Zabel <p.zabel@pengutronix.de>
+Cc: Gabor Juhos <juhosg@openwrt.org>
+---
+ include/linux/reset-controller.h |   16 ++++++++++++++
+ include/linux/reset.h            |   43 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 59 insertions(+)
+
+--- a/include/linux/reset-controller.h
++++ b/include/linux/reset-controller.h
+@@ -45,7 +45,23 @@ struct reset_controller_dev {
+       unsigned int nr_resets;
+ };
++#if defined(CONFIG_RESET_CONTROLLER)
++
+ int reset_controller_register(struct reset_controller_dev *rcdev);
+ void reset_controller_unregister(struct reset_controller_dev *rcdev);
++#else
++
++static inline int reset_controller_register(struct reset_controller_dev *rcdev)
++{
++      return -ENOSYS;
++}
++
++void reset_controller_unregister(struct reset_controller_dev *rcdev)
++{
++
++}
++
++#endif
++
+ #endif
+--- a/include/linux/reset.h
++++ b/include/linux/reset.h
+@@ -1,9 +1,13 @@
+ #ifndef _LINUX_RESET_H_
+ #define _LINUX_RESET_H_
++#include <linux/err.h>
++
+ struct device;
+ struct reset_control;
++#if defined(CONFIG_RESET_CONTROLLER)
++
+ int reset_control_reset(struct reset_control *rstc);
+ int reset_control_assert(struct reset_control *rstc);
+ int reset_control_deassert(struct reset_control *rstc);
+@@ -14,4 +18,43 @@ struct reset_control *devm_reset_control
+ int device_reset(struct device *dev);
++#else /* CONFIG_RESET_CONTROLLER */
++
++static inline int reset_control_reset(struct reset_control *rstc)
++{
++      return -ENOSYS;
++}
++
++static inline int reset_control_assert(struct reset_control *rstc)
++{
++      return -ENOSYS;
++}
++
++static inline int reset_control_deassert(struct reset_control *rstc)
++{
++      return -ENOSYS;
++}
++
++static inline struct reset_control *reset_control_get(struct device *dev, const char *id)
++{
++      return ERR_PTR(-ENOSYS);
++}
++
++static inline void reset_control_put(struct reset_control *rstc)
++{
++
++}
++
++static inline struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
++{
++      return ERR_PTR(-ENOSYS);
++}
++
++static inline int device_reset(struct device *dev)
++{
++      return -ENOSYS;
++}
++
++#endif
++
+ #endif
diff --git a/target/linux/ramips/patches-3.10/0003-DT-Add-documentation-for-rt2880-wdt.patch b/target/linux/ramips/patches-3.10/0003-DT-Add-documentation-for-rt2880-wdt.patch
new file mode 100644 (file)
index 0000000..ea00d3f
--- /dev/null
@@ -0,0 +1,39 @@
+From 8b87087423057f8a06423702f3035634d6e8cd73 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 19:57:20 +0200
+Subject: [PATCH 03/25] DT: Add documentation for rt2880-wdt
+
+This document describes the binding of the watchdog core found ralink wireless
+SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-watchdog@vger.kernel.org
+Cc: linux-mips@linux-mips.org
+Cc: devicetree-discuss@lists.ozlabs.org
+---
+ .../devicetree/bindings/watchdog/rt2880-wdt.txt     |   19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/watchdog/rt2880-wdt.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/watchdog/rt2880-wdt.txt
+@@ -0,0 +1,19 @@
++Ralink Watchdog Timers
++
++Required properties :
++- compatible: must be "ralink,rt2880-wdt"
++- reg: physical base address of the controller and length of the register range
++
++Optional properties :
++- interrupt-parent: phandle to the INTC device node
++- interrupts: Specify the INTC interrupt number
++
++Example:
++
++      watchdog@120 {
++              compatible = "ralink,rt2880-wdt";
++              reg = <0x120 0x10>;
++
++              interrupt-parent = <&intc>;
++              interrupts = <1>;
++      };
diff --git a/target/linux/ramips/patches-3.10/0003-MIPS-ralink-add-support-for-periodic-timer-irq.patch b/target/linux/ramips/patches-3.10/0003-MIPS-ralink-add-support-for-periodic-timer-irq.patch
deleted file mode 100644 (file)
index 5436750..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-From 298e990777004a6a72b1c95af5a2cd984c56135d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 23 Mar 2013 19:44:41 +0100
-Subject: [PATCH 03/33] MIPS: ralink: add support for periodic timer irq
-
-Adds a driver for the periodic timer found on Ralink SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/ralink/Makefile |    2 +-
- arch/mips/ralink/timer.c  |  192 +++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 193 insertions(+), 1 deletion(-)
- create mode 100644 arch/mips/ralink/timer.c
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -6,7 +6,7 @@
- # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
- # Copyright (C) 2013 John Crispin <blogic@openwrt.org>
--obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o
-+obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
---- /dev/null
-+++ b/arch/mips/ralink/timer.c
-@@ -0,0 +1,192 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ *
-+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/timer.h>
-+#include <linux/of_gpio.h>
-+#include <linux/clk.h>
-+
-+#include <asm/mach-ralink/ralink_regs.h>
-+
-+#define TIMER_REG_TMRSTAT             0x00
-+#define TIMER_REG_TMR0LOAD            0x10
-+#define TIMER_REG_TMR0CTL             0x18
-+
-+#define TMRSTAT_TMR0INT                       BIT(0)
-+
-+#define TMR0CTL_ENABLE                        BIT(7)
-+#define TMR0CTL_MODE_PERIODIC         BIT(4)
-+#define TMR0CTL_PRESCALER             1
-+#define TMR0CTL_PRESCALE_VAL          (0xf - TMR0CTL_PRESCALER)
-+#define TMR0CTL_PRESCALE_DIV          (65536 / BIT(TMR0CTL_PRESCALER))
-+
-+struct rt_timer {
-+      struct device   *dev;
-+      void __iomem    *membase;
-+      int             irq;
-+      unsigned long   timer_freq;
-+      unsigned long   timer_div;
-+};
-+
-+static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val)
-+{
-+      __raw_writel(val, rt->membase + reg);
-+}
-+
-+static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg)
-+{
-+      return __raw_readl(rt->membase + reg);
-+}
-+
-+static irqreturn_t rt_timer_irq(int irq, void *_rt)
-+{
-+      struct rt_timer *rt =  (struct rt_timer *) _rt;
-+
-+      rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
-+      rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+
-+static int rt_timer_request(struct rt_timer *rt)
-+{
-+      int err = request_irq(rt->irq, rt_timer_irq, IRQF_DISABLED,
-+                                              dev_name(rt->dev), rt);
-+      if (err) {
-+              dev_err(rt->dev, "failed to request irq\n");
-+      } else {
-+              u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL;
-+              rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
-+      }
-+      return err;
-+}
-+
-+static void rt_timer_free(struct rt_timer *rt)
-+{
-+      free_irq(rt->irq, rt);
-+}
-+
-+static int rt_timer_config(struct rt_timer *rt, unsigned long divisor)
-+{
-+      if (rt->timer_freq < divisor)
-+              rt->timer_div = rt->timer_freq;
-+      else
-+              rt->timer_div = divisor;
-+
-+      rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
-+
-+      return 0;
-+}
-+
-+static int rt_timer_enable(struct rt_timer *rt)
-+{
-+      u32 t;
-+
-+      rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
-+
-+      t = rt_timer_r32(rt, TIMER_REG_TMR0CTL);
-+      t |= TMR0CTL_ENABLE;
-+      rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
-+
-+      return 0;
-+}
-+
-+static void rt_timer_disable(struct rt_timer *rt)
-+{
-+      u32 t;
-+
-+      t = rt_timer_r32(rt, TIMER_REG_TMR0CTL);
-+      t &= ~TMR0CTL_ENABLE;
-+      rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
-+}
-+
-+static int rt_timer_probe(struct platform_device *pdev)
-+{
-+      struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      struct rt_timer *rt;
-+      struct clk *clk;
-+
-+      if (!res) {
-+              dev_err(&pdev->dev, "no memory resource found\n");
-+              return -EINVAL;
-+      }
-+
-+      rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL);
-+      if (!rt) {
-+              dev_err(&pdev->dev, "failed to allocate memory\n");
-+              return -ENOMEM;
-+      }
-+
-+      rt->irq = platform_get_irq(pdev, 0);
-+      if (!rt->irq) {
-+              dev_err(&pdev->dev, "failed to load irq\n");
-+              return -ENOENT;
-+      }
-+
-+      rt->membase = devm_request_and_ioremap(&pdev->dev, res);
-+      if (!rt->membase) {
-+              dev_err(&pdev->dev, "failed to ioremap\n");
-+              return -ENOMEM;
-+      }
-+
-+      clk = devm_clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(clk)) {
-+              dev_err(&pdev->dev, "failed get clock rate\n");
-+              return PTR_ERR(clk);
-+      }
-+
-+      rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV;
-+      if (!rt->timer_freq)
-+              return -EINVAL;
-+
-+      rt->dev = &pdev->dev;
-+      platform_set_drvdata(pdev, rt);
-+
-+      rt_timer_request(rt);
-+      rt_timer_config(rt, 2);
-+      rt_timer_enable(rt);
-+
-+      dev_info(&pdev->dev, "maximum frequncy is %luHz\n", rt->timer_freq);
-+
-+      return 0;
-+}
-+
-+static int rt_timer_remove(struct platform_device *pdev)
-+{
-+      struct rt_timer *rt = platform_get_drvdata(pdev);
-+
-+      rt_timer_disable(rt);
-+      rt_timer_free(rt);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id rt_timer_match[] = {
-+      { .compatible = "ralink,rt2880-timer" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, rt_timer_match);
-+
-+static struct platform_driver rt_timer_driver = {
-+      .probe = rt_timer_probe,
-+      .remove = rt_timer_remove,
-+      .driver = {
-+              .name           = "rt-timer",
-+              .owner          = THIS_MODULE,
-+              .of_match_table = rt_timer_match
-+      },
-+};
-+
-+module_platform_driver(rt_timer_driver);
-+
-+MODULE_DESCRIPTION("Ralink RT2880 timer");
-+MODULE_AUTHOR("John Crispin <blogic@openwrt.org");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/ramips/patches-3.10/0004-MIPS-ralink-add-rt_sysc_m32-helper.patch b/target/linux/ramips/patches-3.10/0004-MIPS-ralink-add-rt_sysc_m32-helper.patch
deleted file mode 100644 (file)
index 915c5be..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 3af962f91035ae4500e63c758c49f1c067bdae09 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 19 May 2013 00:42:23 +0200
-Subject: [PATCH 04/33] 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(+)
-
---- 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 r
-       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);
diff --git a/target/linux/ramips/patches-3.10/0004-watchdog-MIPS-add-ralink-watchdog-driver.patch b/target/linux/ramips/patches-3.10/0004-watchdog-MIPS-add-ralink-watchdog-driver.patch
new file mode 100644 (file)
index 0000000..8f67315
--- /dev/null
@@ -0,0 +1,254 @@
+From 78046b68c1fc757162e32c83f59c3a94e794bf2e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 13:51:58 +0200
+Subject: [PATCH 04/25] watchdog: MIPS: add ralink watchdog driver
+
+Add a driver for the watchdog timer found on Ralink SoC
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-watchdog@vger.kernel.org
+Cc: linux-mips@linux-mips.org
+---
+ drivers/watchdog/Kconfig      |    7 ++
+ drivers/watchdog/Makefile     |    1 +
+ drivers/watchdog/rt2880_wdt.c |  208 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 216 insertions(+)
+ create mode 100644 drivers/watchdog/rt2880_wdt.c
+
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -1104,6 +1104,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
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -134,6 +134,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
+--- /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.max_timeout = (0xfffful / rt288x_wdt_freq);
++      rt288x_wdt_dev.timeout = rt288x_wdt_dev.max_timeout;
++
++      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);
diff --git a/target/linux/ramips/patches-3.10/0005-DT-Add-documentation-for-gpio-ralink.patch b/target/linux/ramips/patches-3.10/0005-DT-Add-documentation-for-gpio-ralink.patch
new file mode 100644 (file)
index 0000000..a6a6b69
--- /dev/null
@@ -0,0 +1,59 @@
+From ad68c2865b360f1b637432b4cbcaaf101d2687b9 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 19:45:30 +0200
+Subject: [PATCH 05/25] DT: Add documentation for gpio-ralink
+
+Describe gpio-ralink binding.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: devicetree@vger.kernel.org
+Cc: linux-gpio@vger.kernel.org
+---
+ .../devicetree/bindings/gpio/gpio-ralink.txt       |   40 ++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt
+@@ -0,0 +1,40 @@
++Ralink SoC GPIO controller bindings
++
++Required properties:
++- compatible:
++  - "ralink,rt2880-gpio" for Ralink controllers
++- #gpio-cells : Should be two.
++  - first cell is the pin number
++  - second cell is used to specify optional parameters (unused)
++- gpio-controller : Marks the device node as a GPIO controller
++- reg : Physical base address and length of the controller's registers
++- interrupt-parent: phandle to the INTC device node
++- interrupts : Specify the INTC interrupt number
++- ralink,num-gpios : Specify the number of GPIOs
++- ralink,register-map : The register layout depends on the GPIO bank and actual
++              SoC type. Register offsets need to be in this order.
++              [ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ]
++
++Optional properties:
++- ralink,gpio-base : Specify the GPIO chips base number
++
++Example:
++
++      gpio0: gpio@600 {
++              compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio";
++
++              #gpio-cells = <2>;
++              gpio-controller;
++
++              reg = <0x600 0x34>;
++
++              interrupt-parent = <&intc>;
++              interrupts = <6>;
++
++              ralink,gpio-base = <0>;
++              ralink,num-gpios = <24>;
++              ralink,register-map = [ 00 04 08 0c
++                              20 24 28 2c
++                              30 34 ];
++
++      };
diff --git a/target/linux/ramips/patches-3.10/0005-MIPS-ralink-make-mt7620-ram-detect-verbose.patch b/target/linux/ramips/patches-3.10/0005-MIPS-ralink-make-mt7620-ram-detect-verbose.patch
deleted file mode 100644 (file)
index c0249a2..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 3f6b346e1dd83c4f43d94aefa0520ffdfafd5f0b Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 20 May 2013 20:30:11 +0200
-Subject: [PATCH 05/33] 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(+)
-
---- a/arch/mips/ralink/mt7620.c
-+++ b/arch/mips/ralink/mt7620.c
-@@ -214,16 +214,19 @@ void prom_soc_init(struct ralink_soc_inf
-       switch (dram_type) {
-       case SYSCFG0_DRAM_TYPE_SDRAM:
-+              pr_info("Board has SDRAM\n");
-               soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN;
-               soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX;
-               break;
-       case SYSCFG0_DRAM_TYPE_DDR1:
-+              pr_info("Board has DDR1\n");
-               soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN;
-               soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX;
-               break;
-       case SYSCFG0_DRAM_TYPE_DDR2:
-+              pr_info("Board has DDR2\n");
-               soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN;
-               soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX;
-               break;
diff --git a/target/linux/ramips/patches-3.10/0006-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch b/target/linux/ramips/patches-3.10/0006-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch
new file mode 100644 (file)
index 0000000..dd1aca1
--- /dev/null
@@ -0,0 +1,423 @@
+From 55833373cf527dc94bc6c63b68d0f39591667a5d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 14:00:25 +0200
+Subject: [PATCH 06/25] GPIO: MIPS: ralink: add gpio driver for ralink SoC
+
+Add gpio driver for Ralink SoC. This driver makes the gpio core on
+RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: linux-gpio@vger.kernel.org
+---
+ arch/mips/Kconfig                        |    1 +
+ arch/mips/include/asm/mach-ralink/gpio.h |   24 +++
+ drivers/gpio/Kconfig                     |    6 +
+ drivers/gpio/Makefile                    |    1 +
+ drivers/gpio/gpio-ralink.c               |  337 ++++++++++++++++++++++++++++++
+ 5 files changed, 369 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h
+ create mode 100644 drivers/gpio/gpio-ralink.c
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -443,6 +443,7 @@ config RALINK
+       select SYS_HAS_EARLY_PRINTK
+       select HAVE_MACH_CLKDEV
+       select CLKDEV_LOOKUP
++      select ARCH_REQUIRE_GPIOLIB
+ config SGI_IP22
+       bool "SGI IP22 (Indy/Indigo2)"
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ralink/gpio.h
+@@ -0,0 +1,24 @@
++/*
++ *  Ralink SoC GPIO API support
++ *
++ *  Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
++ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify it
++ *  under the terms of the GNU General Public License version 2 as published
++ *  by the Free Software Foundation.
++ *
++ */
++
++#ifndef __ASM_MACH_RALINK_GPIO_H
++#define __ASM_MACH_RALINK_GPIO_H
++
++#define ARCH_NR_GPIOS 128
++#include <asm-generic/gpio.h>
++
++#define gpio_get_value        __gpio_get_value
++#define gpio_set_value        __gpio_set_value
++#define gpio_cansleep __gpio_cansleep
++#define gpio_to_irq   __gpio_to_irq
++
++#endif /* __ASM_MACH_RALINK_GPIO_H */
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -209,6 +209,12 @@ config GPIO_RCAR
+       help
+         Say yes here to support GPIO on Renesas R-Car SoCs.
++config GPIO_RALINK
++      bool "Ralink GPIO Support"
++      depends on RALINK
++      help
++        Say yes here to support the Ralink SoC GPIO device
++
+ config GPIO_SPEAR_SPICS
+       bool "ST SPEAr13xx SPI Chip Select as GPIO support"
+       depends on PLAT_SPEAR
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -56,6 +56,7 @@ obj-$(CONFIG_GPIO_PCF857X)   += gpio-pcf85
+ obj-$(CONFIG_GPIO_PCH)                += gpio-pch.o
+ obj-$(CONFIG_GPIO_PL061)      += gpio-pl061.o
+ obj-$(CONFIG_GPIO_PXA)                += gpio-pxa.o
++obj-$(CONFIG_GPIO_RALINK)     += gpio-ralink.o
+ obj-$(CONFIG_GPIO_RC5T583)    += gpio-rc5t583.o
+ obj-$(CONFIG_GPIO_RDC321X)    += gpio-rdc321x.o
+ obj-$(CONFIG_GPIO_RCAR)               += gpio-rcar.o
+--- /dev/null
++++ b/drivers/gpio/gpio-ralink.c
+@@ -0,0 +1,337 @@
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++#include <linux/spinlock.h>
++#include <linux/platform_device.h>
++#include <linux/of_irq.h>
++#include <linux/irqdomain.h>
++#include <linux/interrupt.h>
++
++enum ralink_gpio_reg {
++      GPIO_REG_INT = 0,
++      GPIO_REG_EDGE,
++      GPIO_REG_RENA,
++      GPIO_REG_FENA,
++      GPIO_REG_DATA,
++      GPIO_REG_DIR,
++      GPIO_REG_POL,
++      GPIO_REG_SET,
++      GPIO_REG_RESET,
++      GPIO_REG_TOGGLE,
++      GPIO_REG_MAX
++};
++
++struct ralink_gpio_chip {
++      struct gpio_chip chip;
++      u8 regs[GPIO_REG_MAX];
++
++      spinlock_t lock;
++      void __iomem *membase;
++      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;
++}
++
++static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val)
++{
++      iowrite32(val, rg->membase + rg->regs[reg]);
++}
++
++static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg)
++{
++      return ioread32(rg->membase + rg->regs[reg]);
++}
++
++static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++      struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++
++      rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset));
++}
++
++static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++      struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++
++      return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset));
++}
++
++static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++      struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++      unsigned long flags;
++      u32 t;
++
++      spin_lock_irqsave(&rg->lock, flags);
++      t = rt_gpio_r32(rg, GPIO_REG_DIR);
++      t &= ~BIT(offset);
++      rt_gpio_w32(rg, GPIO_REG_DIR, t);
++      spin_unlock_irqrestore(&rg->lock, flags);
++
++      return 0;
++}
++
++static int ralink_gpio_direction_output(struct gpio_chip *chip,
++                                      unsigned offset, int value)
++{
++      struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++      unsigned long flags;
++      u32 t;
++
++      spin_lock_irqsave(&rg->lock, flags);
++      ralink_gpio_set(chip, offset, value);
++      t = rt_gpio_r32(rg, GPIO_REG_DIR);
++      t |= BIT(offset);
++      rt_gpio_w32(rg, GPIO_REG_DIR, t);
++      spin_unlock_irqrestore(&rg->lock, flags);
++
++      return 0;
++}
++
++static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
++{
++      struct ralink_gpio_chip *rg = to_ralink_gpio(chip);
++
++      if (rg->irq < 1)
++              return -1;
++
++      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;
++              unsigned long pending;
++              int bit;
++
++              rg = (struct ralink_gpio_chip *) domain->host_data;
++              pending = rt_gpio_r32(rg, GPIO_REG_INT);
++
++              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;
++      unsigned long flags;
++      u32 val;
++
++      rg = (struct ralink_gpio_chip *) d->domain->host_data;
++      val = rt_gpio_r32(rg, GPIO_REG_RENA);
++
++      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;
++      unsigned long flags;
++      u32 val;
++
++      rg = (struct ralink_gpio_chip *) d->domain->host_data;
++      val = rt_gpio_r32(rg, GPIO_REG_RENA);
++
++      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;
++      u32 mask = BIT(d->hwirq);
++
++      rg = (struct ralink_gpio_chip *) d->domain->host_data;
++
++      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 *rg;
++      const __be32 *ngpio, *gpiobase;
++
++      if (!res) {
++              dev_err(&pdev->dev, "failed to find resource\n");
++              return -ENOMEM;
++      }
++
++      rg = devm_kzalloc(&pdev->dev,
++                      sizeof(struct ralink_gpio_chip), GFP_KERNEL);
++      if (!rg)
++              return -ENOMEM;
++
++      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",
++                      rg->regs, GPIO_REG_MAX)) {
++              dev_err(&pdev->dev, "failed to read register definition\n");
++              return -EINVAL;
++      }
++
++      ngpio = of_get_property(np, "ralink,num-gpios", NULL);
++      if (!ngpio) {
++              dev_err(&pdev->dev, "failed to read number of pins\n");
++              return -EINVAL;
++      }
++
++      gpiobase = of_get_property(np, "ralink,gpio-base", NULL);
++      if (gpiobase)
++              rg->chip.base = be32_to_cpu(*gpiobase);
++      else
++              rg->chip.base = -1;
++
++      spin_lock_init(&rg->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(rg, GPIO_REG_POL, 0);
++
++      dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio);
++
++      ralink_gpio_irq_init(np, rg);
++
++      return gpiochip_add(&rg->chip);
++}
++
++static const struct of_device_id ralink_gpio_match[] = {
++      { .compatible = "ralink,rt2880-gpio" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, ralink_gpio_match);
++
++static struct platform_driver ralink_gpio_driver = {
++      .probe = ralink_gpio_probe,
++      .driver = {
++              .name = "rt2880_gpio",
++              .owner = THIS_MODULE,
++              .of_match_table = ralink_gpio_match,
++      },
++};
++
++static int __init ralink_gpio_init(void)
++{
++      return platform_driver_register(&ralink_gpio_driver);
++}
++
++subsys_initcall(ralink_gpio_init);
diff --git a/target/linux/ramips/patches-3.10/0006-MIPS-ralink-add-verbose-pmu-info.patch b/target/linux/ramips/patches-3.10/0006-MIPS-ralink-add-verbose-pmu-info.patch
deleted file mode 100644 (file)
index 6349bd3..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From 74339d6eab7a37f7c629b737bf686d30e5014ce2 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 20 May 2013 20:57:09 +0200
-Subject: [PATCH 06/33] 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(+)
-
---- 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_inf
-       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_inf
-               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"));
- }
diff --git a/target/linux/ramips/patches-3.10/0007-MIPS-ralink-adds-a-bootrom-dumper-module.patch b/target/linux/ramips/patches-3.10/0007-MIPS-ralink-adds-a-bootrom-dumper-module.patch
deleted file mode 100644 (file)
index 2b439c6..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-From 71409a190a0c8e3597cae7d46321742e29d8994b Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 21 May 2013 15:50:31 +0200
-Subject: [PATCH 07/33] 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
-
---- 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/
---- /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);
diff --git a/target/linux/ramips/patches-3.10/0007-serial-MIPS-lantiq-add-clk_enable-call-to-driver.patch b/target/linux/ramips/patches-3.10/0007-serial-MIPS-lantiq-add-clk_enable-call-to-driver.patch
new file mode 100644 (file)
index 0000000..cf843ad
--- /dev/null
@@ -0,0 +1,25 @@
+From 0b78522f6e136fa5901e72cdbf4a44693d100826 Mon Sep 17 00:00:00 2001
+From: Thomas Langer <thomas.langer@lantiq.com>
+Date: Sun, 28 Jul 2013 14:44:44 +0200
+Subject: [PATCH 07/25] serial: MIPS: lantiq: add clk_enable() call to driver
+
+Enable the clock if one is present when setting up the console.
+
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Acked-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/tty/serial/lantiq.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/tty/serial/lantiq.c
++++ b/drivers/tty/serial/lantiq.c
+@@ -636,6 +636,9 @@ lqasc_console_setup(struct console *co,
+       port = &ltq_port->port;
++      if (!IS_ERR(ltq_port->clk))
++              clk_enable(ltq_port->clk);
++
+       port->uartclk = clk_get_rate(ltq_port->fpiclk);
+       if (options)
diff --git a/target/linux/ramips/patches-3.10/0008-MIPS-ralink-add-illegal-access-driver.patch b/target/linux/ramips/patches-3.10/0008-MIPS-ralink-add-illegal-access-driver.patch
deleted file mode 100644 (file)
index e3e5823..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-From 46446fcfc6e823005ebe71357b5995524e75542c Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 16 May 2013 23:28:23 +0200
-Subject: [PATCH 08/33] 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, 89 insertions(+)
- create mode 100644 arch/mips/ralink/ill_acc.c
-
---- a/arch/mips/ralink/Makefile
-+++ b/arch/mips/ralink/Makefile
-@@ -8,6 +8,8 @@
- obj-y := prom.o of.o reset.o clk.o irq.o pinmux.o timer.o
-+obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o
-+
- obj-$(CONFIG_SOC_RT288X) += rt288x.o
- obj-$(CONFIG_SOC_RT305X) += rt305x.o
- obj-$(CONFIG_SOC_RT3883) += rt3883.o
---- /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);
diff --git a/target/linux/ramips/patches-3.10/0008-serial-MIPS-lantiq-fix-clock-error-check.patch b/target/linux/ramips/patches-3.10/0008-serial-MIPS-lantiq-fix-clock-error-check.patch
new file mode 100644 (file)
index 0000000..9337942
--- /dev/null
@@ -0,0 +1,32 @@
+From d94da02421c14fa9295feb218cd45fc01d0f470b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Aug 2013 17:19:42 +0200
+Subject: [PATCH 08/25] serial: MIPS: lantiq: fix clock error check
+
+The clk should be checked with the proper IS_ERR() api before accessing it.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/tty/serial/lantiq.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/serial/lantiq.c
++++ b/drivers/tty/serial/lantiq.c
+@@ -318,7 +318,7 @@ lqasc_startup(struct uart_port *port)
+       struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+       int retval;
+-      if (ltq_port->clk)
++      if (!IS_ERR(ltq_port->clk))
+               clk_enable(ltq_port->clk);
+       port->uartclk = clk_get_rate(ltq_port->fpiclk);
+@@ -386,7 +386,7 @@ lqasc_shutdown(struct uart_port *port)
+               port->membase + LTQ_ASC_RXFCON);
+       ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
+               port->membase + LTQ_ASC_TXFCON);
+-      if (ltq_port->clk)
++      if (!IS_ERR(ltq_port->clk))
+               clk_disable(ltq_port->clk);
+ }
diff --git a/target/linux/ramips/patches-3.10/0009-MIPS-ralink-add-support-for-reset-controller-API.patch b/target/linux/ramips/patches-3.10/0009-MIPS-ralink-add-support-for-reset-controller-API.patch
new file mode 100644 (file)
index 0000000..d0f7f20
--- /dev/null
@@ -0,0 +1,126 @@
+From 4e694014a11a407e309f62c7daade545ba71dcf1 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 13:54:22 +0200
+Subject: [PATCH 09/25] MIPS: ralink: add support for reset-controller API
+
+Add a helper for reseting different devices on the SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/Kconfig         |    1 +
+ arch/mips/ralink/common.h |    2 ++
+ arch/mips/ralink/of.c     |    3 +++
+ arch/mips/ralink/reset.c  |   62 +++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 68 insertions(+)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -373,6 +373,7 @@ config MACH_VR41XX
+       select CSRC_R4K
+       select SYS_HAS_CPU_VR41XX
+       select ARCH_REQUIRE_GPIOLIB
++      select ARCH_HAS_RESET_CONTROLLER
+ config NXP_STB220
+       bool "NXP STB220 board"
+--- a/arch/mips/ralink/common.h
++++ b/arch/mips/ralink/common.h
+@@ -46,6 +46,8 @@ extern void ralink_of_remap(void);
+ extern void ralink_clk_init(void);
+ extern void ralink_clk_add(const char *dev, unsigned long rate);
++extern void ralink_rst_init(void);
++
+ extern void prom_soc_init(struct ralink_soc_info *soc_info);
+ __iomem void *plat_of_remap_node(const char *node);
+--- a/arch/mips/ralink/of.c
++++ b/arch/mips/ralink/of.c
+@@ -110,6 +110,9 @@ static int __init plat_of_setup(void)
+       if (of_platform_populate(NULL, of_ids, NULL, NULL))
+               panic("failed to populate DT\n");
++      /* make sure ithat the reset controller is setup early */
++      ralink_rst_init();
++
+       return 0;
+ }
+--- a/arch/mips/ralink/reset.c
++++ b/arch/mips/ralink/reset.c
+@@ -10,6 +10,8 @@
+ #include <linux/pm.h>
+ #include <linux/io.h>
++#include <linux/of.h>
++#include <linux/reset-controller.h>
+ #include <asm/reboot.h>
+@@ -19,6 +21,66 @@
+ #define SYSC_REG_RESET_CTRL     0x034
+ #define RSTCTL_RESET_SYSTEM     BIT(0)
++static int ralink_assert_device(struct reset_controller_dev *rcdev,
++                              unsigned long id)
++{
++      u32 val;
++
++      if (id < 8)
++              return -1;
++
++      val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
++      val |= BIT(id);
++      rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
++
++      return 0;
++}
++
++static int ralink_deassert_device(struct reset_controller_dev *rcdev,
++                                unsigned long id)
++{
++      u32 val;
++
++      if (id < 8)
++              return -1;
++
++      val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
++      val &= ~BIT(id);
++      rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
++
++      return 0;
++}
++
++static int ralink_reset_device(struct reset_controller_dev *rcdev,
++                             unsigned long id)
++{
++      ralink_assert_device(rcdev, id);
++      return ralink_deassert_device(rcdev, id);
++}
++
++static struct reset_control_ops reset_ops = {
++      .reset = ralink_reset_device,
++      .assert = ralink_assert_device,
++      .deassert = ralink_deassert_device,
++};
++
++static struct reset_controller_dev reset_dev = {
++      .ops                    = &reset_ops,
++      .owner                  = THIS_MODULE,
++      .nr_resets              = 32,
++      .of_reset_n_cells       = 1,
++};
++
++void ralink_rst_init(void)
++{
++      reset_dev.of_node = of_find_compatible_node(NULL, NULL,
++                                              "ralink,rt2880-reset");
++      if (!reset_dev.of_node)
++              pr_err("Failed to find reset controller node");
++      else
++              reset_controller_register(&reset_dev);
++}
++
+ static void ralink_restart(char *command)
+ {
+       local_irq_disable();
diff --git a/target/linux/ramips/patches-3.10/0009-MIPS-ralink-workaround-DTB-memory-issue.patch b/target/linux/ramips/patches-3.10/0009-MIPS-ralink-workaround-DTB-memory-issue.patch
deleted file mode 100644 (file)
index 662b356..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 070a389ae536a75b9184784f625949c215c533b6 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 23 May 2013 18:50:56 +0200
-Subject: [PATCH 09/33] 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(-)
-
---- 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)
diff --git a/target/linux/ramips/patches-3.10/0010-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch b/target/linux/ramips/patches-3.10/0010-MIPS-ralink-add-spi-clock-definition-to-mt7620a.patch
deleted file mode 100644 (file)
index f768942..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-From 5340673ba16e3c8c9c1406d5ab84aca82e83e2ce Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 23 May 2013 18:46:25 +0200
-Subject: [PATCH 10/33] 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(+)
-
---- 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);
- }
diff --git a/target/linux/ramips/patches-3.10/0010-MIPS-ralink-add-support-for-periodic-timer-irq.patch b/target/linux/ramips/patches-3.10/0010-MIPS-ralink-add-support-for-periodic-timer-irq.patch
new file mode 100644 (file)
index 0000000..49e64fd
--- /dev/null
@@ -0,0 +1,213 @@
+From 1cd8a1dc8e942bd130dc40ff801f37ad296495e3 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 13:41:04 +0200
+Subject: [PATCH 10/25] MIPS: ralink: add support for periodic timer irq
+
+Adds a driver for the periodic timer found on Ralink SoC.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Makefile |    2 +-
+ arch/mips/ralink/timer.c  |  185 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 186 insertions(+), 1 deletion(-)
+ create mode 100644 arch/mips/ralink/timer.c
+
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -6,7 +6,7 @@
+ # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ # Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+-obj-y := prom.o of.o reset.o clk.o irq.o
++obj-y := prom.o of.o reset.o clk.o irq.o timer.o
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+--- /dev/null
++++ b/arch/mips/ralink/timer.c
+@@ -0,0 +1,185 @@
++/*
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
++*/
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/of_gpio.h>
++#include <linux/clk.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define TIMER_REG_TMRSTAT             0x00
++#define TIMER_REG_TMR0LOAD            0x10
++#define TIMER_REG_TMR0CTL             0x18
++
++#define TMRSTAT_TMR0INT                       BIT(0)
++
++#define TMR0CTL_ENABLE                        BIT(7)
++#define TMR0CTL_MODE_PERIODIC         BIT(4)
++#define TMR0CTL_PRESCALER             1
++#define TMR0CTL_PRESCALE_VAL          (0xf - TMR0CTL_PRESCALER)
++#define TMR0CTL_PRESCALE_DIV          (65536 / BIT(TMR0CTL_PRESCALER))
++
++struct rt_timer {
++      struct device   *dev;
++      void __iomem    *membase;
++      int             irq;
++      unsigned long   timer_freq;
++      unsigned long   timer_div;
++};
++
++static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val)
++{
++      __raw_writel(val, rt->membase + reg);
++}
++
++static inline u32 rt_timer_r32(struct rt_timer *rt, u8 reg)
++{
++      return __raw_readl(rt->membase + reg);
++}
++
++static irqreturn_t rt_timer_irq(int irq, void *_rt)
++{
++      struct rt_timer *rt =  (struct rt_timer *) _rt;
++
++      rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
++      rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT);
++
++      return IRQ_HANDLED;
++}
++
++
++static int rt_timer_request(struct rt_timer *rt)
++{
++      int err = request_irq(rt->irq, rt_timer_irq, IRQF_DISABLED,
++                                              dev_name(rt->dev), rt);
++      if (err) {
++              dev_err(rt->dev, "failed to request irq\n");
++      } else {
++              u32 t = TMR0CTL_MODE_PERIODIC | TMR0CTL_PRESCALE_VAL;
++              rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
++      }
++      return err;
++}
++
++static void rt_timer_free(struct rt_timer *rt)
++{
++      free_irq(rt->irq, rt);
++}
++
++static int rt_timer_config(struct rt_timer *rt, unsigned long divisor)
++{
++      if (rt->timer_freq < divisor)
++              rt->timer_div = rt->timer_freq;
++      else
++              rt->timer_div = divisor;
++
++      rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
++
++      return 0;
++}
++
++static int rt_timer_enable(struct rt_timer *rt)
++{
++      u32 t;
++
++      rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div);
++
++      t = rt_timer_r32(rt, TIMER_REG_TMR0CTL);
++      t |= TMR0CTL_ENABLE;
++      rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
++
++      return 0;
++}
++
++static void rt_timer_disable(struct rt_timer *rt)
++{
++      u32 t;
++
++      t = rt_timer_r32(rt, TIMER_REG_TMR0CTL);
++      t &= ~TMR0CTL_ENABLE;
++      rt_timer_w32(rt, TIMER_REG_TMR0CTL, t);
++}
++
++static int rt_timer_probe(struct platform_device *pdev)
++{
++      struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      struct rt_timer *rt;
++      struct clk *clk;
++
++      rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL);
++      if (!rt) {
++              dev_err(&pdev->dev, "failed to allocate memory\n");
++              return -ENOMEM;
++      }
++
++      rt->irq = platform_get_irq(pdev, 0);
++      if (!rt->irq) {
++              dev_err(&pdev->dev, "failed to load irq\n");
++              return -ENOENT;
++      }
++
++      rt->membase = devm_request_and_ioremap(&pdev->dev, res);
++      if (IS_ERR(rt->membase))
++              return PTR_ERR(rt->membase);
++
++      clk = devm_clk_get(&pdev->dev, NULL);
++      if (IS_ERR(clk)) {
++              dev_err(&pdev->dev, "failed get clock rate\n");
++              return PTR_ERR(clk);
++      }
++
++      rt->timer_freq = clk_get_rate(clk) / TMR0CTL_PRESCALE_DIV;
++      if (!rt->timer_freq)
++              return -EINVAL;
++
++      rt->dev = &pdev->dev;
++      platform_set_drvdata(pdev, rt);
++
++      rt_timer_request(rt);
++      rt_timer_config(rt, 2);
++      rt_timer_enable(rt);
++
++      dev_info(&pdev->dev, "maximum frequncy is %luHz\n", rt->timer_freq);
++
++      return 0;
++}
++
++static int rt_timer_remove(struct platform_device *pdev)
++{
++      struct rt_timer *rt = platform_get_drvdata(pdev);
++
++      rt_timer_disable(rt);
++      rt_timer_free(rt);
++
++      return 0;
++}
++
++static const struct of_device_id rt_timer_match[] = {
++      { .compatible = "ralink,rt2880-timer" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, rt_timer_match);
++
++static struct platform_driver rt_timer_driver = {
++      .probe = rt_timer_probe,
++      .remove = rt_timer_remove,
++      .driver = {
++              .name           = "rt-timer",
++              .owner          = THIS_MODULE,
++              .of_match_table = rt_timer_match
++      },
++};
++
++module_platform_driver(rt_timer_driver);
++
++MODULE_DESCRIPTION("Ralink RT2880 timer");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/ramips/patches-3.10/0011-MIPS-ralink-add-support-for-systick-timer-found-on-n.patch b/target/linux/ramips/patches-3.10/0011-MIPS-ralink-add-support-for-systick-timer-found-on-n.patch
new file mode 100644 (file)
index 0000000..6d4911b
--- /dev/null
@@ -0,0 +1,192 @@
+From 3b511d972b556712f89ccc68825c0ec8f398dc5c Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 13:46:09 +0200
+Subject: [PATCH 11/25] MIPS: ralink: add support for systick timer found on
+ newer ralink SoC
+
+Newer Ralink SoC (MT7620x and RT5350) have a 50KHz clock that runs independent
+of the SoC master clock. If we want to automatic frequency scaling to work we
+need to use the systick timer as the clock source.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Kconfig       |    7 ++
+ arch/mips/ralink/Makefile      |    2 +
+ arch/mips/ralink/cevt-rt3352.c |  145 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 154 insertions(+)
+ create mode 100644 arch/mips/ralink/cevt-rt3352.c
+
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -1,5 +1,12 @@
+ if RALINK
++config CLKEVT_RT3352
++      bool
++      depends on SOC_RT305X || SOC_MT7620
++      default y
++      select CLKSRC_OF
++      select CLKSRC_MMIO
++
+ choice
+       prompt "Ralink SoC selection"
+       default SOC_RT305X
+--- a/arch/mips/ralink/Makefile
++++ b/arch/mips/ralink/Makefile
+@@ -8,6 +8,8 @@
+ obj-y := prom.o of.o reset.o clk.o irq.o timer.o
++obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
++
+ obj-$(CONFIG_SOC_RT288X) += rt288x.o
+ obj-$(CONFIG_SOC_RT305X) += rt305x.o
+ obj-$(CONFIG_SOC_RT3883) += rt3883.o
+--- /dev/null
++++ b/arch/mips/ralink/cevt-rt3352.c
+@@ -0,0 +1,145 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2013 by John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/clockchips.h>
++#include <linux/clocksource.h>
++#include <linux/interrupt.h>
++#include <linux/reset.h>
++#include <linux/init.h>
++#include <linux/time.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++
++#include <asm/mach-ralink/ralink_regs.h>
++
++#define SYSTICK_FREQ          (50 * 1000)
++
++#define SYSTICK_CONFIG                0x00
++#define SYSTICK_COMPARE               0x04
++#define SYSTICK_COUNT         0x08
++
++/* route systick irq to mips irq 7 instead of the r4k-timer */
++#define CFG_EXT_STK_EN                0x2
++/* enable the counter */
++#define CFG_CNT_EN            0x1
++
++struct systick_device {
++      void __iomem *membase;
++      struct clock_event_device dev;
++      int irq_requested;
++      int freq_scale;
++};
++
++static void systick_set_clock_mode(enum clock_event_mode mode,
++                              struct clock_event_device *evt);
++
++static int systick_next_event(unsigned long delta,
++                              struct clock_event_device *evt)
++{
++      struct systick_device *sdev;
++      u32 count;
++
++      sdev = container_of(evt, struct systick_device, dev);
++      count = ioread32(sdev->membase + SYSTICK_COUNT);
++      count = (count + delta) % SYSTICK_FREQ;
++      iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE);
++
++      return 0;
++}
++
++static void systick_event_handler(struct clock_event_device *dev)
++{
++      /* noting to do here */
++}
++
++static irqreturn_t systick_interrupt(int irq, void *dev_id)
++{
++      struct clock_event_device *dev = (struct clock_event_device *) dev_id;
++
++      dev->event_handler(dev);
++
++      return IRQ_HANDLED;
++}
++
++static struct systick_device systick = {
++      .dev = {
++              /*
++               * cevt-r4k uses 300, make sure systick
++               * gets used if available
++               */
++              .rating         = 310,
++              .features       = CLOCK_EVT_FEAT_ONESHOT,
++              .set_next_event = systick_next_event,
++              .set_mode       = systick_set_clock_mode,
++              .event_handler  = systick_event_handler,
++      },
++};
++
++static struct irqaction systick_irqaction = {
++      .handler = systick_interrupt,
++      .flags = IRQF_PERCPU | IRQF_TIMER,
++      .dev_id = &systick.dev,
++};
++
++static void systick_set_clock_mode(enum clock_event_mode mode,
++                              struct clock_event_device *evt)
++{
++      struct systick_device *sdev;
++
++      sdev = container_of(evt, struct systick_device, dev);
++
++      switch (mode) {
++      case CLOCK_EVT_MODE_ONESHOT:
++              if (!sdev->irq_requested)
++                      setup_irq(systick.dev.irq, &systick_irqaction);
++              sdev->irq_requested = 1;
++              iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN,
++                              systick.membase + SYSTICK_CONFIG);
++              break;
++
++      case CLOCK_EVT_MODE_SHUTDOWN:
++              if (sdev->irq_requested)
++                      free_irq(systick.dev.irq, &systick_irqaction);
++              sdev->irq_requested = 0;
++              iowrite32(0, systick.membase + SYSTICK_CONFIG);
++              break;
++
++      default:
++              pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name);
++              break;
++      }
++}
++
++static void __init ralink_systick_init(struct device_node *np)
++{
++      systick.membase = of_iomap(np, 0);
++      if (!systick.membase)
++              return;
++
++      systick_irqaction.name = np->name;
++      systick.dev.name = np->name;
++      clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60);
++      systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev);
++      systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev);
++      systick.dev.irq = irq_of_parse_and_map(np, 0);
++      if (!systick.dev.irq) {
++              pr_err("%s: request_irq failed", np->name);
++              return;
++      }
++
++      clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name,
++                      SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up);
++
++      clockevents_register_device(&systick.dev);
++
++      pr_info("%s: runing - mult: %d, shift: %d\n",
++                      np->name, systick.dev.mult, systick.dev.shift);
++}
++
++CLOCKSOURCE_OF_DECLARE(systick, "ralink,cevt-systick", ralink_systick_init);
diff --git a/target/linux/ramips/patches-3.10/0011-PCI-MIPS-adds-rt2880-pci-support.patch b/target/linux/ramips/patches-3.10/0011-PCI-MIPS-adds-rt2880-pci-support.patch
deleted file mode 100644 (file)
index 8db77a6..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-From 5d57ace094803c95230643941a47d749ff81d022 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 18:27:29 +0100
-Subject: [PATCH 11/33] PCI: MIPS: adds rt2880 pci support
-
-Add support for the pci found on the rt2880 SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/pci/Makefile     |    1 +
- arch/mips/pci/pci-rt2880.c |  281 ++++++++++++++++++++++++++++++++++++++++++++
- arch/mips/ralink/Kconfig   |    1 +
- 3 files changed, 283 insertions(+)
- create mode 100644 arch/mips/pci/pci-rt2880.c
-
---- a/arch/mips/pci/Makefile
-+++ b/arch/mips/pci/Makefile
-@@ -41,6 +41,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1
- obj-$(CONFIG_SNI_RM)          += fixup-sni.o ops-sni.o
- obj-$(CONFIG_LANTIQ)          += fixup-lantiq.o
- obj-$(CONFIG_PCI_LANTIQ)      += pci-lantiq.o ops-lantiq.o
-+obj-$(CONFIG_SOC_RT2880)      += pci-rt2880.o
- obj-$(CONFIG_TANBAC_TB0219)   += fixup-tb0219.o
- obj-$(CONFIG_TANBAC_TB0226)   += fixup-tb0226.o
- obj-$(CONFIG_TANBAC_TB0287)   += fixup-tb0287.o
---- /dev/null
-+++ b/arch/mips/pci/pci-rt2880.c
-@@ -0,0 +1,281 @@
-+/*
-+ *  Ralink RT288x SoC PCI register definitions
-+ *
-+ *  Copyright (C) 2009 John Crispin <blogic@openwrt.org>
-+ *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ *  Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ *  This program is free software; you can redistribute it and/or modify it
-+ *  under the terms of the GNU General Public License version 2 as published
-+ *  by the Free Software Foundation.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/pci.h>
-+#include <linux/io.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/of_platform.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+
-+#include <asm/mach-ralink/rt288x.h>
-+
-+#define RT2880_PCI_BASE               0x00440000
-+#define RT288X_CPU_IRQ_PCI    4
-+
-+#define RT2880_PCI_MEM_BASE   0x20000000
-+#define RT2880_PCI_MEM_SIZE   0x10000000
-+#define RT2880_PCI_IO_BASE    0x00460000
-+#define RT2880_PCI_IO_SIZE    0x00010000
-+
-+#define RT2880_PCI_REG_PCICFG_ADDR    0x00
-+#define RT2880_PCI_REG_PCIMSK_ADDR    0x0c
-+#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10
-+#define RT2880_PCI_REG_IMBASEBAR0_ADDR        0x18
-+#define RT2880_PCI_REG_CONFIG_ADDR    0x20
-+#define RT2880_PCI_REG_CONFIG_DATA    0x24
-+#define RT2880_PCI_REG_MEMBASE                0x28
-+#define RT2880_PCI_REG_IOBASE         0x2c
-+#define RT2880_PCI_REG_ID             0x30
-+#define RT2880_PCI_REG_CLASS          0x34
-+#define RT2880_PCI_REG_SUBID          0x38
-+#define RT2880_PCI_REG_ARBCTL         0x80
-+
-+static void __iomem *rt2880_pci_base;
-+static DEFINE_SPINLOCK(rt2880_pci_lock);
-+
-+static u32 rt2880_pci_reg_read(u32 reg)
-+{
-+      return readl(rt2880_pci_base + reg);
-+}
-+
-+static void rt2880_pci_reg_write(u32 val, u32 reg)
-+{
-+      writel(val, rt2880_pci_base + reg);
-+}
-+
-+static inline u32 rt2880_pci_get_cfgaddr(unsigned int bus, unsigned int slot,
-+                                       unsigned int func, unsigned int where)
-+{
-+      return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) |
-+              0x80000000);
-+}
-+
-+static int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn,
-+                                int where, int size, u32 *val)
-+{
-+      unsigned long flags;
-+      u32 address;
-+      u32 data;
-+
-+      address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+                                       PCI_FUNC(devfn), where);
-+
-+      spin_lock_irqsave(&rt2880_pci_lock, flags);
-+      rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+      data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
-+      spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+
-+      switch (size) {
-+      case 1:
-+              *val = (data >> ((where & 3) << 3)) & 0xff;
-+              break;
-+      case 2:
-+              *val = (data >> ((where & 3) << 3)) & 0xffff;
-+              break;
-+      case 4:
-+              *val = data;
-+              break;
-+      }
-+
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn,
-+                                 int where, int size, u32 val)
-+{
-+      unsigned long flags;
-+      u32 address;
-+      u32 data;
-+
-+      address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+                                       PCI_FUNC(devfn), where);
-+
-+      spin_lock_irqsave(&rt2880_pci_lock, flags);
-+      rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+      data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
-+
-+      switch (size) {
-+      case 1:
-+              data = (data & ~(0xff << ((where & 3) << 3))) |
-+                     (val << ((where & 3) << 3));
-+              break;
-+      case 2:
-+              data = (data & ~(0xffff << ((where & 3) << 3))) |
-+                     (val << ((where & 3) << 3));
-+              break;
-+      case 4:
-+              data = val;
-+              break;
-+      }
-+
-+      rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA);
-+      spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static struct pci_ops rt2880_pci_ops = {
-+      .read   = rt2880_pci_config_read,
-+      .write  = rt2880_pci_config_write,
-+};
-+
-+static struct resource rt2880_pci_mem_resource = {
-+      .name   = "PCI MEM space",
-+      .start  = RT2880_PCI_MEM_BASE,
-+      .end    = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1,
-+      .flags  = IORESOURCE_MEM,
-+};
-+
-+static struct resource rt2880_pci_io_resource = {
-+      .name   = "PCI IO space",
-+      .start  = RT2880_PCI_IO_BASE,
-+      .end    = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1,
-+      .flags  = IORESOURCE_IO,
-+};
-+
-+static struct pci_controller rt2880_pci_controller = {
-+      .pci_ops        = &rt2880_pci_ops,
-+      .mem_resource   = &rt2880_pci_mem_resource,
-+      .io_resource    = &rt2880_pci_io_resource,
-+};
-+
-+static inline u32 rt2880_pci_read_u32(unsigned long reg)
-+{
-+      unsigned long flags;
-+      u32 address;
-+      u32 ret;
-+
-+      address = rt2880_pci_get_cfgaddr(0, 0, 0, reg);
-+
-+      spin_lock_irqsave(&rt2880_pci_lock, flags);
-+      rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+      ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA);
-+      spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+
-+      return ret;
-+}
-+
-+static inline void rt2880_pci_write_u32(unsigned long reg, u32 val)
-+{
-+      unsigned long flags;
-+      u32 address;
-+
-+      address = rt2880_pci_get_cfgaddr(0, 0, 0, reg);
-+
-+      spin_lock_irqsave(&rt2880_pci_lock, flags);
-+      rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR);
-+      rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA);
-+      spin_unlock_irqrestore(&rt2880_pci_lock, flags);
-+}
-+
-+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+      u16 cmd;
-+      int irq = -1;
-+
-+      if (dev->bus->number != 0)
-+              return irq;
-+
-+      switch (PCI_SLOT(dev->devfn)) {
-+      case 0x00:
-+              rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
-+              (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
-+              break;
-+      case 0x11:
-+              irq = RT288X_CPU_IRQ_PCI;
-+              break;
-+      default:
-+              printk("%s:%s[%d] trying to alloc unknown pci irq\n",
-+                     __FILE__, __func__, __LINE__);
-+              BUG();
-+              break;
-+      }
-+
-+      pci_write_config_byte((struct pci_dev*)dev, PCI_CACHE_LINE_SIZE, 0x14);
-+      pci_write_config_byte((struct pci_dev*)dev, PCI_LATENCY_TIMER, 0xFF);
-+      pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd);
-+      cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-+             PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK |
-+             PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY;
-+      pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd);
-+      pci_write_config_byte((struct pci_dev*)dev, PCI_INTERRUPT_LINE,
-+                            dev->irq);
-+      return irq;
-+}
-+
-+static int rt288x_pci_probe(struct platform_device *pdev)
-+{
-+      void __iomem *io_map_base;
-+      int i;
-+
-+      rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE);
-+
-+      io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE);
-+      rt2880_pci_controller.io_map_base = (unsigned long) io_map_base;
-+      set_io_port_base((unsigned long) io_map_base);
-+
-+      ioport_resource.start = RT2880_PCI_IO_BASE;
-+      ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1;
-+
-+      rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR);
-+      for(i = 0; i < 0xfffff; i++) {}
-+
-+      rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL);
-+      rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR);
-+      rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE);
-+      rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE);
-+      rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR);
-+      rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID);
-+      rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS);
-+      rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID);
-+      rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR);
-+
-+      rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
-+      (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
-+
-+      register_pci_controller(&rt2880_pci_controller);
-+      return 0;
-+}
-+
-+int pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+      return 0;
-+}
-+
-+static const struct of_device_id rt288x_pci_match[] = {
-+      { .compatible = "ralink,rt288x-pci" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, rt288x_pci_match);
-+
-+static struct platform_driver rt288x_pci_driver = {
-+      .probe = rt288x_pci_probe,
-+      .driver = {
-+              .name = "rt288x-pci",
-+              .owner = THIS_MODULE,
-+              .of_match_table = rt288x_pci_match,
-+      },
-+};
-+
-+int __init pcibios_init(void)
-+{
-+      int ret = platform_driver_register(&rt288x_pci_driver);
-+      if (ret)
-+              pr_info("rt288x-pci: Error registering platform driver!");
-+      return ret;
-+}
-+
-+arch_initcall(pcibios_init);
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -8,6 +8,7 @@ choice
-       config SOC_RT288X
-               bool "RT288x"
-+              select HW_HAS_PCI
-       config SOC_RT305X
-               bool "RT305x"
diff --git a/target/linux/ramips/patches-3.10/0012-MIPS-ralink-probe-clocksources-from-OF.patch b/target/linux/ramips/patches-3.10/0012-MIPS-ralink-probe-clocksources-from-OF.patch
new file mode 100644 (file)
index 0000000..d46296b
--- /dev/null
@@ -0,0 +1,21 @@
+From c4d6a957efb0c8d919302598ae547bde05137461 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 13:48:39 +0200
+Subject: [PATCH 12/25] MIPS: ralink: probe clocksources from OF
+
+Make plat_time_init() call clocksource_of_init() allowing the systick cevt
+to load.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/clk.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- 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/target/linux/ramips/patches-3.10/0012-PCI-MIPS-adds-rt3883-pci-support.patch b/target/linux/ramips/patches-3.10/0012-PCI-MIPS-adds-rt3883-pci-support.patch
deleted file mode 100644 (file)
index b28ed19..0000000
+++ /dev/null
@@ -1,678 +0,0 @@
-From b43e77699154356a39796d95ef316699dafe409d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 21 Mar 2013 17:34:08 +0100
-Subject: [PATCH 12/33] PCI: MIPS: adds rt3883 pci support
-
-Add support for the pcie found on the rt3883 SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/pci/Makefile     |    1 +
- arch/mips/pci/pci-rt3883.c |  640 ++++++++++++++++++++++++++++++++++++++++++++
- arch/mips/ralink/Kconfig   |    1 +
- 3 files changed, 642 insertions(+)
- create mode 100644 arch/mips/pci/pci-rt3883.c
-
---- a/arch/mips/pci/Makefile
-+++ b/arch/mips/pci/Makefile
-@@ -42,6 +42,7 @@ obj-$(CONFIG_SNI_RM)         += fixup-sni.o ops
- obj-$(CONFIG_LANTIQ)          += fixup-lantiq.o
- obj-$(CONFIG_PCI_LANTIQ)      += pci-lantiq.o ops-lantiq.o
- obj-$(CONFIG_SOC_RT2880)      += pci-rt2880.o
-+obj-$(CONFIG_SOC_RT3883)      += pci-rt3883.o
- obj-$(CONFIG_TANBAC_TB0219)   += fixup-tb0219.o
- obj-$(CONFIG_TANBAC_TB0226)   += fixup-tb0226.o
- obj-$(CONFIG_TANBAC_TB0287)   += fixup-tb0287.o
---- /dev/null
-+++ b/arch/mips/pci/pci-rt3883.c
-@@ -0,0 +1,640 @@
-+/*
-+ *  Ralink RT3662/RT3883 SoC PCI support
-+ *
-+ *  Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ *  Parts of this file are based on Ralink's 2.6.21 BSP
-+ *
-+ *  This program is free software; you can redistribute it and/or modify it
-+ *  under the terms of the GNU General Public License version 2 as published
-+ *  by the Free Software Foundation.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/pci.h>
-+#include <linux/io.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+#include <linux/platform_device.h>
-+
-+#include <asm/mach-ralink/rt3883.h>
-+#include <asm/mach-ralink/ralink_regs.h>
-+
-+#define RT3883_MEMORY_BASE            0x00000000
-+#define RT3883_MEMORY_SIZE            0x02000000
-+
-+#define RT3883_PCI_REG_PCICFG         0x00
-+#define   RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf
-+#define   RT3883_PCICFG_P2P_BR_DEVNUM_S 16
-+#define   RT3883_PCICFG_PCIRST                BIT(1)
-+#define RT3883_PCI_REG_PCIRAW         0x04
-+#define RT3883_PCI_REG_PCIINT         0x08
-+#define RT3883_PCI_REG_PCIENA         0x0c
-+
-+#define RT3883_PCI_REG_CFGADDR                0x20
-+#define RT3883_PCI_REG_CFGDATA                0x24
-+#define RT3883_PCI_REG_MEMBASE                0x28
-+#define RT3883_PCI_REG_IOBASE         0x2c
-+#define RT3883_PCI_REG_ARBCTL         0x80
-+
-+#define RT3883_PCI_REG_BASE(_x)               (0x1000 + (_x) * 0x1000)
-+#define RT3883_PCI_REG_BAR0SETUP(_x)  (RT3883_PCI_REG_BASE((_x)) + 0x10)
-+#define RT3883_PCI_REG_IMBASEBAR0(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18)
-+#define RT3883_PCI_REG_ID(_x)         (RT3883_PCI_REG_BASE((_x)) + 0x30)
-+#define RT3883_PCI_REG_CLASS(_x)      (RT3883_PCI_REG_BASE((_x)) + 0x34)
-+#define RT3883_PCI_REG_SUBID(_x)      (RT3883_PCI_REG_BASE((_x)) + 0x38)
-+#define RT3883_PCI_REG_STATUS(_x)     (RT3883_PCI_REG_BASE((_x)) + 0x50)
-+
-+#define RT3883_PCI_MODE_NONE  0
-+#define RT3883_PCI_MODE_PCI   BIT(0)
-+#define RT3883_PCI_MODE_PCIE  BIT(1)
-+#define RT3883_PCI_MODE_BOTH  (RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE)
-+
-+#define RT3883_PCI_IRQ_COUNT  32
-+
-+#define RT3883_P2P_BR_DEVNUM  1
-+
-+struct rt3883_pci_controller {
-+      void __iomem *base;
-+      spinlock_t lock;
-+
-+      struct irq_domain *irq_domain;
-+
-+      struct pci_controller pci_controller;
-+      struct resource io_res;
-+      struct resource mem_res;
-+
-+      bool pcie_ready;
-+      unsigned char p2p_devnum;
-+};
-+
-+static inline struct rt3883_pci_controller *
-+pci_bus_to_rt3883_controller(struct pci_bus *bus)
-+{
-+      struct pci_controller *hose;
-+
-+      hose = (struct pci_controller *) bus->sysdata;
-+      return container_of(hose, struct rt3883_pci_controller, pci_controller);
-+}
-+
-+static inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc,
-+                               unsigned reg)
-+{
-+      return ioread32(rpc->base + reg);
-+}
-+
-+static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc,
-+                                u32 val, unsigned reg)
-+{
-+      iowrite32(val, rpc->base + reg);
-+}
-+
-+static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot,
-+                                       unsigned int func, unsigned int where)
-+{
-+      return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) |
-+              0x80000000);
-+}
-+
-+static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc,
-+                             unsigned bus, unsigned slot,
-+                             unsigned func, unsigned reg)
-+{
-+      unsigned long flags;
-+      u32 address;
-+      u32 ret;
-+
-+      address = rt3883_pci_get_cfgaddr(bus, slot, func, reg);
-+
-+      spin_lock_irqsave(&rpc->lock, flags);
-+      rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
-+      ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA);
-+      spin_unlock_irqrestore(&rpc->lock, flags);
-+
-+      return ret;
-+}
-+
-+static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc,
-+                               unsigned bus, unsigned slot,
-+                               unsigned func, unsigned reg, u32 val)
-+{
-+      unsigned long flags;
-+      u32 address;
-+
-+      address = rt3883_pci_get_cfgaddr(bus, slot, func, reg);
-+
-+      spin_lock_irqsave(&rpc->lock, flags);
-+      rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
-+      rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA);
-+      spin_unlock_irqrestore(&rpc->lock, flags);
-+}
-+
-+static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      u32 pending;
-+
-+      rpc = irq_get_handler_data(irq);
-+
-+      pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) &
-+                rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
-+
-+      if (!pending) {
-+              spurious_interrupt();
-+              return;
-+      }
-+
-+      while (pending) {
-+              unsigned bit = __ffs(pending);
-+
-+              irq = irq_find_mapping(rpc->irq_domain, bit);
-+              generic_handle_irq(irq);
-+
-+              pending &= ~BIT(bit);
-+      }
-+}
-+
-+static void rt3883_pci_irq_unmask(struct irq_data *d)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      u32 t;
-+
-+      rpc = irq_data_get_irq_chip_data(d);
-+
-+      t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
-+      rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA);
-+      /* flush write */
-+      rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
-+}
-+
-+static void rt3883_pci_irq_mask(struct irq_data *d)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      u32 t;
-+
-+      rpc = irq_data_get_irq_chip_data(d);
-+
-+      t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
-+      rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA);
-+      /* flush write */
-+      rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA);
-+}
-+
-+static struct irq_chip rt3883_pci_irq_chip = {
-+      .name           = "RT3883 PCI",
-+      .irq_mask       = rt3883_pci_irq_mask,
-+      .irq_unmask     = rt3883_pci_irq_unmask,
-+      .irq_mask_ack   = rt3883_pci_irq_mask,
-+};
-+
-+static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq,
-+                            irq_hw_number_t hw)
-+{
-+      irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq);
-+      irq_set_chip_data(irq, d->host_data);
-+
-+      return 0;
-+}
-+
-+static const struct irq_domain_ops rt3883_pci_irq_domain_ops = {
-+      .map = rt3883_pci_irq_map,
-+      .xlate = irq_domain_xlate_onecell,
-+};
-+
-+static int rt3883_pci_irq_init(struct device *dev,
-+                             struct rt3883_pci_controller *rpc)
-+{
-+      struct device_node *np = dev->of_node;
-+      struct device_node *intc_np;
-+      int irq;
-+      int err;
-+
-+      intc_np = of_get_child_by_name(np, "interrupt-controller");
-+      if (!intc_np) {
-+              dev_err(dev, "no %s child node found", "interrupt-controller");
-+              return -ENODEV;
-+      }
-+
-+      irq = irq_of_parse_and_map(intc_np, 0);
-+      if (irq == 0) {
-+              dev_err(dev, "%s has no IRQ", of_node_full_name(intc_np));
-+              err = -EINVAL;
-+              goto err_put_intc;
-+      }
-+
-+      /* disable all interrupts */
-+      rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA);
-+
-+      rpc->irq_domain =
-+              irq_domain_add_linear(intc_np, RT3883_PCI_IRQ_COUNT,
-+                                    &rt3883_pci_irq_domain_ops,
-+                                    rpc);
-+      if (!rpc->irq_domain) {
-+              dev_err(dev, "unable to add IRQ domain\n");
-+              err = -ENODEV;
-+              goto err_put_intc;
-+      }
-+
-+      irq_set_handler_data(irq, rpc);
-+      irq_set_chained_handler(irq, rt3883_pci_irq_handler);
-+
-+      return 0;
-+
-+err_put_intc:
-+      of_node_put(intc_np);
-+      return err;
-+}
-+
-+static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn,
-+                                int where, int size, u32 *val)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      unsigned long flags;
-+      u32 address;
-+      u32 data;
-+
-+      rpc = pci_bus_to_rt3883_controller(bus);
-+
-+      if (!rpc->pcie_ready && bus->number == 1)
-+              return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+      address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+                                       PCI_FUNC(devfn), where);
-+
-+      spin_lock_irqsave(&rpc->lock, flags);
-+      rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
-+      data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA);
-+      spin_unlock_irqrestore(&rpc->lock, flags);
-+
-+      switch (size) {
-+      case 1:
-+              *val = (data >> ((where & 3) << 3)) & 0xff;
-+              break;
-+      case 2:
-+              *val = (data >> ((where & 3) << 3)) & 0xffff;
-+              break;
-+      case 4:
-+              *val = data;
-+              break;
-+      }
-+
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn,
-+                                 int where, int size, u32 val)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      unsigned long flags;
-+      u32 address;
-+      u32 data;
-+
-+      rpc = pci_bus_to_rt3883_controller(bus);
-+
-+      if (!rpc->pcie_ready && bus->number == 1)
-+              return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+      address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn),
-+                                       PCI_FUNC(devfn), where);
-+
-+      spin_lock_irqsave(&rpc->lock, flags);
-+      rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR);
-+      data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA);
-+
-+      switch (size) {
-+      case 1:
-+              data = (data & ~(0xff << ((where & 3) << 3))) |
-+                     (val << ((where & 3) << 3));
-+              break;
-+      case 2:
-+              data = (data & ~(0xffff << ((where & 3) << 3))) |
-+                     (val << ((where & 3) << 3));
-+              break;
-+      case 4:
-+              data = val;
-+              break;
-+      }
-+
-+      rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA);
-+      spin_unlock_irqrestore(&rpc->lock, flags);
-+
-+      return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static struct pci_ops rt3883_pci_ops = {
-+      .read   = rt3883_pci_config_read,
-+      .write  = rt3883_pci_config_write,
-+};
-+
-+static void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode)
-+{
-+      u32 syscfg1;
-+      u32 rstctrl;
-+      u32 clkcfg1;
-+      u32 t;
-+
-+      rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
-+      syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1);
-+      clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1);
-+
-+      if (mode & RT3883_PCI_MODE_PCIE) {
-+              rstctrl |= RT3883_RSTCTRL_PCIE;
-+              rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
-+
-+              /* setup PCI PAD drive mode */
-+              syscfg1 &= ~(0x30);
-+              syscfg1 |= (2 << 4);
-+              rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1);
-+
-+              t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+              t &= ~BIT(31);
-+              rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+
-+              t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+              t &= 0x80ffffff;
-+              rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+
-+              t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+              t |= 0xa << 24;
-+              rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1);
-+
-+              t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+              t |= BIT(31);
-+              rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+
-+              msleep(50);
-+
-+              rstctrl &= ~RT3883_RSTCTRL_PCIE;
-+              rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
-+      }
-+
-+      syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE);
-+
-+      clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN);
-+
-+      if (mode & RT3883_PCI_MODE_PCI) {
-+              clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN;
-+              rstctrl &= ~RT3883_RSTCTRL_PCI;
-+      }
-+
-+      if (mode & RT3883_PCI_MODE_PCIE) {
-+              clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN;
-+              rstctrl &= ~RT3883_RSTCTRL_PCIE;
-+      }
-+
-+      rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1);
-+      rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL);
-+      rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1);
-+
-+      msleep(500);
-+
-+      /*
-+       * setup the device number of the P2P bridge
-+       * and de-assert the reset line
-+       */
-+      t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S);
-+      rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG);
-+
-+      /* flush write */
-+      rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG);
-+      msleep(500);
-+
-+      if (mode & RT3883_PCI_MODE_PCIE) {
-+              msleep(500);
-+
-+              t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1));
-+
-+              rpc->pcie_ready = t & BIT(0);
-+
-+              if (!rpc->pcie_ready) {
-+                      /* reset the PCIe block */
-+                      t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL);
-+                      t |= RT3883_RSTCTRL_PCIE;
-+                      rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
-+                      t &= ~RT3883_RSTCTRL_PCIE;
-+                      rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL);
-+
-+                      /* turn off PCIe clock */
-+                      t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1);
-+                      t &= ~RT3883_CLKCFG1_PCIE_CLK_EN;
-+                      rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1);
-+
-+                      t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+                      t &= ~0xf000c080;
-+                      rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0);
-+              }
-+      }
-+
-+      /* enable PCI arbiter */
-+      rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL);
-+}
-+
-+static inline void
-+rt3883_dump_pci_config(struct rt3883_pci_controller *rpc,
-+                     int bus, int slot)
-+{
-+      int i;
-+
-+      for (i = 0; i < 16; i++) {
-+              u32 val;
-+
-+              val = rt3883_pci_read_cfg32(rpc, bus, slot, 0, i << 2);
-+              pr_info("pci %02x:%02x.0 0x%02x = %08x\n",
-+                      bus, slot, i << 2, val);
-+      }
-+}
-+
-+static int rt3883_pci_probe(struct platform_device *pdev)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      struct device *dev = &pdev->dev;
-+      struct device_node *np = dev->of_node;
-+      struct resource *res;
-+      struct device_node *child;
-+      u32 val;
-+      int err;
-+      int mode;
-+
-+      rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL);
-+      if (!rpc)
-+              return -ENOMEM;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (!res)
-+              return -EINVAL;
-+
-+      rpc->base = devm_ioremap_resource(dev, res);
-+      if (IS_ERR(rpc->base))
-+              return PTR_ERR(rpc->base);
-+
-+      rpc->pci_controller.of_node = of_get_child_by_name(np, "host-bridge");
-+      if (!rpc->pci_controller.of_node) {
-+              dev_err(dev, "no %s child node found", "host-bridge");
-+              return -ENODEV;
-+      }
-+
-+      mode = RT3883_PCI_MODE_NONE;
-+      for_each_child_of_node(rpc->pci_controller.of_node, child) {
-+              u32 slot;
-+
-+              if (!of_device_is_available(child))
-+                      continue;
-+
-+              if (of_property_read_u32(child, "ralink,pci-slot",
-+                                       &slot)) {
-+                      dev_err(dev, "no '%s' property found for %s\n",
-+                              "ralink,pci-slot",
-+                              of_node_full_name(child));
-+                      continue;
-+              }
-+
-+              switch (slot) {
-+              case 1:
-+                      mode |= RT3883_PCI_MODE_PCIE;
-+                      break;
-+
-+              case 17:
-+              case 18:
-+                      mode |= RT3883_PCI_MODE_PCI;
-+                      break;
-+              }
-+      }
-+
-+      if (mode == RT3883_PCI_MODE_NONE) {
-+              dev_err(dev, "unable to determine PCI mode\n");
-+              err = -EINVAL;
-+              goto err_put_hb_node;
-+      }
-+
-+      dev_info(dev, "mode:%s%s\n",
-+               (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "",
-+               (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : "");
-+
-+      rt3883_pci_preinit(rpc, mode);
-+
-+      rpc->pci_controller.pci_ops = &rt3883_pci_ops;
-+      rpc->pci_controller.io_resource = &rpc->io_res;
-+      rpc->pci_controller.mem_resource = &rpc->mem_res;
-+
-+      /* Load PCI I/O and memory resources from DT */
-+      pci_load_of_ranges(&rpc->pci_controller,
-+                         rpc->pci_controller.of_node);
-+
-+      rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE);
-+      rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE);
-+
-+      ioport_resource.start = rpc->io_res.start;
-+      ioport_resource.end = rpc->io_res.end;
-+
-+      /* PCI */
-+      rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0));
-+      rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0));
-+      rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0));
-+      rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0));
-+      rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0));
-+
-+      /* PCIe */
-+      rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1));
-+      rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1));
-+      rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1));
-+      rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1));
-+      rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1));
-+
-+      err = rt3883_pci_irq_init(dev, rpc);
-+      if (err)
-+              goto err_put_hb_node;
-+
-+      /* PCIe */
-+      val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND);
-+      val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-+      rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val);
-+
-+      /* PCI */
-+      val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND);
-+      val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-+      rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val);
-+
-+      if (mode == RT3883_PCI_MODE_PCIE) {
-+              rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0));
-+              rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1));
-+
-+              rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0,
-+                                     PCI_BASE_ADDRESS_0,
-+                                     RT3883_MEMORY_BASE);
-+              /* flush write */
-+              rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0,
-+                                    PCI_BASE_ADDRESS_0);
-+      } else {
-+              rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0,
-+                                     PCI_IO_BASE, 0x00000101);
-+      }
-+
-+      register_pci_controller(&rpc->pci_controller);
-+
-+      return 0;
-+
-+err_put_hb_node:
-+      of_node_put(rpc->pci_controller.of_node);
-+      return err;
-+}
-+
-+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+      struct rt3883_pci_controller *rpc;
-+      struct of_irq dev_irq;
-+      int err;
-+      int irq;
-+
-+      rpc = pci_bus_to_rt3883_controller(dev->bus);
-+      err = of_irq_map_pci(dev, &dev_irq);
-+      if (err) {
-+              pr_err("pci %s: unable to get irq map, err=%d\n",
-+                     pci_name((struct pci_dev *) dev), err);
-+              return 0;
-+      }
-+
-+      irq = irq_create_of_mapping(dev_irq.controller,
-+                                  dev_irq.specifier,
-+                                  dev_irq.size);
-+
-+      if (irq == 0)
-+              pr_crit("pci %s: no irq found for pin %u\n",
-+                      pci_name((struct pci_dev *) dev), pin);
-+      else
-+              pr_info("pci %s: using irq %d for pin %u\n",
-+                      pci_name((struct pci_dev *) dev), irq, pin);
-+
-+      return irq;
-+}
-+
-+int pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+      return 0;
-+}
-+
-+static const struct of_device_id rt3883_pci_ids[] = {
-+      { .compatible = "ralink,rt3883-pci" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, rt3883_pci_ids);
-+
-+static struct platform_driver rt3883_pci_driver = {
-+      .probe = rt3883_pci_probe,
-+      .driver = {
-+              .name = "rt3883-pci",
-+              .owner = THIS_MODULE,
-+              .of_match_table = of_match_ptr(rt3883_pci_ids),
-+      },
-+};
-+
-+static int __init rt3883_pci_init(void)
-+{
-+      return platform_driver_register(&rt3883_pci_driver);
-+}
-+
-+postcore_initcall(rt3883_pci_init);
---- a/arch/mips/ralink/Kconfig
-+++ b/arch/mips/ralink/Kconfig
-@@ -20,6 +20,7 @@ choice
-               bool "RT3883"
-               select USB_ARCH_HAS_OHCI
-               select USB_ARCH_HAS_EHCI
-+              select HW_HAS_PCI
-       config SOC_MT7620
-               bool "MT7620"
diff --git a/target/linux/ramips/patches-3.10/0013-MIPS-ralink-mt7620-add-verbose-ram-info.patch b/target/linux/ramips/patches-3.10/0013-MIPS-ralink-mt7620-add-verbose-ram-info.patch
new file mode 100644 (file)
index 0000000..f82446a
--- /dev/null
@@ -0,0 +1,34 @@
+From 2d17c793a9cd3f67351d1a15c099ef2464e81f47 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 20 May 2013 20:30:11 +0200
+Subject: [PATCH 13/25] MIPS: ralink: mt7620: add verbose ram info
+
+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(+)
+
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -214,16 +214,19 @@ void prom_soc_init(struct ralink_soc_inf
+       switch (dram_type) {
+       case SYSCFG0_DRAM_TYPE_SDRAM:
++              pr_info("Board has SDRAM\n");
+               soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN;
+               soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX;
+               break;
+       case SYSCFG0_DRAM_TYPE_DDR1:
++              pr_info("Board has DDR1\n");
+               soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN;
+               soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX;
+               break;
+       case SYSCFG0_DRAM_TYPE_DDR2:
++              pr_info("Board has DDR2\n");
+               soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN;
+               soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX;
+               break;
diff --git a/target/linux/ramips/patches-3.10/0013-PCI-MIPS-adds-mt7620a-pcie-driver.patch b/target/linux/ramips/patches-3.10/0013-PCI-MIPS-adds-mt7620a-pcie-driver.patch
deleted file mode 100644 (file)
index 0d31f73..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-From ded577553b06a85c12a89b8fbcfa2b51f30bc037 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 18 May 2013 22:06:15 +0200
-Subject: [PATCH 13/33] 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
-
---- a/arch/mips/pci/Makefile
-+++ b/arch/mips/pci/Makefile
-@@ -43,6 +43,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
---- /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);
---- 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
diff --git a/target/linux/ramips/patches-3.10/0014-MIPS-ralink-mt7620-add-spi-clock-definition.patch b/target/linux/ramips/patches-3.10/0014-MIPS-ralink-mt7620-add-spi-clock-definition.patch
new file mode 100644 (file)
index 0000000..16b89dc
--- /dev/null
@@ -0,0 +1,22 @@
+From d0da9f08ef37e9f639e3b7995d722684da2410a2 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 23 May 2013 18:46:25 +0200
+Subject: [PATCH 14/25] MIPS: ralink: mt7620: add spi clock definition
+
+The definition of the spi clock is missing.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/mt7620.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -167,6 +167,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);
+ }
diff --git a/target/linux/ramips/patches-3.10/0014-NET-multi-phy-support.patch b/target/linux/ramips/patches-3.10/0014-NET-multi-phy-support.patch
deleted file mode 100644 (file)
index 345ee14..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From 7407b7d178e783074861a73da858b099f870270d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 11 May 2013 23:40:19 +0200
-Subject: [PATCH 14/33] 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(-)
-
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -820,7 +820,8 @@ void phy_state_machine(struct work_struc
-                        * 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;
-                       }
-@@ -890,7 +891,8 @@ void phy_state_machine(struct work_struc
-                               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);
-@@ -902,7 +904,8 @@ void phy_state_machine(struct work_struc
-               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;
---- 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;
diff --git a/target/linux/ramips/patches-3.10/0015-MIPS-ralink-mt7620-add-wdt-clock-definition.patch b/target/linux/ramips/patches-3.10/0015-MIPS-ralink-mt7620-add-wdt-clock-definition.patch
new file mode 100644 (file)
index 0000000..ec045b5
--- /dev/null
@@ -0,0 +1,22 @@
+From 51db62f58431d9a89c55f59f98879829dcfddcaf Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 13:50:11 +0200
+Subject: [PATCH 15/25] MIPS: ralink: mt7620: add wdt clock definition
+
+The definition of the wdt clock is missing.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/mt7620.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -166,6 +166,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/target/linux/ramips/patches-3.10/0015-NET-add-of_get_mac_address_mtd.patch b/target/linux/ramips/patches-3.10/0015-NET-add-of_get_mac_address_mtd.patch
deleted file mode 100644 (file)
index 408326d..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-From 2a41724b2d0af9b4444572c4302570a3af377715 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 14 Jul 2013 23:26:15 +0200
-Subject: [PATCH 15/33] 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
-network interface. The new property points at a mtd partition with an offset
-where the mac address can be found.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/of/of_net.c    |   37 +++++++++++++++++++++++++++++++++++++
- include/linux/of_net.h |    1 +
- 2 files changed, 38 insertions(+)
-
---- a/drivers/of/of_net.c
-+++ b/drivers/of/of_net.c
-@@ -10,6 +10,7 @@
- #include <linux/of_net.h>
- #include <linux/phy.h>
- #include <linux/export.h>
-+#include <linux/mtd/mtd.h>
- /**
-  * It maps 'enum phy_interface_t' found in include/linux/phy.h
-@@ -92,3 +93,39 @@ const void *of_get_mac_address(struct de
-       return NULL;
- }
- EXPORT_SYMBOL(of_get_mac_address);
-+
-+int of_get_mac_address_mtd(struct device_node *np, void *mac)
-+{
-+      struct device_node *mtd_np = NULL;
-+      size_t retlen;
-+      int size, ret;
-+      struct mtd_info *mtd;
-+      const char *part;
-+      const __be32 *list;
-+      phandle phandle;
-+
-+      list = of_get_property(np, "mtd-mac-address", &size);
-+      if (!list || (size != (2 * sizeof(*list))))
-+              return -ENOENT;
-+
-+      phandle = be32_to_cpup(list++);
-+      if (phandle)
-+              mtd_np = of_find_node_by_phandle(phandle);
-+
-+      if (!mtd_np)
-+              return -ENOENT;
-+
-+      part = of_get_property(mtd_np, "label", NULL);
-+      if (!part)
-+              part = mtd_np->name;
-+
-+      mtd = get_mtd_device_nm(part);
-+      if (IS_ERR(mtd))
-+              return PTR_ERR(mtd);
-+
-+      ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, (u_char *) mac);
-+      put_mtd_device(mtd);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(of_get_mac_address_mtd);
---- a/include/linux/of_net.h
-+++ b/include/linux/of_net.h
-@@ -11,6 +11,7 @@
- #include <linux/of.h>
- extern const int of_get_phy_mode(struct device_node *np);
- extern const void *of_get_mac_address(struct device_node *np);
-+extern int of_get_mac_address_mtd(struct device_node *np, void *mac);
- #else
- static inline const int of_get_phy_mode(struct device_node *np)
- {
diff --git a/target/linux/ramips/patches-3.10/0016-MIPS-ralink-mt7620-fix-usb-issue-during-frequency-sc.patch b/target/linux/ramips/patches-3.10/0016-MIPS-ralink-mt7620-fix-usb-issue-during-frequency-sc.patch
new file mode 100644 (file)
index 0000000..e29bb2b
--- /dev/null
@@ -0,0 +1,63 @@
+From 011f4bdba0dd4d1dff6d33b1a65541fc4f09c78e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 24 May 2013 21:28:08 +0200
+Subject: [PATCH 16/25] MIPS: ralink: mt7620: fix usb issue during frequency
+ scaling
+
+If the USB HCD is running and the cpu is scaled too low, then the USB stops
+working. Increase the idle speed of the core to fix this if the kernel is
+built with USB support.
+
+The values are taken from the Ralink SDK Kernel.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/include/asm/mach-ralink/mt7620.h |    1 +
+ arch/mips/ralink/mt7620.c                  |   19 +++++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+--- 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
+--- a/arch/mips/ralink/mt7620.c
++++ b/arch/mips/ralink/mt7620.c
+@@ -20,6 +20,12 @@
+ #include "common.h"
++/* clock scaling */
++#define CLKCFG_FDIV_MASK      0x1f00
++#define CLKCFG_FDIV_USB_VAL   0x0300
++#define CLKCFG_FFRAC_MASK     0x001f
++#define CLKCFG_FFRAC_USB_VAL  0x0003
++
+ /* does the board have sdram or ddram */
+ static int dram_type;
+@@ -170,6 +176,19 @@ void __init ralink_clk_init(void)
+       ralink_clk_add("10000500.uart", 40000000);
+       ralink_clk_add("10000b00.spi", 40000000);
+       ralink_clk_add("10000c00.uartlite", 40000000);
++
++      if (IS_ENABLED(CONFIG_USB)) {
++              /*
++               * When the CPU goes into sleep mode, the BUS clock will be too low for
++               * USB to function properly
++               */
++              u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG);
++
++              val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
++              val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
++
++              rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG);
++      }
+ }
+ void __init ralink_of_remap(void)
diff --git a/target/linux/ramips/patches-3.10/0016-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.10/0016-NET-MIPS-add-ralink-SoC-ethernet-driver.patch
deleted file mode 100644 (file)
index 4b20d62..0000000
+++ /dev/null
@@ -1,4732 +0,0 @@
-From ad11aedcc16574c0b3d3f5e40c67227d1846b94e Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 22 Apr 2013 23:20:03 +0200
-Subject: [PATCH 16/33] 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          |  232 ++++
- drivers/net/ethernet/ralink/mdio_rt2880.h          |   26 +
- drivers/net/ethernet/ralink/ralink_soc_eth.c       |  735 ++++++++++
- drivers/net/ethernet/ralink/ralink_soc_eth.h       |  374 +++++
- drivers/net/ethernet/ralink/soc_mt7620.c           |  111 ++
- drivers/net/ethernet/ralink/soc_rt2880.c           |   51 +
- drivers/net/ethernet/ralink/soc_rt305x.c           |  113 ++
- drivers/net/ethernet/ralink/soc_rt3883.c           |   60 +
- 20 files changed, 4606 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
-
---- /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
-@@ -135,6 +135,7 @@ config ETHOC
- source "drivers/net/ethernet/packetengines/Kconfig"
- source "drivers/net/ethernet/pasemi/Kconfig"
- source "drivers/net/ethernet/qlogic/Kconfig"
-+source "drivers/net/ethernet/ralink/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
-@@ -53,6 +53,7 @@ obj-$(CONFIG_ETHOC) += ethoc.o
- obj-$(CONFIG_NET_PACKET_ENGINE) += packetengines/
- obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/
- obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
-+obj-$(CONFIG_NET_RALINK) += ralink/
- obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
- obj-$(CONFIG_SH_ETH) += renesas/
- obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
---- /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
---- /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
---- /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);
-+}
---- /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
---- /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;
-+}
---- /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
---- /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);
-+}
---- /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
---- /dev/null
-+++ b/drivers/net/ethernet/ralink/mdio_rt2880.c
-@@ -0,0 +1,232 @@
-+/*
-+ *   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"
-+#include "mdio.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, int port)
-+{
-+      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[0])
-+              mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX;
-+
-+      if (priv->phy->rx_fc[0])
-+              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);
-+}
-+
-+void rt2880_port_init(struct fe_priv *priv, struct device_node *np)
-+{
-+      const __be32 *id = of_get_property(np, "reg", NULL);
-+      const __be32 *link;
-+      int size;
-+      int phy_mode;
-+
-+      if (!id || (be32_to_cpu(*id) != 0)) {
-+              pr_err("%s: invalid port id\n", np->name);
-+              return;
-+      }
-+
-+      priv->phy->phy_fixed[0] = of_get_property(np, "ralink,fixed-link", &size);
-+      if (priv->phy->phy_fixed[0] && (size != (4 * sizeof(*priv->phy->phy_fixed[0])))) {
-+              pr_err("%s: invalid fixed link property\n", np->name);
-+              priv->phy->phy_fixed[0] = NULL;
-+              return;
-+      }
-+
-+      phy_mode = of_get_phy_mode(np);
-+      switch (phy_mode) {
-+      case PHY_INTERFACE_MODE_RGMII:
-+              break;
-+      case PHY_INTERFACE_MODE_MII:
-+              break;
-+      case PHY_INTERFACE_MODE_RMII:
-+              break;
-+      default:
-+              if (!priv->phy->phy_fixed[0])
-+                      dev_err(priv->device, "port %d - invalid phy mode\n", priv->phy->speed[0]);
-+              break;
-+      }
-+
-+      priv->phy->phy_node[0] = of_parse_phandle(np, "phy-handle", 0);
-+      if (!priv->phy->phy_node[0] && !priv->phy->phy_fixed[0])
-+              return;
-+
-+      if (priv->phy->phy_fixed[0]) {
-+              link = priv->phy->phy_fixed[0];
-+              priv->phy->speed[0] = be32_to_cpup(link++);
-+              priv->phy->duplex[0] = be32_to_cpup(link++);
-+              priv->phy->tx_fc[0] = be32_to_cpup(link++);
-+              priv->phy->rx_fc[0] = be32_to_cpup(link++);
-+
-+              priv->link[0] = 1;
-+              switch (priv->phy->speed[0]) {
-+              case SPEED_10:
-+                      break;
-+              case SPEED_100:
-+                      break;
-+              case SPEED_1000:
-+                      break;
-+              default:
-+                      dev_err(priv->device, "invalid link speed: %d\n", priv->phy->speed[0]);
-+                      priv->phy->phy_fixed[0] = 0;
-+                      return;
-+              }
-+              dev_info(priv->device, "using fixed link parameters\n");
-+              rt2880_mdio_link_adjust(priv, 0);
-+              return;
-+      }
-+      if (priv->phy->phy_node[0] && priv->mii_bus->phy_map[0]) {
-+              fe_connect_phy_node(priv, priv->phy->phy_node[0]);
-+      }
-+
-+      return;
-+}
---- /dev/null
-+++ b/drivers/net/ethernet/ralink/mdio_rt2880.h
-@@ -0,0 +1,26 @@
-+/*
-+ *   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 port);
-+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);
-+void rt2880_port_init(struct fe_priv *priv, struct device_node *np);
-+
-+#endif
---- /dev/null
-+++ b/drivers/net/ethernet/ralink/ralink_soc_eth.c
-@@ -0,0 +1,735 @@
-+/*
-+ *   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,
-+};
-+
-+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;
-+
-+      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);
-+      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_receive_skb(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) {
-+              napi_complete(&priv->rx_napi);
-+              fe_int_enable(priv->soc->rx_dly_int);
-+      }
-+
-+      return rx;
-+}
-+
-+static void fe_tx_housekeeping(unsigned long ptr)
-+{
-+      struct net_device *dev = (struct net_device*)ptr;
-+      struct fe_priv *priv = netdev_priv(dev);
-+      unsigned int bytes_compl = 0;
-+      unsigned int pkts_compl = 0;
-+
-+      spin_lock(&priv->page_lock);
-+      while (1) {
-+              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;
-+      }
-+
-+      netdev_completed_queue(priv->netdev, pkts_compl, bytes_compl);
-+        spin_unlock(&priv->page_lock);
-+
-+      fe_int_enable(priv->soc->tx_dly_int);
-+}
-+
-+static void fe_tx_timeout(struct net_device *dev)
-+{
-+      struct fe_priv *priv = netdev_priv(dev);
-+
-+        tasklet_schedule(&priv->tx_tasklet);
-+      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);
-+              tasklet_schedule(&priv->tx_tasklet);
-+      }
-+
-+      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;
-+
-+      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);
-+
-+      tasklet_init(&priv->tx_tasklet, fe_tx_housekeeping, (unsigned long)dev);
-+
-+      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)) | 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);
-+
-+      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);
-+
-+      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);
-+
-+      tasklet_kill(&priv->tx_tasklet);
-+
-+      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;
-+
-+      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);
-+
-+      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);
-+
-+      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");
---- /dev/null
-+++ b/drivers/net/ethernet/ralink/ralink_soc_eth.h
-@@ -0,0 +1,374 @@
-+/*
-+ *   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];
-+      int                     tx_fc[8];
-+      int                     rx_fc[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 napi_struct            rx_napi;
-+      struct sk_buff                  *rx_skb[NUM_DMA_DESC];
-+      dma_addr_t                      rx_phys;
-+
-+      struct fe_tx_dma                *tx_dma;
-+      struct tasklet_struct           tx_tasklet;
-+      struct sk_buff                  *tx_skb[NUM_DMA_DESC];
-+      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 */
---- /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);
---- /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_adjust_link = 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);
---- /dev/null
-+++ b/drivers/net/ethernet/ralink/soc_rt305x.c
-@@ -0,0 +1,113 @@
-+/*
-+ *   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)
-+{
-+      unsigned long sysclk = priv->sysclk;
-+
-+      if (sysclk) {
-+              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)) | sysclk,
-+                      FE_FE_GLO_CFG);
-+      }
-+
-+      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);
---- /dev/null
-+++ b/drivers/net/ethernet/ralink/soc_rt3883.c
-@@ -0,0 +1,60 @@
-+/*
-+ *   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_adjust_link = rt2880_mdio_link_adjust,
-+      .port_init = rt2880_port_init,
-+};
-+
-+const struct of_device_id of_fe_match[] = {
-+      { .compatible = "ralink,rt3883-eth", .data = &rt3883_data },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, of_fe_match);
-+
diff --git a/target/linux/ramips/patches-3.10/0017-MIPS-ralink-mt7620-this-SoC-has-ehci-and-ohci-hosts.patch b/target/linux/ramips/patches-3.10/0017-MIPS-ralink-mt7620-this-SoC-has-ehci-and-ohci-hosts.patch
new file mode 100644 (file)
index 0000000..a783bd0
--- /dev/null
@@ -0,0 +1,23 @@
+From c16c0b66594cb0be44e150dbe3fda747817b873d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jul 2013 17:50:53 +0200
+Subject: [PATCH 17/25] MIPS: ralink: mt7620: this SoC has ehci and ohci hosts
+
+Select the the EHCI and OHCI symbols.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/ralink/Kconfig |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/mips/ralink/Kconfig
++++ b/arch/mips/ralink/Kconfig
+@@ -29,6 +29,8 @@ choice
+       config SOC_MT7620
+               bool "MT7620"
++              select USB_ARCH_HAS_OHCI
++              select USB_ARCH_HAS_EHCI
+ endchoice
diff --git a/target/linux/ramips/patches-3.10/0017-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch b/target/linux/ramips/patches-3.10/0017-USB-MIPS-ralink-fix-usb-issue-on-mt7620.patch
deleted file mode 100644 (file)
index aa00e87..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-From 3f40514a51b44171d274ef6a7d66dce9ae7c349d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 24 May 2013 21:28:08 +0200
-Subject: [PATCH 17/33] 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(+)
-
---- 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
---- a/arch/mips/ralink/mt7620.c
-+++ b/arch/mips/ralink/mt7620.c
-@@ -185,6 +185,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
- }