lantiq: update 3.14 patches
authorJohn Crispin <john@openwrt.org>
Thu, 11 Sep 2014 17:49:57 +0000 (17:49 +0000)
committerJohn Crispin <john@openwrt.org>
Thu, 11 Sep 2014 17:49:57 +0000 (17:49 +0000)
Signed-off-by: John Crispin <blogic@openwrt.org>
SVN-Revision: 42476

56 files changed:
target/linux/lantiq/patches-3.14/0001-MIPS-lantiq-add-pcie-driver.patch
target/linux/lantiq/patches-3.14/0002-MIPS-lantiq-dtb-image-hack.patch
target/linux/lantiq/patches-3.14/0003-MIPS-lantiq-handle-vmmc-memory-reservation.patch
target/linux/lantiq/patches-3.14/0004-MIPS-lantiq-add-atm-hack.patch
target/linux/lantiq/patches-3.14/0005-MIPS-lantiq-add-reset-controller-api-support.patch
target/linux/lantiq/patches-3.14/0006-MIPS-lantiq-reboot-gphy-on-restart.patch
target/linux/lantiq/patches-3.14/0007-MIPS-lantiq-add-basic-tffs-driver.patch
target/linux/lantiq/patches-3.14/0008-MIPS-lantiq-backport-old-timer-code.patch
target/linux/lantiq/patches-3.14/0009-MIPS-lantiq-command-line-work-around.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0009-pinctrl-lantiq-fix-up-pinmux.patch [deleted file]
target/linux/lantiq/patches-3.14/0010-MIPS-lantiq-export-soc-type.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0010-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch [deleted file]
target/linux/lantiq/patches-3.14/0011-lantiq-add-support-for-xrx200-firmware-depending-on-.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0011-owrt-generic-dtb-image-hack.patch [deleted file]
target/linux/lantiq/patches-3.14/0012-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch [deleted file]
target/linux/lantiq/patches-3.14/0012-pinctrl-lantiq-fix-up-pinmux.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0013-MTD-lantiq-xway-fix-invalid-operator.patch
target/linux/lantiq/patches-3.14/0014-MTD-lantiq-xway-the-latched-command-should-be-persis.patch
target/linux/lantiq/patches-3.14/0015-MTD-lantiq-xway-remove-endless-loop.patch
target/linux/lantiq/patches-3.14/0016-MTD-lantiq-xway-add-missing-write_buf-and-read_buf-t.patch
target/linux/lantiq/patches-3.14/0017-MTD-xway-fix-nand-locking.patch
target/linux/lantiq/patches-3.14/0018-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch [deleted file]
target/linux/lantiq/patches-3.14/0018-MTD-nand-lots-of-xrx200-fixes.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch [deleted file]
target/linux/lantiq/patches-3.14/0020-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0020-NET-PHY-adds-driver-for-lantiq-PHY11G.patch [deleted file]
target/linux/lantiq/patches-3.14/0021-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0021-NET-lantiq-adds-PHY11G-firmware-blobs.patch [deleted file]
target/linux/lantiq/patches-3.14/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0022-NET-MIPS-lantiq-adds-xrx200-net.patch [deleted file]
target/linux/lantiq/patches-3.14/0023-NET-PHY-adds-driver-for-lantiq-PHY11G.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0023-NET-multi-phy-support.patch [deleted file]
target/linux/lantiq/patches-3.14/0024-NET-add-of_get_mac_address_mtd.patch [deleted file]
target/linux/lantiq/patches-3.14/0024-NET-lantiq-adds-PHY11G-firmware-blobs.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0025-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch [deleted file]
target/linux/lantiq/patches-3.14/0025-NET-MIPS-lantiq-adds-xrx200-net.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0026-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch [deleted file]
target/linux/lantiq/patches-3.14/0026-NET-multi-phy-support.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0027-NET-add-of_get_mac_address_mtd.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0027-USB-fix-roothub-for-IFXHCD.patch [deleted file]
target/linux/lantiq/patches-3.14/0028-NET-lantiq-various-etop-fixes.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0028-SPI-MIPS-lantiq-adds-spi-xway.patch [deleted file]
target/linux/lantiq/patches-3.14/0029-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0029-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch [deleted file]
target/linux/lantiq/patches-3.14/0030-GPIO-add-named-gpio-exports.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0030-MIPS-lantiq-command-line-work-around.patch [deleted file]
target/linux/lantiq/patches-3.14/0031-GPIO-add-named-gpio-exports.patch [deleted file]
target/linux/lantiq/patches-3.14/0031-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0032-USB-fix-roothub-for-IFXHCD.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0033-SPI-MIPS-lantiq-adds-spi-xway.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0034-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0036-owrt-generic-dtb-image-hack.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0037-MIPS-lantiq-move-eiu-init-after-irq_domain-register.patch [new file with mode: 0644]
target/linux/lantiq/patches-3.14/0101-mtd-split.patch [new file with mode: 0644]

index 9a9ac3611dd96310d1755301996eb654959476e2..3b4ad037d0fbf6e48690d5197b33ca88e5405c49 100644 (file)
@@ -1,7 +1,7 @@
 From 6f933347d0b4ed02d9534f5fa07f7b99f13eeaa1 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Thu, 7 Aug 2014 18:12:28 +0200
-Subject: [PATCH 01/31] MIPS: lantiq: add pcie driver
+Subject: [PATCH 01/36] MIPS: lantiq: add pcie driver
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
index 0b23afe06bf3d28f93ea898edb1e16eb637d668e..ce6c637131d54477d6360172b2441c7a85d1e13f 100644 (file)
@@ -1,7 +1,7 @@
 From 17348293f7f8103c97c8d2a6b0ef36eae06ec371 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Wed, 13 Mar 2013 09:36:16 +0100
-Subject: [PATCH 02/31] MIPS: lantiq: dtb image hack
+Subject: [PATCH 02/36] MIPS: lantiq: dtb image hack
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
index 36a53f2bae180695e7258bf1969d77218fedec66..eb1e2004a1ba98cf3247b5448ddf5d941a70fde4 100644 (file)
@@ -1,7 +1,7 @@
 From 16e315864132b59749faff739230daf4cee9abbb Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Wed, 13 Mar 2013 10:04:01 +0100
-Subject: [PATCH 03/31] MIPS: lantiq: handle vmmc memory reservation
+Subject: [PATCH 03/36] MIPS: lantiq: handle vmmc memory reservation
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
index f4262e53f9c97014887855a362902adcb6dd12f7..a01967f9c7781f87dffb137485a503f6218c64a8 100644 (file)
@@ -1,7 +1,7 @@
 From 9afadf01b1be371ee88491819aa67364684461f9 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Fri, 3 Aug 2012 10:27:25 +0200
-Subject: [PATCH 04/31] MIPS: lantiq: add atm hack
+Subject: [PATCH 04/36] MIPS: lantiq: add atm hack
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
index 36f64106866692594bbb86d3771be7fd0ba93059..c4540c930602983cd8db19301df97e6f6632f3a4 100644 (file)
@@ -1,7 +1,7 @@
 From 223f1c46e109a8420765aee099a5d1dc4ab7ee98 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Tue, 3 Sep 2013 13:18:12 +0200
-Subject: [PATCH 05/31] MIPS: lantiq: add reset-controller api support
+Subject: [PATCH 05/36] MIPS: lantiq: add reset-controller api support
 
 Add a reset-controller binding for the reset registers found on the lantiq
 SoC.
index 09a3b12b8ca09485362ce397468ef6cc4b2276d1..42acac21f270c51168e069918eaecc8eac1968c3 100644 (file)
@@ -1,7 +1,7 @@
 From f81979f4b297693ac70616feaa4a79bdcb11db35 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Thu, 7 Aug 2014 18:55:57 +0200
-Subject: [PATCH 06/31] MIPS: lantiq: reboot gphy on restart
+Subject: [PATCH 06/36] MIPS: lantiq: reboot gphy on restart
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
index a031b8e9a028d42aa8ae1b5450dddb2fba3074ba..a41d48ed322f57aa4a15d5ea4ee0251d0ca54479 100644 (file)
@@ -1,7 +1,7 @@
 From d27ec8bb97db0f60d81ab255d51ac4e967362067 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Thu, 7 Aug 2014 18:34:19 +0200
-Subject: [PATCH 07/31] MIPS: lantiq: add basic tffs driver
+Subject: [PATCH 07/36] MIPS: lantiq: add basic tffs driver
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
index bceda4c5875ad2531cd95861759369464199ac31..d946e560a4662e7ec19f6d303f62dfd7b203e228 100644 (file)
@@ -1,7 +1,7 @@
 From 94800350cb8d2f29dda2206b5e9a3772024ee168 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Thu, 7 Aug 2014 18:30:56 +0200
-Subject: [PATCH 08/31] MIPS: lantiq: backport old timer code
+Subject: [PATCH 08/36] MIPS: lantiq: backport old timer code
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
diff --git a/target/linux/lantiq/patches-3.14/0009-MIPS-lantiq-command-line-work-around.patch b/target/linux/lantiq/patches-3.14/0009-MIPS-lantiq-command-line-work-around.patch
new file mode 100644 (file)
index 0000000..2536745
--- /dev/null
@@ -0,0 +1,26 @@
+From ed348924cd59ef0c8a4bc4e015e2b7e581a00fa8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 12 Aug 2014 21:40:41 +0200
+Subject: [PATCH 09/36] MIPS: lantiq: command line work around
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/prom.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
+index 202e118..227feed 100644
+--- a/arch/mips/lantiq/prom.c
++++ b/arch/mips/lantiq/prom.c
+@@ -74,6 +74,8 @@ void __init plat_mem_setup(void)
+        * parsed resulting in our memory appearing
+        */
+       __dt_setup_arch(&__image_dtb);
++
++      strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+ }
+ void __init device_tree_init(void)
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0009-pinctrl-lantiq-fix-up-pinmux.patch b/target/linux/lantiq/patches-3.14/0009-pinctrl-lantiq-fix-up-pinmux.patch
deleted file mode 100644 (file)
index 267c898..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-From 29452de974f2cdc87876dbdc18a16405ef80c05f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 9 Aug 2013 20:38:15 +0200
-Subject: [PATCH 09/31] pinctrl/lantiq: fix up pinmux
-
-We found out how to set the gphy led pinmuxing.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/pinctrl/pinctrl-xway.c |   28 ++++++++++++++++++++++++++--
- 1 file changed, 26 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
-index e66f4ca..b5f43c8 100644
---- a/drivers/pinctrl/pinctrl-xway.c
-+++ b/drivers/pinctrl/pinctrl-xway.c
-@@ -609,10 +609,9 @@ static struct pinctrl_desc xway_pctrl_desc = {
-       .confops        = &xway_pinconf_ops,
- };
--static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
-+static int mux_apply(struct ltq_pinmux_info *info,
-                               int pin, int mux)
- {
--      struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-       int port = PORT(pin);
-       u32 alt1_reg = GPIO_ALT1(pin);
-@@ -632,6 +631,14 @@ static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
-       return 0;
- }
-+static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
-+                              int pin, int mux)
-+{
-+      struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-+
-+      return mux_apply(info, pin, mux);
-+}
-+
- static const struct ltq_cfg_param xway_cfg_params[] = {
-       {"lantiq,pull",         LTQ_PINCONF_PARAM_PULL},
-       {"lantiq,open-drain",   LTQ_PINCONF_PARAM_OPEN_DRAIN},
-@@ -676,6 +683,10 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
- {
-       struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
-+      if (PORT(pin) == PORT3)
-+              gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin));
-+      else
-+              gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin));
-       gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
-       xway_gpio_set(chip, pin, val);
-@@ -696,6 +707,18 @@ static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
-       pinctrl_free_gpio(gpio);
- }
-+static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-+{
-+      struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
-+      int i;
-+
-+      for (i = 0; i < info->num_exin; i++)
-+              if (info->exin[i] == offset)
-+                      return ltq_eiu_get_irq(i);
-+
-+      return -1;
-+}
-+
- static struct gpio_chip xway_chip = {
-       .label = "gpio-xway",
-       .direction_input = xway_gpio_dir_in,
-@@ -704,6 +727,7 @@ static struct gpio_chip xway_chip = {
-       .set = xway_gpio_set,
-       .request = xway_gpio_req,
-       .free = xway_gpio_free,
-+      .to_irq = xway_gpio_to_irq,
-       .base = -1,
- };
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0010-MIPS-lantiq-export-soc-type.patch b/target/linux/lantiq/patches-3.14/0010-MIPS-lantiq-export-soc-type.patch
new file mode 100644 (file)
index 0000000..de1cd52
--- /dev/null
@@ -0,0 +1,46 @@
+From 6804142b47f2634b0657e4dfcec7a34e982b6ddb Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 10 Sep 2014 22:29:21 +0200
+Subject: [PATCH 10/36] MIPS: lantiq: export soc type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ arch/mips/include/asm/mach-lantiq/lantiq.h |    2 ++
+ arch/mips/lantiq/prom.c                    |    5 +++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
+index f196cce..4e5ae65 100644
+--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
++++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
+@@ -48,6 +48,8 @@ extern struct clk *clk_get_ppe(void);
+ extern unsigned char ltq_boot_select(void);
+ /* find out what caused the last cpu reset */
+ extern int ltq_reset_cause(void);
++/* find out the soc type */
++extern int ltq_soc_type(void);
+ #define IOPORT_RESOURCE_START 0x10000000
+ #define IOPORT_RESOURCE_END   0xffffffff
+diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
+index 227feed..4c652c6 100644
+--- a/arch/mips/lantiq/prom.c
++++ b/arch/mips/lantiq/prom.c
+@@ -36,6 +36,11 @@ const char *get_system_type(void)
+       return soc_info.sys_type;
+ }
++int ltq_soc_type(void)
++{
++      return soc_info.type;
++}
++
+ void prom_free_prom_memory(void)
+ {
+ }
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0010-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch b/target/linux/lantiq/patches-3.14/0010-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch
deleted file mode 100644 (file)
index 849e670..0000000
+++ /dev/null
@@ -1,606 +0,0 @@
-From 9f921445b6dbf2beef397c6aa038db135e92eb80 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Wed, 13 Mar 2013 10:02:58 +0100
-Subject: [PATCH 10/31] owrt: lantiq: wifi and ethernet eeprom handling
-
----
- arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h  |    6 +
- .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    3 +
- arch/mips/lantiq/xway/Makefile                     |    3 +
- arch/mips/lantiq/xway/ath_eep.c                    |  277 ++++++++++++++++++++
- arch/mips/lantiq/xway/eth_mac.c                    |   76 ++++++
- arch/mips/lantiq/xway/pci-ath-fixup.c              |  109 ++++++++
- arch/mips/lantiq/xway/rt_eep.c                     |   60 +++++
- 7 files changed, 534 insertions(+)
- create mode 100644 arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
- create mode 100644 arch/mips/lantiq/xway/ath_eep.c
- create mode 100644 arch/mips/lantiq/xway/eth_mac.c
- create mode 100644 arch/mips/lantiq/xway/pci-ath-fixup.c
- create mode 100644 arch/mips/lantiq/xway/rt_eep.c
-
-diff --git a/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h b/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
-new file mode 100644
-index 0000000..095d261
---- /dev/null
-+++ b/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
-@@ -0,0 +1,6 @@
-+#ifndef _PCI_ATH_FIXUP
-+#define _PCI_ATH_FIXUP
-+
-+void ltq_pci_ath_fixup(unsigned slot, u16 *cal_data) __init;
-+
-+#endif /* _PCI_ATH_FIXUP */
-diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-index 133336b..779715c 100644
---- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -90,5 +90,8 @@ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
- extern void ltq_pmu_enable(unsigned int module);
- extern void ltq_pmu_disable(unsigned int module);
-+/* allow the ethernet driver to load a flash mapped mac addr */
-+const u8* ltq_get_eth_mac(void);
-+
- #endif /* CONFIG_SOC_TYPE_XWAY */
- #endif /* _LTQ_XWAY_H__ */
-diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
-index 2dd442c..de876e1 100644
---- a/arch/mips/lantiq/xway/Makefile
-+++ b/arch/mips/lantiq/xway/Makefile
-@@ -2,4 +2,7 @@ obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
- obj-y += vmmc.o tffs.o
-+obj-y += eth_mac.o
-+obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
-+
- obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
-diff --git a/arch/mips/lantiq/xway/ath_eep.c b/arch/mips/lantiq/xway/ath_eep.c
-new file mode 100644
-index 0000000..cd07f9a
---- /dev/null
-+++ b/arch/mips/lantiq/xway/ath_eep.c
-@@ -0,0 +1,277 @@
-+/*
-+ *  Copyright (C) 2011 Luca Olivetti <luca@ventoso.org>
-+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
-+ *  Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com>
-+ *  Copyright (C) 2013 Álvaro Fernández Rojas <noltari@gmail.com>
-+ *  Copyright (C) 2013 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
-+ *
-+ *  This program is free software; you can redistribute it and/or modify it
-+ *  under the terms of the GNU General Public License version 2 as published
-+ *  by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ath5k_platform.h>
-+#include <linux/ath9k_platform.h>
-+#include <linux/pci.h>
-+#include <linux/err.h>
-+#include <linux/mtd/mtd.h>
-+#include <pci-ath-fixup.h>
-+#include <lantiq_soc.h>
-+
-+extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
-+struct ath5k_platform_data ath5k_pdata;
-+struct ath9k_platform_data ath9k_pdata = {
-+      .led_pin = -1,
-+};
-+static u8 athxk_eeprom_mac[6];
-+
-+static int ath9k_pci_plat_dev_init(struct pci_dev *dev)
-+{
-+      dev->dev.platform_data = &ath9k_pdata;
-+      return 0;
-+}
-+
-+static int ath9k_eep_load;
-+int __init of_ath9k_eeprom_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node, *mtd_np;
-+      struct resource *eep_res, *mac_res = NULL;
-+      void __iomem *eep, *mac;
-+      int mac_offset;
-+      u32 mac_inc = 0, pci_slot = 0;
-+      int i;
-+      struct mtd_info *the_mtd;
-+      size_t flash_readlen;
-+      const __be32 *list;
-+      const char *part;
-+      phandle phandle;
-+
-+      if ((list = of_get_property(np, "ath,eep-flash", &i)) && i == 2 *
-+                      sizeof(*list) && (phandle = be32_to_cpup(list++)) &&
-+                      (mtd_np = of_find_node_by_phandle(phandle)) && ((part =
-+                      of_get_property(mtd_np, "label", NULL)) || (part =
-+                      mtd_np->name)) && (the_mtd = get_mtd_device_nm(part))
-+                      != ERR_PTR(-ENODEV)) {
-+              i = mtd_read(the_mtd, be32_to_cpup(list),
-+                              ATH9K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
-+                              (void *) ath9k_pdata.eeprom_data);
-+              if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
-+                      size_t mac_readlen;
-+                      mtd_read(the_mtd, mac_offset, 6, &mac_readlen,
-+                              (void *) athxk_eeprom_mac);
-+              }
-+              put_mtd_device(the_mtd);
-+              if ((sizeof(ath9k_pdata.eeprom_data) != flash_readlen) || i) {
-+                      dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
-+                      return -ENODEV;
-+              }
-+      } else {
-+              eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+              mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+
-+              if (!eep_res) {
-+                      dev_err(&pdev->dev, "failed to load eeprom address\n");
-+                      return -ENODEV;
-+              }
-+              if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS << 1) {
-+                      dev_err(&pdev->dev, "eeprom has an invalid size\n");
-+                      return -EINVAL;
-+              }
-+
-+              eep = ioremap(eep_res->start, resource_size(eep_res));
-+              memcpy_fromio(ath9k_pdata.eeprom_data, eep,
-+                              ATH9K_PLAT_EEP_MAX_WORDS << 1);
-+      }
-+
-+      if (of_find_property(np, "ath,eep-swap", NULL))
-+              for (i = 0; i < ATH9K_PLAT_EEP_MAX_WORDS; i++)
-+                      ath9k_pdata.eeprom_data[i] = swab16(ath9k_pdata.eeprom_data[i]);
-+
-+      if (of_find_property(np, "ath,eep-endian", NULL)) {
-+              ath9k_pdata.endian_check = true;
-+
-+              dev_info(&pdev->dev, "endian check enabled.\n");
-+      }
-+
-+      if (!is_valid_ether_addr(athxk_eeprom_mac)) {
-+              if (mac_res) {
-+                      if (resource_size(mac_res) != 6) {
-+                              dev_err(&pdev->dev, "mac has an invalid size\n");
-+                              return -EINVAL;
-+                      }
-+                      mac = ioremap(mac_res->start, resource_size(mac_res));
-+                      memcpy_fromio(athxk_eeprom_mac, mac, 6);
-+              } else if (ltq_get_eth_mac()) {
-+                      memcpy(athxk_eeprom_mac, ltq_get_eth_mac(), 6);
-+              }
-+      }
-+      if (!is_valid_ether_addr(athxk_eeprom_mac)) {
-+              dev_warn(&pdev->dev, "using random mac\n");
-+              random_ether_addr(athxk_eeprom_mac);
-+      }
-+
-+      if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
-+              athxk_eeprom_mac[5] += mac_inc;
-+
-+      ath9k_pdata.macaddr = athxk_eeprom_mac;
-+      ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
-+
-+      if (!of_property_read_u32(np, "ath,pci-slot", &pci_slot)) {
-+              ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
-+
-+              dev_info(&pdev->dev, "pci slot: %u\n", pci_slot);
-+                if (ath9k_eep_load) {
-+                        struct pci_dev *d = NULL;
-+                        while ((d = pci_get_device(PCI_VENDOR_ID_ATHEROS,
-+                                        PCI_ANY_ID, d)) != NULL)
-+                                pci_fixup_device(pci_fixup_early, d);
-+                }
-+
-+      }
-+
-+      dev_info(&pdev->dev, "loaded ath9k eeprom\n");
-+
-+      return 0;
-+}
-+
-+static struct of_device_id ath9k_eeprom_ids[] = {
-+      { .compatible = "ath9k,eeprom" },
-+      { }
-+};
-+
-+static struct platform_driver ath9k_eeprom_driver = {
-+      .driver         = {
-+              .name           = "ath9k,eeprom",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = of_match_ptr(ath9k_eeprom_ids),
-+      },
-+};
-+
-+static int __init of_ath9k_eeprom_init(void)
-+{
-+        int ret = platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
-+
-+        if (ret)
-+                ath9k_eep_load = 1;
-+
-+        return ret;
-+}
-+
-+static int __init of_ath9k_eeprom_init_late(void)
-+{
-+        if (!ath9k_eep_load)
-+                return 0;
-+        return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
-+}
-+late_initcall(of_ath9k_eeprom_init_late);
-+subsys_initcall(of_ath9k_eeprom_init);
-+
-+
-+static int ath5k_pci_plat_dev_init(struct pci_dev *dev)
-+{
-+      dev->dev.platform_data = &ath5k_pdata;
-+      return 0;
-+}
-+
-+int __init of_ath5k_eeprom_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node, *mtd_np;
-+      struct resource *eep_res, *mac_res = NULL;
-+      void __iomem *eep, *mac;
-+      int mac_offset;
-+      u32 mac_inc = 0;
-+      int i;
-+      struct mtd_info *the_mtd;
-+      size_t flash_readlen;
-+      const __be32 *list;
-+      const char *part;
-+      phandle phandle;
-+
-+      if ((list = of_get_property(np, "ath,eep-flash", &i)) && i == 2 *
-+                      sizeof(*list) && (phandle = be32_to_cpup(list++)) &&
-+                      (mtd_np = of_find_node_by_phandle(phandle)) && ((part =
-+                      of_get_property(mtd_np, "label", NULL)) || (part =
-+                      mtd_np->name)) && (the_mtd = get_mtd_device_nm(part))
-+                      != ERR_PTR(-ENODEV)) {
-+              i = mtd_read(the_mtd, be32_to_cpup(list),
-+                              ATH5K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
-+                              (void *) ath5k_pdata.eeprom_data);
-+              put_mtd_device(the_mtd);
-+              if ((sizeof(ATH5K_PLAT_EEP_MAX_WORDS << 1) != flash_readlen)
-+                              || i) {
-+                      dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
-+                      return -ENODEV;
-+              }
-+      } else {
-+              eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+              mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+
-+              if (!eep_res) {
-+                      dev_err(&pdev->dev, "failed to load eeprom address\n");
-+                      return -ENODEV;
-+              }
-+              if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS << 1) {
-+                      dev_err(&pdev->dev, "eeprom has an invalid size\n");
-+                      return -EINVAL;
-+              }
-+
-+              eep = ioremap(eep_res->start, resource_size(eep_res));
-+              ath5k_pdata.eeprom_data = kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1,
-+                              GFP_KERNEL);
-+              memcpy_fromio(ath5k_pdata.eeprom_data, eep,
-+                              ATH5K_PLAT_EEP_MAX_WORDS << 1);
-+      }
-+
-+      if (of_find_property(np, "ath,eep-swap", NULL))
-+              for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS; i++)
-+                      ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]);
-+
-+      if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
-+              memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data + mac_offset, 6);
-+      } else if (mac_res) {
-+              if (resource_size(mac_res) != 6) {
-+                      dev_err(&pdev->dev, "mac has an invalid size\n");
-+                      return -EINVAL;
-+              }
-+              mac = ioremap(mac_res->start, resource_size(mac_res));
-+              memcpy_fromio(athxk_eeprom_mac, mac, 6);
-+      } else if (ltq_get_eth_mac())
-+              memcpy(athxk_eeprom_mac, ltq_get_eth_mac(), 6);
-+      else {
-+              dev_warn(&pdev->dev, "using random mac\n");
-+              random_ether_addr(athxk_eeprom_mac);
-+      }
-+
-+      if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
-+              athxk_eeprom_mac[5] += mac_inc;
-+
-+      ath5k_pdata.macaddr = athxk_eeprom_mac;
-+      ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
-+
-+      dev_info(&pdev->dev, "loaded ath5k eeprom\n");
-+
-+      return 0;
-+}
-+
-+static struct of_device_id ath5k_eeprom_ids[] = {
-+      { .compatible = "ath5k,eeprom" },
-+      { }
-+};
-+
-+static struct platform_driver ath5k_eeprom_driver = {
-+      .driver         = {
-+              .name           = "ath5k,eeprom",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = of_match_ptr(ath5k_eeprom_ids),
-+      },
-+};
-+
-+static int __init of_ath5k_eeprom_init(void)
-+{
-+      return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe);
-+}
-+device_initcall(of_ath5k_eeprom_init);
-diff --git a/arch/mips/lantiq/xway/eth_mac.c b/arch/mips/lantiq/xway/eth_mac.c
-new file mode 100644
-index 0000000..d288a0e
---- /dev/null
-+++ b/arch/mips/lantiq/xway/eth_mac.c
-@@ -0,0 +1,76 @@
-+/*
-+ *  Copyright (C) 2012 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/init.h>
-+#include <linux/module.h>
-+#include <linux/of_platform.h>
-+#include <linux/if_ether.h>
-+
-+static u8 eth_mac[6];
-+static int eth_mac_set;
-+
-+const u8* ltq_get_eth_mac(void)
-+{
-+      return eth_mac;
-+}
-+
-+static int __init setup_ethaddr(char *str)
-+{
-+      eth_mac_set = mac_pton(str, eth_mac);
-+      return !eth_mac_set;
-+}
-+__setup("ethaddr=", setup_ethaddr);
-+
-+int __init of_eth_mac_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node;
-+      struct resource *mac_res;
-+      void __iomem *mac;
-+      u32 mac_inc = 0;
-+
-+      if (eth_mac_set) {
-+              dev_err(&pdev->dev, "mac was already set by bootloader\n");
-+              return -EINVAL;
-+      }
-+      mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+
-+      if (!mac_res) {
-+              dev_err(&pdev->dev, "failed to load mac\n");
-+              return -EINVAL;
-+      }
-+      if (resource_size(mac_res) != 6) {
-+              dev_err(&pdev->dev, "mac has an invalid size\n");
-+              return -EINVAL;
-+      }
-+      mac = ioremap(mac_res->start, resource_size(mac_res));
-+      memcpy_fromio(eth_mac, mac, 6);
-+
-+      if (!of_property_read_u32(np, "mac-increment", &mac_inc))
-+              eth_mac[5] += mac_inc;
-+
-+      return 0;
-+}
-+
-+static struct of_device_id eth_mac_ids[] = {
-+      { .compatible = "lantiq,eth-mac" },
-+      { /* sentinel */ }
-+};
-+
-+static struct platform_driver eth_mac_driver = {
-+      .driver         = {
-+              .name           = "lantiq,eth-mac",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = of_match_ptr(eth_mac_ids),
-+      },
-+};
-+
-+static int __init of_eth_mac_init(void)
-+{
-+      return platform_driver_probe(&eth_mac_driver, of_eth_mac_probe);
-+}
-+device_initcall(of_eth_mac_init);
-diff --git a/arch/mips/lantiq/xway/pci-ath-fixup.c b/arch/mips/lantiq/xway/pci-ath-fixup.c
-new file mode 100644
-index 0000000..c87ffb2
---- /dev/null
-+++ b/arch/mips/lantiq/xway/pci-ath-fixup.c
-@@ -0,0 +1,109 @@
-+/*
-+ *  Atheros AP94 reference board PCI initialization
-+ *
-+ *  Copyright (C) 2009-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.
-+ */
-+
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <lantiq_soc.h>
-+
-+#define LTQ_PCI_MEM_BASE              0x18000000
-+
-+struct ath_fixup {
-+      u16             *cal_data;
-+      unsigned        slot;
-+};
-+
-+static int ath_num_fixups;
-+static struct ath_fixup ath_fixups[2];
-+
-+static void ath_pci_fixup(struct pci_dev *dev)
-+{
-+      void __iomem *mem;
-+      u16 *cal_data = NULL;
-+      u16 cmd;
-+      u32 bar0;
-+      u32 val;
-+      unsigned i;
-+
-+      for (i = 0; i < ath_num_fixups; i++) {
-+              if (ath_fixups[i].cal_data == NULL)
-+                      continue;
-+
-+              if (ath_fixups[i].slot != PCI_SLOT(dev->devfn))
-+                      continue;
-+
-+              cal_data = ath_fixups[i].cal_data;
-+              break;
-+      }
-+
-+      if (cal_data == NULL)
-+              return;
-+
-+      if (*cal_data != 0xa55a) {
-+              pr_err("pci %s: invalid calibration data\n", pci_name(dev));
-+              return;
-+      }
-+
-+      pr_info("pci %s: fixup device configuration\n", pci_name(dev));
-+
-+      mem = ioremap(LTQ_PCI_MEM_BASE, 0x10000);
-+      if (!mem) {
-+              pr_err("pci %s: ioremap error\n", pci_name(dev));
-+              return;
-+      }
-+
-+      pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
-+      pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, LTQ_PCI_MEM_BASE);
-+      pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+      cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
-+      pci_write_config_word(dev, PCI_COMMAND, cmd);
-+
-+      /* set pointer to first reg address */
-+      cal_data += 3;
-+      while (*cal_data != 0xffff) {
-+              u32 reg;
-+              reg = *cal_data++;
-+              val = *cal_data++;
-+              val |= (*cal_data++) << 16;
-+
-+              ltq_w32(swab32(val), mem + reg);
-+              udelay(100);
-+      }
-+
-+      pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
-+      dev->vendor = val & 0xffff;
-+      dev->device = (val >> 16) & 0xffff;
-+
-+      pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
-+      dev->revision = val & 0xff;
-+      dev->class = val >> 8; /* upper 3 bytes */
-+
-+      pr_info("pci %s: fixup info: [%04x:%04x] revision %02x class %#08x\n", 
-+              pci_name(dev), dev->vendor, dev->device, dev->revision, dev->class);
-+
-+      pci_read_config_word(dev, PCI_COMMAND, &cmd);
-+      cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-+      pci_write_config_word(dev, PCI_COMMAND, cmd);
-+
-+      pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
-+
-+      iounmap(mem);
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath_pci_fixup);
-+
-+void __init ltq_pci_ath_fixup(unsigned slot, u16 *cal_data)
-+{
-+      if (ath_num_fixups >= ARRAY_SIZE(ath_fixups))
-+              return;
-+
-+      ath_fixups[ath_num_fixups].slot = slot;
-+      ath_fixups[ath_num_fixups].cal_data = cal_data;
-+      ath_num_fixups++;
-+}
-diff --git a/arch/mips/lantiq/xway/rt_eep.c b/arch/mips/lantiq/xway/rt_eep.c
-new file mode 100644
-index 0000000..00f2d4c
---- /dev/null
-+++ b/arch/mips/lantiq/xway/rt_eep.c
-@@ -0,0 +1,60 @@
-+/*
-+ *  Copyright (C) 2011 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/init.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/platform_device.h>
-+#include <linux/rt2x00_platform.h>
-+
-+extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
-+static struct rt2x00_platform_data rt2x00_pdata;
-+
-+static int rt2x00_pci_plat_dev_init(struct pci_dev *dev)
-+{
-+      dev->dev.platform_data = &rt2x00_pdata;
-+      return 0;
-+}
-+
-+int __init of_ralink_eeprom_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node;
-+      const char *eeprom;
-+
-+      if (of_property_read_string(np, "ralink,eeprom", &eeprom)) {
-+              dev_err(&pdev->dev, "failed to load eeprom filename\n");
-+              return 0;
-+      }
-+
-+      rt2x00_pdata.eeprom_file_name = kstrdup(eeprom, GFP_KERNEL);
-+//    rt2x00_pdata.mac_address = mac;
-+      ltq_pci_plat_dev_init = rt2x00_pci_plat_dev_init;
-+
-+      dev_info(&pdev->dev, "using %s as eeprom\n", eeprom);
-+
-+      return 0;
-+}
-+
-+static struct of_device_id ralink_eeprom_ids[] = {
-+      { .compatible = "ralink,eeprom" },
-+      { }
-+};
-+
-+static struct platform_driver ralink_eeprom_driver = {
-+      .driver         = {
-+              .name           = "ralink,eeprom",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = of_match_ptr(ralink_eeprom_ids),
-+      },
-+};
-+
-+static int __init of_ralink_eeprom_init(void)
-+{
-+      return platform_driver_probe(&ralink_eeprom_driver, of_ralink_eeprom_probe);
-+}
-+device_initcall(of_ralink_eeprom_init);
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0011-lantiq-add-support-for-xrx200-firmware-depending-on-.patch b/target/linux/lantiq/patches-3.14/0011-lantiq-add-support-for-xrx200-firmware-depending-on-.patch
new file mode 100644 (file)
index 0000000..36d03b1
--- /dev/null
@@ -0,0 +1,46 @@
+From 85f0df34dee96048515ef1e01d88524bd579f8e0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 10 Sep 2014 22:39:19 +0200
+Subject: [PATCH 11/36] lantiq: add support for xrx200 firmware depending on
+ soc type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+---
+ arch/mips/lantiq/xway/xrx200_phy_fw.c |   18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/arch/mips/lantiq/xway/xrx200_phy_fw.c b/arch/mips/lantiq/xway/xrx200_phy_fw.c
+index d4d9d31..3479b77 100644
+--- a/arch/mips/lantiq/xway/xrx200_phy_fw.c
++++ b/arch/mips/lantiq/xway/xrx200_phy_fw.c
+@@ -24,7 +24,23 @@ static dma_addr_t xway_gphy_load(struct platform_device *pdev)
+       void *fw_addr;
+       size_t size;
+-      if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
++      if (of_get_property(pdev->dev.of_node, "firmware1", NULL) || of_get_property(pdev->dev.of_node, "firmware2", NULL)) {
++              switch(ltq_soc_type()) {
++                      case SOC_TYPE_VR9:
++                              if (of_property_read_string(pdev->dev.of_node, "firmware1", &fw_name)) {
++                                      dev_err(&pdev->dev, "failed to load firmware filename\n");
++                                      return 0;
++                              }
++                              break;
++                      case SOC_TYPE_VR9_2:
++                              if (of_property_read_string(pdev->dev.of_node, "firmware2", &fw_name)) {
++                                      dev_err(&pdev->dev, "failed to load firmware filename\n");
++                                      return 0;
++                              }
++                              break;
++              }
++      }
++      else if (of_property_read_string(pdev->dev.of_node, "firmware", &fw_name)) {
+               dev_err(&pdev->dev, "failed to load firmware filename\n");
+               return 0;
+       }
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0011-owrt-generic-dtb-image-hack.patch b/target/linux/lantiq/patches-3.14/0011-owrt-generic-dtb-image-hack.patch
deleted file mode 100644 (file)
index e07d7ce..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 572e107a37deb7bc8512ca9144f4e8f24b36e451 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 7 Aug 2014 18:32:12 +0200
-Subject: [PATCH 11/31] owrt: generic dtb image hack
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/kernel/head.S |    3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
-index 7b6a5b3..78518b8 100644
---- a/arch/mips/kernel/head.S
-+++ b/arch/mips/kernel/head.S
-@@ -101,6 +101,9 @@ FEXPORT(__kernel_entry)
-       j       kernel_entry
- #endif
-+      .ascii  "OWRTDTB:"
-+      EXPORT(__image_dtb)
-+      .fill   0x4000
-       __REF
- NESTED(kernel_entry, 16, sp)                  # kernel entry point
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0012-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch b/target/linux/lantiq/patches-3.14/0012-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch
deleted file mode 100644 (file)
index 432fa6b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 6c476b89f3d685b41f2e216698fc8c90ddb11dfd Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 7 Aug 2014 18:18:00 +0200
-Subject: [PATCH 12/31] MTD: lantiq: handle NO_XIP on cfi0001 flash
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/mtd/maps/lantiq-flash.c |    6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
-index 93c507a..710d699 100644
---- a/drivers/mtd/maps/lantiq-flash.c
-+++ b/drivers/mtd/maps/lantiq-flash.c
-@@ -140,7 +140,11 @@ ltq_mtd_probe(struct platform_device *pdev)
-       if (!ltq_mtd->map)
-               return -ENOMEM;
--      ltq_mtd->map->phys = ltq_mtd->res->start;
-+      if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL))
-+              ltq_mtd->map->phys = NO_XIP;
-+      else
-+              ltq_mtd->map->phys = ltq_mtd->res->start;
-+      ltq_mtd->res->start;
-       ltq_mtd->map->size = resource_size(ltq_mtd->res);
-       ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res);
-       if (IS_ERR(ltq_mtd->map->virt))
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0012-pinctrl-lantiq-fix-up-pinmux.patch b/target/linux/lantiq/patches-3.14/0012-pinctrl-lantiq-fix-up-pinmux.patch
new file mode 100644 (file)
index 0000000..9b45bf7
--- /dev/null
@@ -0,0 +1,84 @@
+From 25494c55a4007a1409f53ddbafd661636e47ea34 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 9 Aug 2013 20:38:15 +0200
+Subject: [PATCH 12/36] pinctrl/lantiq: fix up pinmux
+
+We found out how to set the gphy led pinmuxing.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/pinctrl/pinctrl-xway.c |   28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
+index e66f4ca..b5f43c8 100644
+--- a/drivers/pinctrl/pinctrl-xway.c
++++ b/drivers/pinctrl/pinctrl-xway.c
+@@ -609,10 +609,9 @@ static struct pinctrl_desc xway_pctrl_desc = {
+       .confops        = &xway_pinconf_ops,
+ };
+-static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
++static int mux_apply(struct ltq_pinmux_info *info,
+                               int pin, int mux)
+ {
+-      struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
+       int port = PORT(pin);
+       u32 alt1_reg = GPIO_ALT1(pin);
+@@ -632,6 +631,14 @@ static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
+       return 0;
+ }
++static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
++                              int pin, int mux)
++{
++      struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
++
++      return mux_apply(info, pin, mux);
++}
++
+ static const struct ltq_cfg_param xway_cfg_params[] = {
+       {"lantiq,pull",         LTQ_PINCONF_PARAM_PULL},
+       {"lantiq,open-drain",   LTQ_PINCONF_PARAM_OPEN_DRAIN},
+@@ -676,6 +683,10 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
+ {
+       struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
++      if (PORT(pin) == PORT3)
++              gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin));
++      else
++              gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin));
+       gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
+       xway_gpio_set(chip, pin, val);
+@@ -696,6 +707,18 @@ static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
+       pinctrl_free_gpio(gpio);
+ }
++static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
++{
++      struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
++      int i;
++
++      for (i = 0; i < info->num_exin; i++)
++              if (info->exin[i] == offset)
++                      return ltq_eiu_get_irq(i);
++
++      return -1;
++}
++
+ static struct gpio_chip xway_chip = {
+       .label = "gpio-xway",
+       .direction_input = xway_gpio_dir_in,
+@@ -704,6 +727,7 @@ static struct gpio_chip xway_chip = {
+       .set = xway_gpio_set,
+       .request = xway_gpio_req,
+       .free = xway_gpio_free,
++      .to_irq = xway_gpio_to_irq,
+       .base = -1,
+ };
+-- 
+1.7.10.4
+
index 5aad493a507b3d1e8def7e204c30ec81e3515262..7d900fac7915007c894ad15ecf248ed54bc78043 100644 (file)
@@ -1,7 +1,7 @@
-From c243da18ea2a02e8cfb3f821232783376131948a Mon Sep 17 00:00:00 2001
+From 8e34da603f442624bb70e887d8f42064bb924224 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Sun, 28 Jul 2013 18:03:54 +0200
-Subject: [PATCH 13/31] MTD: lantiq: xway: fix invalid operator
+Subject: [PATCH 13/36] MTD: lantiq: xway: fix invalid operator
 
 xway_read_byte should use a logic or and not an add operator when working out
 the nand address.
index a8b5c749fb45ae199caee120bfb96dc649b6aa93..d3c197ef7e3d6609878b0bfacdc2ea270f2a51c6 100644 (file)
@@ -1,7 +1,7 @@
-From b2ef79004dd8e26f3a4625610bff5362b70e956b Mon Sep 17 00:00:00 2001
+From b454cefd675fc1bd3d8c690c1bd1d8f4678e9922 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Sun, 28 Jul 2013 18:06:39 +0200
-Subject: [PATCH 14/31] MTD: lantiq: xway: the latched command should be
+Subject: [PATCH 14/36] MTD: lantiq: xway: the latched command should be
  persistent
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
index 51c8dd3c632debd8619724a3a4505e01079b8602..910fc148ffc706780299a8d96048cff366cc3610 100644 (file)
@@ -1,7 +1,7 @@
-From 836c433cec22555d81bf02bb205dee5772b8df08 Mon Sep 17 00:00:00 2001
+From 76e153079f02d26e3357302d2886a0c8aaaec64d Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Sun, 28 Jul 2013 18:02:06 +0200
-Subject: [PATCH 15/31] MTD: lantiq: xway: remove endless loop
+Subject: [PATCH 15/36] MTD: lantiq: xway: remove endless loop
 
 The reset loop logic could run into a endless loop. Lets fix it as requested.
 
index e00dc47941307f748f4c9b30077d07126d770fb8..8d07654d47bad23bfa9e62745132c79233e7d706 100644 (file)
@@ -1,7 +1,7 @@
-From 6f5bf300afa3c6f41a973fb3f39827db59512343 Mon Sep 17 00:00:00 2001
+From 65df9d63eaee02c25e879b33dd42aceb78e57842 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Sun, 28 Jul 2013 17:59:51 +0200
-Subject: [PATCH 16/31] MTD: lantiq: xway: add missing write_buf and read_buf
+Subject: [PATCH 16/36] MTD: lantiq: xway: add missing write_buf and read_buf
  to nand driver
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
index 9f87586d345bb78f0c2a09fa7feecd956bf276ce..882a405f0a44caf8ca2209c86421c5c9dd595feb 100644 (file)
@@ -1,7 +1,7 @@
-From bbaf5aaf4b430f2139e5f561b6372008d26766a2 Mon Sep 17 00:00:00 2001
+From aa705c1b0860da91f2ed1a4c0b57337e6de689e1 Mon Sep 17 00:00:00 2001
 From: John Crispin <blogic@openwrt.org>
 Date: Thu, 7 Aug 2014 18:55:31 +0200
-Subject: [PATCH 17/31] MTD: xway: fix nand locking
+Subject: [PATCH 17/36] MTD: xway: fix nand locking
 
 Signed-off-by: John Crispin <blogic@openwrt.org>
 ---
diff --git a/target/linux/lantiq/patches-3.14/0018-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch b/target/linux/lantiq/patches-3.14/0018-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch
deleted file mode 100644 (file)
index bfe5523..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-From e2c285e95e75258c196fbc04a742d91be6d00f49 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Wed, 30 Jan 2013 21:12:47 +0100
-Subject: [PATCH 18/31] MTD: lantiq: Add NAND support on Lantiq Falcon SoC.
-
-The driver uses plat_nand. As the platform_device is loaded from DT, we need
-to lookup the node and attach our falcon specific "struct platform_nand_data"
-to it.
-
-Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/mtd/nand/Kconfig       |    8 ++++
- drivers/mtd/nand/Makefile      |    1 +
- drivers/mtd/nand/falcon_nand.c |   83 ++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 92 insertions(+)
- create mode 100644 drivers/mtd/nand/falcon_nand.c
-
-diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
-index 90ff447..7064f0e 100644
---- a/drivers/mtd/nand/Kconfig
-+++ b/drivers/mtd/nand/Kconfig
-@@ -510,4 +510,12 @@ config MTD_NAND_XWAY
-         Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
-         to the External Bus Unit (EBU).
-+config MTD_NAND_FALCON
-+      tristate "Support for NAND on Lantiq FALC-ON SoC"
-+      depends on LANTIQ && SOC_FALCON
-+      select MTD_NAND_PLATFORM
-+      help
-+        Enables support for NAND Flash chips on Lantiq FALC-ON SoCs. NAND is
-+        attached to the External Bus Unit (EBU).
-+
- endif # MTD_NAND
-diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
-index 542b568..78a1cd2 100644
---- a/drivers/mtd/nand/Makefile
-+++ b/drivers/mtd/nand/Makefile
-@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740)                += jz4740_nand.o
- obj-$(CONFIG_MTD_NAND_GPMI_NAND)      += gpmi-nand/
- obj-$(CONFIG_MTD_NAND_XWAY)           += xway_nand.o
- obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)  += bcm47xxnflash/
-+obj-$(CONFIG_MTD_NAND_FALCON)         += falcon_nand.o
- nand-objs := nand_base.o nand_bbt.o
-diff --git a/drivers/mtd/nand/falcon_nand.c b/drivers/mtd/nand/falcon_nand.c
-new file mode 100644
-index 0000000..13458d3
---- /dev/null
-+++ b/drivers/mtd/nand/falcon_nand.c
-@@ -0,0 +1,83 @@
-+/*
-+ * 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) 2011 Thomas Langer <thomas.langer@lantiq.com>
-+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/mtd/nand.h>
-+#include <linux/of_platform.h>
-+
-+#include <lantiq_soc.h>
-+
-+/* address lines used for NAND control signals */
-+#define NAND_ADDR_ALE         0x10000
-+#define NAND_ADDR_CLE         0x20000
-+
-+/* Ready/Busy Status */
-+#define MODCON_STS            0x0002
-+
-+/* Ready/Busy Status Edge */
-+#define MODCON_STSEDGE                0x0004
-+#define LTQ_EBU_MODCON                0x000C
-+
-+static const char const *part_probes[] = { "cmdlinepart", "ofpart", NULL };
-+
-+static int falcon_nand_ready(struct mtd_info *mtd)
-+{
-+      u32 modcon = ltq_ebu_r32(LTQ_EBU_MODCON);
-+
-+      return (((modcon & (MODCON_STS | MODCON_STSEDGE)) ==
-+                                              (MODCON_STS | MODCON_STSEDGE)));
-+}
-+
-+static void falcon_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
-+
-+      if (ctrl & NAND_CTRL_CHANGE) {
-+              nandaddr &= ~(NAND_ADDR_ALE | NAND_ADDR_CLE);
-+
-+              if (ctrl & NAND_CLE)
-+                      nandaddr |= NAND_ADDR_CLE;
-+              if (ctrl & NAND_ALE)
-+                      nandaddr |= NAND_ADDR_ALE;
-+
-+              this->IO_ADDR_W = (void __iomem *) nandaddr;
-+      }
-+
-+      if (cmd != NAND_CMD_NONE)
-+              writeb(cmd, this->IO_ADDR_W);
-+}
-+
-+static struct platform_nand_data falcon_nand_data = {
-+      .chip = {
-+              .nr_chips               = 1,
-+              .chip_delay             = 25,
-+              .part_probe_types       = part_probes,
-+      },
-+      .ctrl = {
-+              .cmd_ctrl               = falcon_hwcontrol,
-+              .dev_ready              = falcon_nand_ready,
-+      }
-+};
-+
-+int __init falcon_register_nand(void)
-+{
-+      struct device_node *node;
-+      struct platform_device *pdev;
-+
-+      node = of_find_compatible_node(NULL, NULL, "lantiq,nand-falcon");
-+      if (!node)
-+              return -1;
-+      pdev = of_find_device_by_node(node);
-+      if (pdev)
-+              pdev->dev.platform_data = &falcon_nand_data;
-+      of_node_put(node);
-+      return 0;
-+}
-+
-+arch_initcall(falcon_register_nand);
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0018-MTD-nand-lots-of-xrx200-fixes.patch b/target/linux/lantiq/patches-3.14/0018-MTD-nand-lots-of-xrx200-fixes.patch
new file mode 100644 (file)
index 0000000..1e1f299
--- /dev/null
@@ -0,0 +1,130 @@
+From 997a8965db8417266bea3fbdcfa3e5655a1b52fa Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 9 Sep 2014 23:12:15 +0200
+Subject: [PATCH 18/36] MTD: nand: lots of xrx200 fixes
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mtd/nand/xway_nand.c |   63 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 63 insertions(+)
+
+diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c
+index e430f2d..fedf2c4 100644
+--- a/drivers/mtd/nand/xway_nand.c
++++ b/drivers/mtd/nand/xway_nand.c
+@@ -54,8 +54,27 @@
+ #define NAND_CON_CSMUX                (1 << 1)
+ #define NAND_CON_NANDM                1
++#define DANUBE_PCI_REG32( addr )    (*(volatile u32 *)(addr))
++#define PCI_CR_PR_OFFSET          (KSEG1+0x1E105400)
++#define PCI_CR_PC_ARB             (PCI_CR_PR_OFFSET + 0x0080)
++
+ static u32 xway_latchcmd;
++/*
++ * req_mask provides a mechanism to prevent interference between
++ * nand and pci (probably only relevant for the BT Home Hub 2B).
++ * Setting it causes the corresponding pci req pins to be masked
++ * during nand access, and also moves ebu locking from the read/write
++ * functions to the chip select function to ensure that the whole
++ * operation runs with interrupts disabled.
++ * In addition it switches on some extra waiting in xway_cmd_ctrl().
++ * This seems to be necessary if the ebu_cs1 pin has open-drain disabled,
++ * which in turn seems to be necessary for the nor chip to be recognised
++ * reliably, on a board (Home Hub 2B again) which has both nor and nand.
++ */
++
++static __be32 req_mask = 0;
++
+ static void xway_reset_chip(struct nand_chip *chip)
+ {
+       unsigned long nandaddr = (unsigned long) chip->IO_ADDR_W;
+@@ -86,12 +105,24 @@ static void xway_select_chip(struct mtd_info *mtd, int chip)
+       case -1:
+               ltq_ebu_w32_mask(NAND_CON_CE, 0, EBU_NAND_CON);
+               ltq_ebu_w32_mask(NAND_CON_NANDM, 0, EBU_NAND_CON);
++
++              if (req_mask) {
++                      /* Unmask all external PCI request */
++                      DANUBE_PCI_REG32(PCI_CR_PC_ARB) &= ~(req_mask << 16);
++              }
+               spin_unlock_irqrestore(&ebu_lock, csflags);
++
+               break;
+       case 0:
+               spin_lock_irqsave(&ebu_lock, csflags);
++              if (req_mask) {
++                      /* Mask all external PCI request */
++                      DANUBE_PCI_REG32(PCI_CR_PC_ARB) |= (req_mask << 16);
++              }
++
+               ltq_ebu_w32_mask(0, NAND_CON_NANDM, EBU_NAND_CON);
+               ltq_ebu_w32_mask(0, NAND_CON_CE, EBU_NAND_CON);
++
+               break;
+       default:
+               BUG();
+@@ -103,6 +134,12 @@ static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+       struct nand_chip *this = mtd->priv;
+       unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
++      if (req_mask) {
++              if (cmd != NAND_CMD_STATUS)
++                      ltq_ebu_w32(EBU_NAND_WAIT, 0); /* Clear nand ready */
++      }
++
++
+       if (ctrl & NAND_CTRL_CHANGE) {
+               if (ctrl & NAND_CLE)
+                       xway_latchcmd = NAND_WRITE_CMD;
+@@ -115,6 +152,24 @@ static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+               while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
+                       ;
+       }
++
++      if (req_mask) {
++             /*
++              * program and erase have their own busy handlers
++              * status and sequential in needs no delay
++              */
++              switch (cmd) {
++                      case NAND_CMD_ERASE1:
++                      case NAND_CMD_SEQIN:
++                      case NAND_CMD_STATUS:
++                      case NAND_CMD_READID:
++                      return;
++              }
++
++              /* wait until command is processed */
++              while ((ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD) == 0)
++                      ;
++      }
+ }
+ static int xway_dev_ready(struct mtd_info *mtd)
+@@ -157,6 +212,8 @@ static int xway_nand_probe(struct platform_device *pdev)
+ {
+       struct nand_chip *this = platform_get_drvdata(pdev);
+       unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
++      const __be32 *req_mask_ptr = of_get_property(pdev->dev.of_node,
++                                      "req-mask", NULL);
+       const __be32 *cs = of_get_property(pdev->dev.of_node,
+                                       "lantiq,cs", NULL);
+       u32 cs_flag = 0;
+@@ -165,6 +222,12 @@ static int xway_nand_probe(struct platform_device *pdev)
+       if (cs && (*cs == 1))
+               cs_flag = NAND_CON_IN_CS1 | NAND_CON_OUT_CS1;
++      /*
++       * Load the PCI req lines to mask from the device tree. If the
++       * property is not present, setting req_mask to 0 disables masking.
++       */
++      req_mask = (req_mask_ptr ? *req_mask_ptr : 0);
++
+       /* setup the EBU to run in NAND mode on our base addr */
+       ltq_ebu_w32(CPHYSADDR(nandaddr)
+               | ADDSEL1_MASK(3) | ADDSEL1_REGEN, EBU_ADDSEL1);
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch b/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Add-NAND-support-on-Lantiq-Falcon-SoC.patch
new file mode 100644 (file)
index 0000000..ad1c2cf
--- /dev/null
@@ -0,0 +1,138 @@
+From c21eed4418956ecc95966a2e174d47f58397071a Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 30 Jan 2013 21:12:47 +0100
+Subject: [PATCH 19/36] MTD: lantiq: Add NAND support on Lantiq Falcon SoC.
+
+The driver uses plat_nand. As the platform_device is loaded from DT, we need
+to lookup the node and attach our falcon specific "struct platform_nand_data"
+to it.
+
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mtd/nand/Kconfig       |    8 ++++
+ drivers/mtd/nand/Makefile      |    1 +
+ drivers/mtd/nand/falcon_nand.c |   83 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 92 insertions(+)
+ create mode 100644 drivers/mtd/nand/falcon_nand.c
+
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 90ff447..7064f0e 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -510,4 +510,12 @@ config MTD_NAND_XWAY
+         Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
+         to the External Bus Unit (EBU).
++config MTD_NAND_FALCON
++      tristate "Support for NAND on Lantiq FALC-ON SoC"
++      depends on LANTIQ && SOC_FALCON
++      select MTD_NAND_PLATFORM
++      help
++        Enables support for NAND Flash chips on Lantiq FALC-ON SoCs. NAND is
++        attached to the External Bus Unit (EBU).
++
+ endif # MTD_NAND
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index 542b568..78a1cd2 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740)                += jz4740_nand.o
+ obj-$(CONFIG_MTD_NAND_GPMI_NAND)      += gpmi-nand/
+ obj-$(CONFIG_MTD_NAND_XWAY)           += xway_nand.o
+ obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)  += bcm47xxnflash/
++obj-$(CONFIG_MTD_NAND_FALCON)         += falcon_nand.o
+ nand-objs := nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/falcon_nand.c b/drivers/mtd/nand/falcon_nand.c
+new file mode 100644
+index 0000000..13458d3
+--- /dev/null
++++ b/drivers/mtd/nand/falcon_nand.c
+@@ -0,0 +1,83 @@
++/*
++ * 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) 2011 Thomas Langer <thomas.langer@lantiq.com>
++ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/mtd/nand.h>
++#include <linux/of_platform.h>
++
++#include <lantiq_soc.h>
++
++/* address lines used for NAND control signals */
++#define NAND_ADDR_ALE         0x10000
++#define NAND_ADDR_CLE         0x20000
++
++/* Ready/Busy Status */
++#define MODCON_STS            0x0002
++
++/* Ready/Busy Status Edge */
++#define MODCON_STSEDGE                0x0004
++#define LTQ_EBU_MODCON                0x000C
++
++static const char const *part_probes[] = { "cmdlinepart", "ofpart", NULL };
++
++static int falcon_nand_ready(struct mtd_info *mtd)
++{
++      u32 modcon = ltq_ebu_r32(LTQ_EBU_MODCON);
++
++      return (((modcon & (MODCON_STS | MODCON_STSEDGE)) ==
++                                              (MODCON_STS | MODCON_STSEDGE)));
++}
++
++static void falcon_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
++{
++      struct nand_chip *this = mtd->priv;
++      unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
++
++      if (ctrl & NAND_CTRL_CHANGE) {
++              nandaddr &= ~(NAND_ADDR_ALE | NAND_ADDR_CLE);
++
++              if (ctrl & NAND_CLE)
++                      nandaddr |= NAND_ADDR_CLE;
++              if (ctrl & NAND_ALE)
++                      nandaddr |= NAND_ADDR_ALE;
++
++              this->IO_ADDR_W = (void __iomem *) nandaddr;
++      }
++
++      if (cmd != NAND_CMD_NONE)
++              writeb(cmd, this->IO_ADDR_W);
++}
++
++static struct platform_nand_data falcon_nand_data = {
++      .chip = {
++              .nr_chips               = 1,
++              .chip_delay             = 25,
++              .part_probe_types       = part_probes,
++      },
++      .ctrl = {
++              .cmd_ctrl               = falcon_hwcontrol,
++              .dev_ready              = falcon_nand_ready,
++      }
++};
++
++int __init falcon_register_nand(void)
++{
++      struct device_node *node;
++      struct platform_device *pdev;
++
++      node = of_find_compatible_node(NULL, NULL, "lantiq,nand-falcon");
++      if (!node)
++              return -1;
++      pdev = of_find_device_by_node(node);
++      if (pdev)
++              pdev->dev.platform_data = &falcon_nand_data;
++      of_node_put(node);
++      return 0;
++}
++
++arch_initcall(falcon_register_nand);
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch b/target/linux/lantiq/patches-3.14/0019-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch
deleted file mode 100644 (file)
index 4f36270..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From 4e2a4dcadb70985e86d9cebfca308891be377510 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 7 Aug 2014 18:57:30 +0200
-Subject: [PATCH 19/31] MTD: lantiq: Makes the Lantiq flash driver try jedec
- probing if cfi probing fails.
-
-(Based on work by Simon Hayes first published on www.psidoc.com and
-http://sourceforge.net/projects/hh2b4ever/)
-
-Signed-off-by: Ben Mulvihill <ben.mulvihill@gmail.com>
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/mtd/maps/lantiq-flash.c |   10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
-index 710d699..dd1e853 100644
---- a/drivers/mtd/maps/lantiq-flash.c
-+++ b/drivers/mtd/maps/lantiq-flash.c
-@@ -117,6 +117,11 @@ ltq_mtd_probe(struct platform_device *pdev)
-       struct cfi_private *cfi;
-       int err;
-+      static const char *rom_probe_types[] = {
-+              "cfi_probe", "jedec_probe", NULL
-+      };
-+      const char **type;
-+
-       if (of_machine_is_compatible("lantiq,falcon") &&
-                       (ltq_boot_select() != BS_FLASH)) {
-               dev_err(&pdev->dev, "invalid bootstrap options\n");
-@@ -158,7 +163,10 @@ ltq_mtd_probe(struct platform_device *pdev)
-       ltq_mtd->map->copy_to = ltq_copy_to;
-       ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
--      ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
-+
-+      for (type = rom_probe_types; !ltq_mtd->mtd && *type; type++)
-+              ltq_mtd->mtd = do_map_probe(*type, ltq_mtd->map);
-+
-       ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
-       if (!ltq_mtd->mtd) {
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0020-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch b/target/linux/lantiq/patches-3.14/0020-MTD-lantiq-handle-NO_XIP-on-cfi0001-flash.patch
new file mode 100644 (file)
index 0000000..4a23170
--- /dev/null
@@ -0,0 +1,30 @@
+From e3b20f04e9f9cae1babe091fdc1d08d7703ae344 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 7 Aug 2014 18:18:00 +0200
+Subject: [PATCH 20/36] MTD: lantiq: handle NO_XIP on cfi0001 flash
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mtd/maps/lantiq-flash.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 93c507a..710d699 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -140,7 +140,11 @@ ltq_mtd_probe(struct platform_device *pdev)
+       if (!ltq_mtd->map)
+               return -ENOMEM;
+-      ltq_mtd->map->phys = ltq_mtd->res->start;
++      if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL))
++              ltq_mtd->map->phys = NO_XIP;
++      else
++              ltq_mtd->map->phys = ltq_mtd->res->start;
++      ltq_mtd->res->start;
+       ltq_mtd->map->size = resource_size(ltq_mtd->res);
+       ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res);
+       if (IS_ERR(ltq_mtd->map->virt))
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0020-NET-PHY-adds-driver-for-lantiq-PHY11G.patch b/target/linux/lantiq/patches-3.14/0020-NET-PHY-adds-driver-for-lantiq-PHY11G.patch
deleted file mode 100644 (file)
index 5d9d82b..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-From 6c895c9b0ceff79fdeb73876e35b536a312f851b Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 7 Aug 2014 18:15:36 +0200
-Subject: [PATCH 20/31] NET: PHY: adds driver for lantiq PHY11G
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/net/phy/Kconfig  |    5 +
- drivers/net/phy/Makefile |    1 +
- drivers/net/phy/lantiq.c |  231 ++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 237 insertions(+)
- create mode 100644 drivers/net/phy/lantiq.c
-
-diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
-index 9b5d46c..f3724b1 100644
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -106,6 +106,11 @@ config MICREL_PHY
-       ---help---
-         Supports the KSZ9021, VSC8201, KS8001 PHYs.
-+config LANTIQ_PHY
-+      tristate "Driver for Lantiq PHYs"
-+      ---help---
-+        Supports the 11G and 22E PHYs.
-+
- config FIXED_PHY
-       bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
-       depends on PHYLIB=y
-diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
-index 9013dfa..b5e030f 100644
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -23,6 +23,7 @@ obj-$(CONFIG_NATIONAL_PHY)   += national.o
- obj-$(CONFIG_DP83640_PHY)     += dp83640.o
- obj-$(CONFIG_STE10XP)         += ste10Xp.o
- obj-$(CONFIG_MICREL_PHY)      += micrel.o
-+obj-$(CONFIG_LANTIQ_PHY)        += lantiq.o
- obj-$(CONFIG_MDIO_OCTEON)     += mdio-octeon.o
- obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
- obj-$(CONFIG_AT803X_PHY)      += at803x.o
-diff --git a/drivers/net/phy/lantiq.c b/drivers/net/phy/lantiq.c
-new file mode 100644
-index 0000000..f109bb9
---- /dev/null
-+++ b/drivers/net/phy/lantiq.c
-@@ -0,0 +1,231 @@
-+/*
-+ *   This program is free software; you can redistribute it and/or modify
-+ *   it under the terms of the GNU General Public License as published by
-+ *   the Free Software Foundation; either version 2 of the License, or
-+ *   (at your option) any later version.
-+ *
-+ *   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) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/phy.h>
-+
-+#define MII_MMDCTRL           0x0d
-+#define MII_MMDDATA           0x0e
-+
-+#define MII_VR9_11G_IMASK     0x19    /* interrupt mask */
-+#define MII_VR9_11G_ISTAT     0x1a    /* interrupt status */
-+
-+#define INT_VR9_11G_WOL               BIT(15) /* Wake-On-LAN */
-+#define INT_VR9_11G_ANE               BIT(11) /* Auto-Neg error */
-+#define INT_VR9_11G_ANC               BIT(10) /* Auto-Neg complete */
-+#define INT_VR9_11G_ADSC      BIT(5)  /* Link auto-downspeed detect */
-+#define INT_VR9_11G_DXMC      BIT(2)  /* Duplex mode change */
-+#define INT_VR9_11G_LSPC      BIT(1)  /* Link speed change */
-+#define INT_VR9_11G_LSTC      BIT(0)  /* Link state change */
-+#define INT_VR9_11G_MASK      (INT_VR9_11G_LSTC | INT_VR9_11G_ADSC)
-+
-+#define ADVERTISED_MPD                BIT(10) /* Multi-port device */
-+
-+#define MMD_DEVAD             0x1f
-+#define MMD_ACTYPE_SHIFT      14
-+#define MMD_ACTYPE_ADDRESS    (0 << MMD_ACTYPE_SHIFT)
-+#define MMD_ACTYPE_DATA               (1 << MMD_ACTYPE_SHIFT)
-+#define MMD_ACTYPE_DATA_PI    (2 << MMD_ACTYPE_SHIFT)
-+#define MMD_ACTYPE_DATA_PIWR  (3 << MMD_ACTYPE_SHIFT)
-+
-+static __maybe_unused int vr9_gphy_mmd_read(struct phy_device *phydev,
-+                                              u16 regnum)
-+{
-+      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
-+      phy_write(phydev, MII_MMDDATA, regnum);
-+      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
-+
-+      return phy_read(phydev, MII_MMDDATA);
-+}
-+
-+static __maybe_unused int vr9_gphy_mmd_write(struct phy_device *phydev,
-+                                              u16 regnum, u16 val)
-+{
-+      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
-+      phy_write(phydev, MII_MMDDATA, regnum);
-+      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
-+      phy_write(phydev, MII_MMDDATA, val);
-+
-+      return 0;
-+}
-+
-+static int vr9_gphy_config_init(struct phy_device *phydev)
-+{
-+      int err;
-+
-+      dev_dbg(&phydev->dev, "%s\n", __func__);
-+
-+      /* Mask all interrupts */
-+      err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
-+      if (err)
-+              return err;
-+
-+      /* Clear all pending interrupts */
-+      phy_read(phydev, MII_VR9_11G_ISTAT);
-+
-+      vr9_gphy_mmd_write(phydev, 0x1e0, 0xc5);
-+      vr9_gphy_mmd_write(phydev, 0x1e1, 0x67);
-+      vr9_gphy_mmd_write(phydev, 0x1e2, 0x42);
-+      vr9_gphy_mmd_write(phydev, 0x1e3, 0x10);
-+      vr9_gphy_mmd_write(phydev, 0x1e4, 0x70);
-+      vr9_gphy_mmd_write(phydev, 0x1e5, 0x03);
-+      vr9_gphy_mmd_write(phydev, 0x1e6, 0x20);
-+      vr9_gphy_mmd_write(phydev, 0x1e7, 0x00);
-+      vr9_gphy_mmd_write(phydev, 0x1e8, 0x40);
-+      vr9_gphy_mmd_write(phydev, 0x1e9, 0x20);
-+
-+      return 0;
-+}
-+
-+static int vr9_gphy_config_aneg(struct phy_device *phydev)
-+{
-+      int reg, err;
-+
-+      /* Advertise as multi-port device */
-+      reg = phy_read(phydev, MII_CTRL1000);
-+      reg |= ADVERTISED_MPD;
-+      err = phy_write(phydev, MII_CTRL1000, reg);
-+      if (err)
-+              return err;
-+
-+      return genphy_config_aneg(phydev);
-+}
-+
-+static int vr9_gphy_ack_interrupt(struct phy_device *phydev)
-+{
-+      int reg;
-+
-+      /*
-+       * Possible IRQ numbers:
-+       * - IM3_IRL18 for GPHY0
-+       * - IM3_IRL17 for GPHY1
-+       *
-+       * Due to a silicon bug IRQ lines are not really independent from
-+       * each other. Sometimes the two lines are driven at the same time
-+       * if only one GPHY core raises the interrupt.
-+       */
-+
-+      reg = phy_read(phydev, MII_VR9_11G_ISTAT);
-+
-+      return (reg < 0) ? reg : 0;
-+}
-+
-+static int vr9_gphy_did_interrupt(struct phy_device *phydev)
-+{
-+      int reg;
-+
-+      reg = phy_read(phydev, MII_VR9_11G_ISTAT);
-+
-+      return reg > 0;
-+}
-+
-+static int vr9_gphy_config_intr(struct phy_device *phydev)
-+{
-+      int err;
-+
-+      if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
-+              err = phy_write(phydev, MII_VR9_11G_IMASK, INT_VR9_11G_MASK);
-+      else
-+              err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
-+
-+      return err;
-+}
-+
-+static struct phy_driver lantiq_phy[] = {
-+      {
-+              .phy_id         = 0xd565a400,
-+              .phy_id_mask    = 0xffffffff,
-+              .name           = "Lantiq XWAY PEF7071",
-+              .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
-+              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
-+              .config_init    = vr9_gphy_config_init,
-+              .config_aneg    = vr9_gphy_config_aneg,
-+              .read_status    = genphy_read_status,
-+              .ack_interrupt  = vr9_gphy_ack_interrupt,
-+              .did_interrupt  = vr9_gphy_did_interrupt,
-+              .config_intr    = vr9_gphy_config_intr,
-+              .driver         = { .owner = THIS_MODULE },
-+      }, {
-+              .phy_id         = 0x030260D0,
-+              .phy_id_mask    = 0xfffffff0,
-+              .name           = "Lantiq XWAY VR9 GPHY 11G v1.3",
-+              .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
-+              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
-+              .config_init    = vr9_gphy_config_init,
-+              .config_aneg    = vr9_gphy_config_aneg,
-+              .read_status    = genphy_read_status,
-+              .ack_interrupt  = vr9_gphy_ack_interrupt,
-+              .did_interrupt  = vr9_gphy_did_interrupt,
-+              .config_intr    = vr9_gphy_config_intr,
-+              .driver         = { .owner = THIS_MODULE },
-+      }, {
-+              .phy_id         = 0xd565a408,
-+              .phy_id_mask    = 0xfffffff8,
-+              .name           = "Lantiq XWAY VR9 GPHY 11G v1.4",
-+              .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
-+              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
-+              .config_init    = vr9_gphy_config_init,
-+              .config_aneg    = vr9_gphy_config_aneg,
-+              .read_status    = genphy_read_status,
-+              .ack_interrupt  = vr9_gphy_ack_interrupt,
-+              .did_interrupt  = vr9_gphy_did_interrupt,
-+              .config_intr    = vr9_gphy_config_intr,
-+              .driver         = { .owner = THIS_MODULE },
-+      }, {
-+              .phy_id         = 0xd565a418,
-+              .phy_id_mask    = 0xfffffff8,
-+              .name           = "Lantiq XWAY XRX PHY22F v1.4",
-+              .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
-+              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
-+              .config_init    = vr9_gphy_config_init,
-+              .config_aneg    = vr9_gphy_config_aneg,
-+              .read_status    = genphy_read_status,
-+              .ack_interrupt  = vr9_gphy_ack_interrupt,
-+              .did_interrupt  = vr9_gphy_did_interrupt,
-+              .config_intr    = vr9_gphy_config_intr,
-+              .driver         = { .owner = THIS_MODULE },
-+      },
-+};
-+
-+static int __init ltq_phy_init(void)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(lantiq_phy); i++) {
-+              int err = phy_driver_register(&lantiq_phy[i]);
-+              if (err)
-+                      pr_err("lantiq_phy: failed to load %s\n", lantiq_phy[i].name);
-+      }
-+
-+      return 0;
-+}
-+
-+static void __exit ltq_phy_exit(void)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(lantiq_phy); i++)
-+              phy_driver_unregister(&lantiq_phy[i]);
-+}
-+
-+module_init(ltq_phy_init);
-+module_exit(ltq_phy_exit);
-+
-+MODULE_DESCRIPTION("Lantiq PHY drivers");
-+MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
-+MODULE_LICENSE("GPL");
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0021-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch b/target/linux/lantiq/patches-3.14/0021-MTD-lantiq-Makes-the-Lantiq-flash-driver-try-jedec-p.patch
new file mode 100644 (file)
index 0000000..00a2c8e
--- /dev/null
@@ -0,0 +1,46 @@
+From 11180582ca6efdff86314ae4514e9df3d34a6475 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 7 Aug 2014 18:57:30 +0200
+Subject: [PATCH 21/36] MTD: lantiq: Makes the Lantiq flash driver try jedec
+ probing if cfi probing fails.
+
+(Based on work by Simon Hayes first published on www.psidoc.com and
+http://sourceforge.net/projects/hh2b4ever/)
+
+Signed-off-by: Ben Mulvihill <ben.mulvihill@gmail.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mtd/maps/lantiq-flash.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 710d699..dd1e853 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -117,6 +117,11 @@ ltq_mtd_probe(struct platform_device *pdev)
+       struct cfi_private *cfi;
+       int err;
++      static const char *rom_probe_types[] = {
++              "cfi_probe", "jedec_probe", NULL
++      };
++      const char **type;
++
+       if (of_machine_is_compatible("lantiq,falcon") &&
+                       (ltq_boot_select() != BS_FLASH)) {
+               dev_err(&pdev->dev, "invalid bootstrap options\n");
+@@ -158,7 +163,10 @@ ltq_mtd_probe(struct platform_device *pdev)
+       ltq_mtd->map->copy_to = ltq_copy_to;
+       ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
+-      ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
++
++      for (type = rom_probe_types; !ltq_mtd->mtd && *type; type++)
++              ltq_mtd->mtd = do_map_probe(*type, ltq_mtd->map);
++
+       ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
+       if (!ltq_mtd->mtd) {
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0021-NET-lantiq-adds-PHY11G-firmware-blobs.patch b/target/linux/lantiq/patches-3.14/0021-NET-lantiq-adds-PHY11G-firmware-blobs.patch
deleted file mode 100644 (file)
index 1de297f..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-From c64015eb950202f84829498a9c9daf949eded81f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 22 Oct 2012 09:26:24 +0200
-Subject: [PATCH 21/31] NET: lantiq: adds PHY11G firmware blobs
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- firmware/Makefile       |    4 +
- firmware/lantiq/COPYING |  286 +++++++++++++++++++++++++++++++++++++++++++++++
- firmware/lantiq/README  |   45 ++++++++
- 3 files changed, 335 insertions(+)
- create mode 100644 firmware/lantiq/COPYING
- create mode 100644 firmware/lantiq/README
-
-diff --git a/firmware/Makefile b/firmware/Makefile
-index cbb09ce..171ebab 100644
---- a/firmware/Makefile
-+++ b/firmware/Makefile
-@@ -134,6 +134,10 @@ fw-shipped-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda/keyspan_pda.fw
- fw-shipped-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda/xircom_pgs.fw
- fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw
- fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin
-+fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy11g_a1x.bin
-+fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy11g_a2x.bin
-+fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy22f_a1x.bin
-+fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy22f_a2x.bin
- fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
- fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
-diff --git a/firmware/lantiq/COPYING b/firmware/lantiq/COPYING
-new file mode 100644
-index 0000000..5ec70b2
---- /dev/null
-+++ b/firmware/lantiq/COPYING
-@@ -0,0 +1,286 @@
-+All firmware files are copyrighted by Lantiq Deutschland GmbH.
-+The files have been extracted from header files found in Lantiq BSPs.
-+If not stated otherwise all files are licensed under GPL.
-+
-+=======================================================================
-+
-+                  GNU GENERAL PUBLIC LICENSE
-+                     Version 2, June 1991
-+
-+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+                          Preamble
-+
-+  The licenses for most software are designed to take away your
-+freedom to share and change it.  By contrast, the GNU General Public
-+License is intended to guarantee your freedom to share and change free
-+software--to make sure the software is free for all its users.  This
-+General Public License applies to most of the Free Software
-+Foundation's software and to any other program whose authors commit to
-+using it.  (Some other Free Software Foundation software is covered by
-+the GNU Library General Public License instead.)  You can apply it to
-+your programs, too.
-+
-+  When we speak of free software, we are referring to freedom, not
-+price.  Our General Public Licenses are designed to make sure that you
-+have the freedom to distribute copies of free software (and charge for
-+this service if you wish), that you receive source code or can get it
-+if you want it, that you can change the software or use pieces of it
-+in new free programs; and that you know you can do these things.
-+
-+  To protect your rights, we need to make restrictions that forbid
-+anyone to deny you these rights or to ask you to surrender the rights.
-+These restrictions translate to certain responsibilities for you if you
-+distribute copies of the software, or if you modify it.
-+
-+  For example, if you distribute copies of such a program, whether
-+gratis or for a fee, you must give the recipients all the rights that
-+you have.  You must make sure that they, too, receive or can get the
-+source code.  And you must show them these terms so they know their
-+rights.
-+
-+  We protect your rights with two steps: (1) copyright the software, and
-+(2) offer you this license which gives you legal permission to copy,
-+distribute and/or modify the software.
-+
-+  Also, for each author's protection and ours, we want to make certain
-+that everyone understands that there is no warranty for this free
-+software.  If the software is modified by someone else and passed on, we
-+want its recipients to know that what they have is not the original, so
-+that any problems introduced by others will not reflect on the original
-+authors' reputations.
-+
-+  Finally, any free program is threatened constantly by software
-+patents.  We wish to avoid the danger that redistributors of a free
-+program will individually obtain patent licenses, in effect making the
-+program proprietary.  To prevent this, we have made it clear that any
-+patent must be licensed for everyone's free use or not licensed at all.
-+
-+  The precise terms and conditions for copying, distribution and
-+modification follow.
-+\f
-+                  GNU GENERAL PUBLIC LICENSE
-+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+  0. This License applies to any program or other work which contains
-+a notice placed by the copyright holder saying it may be distributed
-+under the terms of this General Public License.  The "Program", below,
-+refers to any such program or work, and a "work based on the Program"
-+means either the Program or any derivative work under copyright law:
-+that is to say, a work containing the Program or a portion of it,
-+either verbatim or with modifications and/or translated into another
-+language.  (Hereinafter, translation is included without limitation in
-+the term "modification".)  Each licensee is addressed as "you".
-+
-+Activities other than copying, distribution and modification are not
-+covered by this License; they are outside its scope.  The act of
-+running the Program is not restricted, and the output from the Program
-+is covered only if its contents constitute a work based on the
-+Program (independent of having been made by running the Program).
-+Whether that is true depends on what the Program does.
-+
-+  1. You may copy and distribute verbatim copies of the Program's
-+source code as you receive it, in any medium, provided that you
-+conspicuously and appropriately publish on each copy an appropriate
-+copyright notice and disclaimer of warranty; keep intact all the
-+notices that refer to this License and to the absence of any warranty;
-+and give any other recipients of the Program a copy of this License
-+along with the Program.
-+
-+You may charge a fee for the physical act of transferring a copy, and
-+you may at your option offer warranty protection in exchange for a fee.
-+
-+  2. You may modify your copy or copies of the Program or any portion
-+of it, thus forming a work based on the Program, and copy and
-+distribute such modifications or work under the terms of Section 1
-+above, provided that you also meet all of these conditions:
-+
-+    a) You must cause the modified files to carry prominent notices
-+    stating that you changed the files and the date of any change.
-+
-+    b) You must cause any work that you distribute or publish, that in
-+    whole or in part contains or is derived from the Program or any
-+    part thereof, to be licensed as a whole at no charge to all third
-+    parties under the terms of this License.
-+
-+    c) If the modified program normally reads commands interactively
-+    when run, you must cause it, when started running for such
-+    interactive use in the most ordinary way, to print or display an
-+    announcement including an appropriate copyright notice and a
-+    notice that there is no warranty (or else, saying that you provide
-+    a warranty) and that users may redistribute the program under
-+    these conditions, and telling the user how to view a copy of this
-+    License.  (Exception: if the Program itself is interactive but
-+    does not normally print such an announcement, your work based on
-+    the Program is not required to print an announcement.)
-+\f
-+These requirements apply to the modified work as a whole.  If
-+identifiable sections of that work are not derived from the Program,
-+and can be reasonably considered independent and separate works in
-+themselves, then this License, and its terms, do not apply to those
-+sections when you distribute them as separate works.  But when you
-+distribute the same sections as part of a whole which is a work based
-+on the Program, the distribution of the whole must be on the terms of
-+this License, whose permissions for other licensees extend to the
-+entire whole, and thus to each and every part regardless of who wrote it.
-+
-+Thus, it is not the intent of this section to claim rights or contest
-+your rights to work written entirely by you; rather, the intent is to
-+exercise the right to control the distribution of derivative or
-+collective works based on the Program.
-+
-+In addition, mere aggregation of another work not based on the Program
-+with the Program (or with a work based on the Program) on a volume of
-+a storage or distribution medium does not bring the other work under
-+the scope of this License.
-+
-+  3. You may copy and distribute the Program (or a work based on it,
-+under Section 2) in object code or executable form under the terms of
-+Sections 1 and 2 above provided that you also do one of the following:
-+
-+    a) Accompany it with the complete corresponding machine-readable
-+    source code, which must be distributed under the terms of Sections
-+    1 and 2 above on a medium customarily used for software interchange; or,
-+
-+    b) Accompany it with a written offer, valid for at least three
-+    years, to give any third party, for a charge no more than your
-+    cost of physically performing source distribution, a complete
-+    machine-readable copy of the corresponding source code, to be
-+    distributed under the terms of Sections 1 and 2 above on a medium
-+    customarily used for software interchange; or,
-+
-+    c) Accompany it with the information you received as to the offer
-+    to distribute corresponding source code.  (This alternative is
-+    allowed only for noncommercial distribution and only if you
-+    received the program in object code or executable form with such
-+    an offer, in accord with Subsection b above.)
-+
-+The source code for a work means the preferred form of the work for
-+making modifications to it.  For an executable work, complete source
-+code means all the source code for all modules it contains, plus any
-+associated interface definition files, plus the scripts used to
-+control compilation and installation of the executable.  However, as a
-+special exception, the source code distributed need not include
-+anything that is normally distributed (in either source or binary
-+form) with the major components (compiler, kernel, and so on) of the
-+operating system on which the executable runs, unless that component
-+itself accompanies the executable.
-+
-+If distribution of executable or object code is made by offering
-+access to copy from a designated place, then offering equivalent
-+access to copy the source code from the same place counts as
-+distribution of the source code, even though third parties are not
-+compelled to copy the source along with the object code.
-+\f
-+  4. You may not copy, modify, sublicense, or distribute the Program
-+except as expressly provided under this License.  Any attempt
-+otherwise to copy, modify, sublicense or distribute the Program is
-+void, and will automatically terminate your rights under this License.
-+However, parties who have received copies, or rights, from you under
-+this License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+  5. You are not required to accept this License, since you have not
-+signed it.  However, nothing else grants you permission to modify or
-+distribute the Program or its derivative works.  These actions are
-+prohibited by law if you do not accept this License.  Therefore, by
-+modifying or distributing the Program (or any work based on the
-+Program), you indicate your acceptance of this License to do so, and
-+all its terms and conditions for copying, distributing or modifying
-+the Program or works based on it.
-+
-+  6. Each time you redistribute the Program (or any work based on the
-+Program), the recipient automatically receives a license from the
-+original licensor to copy, distribute or modify the Program subject to
-+these terms and conditions.  You may not impose any further
-+restrictions on the recipients' exercise of the rights granted herein.
-+You are not responsible for enforcing compliance by third parties to
-+this License.
-+
-+  7. If, as a consequence of a court judgment or allegation of patent
-+infringement or for any other reason (not limited to patent issues),
-+conditions are imposed on you (whether by court order, agreement or
-+otherwise) that contradict the conditions of this License, they do not
-+excuse you from the conditions of this License.  If you cannot
-+distribute so as to satisfy simultaneously your obligations under this
-+License and any other pertinent obligations, then as a consequence you
-+may not distribute the Program at all.  For example, if a patent
-+license would not permit royalty-free redistribution of the Program by
-+all those who receive copies directly or indirectly through you, then
-+the only way you could satisfy both it and this License would be to
-+refrain entirely from distribution of the Program.
-+
-+If any portion of this section is held invalid or unenforceable under
-+any particular circumstance, the balance of the section is intended to
-+apply and the section as a whole is intended to apply in other
-+circumstances.
-+
-+It is not the purpose of this section to induce you to infringe any
-+patents or other property right claims or to contest validity of any
-+such claims; this section has the sole purpose of protecting the
-+integrity of the free software distribution system, which is
-+implemented by public license practices.  Many people have made
-+generous contributions to the wide range of software distributed
-+through that system in reliance on consistent application of that
-+system; it is up to the author/donor to decide if he or she is willing
-+to distribute software through any other system and a licensee cannot
-+impose that choice.
-+
-+This section is intended to make thoroughly clear what is believed to
-+be a consequence of the rest of this License.
-+\f
-+  8. If the distribution and/or use of the Program is restricted in
-+certain countries either by patents or by copyrighted interfaces, the
-+original copyright holder who places the Program under this License
-+may add an explicit geographical distribution limitation excluding
-+those countries, so that distribution is permitted only in or among
-+countries not thus excluded.  In such case, this License incorporates
-+the limitation as if written in the body of this License.
-+
-+  9. The Free Software Foundation may publish revised and/or new versions
-+of the General Public License from time to time.  Such new versions will
-+be similar in spirit to the present version, but may differ in detail to
-+address new problems or concerns.
-+
-+Each version is given a distinguishing version number.  If the Program
-+specifies a version number of this License which applies to it and "any
-+later version", you have the option of following the terms and conditions
-+either of that version or of any later version published by the Free
-+Software Foundation.  If the Program does not specify a version number of
-+this License, you may choose any version ever published by the Free Software
-+Foundation.
-+
-+  10. If you wish to incorporate parts of the Program into other free
-+programs whose distribution conditions are different, write to the author
-+to ask for permission.  For software which is copyrighted by the Free
-+Software Foundation, write to the Free Software Foundation; we sometimes
-+make exceptions for this.  Our decision will be guided by the two goals
-+of preserving the free status of all derivatives of our free software and
-+of promoting the sharing and reuse of software generally.
-+
-+                          NO WARRANTY
-+
-+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-+REPAIR OR CORRECTION.
-+
-+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-+POSSIBILITY OF SUCH DAMAGES.
-+
-+                   END OF TERMS AND CONDITIONS
-diff --git a/firmware/lantiq/README b/firmware/lantiq/README
-new file mode 100644
-index 0000000..1b666d4
---- /dev/null
-+++ b/firmware/lantiq/README
-@@ -0,0 +1,45 @@
-+#
-+# This program is free software; you can redistribute it and/or
-+# modify it under the terms of the GNU General Public License as
-+# published by the Free Software Foundation; either version 2 of
-+# the License, or (at your option) any later version.
-+#
-+# 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
-+#
-+# (C) Copyright 2007 - 2012
-+# Lantiq Deutschland GmbH
-+#
-+# (C) Copyright 2012
-+# Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
-+#
-+
-+#
-+# How to use
-+#
-+Configure kernel with:
-+CONFIG_FW_LOADER=y
-+CONFIG_EXTRA_FIRMWARE_DIR="FIRMWARE_DIR"
-+CONFIG_EXTRA_FIRMWARE="FIRMWARE_FILES"
-+
-+where FIRMWARE_DIR should point to this git tree and FIRMWARE_FILES is a list
-+of space separated files from list below.
-+
-+#
-+# Firmware files
-+#
-+
-+# GPHY core on Lantiq XWAY VR9 v1.1
-+lantiq/vr9_phy11g_a1x.bin
-+lantiq/vr9_phy22f_a1x.bin
-+
-+# GPHY core on Lantiq XWAY VR9 v1.2
-+lantiq/vr9_phy11g_a2x.bin
-+lantiq/vr9_phy22f_a2x.bin
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch b/target/linux/lantiq/patches-3.14/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch
new file mode 100644 (file)
index 0000000..44970a5
--- /dev/null
@@ -0,0 +1,41 @@
+From 4400e1f593ea40a51912128adb4f53d59e62cad8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 10 Sep 2014 22:40:18 +0200
+Subject: [PATCH 22/36] 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 |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index ad19139..9f7b35a 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -1097,6 +1097,10 @@ static int m25p_probe(struct spi_device *spi)
+       struct mtd_part_parser_data     ppdata;
+       struct device_node *np = spi->dev.of_node;
+       int ret;
++      const char __maybe_unused       *of_mtd_name = NULL;
++
++      of_property_read_string(spi->dev.of_node,
++              "linux,mtd-name", &of_mtd_name);
+       /* Platform data helps sort out which chip type we have, as
+        * well as how this board partitions it.  If we don't have
+@@ -1169,6 +1173,8 @@ static int m25p_probe(struct spi_device *spi)
+       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);
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0022-NET-MIPS-lantiq-adds-xrx200-net.patch b/target/linux/lantiq/patches-3.14/0022-NET-MIPS-lantiq-adds-xrx200-net.patch
deleted file mode 100644 (file)
index e47a519..0000000
+++ /dev/null
@@ -1,3357 +0,0 @@
-From 96f50ccba9258367e5c3a48fe6295572daac69d3 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 22 Oct 2012 12:22:23 +0200
-Subject: [PATCH 22/31] NET: MIPS: lantiq: adds xrx200-net
-
----
- drivers/net/ethernet/Kconfig            |    8 +-
- drivers/net/ethernet/Makefile           |    1 +
- drivers/net/ethernet/lantiq_pce.h       |  163 +++
- drivers/net/ethernet/lantiq_xrx200.c    | 1798 +++++++++++++++++++++++++++++++
- drivers/net/ethernet/lantiq_xrx200_sw.h | 1328 +++++++++++++++++++++++
- 5 files changed, 3297 insertions(+), 1 deletion(-)
- create mode 100644 drivers/net/ethernet/lantiq_pce.h
- create mode 100644 drivers/net/ethernet/lantiq_xrx200.c
- create mode 100644 drivers/net/ethernet/lantiq_xrx200_sw.h
-
-diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
-index 506b024..0a0dbe6 100644
---- a/drivers/net/ethernet/Kconfig
-+++ b/drivers/net/ethernet/Kconfig
-@@ -84,7 +84,13 @@ config LANTIQ_ETOP
-       tristate "Lantiq SoC ETOP driver"
-       depends on SOC_TYPE_XWAY
-       ---help---
--        Support for the MII0 inside the Lantiq SoC
-+        Support for the MII0 inside the Lantiq ADSL SoC
-+
-+config LANTIQ_XRX200
-+      tristate "Lantiq SoC XRX200 driver"
-+      depends on SOC_TYPE_XWAY
-+      ---help---
-+        Support for the MII0 inside the Lantiq VDSL SoC
- source "drivers/net/ethernet/marvell/Kconfig"
- source "drivers/net/ethernet/mellanox/Kconfig"
-diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
-index c0b8789..459cce8 100644
---- a/drivers/net/ethernet/Makefile
-+++ b/drivers/net/ethernet/Makefile
-@@ -38,6 +38,7 @@ obj-$(CONFIG_IP1000) += icplus/
- obj-$(CONFIG_JME) += jme.o
- obj-$(CONFIG_KORINA) += korina.o
- obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
-+obj-$(CONFIG_LANTIQ_XRX200) += lantiq_xrx200.o
- obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
- obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
- obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
-diff --git a/drivers/net/ethernet/lantiq_pce.h b/drivers/net/ethernet/lantiq_pce.h
-new file mode 100644
-index 0000000..0c38efe
---- /dev/null
-+++ b/drivers/net/ethernet/lantiq_pce.h
-@@ -0,0 +1,163 @@
-+/*
-+ *   This program is free software; you can redistribute it and/or modify it
-+ *   under the terms of the GNU General Public License version 2 as published
-+ *   by the Free Software Foundation.
-+ *
-+ *   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) 2010 Lantiq Deutschland GmbH
-+ *   Copyright (C) 2012 John Crispin <blogic@openwrt.org>
-+ *
-+ *   PCE microcode extracted from UGW5.2 switch api
-+ */
-+
-+/* Switch API Micro Code V0.3 */
-+enum {
-+      OUT_MAC0 = 0,
-+      OUT_MAC1,
-+      OUT_MAC2,
-+      OUT_MAC3,
-+      OUT_MAC4,
-+      OUT_MAC5,
-+      OUT_ETHTYP,
-+      OUT_VTAG0,
-+      OUT_VTAG1,
-+      OUT_ITAG0,
-+      OUT_ITAG1,      /*10 */
-+      OUT_ITAG2,
-+      OUT_ITAG3,
-+      OUT_IP0,
-+      OUT_IP1,
-+      OUT_IP2,
-+      OUT_IP3,
-+      OUT_SIP0,
-+      OUT_SIP1,
-+      OUT_SIP2,
-+      OUT_SIP3,       /*20*/
-+      OUT_SIP4,
-+      OUT_SIP5,
-+      OUT_SIP6,
-+      OUT_SIP7,
-+      OUT_DIP0,
-+      OUT_DIP1,
-+      OUT_DIP2,
-+      OUT_DIP3,
-+      OUT_DIP4,
-+      OUT_DIP5,       /*30*/
-+      OUT_DIP6,
-+      OUT_DIP7,
-+      OUT_SESID,
-+      OUT_PROT,
-+      OUT_APP0,
-+      OUT_APP1,
-+      OUT_IGMP0,
-+      OUT_IGMP1,
-+      OUT_IPOFF,      /*39*/
-+      OUT_NONE =  63
-+};
-+
-+/* parser's microcode length type */
-+#define INSTR         0
-+#define IPV6          1
-+#define LENACCU               2
-+
-+/* parser's microcode flag type */
-+enum {
-+      FLAG_ITAG =  0,
-+      FLAG_VLAN,
-+      FLAG_SNAP,
-+      FLAG_PPPOE,
-+      FLAG_IPV6,
-+      FLAG_IPV6FL,
-+      FLAG_IPV4,
-+      FLAG_IGMP,
-+      FLAG_TU,
-+      FLAG_HOP,
-+      FLAG_NN1,       /*10 */
-+      FLAG_NN2,
-+      FLAG_END,
-+      FLAG_NO,        /*13*/
-+};
-+
-+/* Micro code version V2_11 (extension for parsing IPv6 in PPPoE) */
-+#define MC_ENTRY(val, msk, ns, out, len, type, flags, ipv4_len) \
-+      { {val, msk, (ns<<10 | out<<4 | len>>1), (len&1)<<15 | type<<13 | flags<<9 | ipv4_len<<8 }}
-+struct pce_microcode {
-+      unsigned short val[4];
-+/*    unsigned short val_2;
-+      unsigned short val_1;
-+      unsigned short val_0;*/
-+} pce_microcode[] = {
-+      /*      value    mask    ns  fields      L  type     flags       ipv4_len */
-+      MC_ENTRY(0x88c3, 0xFFFF,  1, OUT_ITAG0,  4, INSTR,   FLAG_ITAG,  0),
-+      MC_ENTRY(0x8100, 0xFFFF,  2, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
-+      MC_ENTRY(0x88A8, 0xFFFF,  1, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
-+      MC_ENTRY(0x8100, 0xFFFF,  1, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
-+      MC_ENTRY(0x8864, 0xFFFF, 17, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0800, 0xFFFF, 21, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x86DD, 0xFFFF, 22, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x8863, 0xFFFF, 16, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0xF800, 10, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 38, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0600, 0x0600, 38, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 12, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0xAAAA, 0xFFFF, 14, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0300, 0xFF00, 39, OUT_NONE,   0, INSTR,   FLAG_SNAP,  0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_DIP7,   3, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 18, OUT_DIP7,   3, INSTR,   FLAG_PPPOE, 0),
-+      MC_ENTRY(0x0021, 0xFFFF, 21, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0057, 0xFFFF, 22, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x4000, 0xF000, 24, OUT_IP0,    4, INSTR,   FLAG_IPV4,  1),
-+      MC_ENTRY(0x6000, 0xF000, 27, OUT_IP0,    3, INSTR,   FLAG_IPV6,  0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 25, OUT_IP3,    2, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 26, OUT_SIP0,   4, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 38, OUT_NONE,   0, LENACCU, FLAG_NO,    0),
-+      MC_ENTRY(0x1100, 0xFF00, 37, OUT_PROT,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0600, 0xFF00, 37, OUT_PROT,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_HOP,   0),
-+      MC_ENTRY(0x2B00, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_NN1,   0),
-+      MC_ENTRY(0x3C00, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_NN2,   0),
-+      MC_ENTRY(0x0000, 0x0000, 37, OUT_PROT,   1, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0xFF00, 33, OUT_NONE,   0, IPV6,    FLAG_HOP,   0),
-+      MC_ENTRY(0x2B00, 0xFF00, 33, OUT_NONE,   0, IPV6,    FLAG_NN1,   0),
-+      MC_ENTRY(0x3C00, 0xFF00, 33, OUT_NONE,   0, IPV6,    FLAG_NN2,   0),
-+      MC_ENTRY(0x0000, 0x0000, 38, OUT_PROT,   1, IPV6,    FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 38, OUT_SIP0,  16, INSTR,   FLAG_NO,    0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_APP0,   4, INSTR,   FLAG_IGMP,  0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
-+};
-diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c
-new file mode 100644
-index 0000000..2da9d47
---- /dev/null
-+++ b/drivers/net/ethernet/lantiq_xrx200.c
-@@ -0,0 +1,1798 @@
-+/*
-+ *   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.
-+ *
-+ *   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) 2010 Lantiq Deutschland
-+ *   Copyright (C) 2012 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/switch.h>
-+#include <linux/etherdevice.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/clk.h>
-+#include <asm/delay.h>
-+
-+#include <linux/of_net.h>
-+#include <linux/of_mdio.h>
-+#include <linux/of_gpio.h>
-+
-+#include <xway_dma.h>
-+#include <lantiq_soc.h>
-+
-+#include "lantiq_pce.h"
-+#include "lantiq_xrx200_sw.h"
-+
-+#define SW_POLLING
-+#define SW_ROUTING
-+#define SW_PORTMAP
-+
-+#ifdef SW_ROUTING
-+  #ifdef SW_PORTMAP
-+#define XRX200_MAX_DEV                2
-+  #else
-+#define XRX200_MAX_DEV                2
-+  #endif
-+#else
-+#define XRX200_MAX_DEV                1
-+#endif
-+
-+#define XRX200_MAX_VLAN               64
-+#define XRX200_PCE_ACTVLAN_IDX        0x01
-+#define XRX200_PCE_VLANMAP_IDX        0x02
-+
-+#define XRX200_MAX_PORT               7
-+#define XRX200_MAX_DMA                8
-+
-+#define XRX200_HEADROOM               4
-+
-+#define XRX200_TX_TIMEOUT     (10 * HZ)
-+
-+/* port type */
-+#define XRX200_PORT_TYPE_PHY  1
-+#define XRX200_PORT_TYPE_MAC  2
-+
-+/* DMA */
-+#define XRX200_DMA_DATA_LEN   0x600
-+#define XRX200_DMA_IRQ                INT_NUM_IM2_IRL0
-+#define XRX200_DMA_RX         0
-+#define XRX200_DMA_TX         1
-+#define XRX200_DMA_IS_TX(x)   (x%2)
-+#define XRX200_DMA_IS_RX(x)   (!XRX200_DMA_IS_TX(x))
-+
-+/* fetch / store dma */
-+#define FDMA_PCTRL0           0x2A00
-+#define FDMA_PCTRLx(x)                (FDMA_PCTRL0 + (x * 0x18))
-+#define SDMA_PCTRL0           0x2F00
-+#define SDMA_PCTRLx(x)                (SDMA_PCTRL0 + (x * 0x18))
-+
-+/* buffer management */
-+#define BM_PCFG0              0x200
-+#define BM_PCFGx(x)           (BM_PCFG0 + (x * 8))
-+
-+/* MDIO */
-+#define MDIO_GLOB             0x0000
-+#define MDIO_CTRL             0x0020
-+#define MDIO_READ             0x0024
-+#define MDIO_WRITE            0x0028
-+#define MDIO_PHY0             0x0054
-+#define MDIO_PHY(x)           (0x0054 - (x * sizeof(unsigned)))
-+#define MDIO_CLK_CFG0         0x002C
-+#define MDIO_CLK_CFG1         0x0030
-+
-+#define MDIO_GLOB_ENABLE      0x8000
-+#define MDIO_BUSY             BIT(12)
-+#define MDIO_RD                       BIT(11)
-+#define MDIO_WR                       BIT(10)
-+#define MDIO_MASK             0x1f
-+#define MDIO_ADDRSHIFT                5
-+#define MDIO1_25MHZ           9
-+
-+#define MDIO_PHY_LINK_DOWN    0x4000
-+#define MDIO_PHY_LINK_UP      0x2000
-+
-+#define MDIO_PHY_SPEED_M10    0x0000
-+#define MDIO_PHY_SPEED_M100   0x0800
-+#define MDIO_PHY_SPEED_G1     0x1000
-+
-+#define MDIO_PHY_FDUP_EN      0x0200
-+#define MDIO_PHY_FDUP_DIS     0x0600
-+
-+#define MDIO_PHY_LINK_MASK    0x6000
-+#define MDIO_PHY_SPEED_MASK   0x1800
-+#define MDIO_PHY_FDUP_MASK    0x0600
-+#define MDIO_PHY_ADDR_MASK    0x001f
-+#define MDIO_UPDATE_MASK      MDIO_PHY_ADDR_MASK | MDIO_PHY_LINK_MASK | \
-+                                      MDIO_PHY_SPEED_MASK | MDIO_PHY_FDUP_MASK
-+
-+/* MII */
-+#define MII_CFG(p)            (p * 8)
-+
-+#define MII_CFG_EN            BIT(14)
-+
-+#define MII_CFG_MODE_MIIP     0x0
-+#define MII_CFG_MODE_MIIM     0x1
-+#define MII_CFG_MODE_RMIIP    0x2
-+#define MII_CFG_MODE_RMIIM    0x3
-+#define MII_CFG_MODE_RGMII    0x4
-+#define MII_CFG_MODE_MASK     0xf
-+
-+#define MII_CFG_RATE_M2P5     0x00
-+#define MII_CFG_RATE_M25      0x10
-+#define MII_CFG_RATE_M125     0x20
-+#define MII_CFG_RATE_M50      0x30
-+#define MII_CFG_RATE_AUTO     0x40
-+#define MII_CFG_RATE_MASK     0x70
-+
-+/* cpu port mac */
-+#define PMAC_HD_CTL           0x0000
-+#define PMAC_RX_IPG           0x0024
-+#define PMAC_EWAN             0x002c
-+
-+#define PMAC_IPG_MASK         0xf
-+#define PMAC_HD_CTL_AS                0x0008
-+#define PMAC_HD_CTL_AC                0x0004
-+#define PMAC_HD_CTL_RXSH      0x0040
-+#define PMAC_HD_CTL_AST               0x0080
-+#define PMAC_HD_CTL_RST               0x0100
-+
-+/* PCE */
-+#define PCE_TBL_KEY(x)                (0x1100 + ((7 - x) * 4))
-+#define PCE_TBL_MASK          0x1120
-+#define PCE_TBL_VAL(x)                (0x1124 + ((4 - x) * 4))
-+#define PCE_TBL_ADDR          0x1138
-+#define PCE_TBL_CTRL          0x113c
-+#define PCE_PMAP1             0x114c
-+#define PCE_PMAP2             0x1150
-+#define PCE_PMAP3             0x1154
-+#define PCE_GCTRL_REG(x)      (0x1158 + (x * 4))
-+#define PCE_PCTRL_REG(p, x)   (0x1200 + (((p * 0xa) + x) * 4))
-+
-+#define PCE_TBL_BUSY          BIT(15)
-+#define PCE_TBL_CFG_ADDR_MASK 0x1f
-+#define PCE_TBL_CFG_ADWR      0x20
-+#define PCE_TBL_CFG_ADWR_MASK 0x60
-+#define PCE_INGRESS           BIT(11)
-+
-+/* MAC */
-+#define MAC_FLEN_REG          (0x2314)
-+#define MAC_CTRL_REG(p, x)    (0x240c + (((p * 0xc) + x) * 4))
-+
-+/* buffer management */
-+#define BM_PCFG(p)            (0x200 + (p * 8))
-+
-+/* special tag in TX path header */
-+#define SPID_SHIFT            24
-+#define DPID_SHIFT            16
-+#define DPID_ENABLE           1
-+#define SPID_CPU_PORT         2
-+#define PORT_MAP_SEL          BIT(15)
-+#define PORT_MAP_EN           BIT(14)
-+#define PORT_MAP_SHIFT                1
-+#define PORT_MAP_MASK         0x3f
-+
-+#define SPPID_MASK            0x7
-+#define SPPID_SHIFT           4
-+
-+/* MII regs not yet in linux */
-+#define MDIO_DEVAD_NONE               (-1)
-+#define ADVERTIZE_MPD         (1 << 10)
-+
-+struct xrx200_port {
-+      u8 num;
-+      u8 phy_addr;
-+      u16 flags;
-+      phy_interface_t phy_if;
-+
-+      int link;
-+      int gpio;
-+      enum of_gpio_flags gpio_flags;
-+
-+      struct phy_device *phydev;
-+      struct device_node *phy_node;
-+};
-+
-+struct xrx200_chan {
-+      int idx;
-+      int refcount;
-+      int tx_free;
-+
-+      struct net_device dummy_dev;
-+      struct net_device *devs[XRX200_MAX_DEV];
-+
-+      struct tasklet_struct tasklet;
-+      struct napi_struct napi;
-+      struct ltq_dma_channel dma;
-+      struct sk_buff *skb[LTQ_DESC_NUM];
-+};
-+
-+struct xrx200_hw {
-+      struct clk *clk;
-+      struct mii_bus *mii_bus;
-+
-+      struct xrx200_chan chan[XRX200_MAX_DMA];
-+
-+      struct net_device *devs[XRX200_MAX_DEV];
-+      int num_devs;
-+
-+      int port_map[XRX200_MAX_PORT];
-+      unsigned short wan_map;
-+
-+      spinlock_t lock;
-+
-+      struct switch_dev swdev;
-+};
-+
-+struct xrx200_priv {
-+      struct net_device_stats stats;
-+      int id;
-+
-+      struct xrx200_port port[XRX200_MAX_PORT];
-+      int num_port;
-+      bool wan;
-+      bool sw;
-+      unsigned short port_map;
-+      unsigned char mac[6];
-+
-+      struct xrx200_hw *hw;
-+};
-+
-+static __iomem void *xrx200_switch_membase;
-+static __iomem void *xrx200_mii_membase;
-+static __iomem void *xrx200_mdio_membase;
-+static __iomem void *xrx200_pmac_membase;
-+
-+#define ltq_switch_r32(x)     ltq_r32(xrx200_switch_membase + (x))
-+#define ltq_switch_w32(x, y)  ltq_w32(x, xrx200_switch_membase + (y))
-+#define ltq_switch_w32_mask(x, y, z) \
-+                      ltq_w32_mask(x, y, xrx200_switch_membase + (z))
-+
-+#define ltq_mdio_r32(x)               ltq_r32(xrx200_mdio_membase + (x))
-+#define ltq_mdio_w32(x, y)    ltq_w32(x, xrx200_mdio_membase + (y))
-+#define ltq_mdio_w32_mask(x, y, z) \
-+                      ltq_w32_mask(x, y, xrx200_mdio_membase + (z))
-+
-+#define ltq_mii_r32(x)                ltq_r32(xrx200_mii_membase + (x))
-+#define ltq_mii_w32(x, y)     ltq_w32(x, xrx200_mii_membase + (y))
-+#define ltq_mii_w32_mask(x, y, z) \
-+                      ltq_w32_mask(x, y, xrx200_mii_membase + (z))
-+
-+#define ltq_pmac_r32(x)               ltq_r32(xrx200_pmac_membase + (x))
-+#define ltq_pmac_w32(x, y)    ltq_w32(x, xrx200_pmac_membase + (y))
-+#define ltq_pmac_w32_mask(x, y, z) \
-+                      ltq_w32_mask(x, y, xrx200_pmac_membase + (z))
-+
-+#define XRX200_GLOBAL_REGATTR(reg) \
-+      .id = reg, \
-+      .type = SWITCH_TYPE_INT, \
-+      .set = xrx200_set_global_attr, \
-+      .get = xrx200_get_global_attr
-+
-+#define XRX200_PORT_REGATTR(reg) \
-+      .id = reg, \
-+      .type = SWITCH_TYPE_INT, \
-+      .set = xrx200_set_port_attr, \
-+      .get = xrx200_get_port_attr
-+
-+static int xrx200sw_read_x(int reg, int x)
-+{
-+      int value, mask, addr;
-+
-+      addr = xrx200sw_reg[reg].offset + (xrx200sw_reg[reg].mult * x);
-+      value = ltq_switch_r32(addr);
-+      mask = (1 << xrx200sw_reg[reg].size) - 1;
-+      value = (value >> xrx200sw_reg[reg].shift);
-+
-+      return (value & mask);
-+}
-+
-+static int xrx200sw_read(int reg)
-+{
-+      return xrx200sw_read_x(reg, 0);
-+}
-+
-+static void xrx200sw_write_x(int value, int reg, int x)
-+{
-+      int mask, addr;
-+
-+      addr = xrx200sw_reg[reg].offset + (xrx200sw_reg[reg].mult * x);
-+      mask = (1 << xrx200sw_reg[reg].size) - 1;
-+      mask = (mask << xrx200sw_reg[reg].shift);
-+      value = (value << xrx200sw_reg[reg].shift) & mask;
-+
-+      ltq_switch_w32_mask(mask, value, addr);
-+}
-+
-+static void xrx200sw_write(int value, int reg)
-+{
-+      xrx200sw_write_x(value, reg, 0);
-+}
-+
-+struct xrx200_pce_table_entry {
-+      int index;      // PCE_TBL_ADDR.ADDR = pData->table_index
-+      int table;      // PCE_TBL_CTRL.ADDR = pData->table
-+      unsigned short key[8];
-+      unsigned short val[5];
-+      unsigned short mask;
-+      unsigned short type;
-+      unsigned short valid;
-+      unsigned short gmap;
-+};
-+
-+static int xrx200_pce_table_entry_read(struct xrx200_pce_table_entry *tbl)
-+{
-+      // wait until hardware is ready
-+      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
-+
-+      // prepare the table access:
-+      // PCE_TBL_ADDR.ADDR = pData->table_index
-+      xrx200sw_write(tbl->index, XRX200_PCE_TBL_ADDR_ADDR);
-+      // PCE_TBL_CTRL.ADDR = pData->table
-+      xrx200sw_write(tbl->table, XRX200_PCE_TBL_CTRL_ADDR);
-+
-+      //(address-based read)
-+      xrx200sw_write(0, XRX200_PCE_TBL_CTRL_OPMOD); // OPMOD_ADRD
-+
-+      xrx200sw_write(1, XRX200_PCE_TBL_CTRL_BAS); // start access
-+
-+      // wait until hardware is ready
-+      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
-+
-+      // read the keys
-+      tbl->key[7] = xrx200sw_read(XRX200_PCE_TBL_KEY_7);
-+      tbl->key[6] = xrx200sw_read(XRX200_PCE_TBL_KEY_6);
-+      tbl->key[5] = xrx200sw_read(XRX200_PCE_TBL_KEY_5);
-+      tbl->key[4] = xrx200sw_read(XRX200_PCE_TBL_KEY_4);
-+      tbl->key[3] = xrx200sw_read(XRX200_PCE_TBL_KEY_3);
-+      tbl->key[2] = xrx200sw_read(XRX200_PCE_TBL_KEY_2);
-+      tbl->key[1] = xrx200sw_read(XRX200_PCE_TBL_KEY_1);
-+      tbl->key[0] = xrx200sw_read(XRX200_PCE_TBL_KEY_0);
-+
-+      // read the values
-+      tbl->val[4] = xrx200sw_read(XRX200_PCE_TBL_VAL_4);
-+      tbl->val[3] = xrx200sw_read(XRX200_PCE_TBL_VAL_3);
-+      tbl->val[2] = xrx200sw_read(XRX200_PCE_TBL_VAL_2);
-+      tbl->val[1] = xrx200sw_read(XRX200_PCE_TBL_VAL_1);
-+      tbl->val[0] = xrx200sw_read(XRX200_PCE_TBL_VAL_0);
-+
-+      // read the mask
-+      tbl->mask = xrx200sw_read(XRX200_PCE_TBL_MASK_0);
-+      // read the type
-+      tbl->type = xrx200sw_read(XRX200_PCE_TBL_CTRL_TYPE);
-+      // read the valid flag
-+      tbl->valid = xrx200sw_read(XRX200_PCE_TBL_CTRL_VLD);
-+      // read the group map
-+      tbl->gmap = xrx200sw_read(XRX200_PCE_TBL_CTRL_GMAP);
-+
-+      return 0;
-+}
-+
-+static int xrx200_pce_table_entry_write(struct xrx200_pce_table_entry *tbl)
-+{
-+      // wait until hardware is ready
-+      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
-+
-+      // prepare the table access:
-+      // PCE_TBL_ADDR.ADDR = pData->table_index
-+      xrx200sw_write(tbl->index, XRX200_PCE_TBL_ADDR_ADDR);
-+      // PCE_TBL_CTRL.ADDR = pData->table
-+      xrx200sw_write(tbl->table, XRX200_PCE_TBL_CTRL_ADDR);
-+
-+      //(address-based write)
-+      xrx200sw_write(1, XRX200_PCE_TBL_CTRL_OPMOD); // OPMOD_ADRD
-+
-+      // read the keys
-+      xrx200sw_write(tbl->key[7], XRX200_PCE_TBL_KEY_7);
-+      xrx200sw_write(tbl->key[6], XRX200_PCE_TBL_KEY_6);
-+      xrx200sw_write(tbl->key[5], XRX200_PCE_TBL_KEY_5);
-+      xrx200sw_write(tbl->key[4], XRX200_PCE_TBL_KEY_4);
-+      xrx200sw_write(tbl->key[3], XRX200_PCE_TBL_KEY_3);
-+      xrx200sw_write(tbl->key[2], XRX200_PCE_TBL_KEY_2);
-+      xrx200sw_write(tbl->key[1], XRX200_PCE_TBL_KEY_1);
-+      xrx200sw_write(tbl->key[0], XRX200_PCE_TBL_KEY_0);
-+
-+      // read the values
-+      xrx200sw_write(tbl->val[4], XRX200_PCE_TBL_VAL_4);
-+      xrx200sw_write(tbl->val[3], XRX200_PCE_TBL_VAL_3);
-+      xrx200sw_write(tbl->val[2], XRX200_PCE_TBL_VAL_2);
-+      xrx200sw_write(tbl->val[1], XRX200_PCE_TBL_VAL_1);
-+      xrx200sw_write(tbl->val[0], XRX200_PCE_TBL_VAL_0);
-+
-+      // read the mask
-+      xrx200sw_write(tbl->mask, XRX200_PCE_TBL_MASK_0);
-+      // read the type
-+      xrx200sw_write(tbl->type, XRX200_PCE_TBL_CTRL_TYPE);
-+      // read the valid flag
-+      xrx200sw_write(tbl->valid, XRX200_PCE_TBL_CTRL_VLD);
-+      // read the group map
-+      xrx200sw_write(tbl->gmap, XRX200_PCE_TBL_CTRL_GMAP);
-+
-+      xrx200sw_write(1, XRX200_PCE_TBL_CTRL_BAS); // start access
-+
-+      // wait until hardware is ready
-+      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
-+
-+      return 0;
-+}
-+
-+static void xrx200sw_fixup_pvids(void)
-+{
-+      int index, p, portmap, untagged;
-+      struct xrx200_pce_table_entry tem;
-+      struct xrx200_pce_table_entry tev;
-+
-+      portmap = 0;
-+      for (p = 0; p < XRX200_MAX_PORT; p++)
-+              portmap |= BIT(p);
-+
-+      tem.table = XRX200_PCE_VLANMAP_IDX;
-+      tev.table = XRX200_PCE_ACTVLAN_IDX;
-+
-+      for (index = XRX200_MAX_VLAN; index-- > 0;)
-+      {
-+              tev.index = index;
-+              xrx200_pce_table_entry_read(&tev);
-+
-+              if (tev.valid == 0)
-+                      continue;
-+
-+              tem.index = index;
-+              xrx200_pce_table_entry_read(&tem);
-+
-+              if (tem.val[0] == 0)
-+                      continue;
-+
-+              untagged = portmap & (tem.val[1] ^ tem.val[2]);
-+
-+              for (p = 0; p < XRX200_MAX_PORT; p++)
-+                      if (untagged & BIT(p))
-+                      {
-+                              portmap &= ~BIT(p);
-+                              xrx200sw_write_x(index, XRX200_PCE_DEFPVID_PVID, p);
-+                      }
-+
-+              for (p = 0; p < XRX200_MAX_PORT; p++)
-+                      if (portmap & BIT(p))
-+                              xrx200sw_write_x(index, XRX200_PCE_DEFPVID_PVID, p);
-+      }
-+}
-+
-+// swconfig interface
-+static void xrx200_hw_init(struct xrx200_hw *hw);
-+
-+// global
-+static int xrx200sw_reset_switch(struct switch_dev *dev)
-+{
-+      struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev);
-+
-+      xrx200_hw_init(hw);
-+
-+      return 0;
-+}
-+
-+static int xrx200_set_vlan_mode_enable(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
-+{
-+      int p;
-+
-+      if ((attr->max > 0) && (val->value.i > attr->max))
-+              return -EINVAL;
-+
-+      for (p = 0; p < XRX200_MAX_PORT; p++) {
-+              xrx200sw_write_x(val->value.i, XRX200_PCE_VCTRL_VEMR, p);
-+              xrx200sw_write_x(val->value.i, XRX200_PCE_VCTRL_VIMR, p);
-+      }
-+
-+      xrx200sw_write(val->value.i, XRX200_PCE_GCTRL_0_VLAN);
-+      return 0;
-+}
-+
-+static int xrx200_get_vlan_mode_enable(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
-+{
-+      val->value.i = xrx200sw_read(attr->id);
-+      return 0;
-+}
-+
-+static int xrx200_set_global_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
-+{
-+      if ((attr->max > 0) && (val->value.i > attr->max))
-+              return -EINVAL;
-+
-+      xrx200sw_write(val->value.i, attr->id);
-+      return 0;
-+}
-+
-+static int xrx200_get_global_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
-+{
-+      val->value.i = xrx200sw_read(attr->id);
-+      return 0;
-+}
-+
-+// vlan
-+static int xrx200sw_set_vlan_vid(struct switch_dev *dev, const struct switch_attr *attr,
-+                               struct switch_val *val)
-+{
-+      int i;
-+      struct xrx200_pce_table_entry tev;
-+      struct xrx200_pce_table_entry tem;
-+
-+      tev.table = XRX200_PCE_ACTVLAN_IDX;
-+
-+      for (i = 0; i < XRX200_MAX_VLAN; i++)
-+      {
-+              tev.index = i;
-+              xrx200_pce_table_entry_read(&tev);
-+              if (tev.key[0] == val->value.i && i != val->port_vlan)
-+                      return -EINVAL;
-+      }
-+
-+      tev.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&tev);
-+      tev.key[0] = val->value.i;
-+      tev.valid = val->value.i > 0;
-+      xrx200_pce_table_entry_write(&tev);
-+
-+      tem.table = XRX200_PCE_VLANMAP_IDX;
-+      tem.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&tem);
-+      tem.val[0] = val->value.i;
-+      xrx200_pce_table_entry_write(&tem);
-+
-+      xrx200sw_fixup_pvids();
-+      return 0;
-+}
-+
-+static int xrx200sw_get_vlan_vid(struct switch_dev *dev, const struct switch_attr *attr,
-+                               struct switch_val *val)
-+{
-+      struct xrx200_pce_table_entry te;
-+
-+      te.table = XRX200_PCE_ACTVLAN_IDX;
-+      te.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&te);
-+      val->value.i = te.key[0];
-+
-+      return 0;
-+}
-+
-+static int xrx200sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
-+{
-+      int i, portmap, tagmap, untagged;
-+      struct xrx200_pce_table_entry tem;
-+
-+      portmap = 0;
-+      tagmap = 0;
-+      for (i = 0; i < val->len; i++)
-+      {
-+              struct switch_port *p = &val->value.ports[i];
-+
-+              portmap |= (1 << p->id);
-+              if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
-+                      tagmap |= (1 << p->id);
-+      }
-+
-+      tem.table = XRX200_PCE_VLANMAP_IDX;
-+
-+      untagged = portmap ^ tagmap;
-+      for (i = 0; i < XRX200_MAX_VLAN; i++)
-+      {
-+              tem.index = i;
-+              xrx200_pce_table_entry_read(&tem);
-+
-+              if (tem.val[0] == 0)
-+                      continue;
-+
-+              if ((untagged & (tem.val[1] ^ tem.val[2])) && (val->port_vlan != i))
-+                      return -EINVAL;
-+      }
-+
-+      tem.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&tem);
-+
-+      // auto-enable this vlan if not enabled already
-+      if (tem.val[0] == 0)
-+      {
-+              struct switch_val v;
-+              v.port_vlan = val->port_vlan;
-+              v.value.i = val->port_vlan;
-+              if(xrx200sw_set_vlan_vid(dev, NULL, &v))
-+                      return -EINVAL;
-+
-+              //read updated tem
-+              tem.index = val->port_vlan;
-+              xrx200_pce_table_entry_read(&tem);
-+      }
-+
-+      tem.val[1] = portmap;
-+      tem.val[2] = tagmap;
-+      xrx200_pce_table_entry_write(&tem);
-+
-+      xrx200sw_fixup_pvids();
-+
-+      return 0;
-+}
-+
-+static int xrx200sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
-+{
-+      int i;
-+      unsigned short ports, tags;
-+      struct xrx200_pce_table_entry tem;
-+
-+      tem.table = XRX200_PCE_VLANMAP_IDX;
-+      tem.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&tem);
-+
-+      ports = tem.val[1];
-+      tags = tem.val[2];
-+
-+      for (i = 0; i < XRX200_MAX_PORT; i++) {
-+              struct switch_port *p;
-+
-+              if (!(ports & (1 << i)))
-+                      continue;
-+
-+              p = &val->value.ports[val->len++];
-+              p->id = i;
-+              if (tags & (1 << i))
-+                      p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
-+              else
-+                      p->flags = 0;
-+      }
-+
-+      return 0;
-+}
-+
-+static int xrx200sw_set_vlan_enable(struct switch_dev *dev, const struct switch_attr *attr,
-+                               struct switch_val *val)
-+{
-+      struct xrx200_pce_table_entry tev;
-+
-+      tev.table = XRX200_PCE_ACTVLAN_IDX;
-+      tev.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&tev);
-+
-+      if (tev.key[0] == 0)
-+              return -EINVAL;
-+
-+      tev.valid = val->value.i;
-+      xrx200_pce_table_entry_write(&tev);
-+
-+      xrx200sw_fixup_pvids();
-+      return 0;
-+}
-+
-+static int xrx200sw_get_vlan_enable(struct switch_dev *dev, const struct switch_attr *attr,
-+                               struct switch_val *val)
-+{
-+      struct xrx200_pce_table_entry tev;
-+
-+      tev.table = XRX200_PCE_ACTVLAN_IDX;
-+      tev.index = val->port_vlan;
-+      xrx200_pce_table_entry_read(&tev);
-+      val->value.i = tev.valid;
-+
-+      return 0;
-+}
-+
-+// port
-+static int xrx200sw_get_port_pvid(struct switch_dev *dev, int port, int *val)
-+{
-+      struct xrx200_pce_table_entry tev;
-+
-+      if (port >= XRX200_MAX_PORT)
-+              return -EINVAL;
-+
-+      tev.table = XRX200_PCE_ACTVLAN_IDX;
-+      tev.index = xrx200sw_read_x(XRX200_PCE_DEFPVID_PVID, port);
-+      xrx200_pce_table_entry_read(&tev);
-+
-+      *val = tev.key[0];
-+      return 0;
-+}
-+
-+static int xrx200sw_get_port_link(struct switch_dev *dev,
-+                                int port,
-+                                struct switch_port_link *link)
-+{
-+      if (port >= XRX200_MAX_PORT)
-+              return -EINVAL;
-+
-+      link->link = xrx200sw_read_x(XRX200_MAC_PSTAT_LSTAT, port);
-+      if (!link->link)
-+              return 0;
-+
-+      link->duplex = xrx200sw_read_x(XRX200_MAC_PSTAT_FDUP, port);
-+
-+      link->rx_flow = !!(xrx200sw_read_x(XRX200_MAC_CTRL_0_FCON, port) && 0x0010);
-+      link->tx_flow = !!(xrx200sw_read_x(XRX200_MAC_CTRL_0_FCON, port) && 0x0020);
-+      link->aneg = !(xrx200sw_read_x(XRX200_MAC_CTRL_0_FCON, port));
-+
-+      link->speed = SWITCH_PORT_SPEED_10;
-+      if (xrx200sw_read_x(XRX200_MAC_PSTAT_MBIT, port))
-+              link->speed = SWITCH_PORT_SPEED_100;
-+      if (xrx200sw_read_x(XRX200_MAC_PSTAT_GBIT, port))
-+              link->speed = SWITCH_PORT_SPEED_1000;
-+
-+      return 0;
-+}
-+
-+static int xrx200_set_port_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
-+{
-+      printk("%s %s(%d)\n", __FILE__, __func__, __LINE__);
-+      if (val->port_vlan >= XRX200_MAX_PORT)
-+              return -EINVAL;
-+
-+      if ((attr->max > 0) && (val->value.i > attr->max))
-+              return -EINVAL;
-+
-+      xrx200sw_write_x(val->value.i, attr->id, val->port_vlan);
-+      return 0;
-+}
-+
-+static int xrx200_get_port_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
-+{
-+      if (val->port_vlan >= XRX200_MAX_PORT)
-+              return -EINVAL;
-+
-+      val->value.i = xrx200sw_read_x(attr->id, val->port_vlan);
-+      return 0;
-+}
-+
-+// attributes
-+static struct switch_attr xrx200sw_globals[] = {
-+      {
-+              .type = SWITCH_TYPE_INT,
-+              .set = xrx200_set_vlan_mode_enable,
-+              .get = xrx200_get_vlan_mode_enable,
-+              .name = "enable_vlan",
-+              .description = "Enable VLAN mode",
-+              .max = 1},
-+};
-+
-+static struct switch_attr xrx200sw_port[] = {
-+      {
-+      XRX200_PORT_REGATTR(XRX200_PCE_VCTRL_UVR),
-+      .name = "uvr",
-+      .description = "Unknown VLAN Rule",
-+      .max = 1,
-+      },
-+      {
-+      XRX200_PORT_REGATTR(XRX200_PCE_VCTRL_VSR),
-+      .name = "vsr",
-+      .description = "VLAN Security Rule",
-+      .max = 1,
-+      },
-+      {
-+      XRX200_PORT_REGATTR(XRX200_PCE_VCTRL_VINR),
-+      .name = "vinr",
-+      .description = "VLAN Ingress Tag Rule",
-+      .max = 2,
-+      },
-+      {
-+      XRX200_PORT_REGATTR(XRX200_PCE_PCTRL_0_TVM),
-+      .name = "tvm",
-+      .description = "Transparent VLAN Mode",
-+      .max = 1,
-+      },
-+};
-+
-+static struct switch_attr xrx200sw_vlan[] = {
-+      {
-+              .type = SWITCH_TYPE_INT,
-+              .name = "vid",
-+              .description = "VLAN ID (0-4094)",
-+              .set = xrx200sw_set_vlan_vid,
-+              .get = xrx200sw_get_vlan_vid,
-+              .max = 4094,
-+      },
-+      {
-+              .type = SWITCH_TYPE_INT,
-+              .name = "enable",
-+              .description = "Enable VLAN",
-+              .set = xrx200sw_set_vlan_enable,
-+              .get = xrx200sw_get_vlan_enable,
-+              .max = 1,
-+      },
-+};
-+
-+static const struct switch_dev_ops xrx200sw_ops = {
-+      .attr_global = {
-+              .attr = xrx200sw_globals,
-+              .n_attr = ARRAY_SIZE(xrx200sw_globals),
-+      },
-+      .attr_port = {
-+              .attr = xrx200sw_port,
-+              .n_attr = ARRAY_SIZE(xrx200sw_port),
-+      },
-+      .attr_vlan = {
-+              .attr = xrx200sw_vlan,
-+              .n_attr = ARRAY_SIZE(xrx200sw_vlan),
-+      },
-+      .get_vlan_ports = xrx200sw_get_vlan_ports,
-+      .set_vlan_ports = xrx200sw_set_vlan_ports,
-+      .get_port_pvid = xrx200sw_get_port_pvid,
-+      .reset_switch = xrx200sw_reset_switch,
-+      .get_port_link = xrx200sw_get_port_link,
-+//    .get_port_stats = xrx200sw_get_port_stats, //TODO
-+};
-+
-+static int xrx200sw_init(struct xrx200_hw *hw)
-+{
-+      int netdev_num;
-+
-+      for (netdev_num = 0; netdev_num < hw->num_devs; netdev_num++)
-+      {
-+              struct switch_dev *swdev;
-+              struct net_device *dev = hw->devs[netdev_num];
-+              struct xrx200_priv *priv = netdev_priv(dev);
-+              if (!priv->sw)
-+                      continue;
-+
-+              swdev = &hw->swdev;
-+
-+              swdev->name = "Lantiq XRX200 Switch";
-+              swdev->vlans = XRX200_MAX_VLAN;
-+              swdev->ports = XRX200_MAX_PORT;
-+              swdev->cpu_port = 6;
-+              swdev->ops = &xrx200sw_ops;
-+
-+              register_switch(swdev, dev);
-+              return 0; // enough switches
-+      }
-+      return 0;
-+}
-+
-+static int xrx200_open(struct net_device *dev)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      int i;
-+
-+      for (i = 0; i < XRX200_MAX_DMA; i++) {
-+              if (!priv->hw->chan[i].dma.irq)
-+                      continue;
-+              spin_lock_irqsave(&priv->hw->lock, flags);
-+              if (!priv->hw->chan[i].refcount) {
-+                      if (XRX200_DMA_IS_RX(i))
-+                              napi_enable(&priv->hw->chan[i].napi);
-+                      ltq_dma_open(&priv->hw->chan[i].dma);
-+              }
-+              priv->hw->chan[i].refcount++;
-+              spin_unlock_irqrestore(&priv->hw->lock, flags);
-+      }
-+      for (i = 0; i < priv->num_port; i++)
-+              if (priv->port[i].phydev)
-+                      phy_start(priv->port[i].phydev);
-+      netif_start_queue(dev);
-+
-+      return 0;
-+}
-+
-+static int xrx200_close(struct net_device *dev)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      unsigned long flags;
-+      int i;
-+
-+      netif_stop_queue(dev);
-+
-+      for (i = 0; i < priv->num_port; i++)
-+              if (priv->port[i].phydev)
-+                      phy_stop(priv->port[i].phydev);
-+
-+      for (i = 0; i < XRX200_MAX_DMA; i++) {
-+              if (!priv->hw->chan[i].dma.irq)
-+                      continue;
-+              spin_lock_irqsave(&priv->hw->lock, flags);
-+              priv->hw->chan[i].refcount--;
-+              if (!priv->hw->chan[i].refcount) {
-+                      if (XRX200_DMA_IS_RX(i))
-+                              napi_disable(&priv->hw->chan[i].napi);
-+                      ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma);
-+              }
-+              spin_unlock_irqrestore(&priv->hw->lock, flags);
-+      }
-+
-+      return 0;
-+}
-+
-+static int xrx200_alloc_skb(struct xrx200_chan *ch)
-+{
-+#define DMA_PAD       (NET_IP_ALIGN + NET_SKB_PAD)
-+      ch->skb[ch->dma.desc] = dev_alloc_skb(XRX200_DMA_DATA_LEN + DMA_PAD);
-+      if (!ch->skb[ch->dma.desc])
-+              return -ENOMEM;
-+
-+      skb_reserve(ch->skb[ch->dma.desc], NET_SKB_PAD);
-+      ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
-+              ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN,
-+                      DMA_FROM_DEVICE);
-+      ch->dma.desc_base[ch->dma.desc].addr =
-+              CPHYSADDR(ch->skb[ch->dma.desc]->data);
-+      ch->dma.desc_base[ch->dma.desc].ctl =
-+              LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
-+              XRX200_DMA_DATA_LEN;
-+      skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
-+
-+      return 0;
-+}
-+
-+static void xrx200_hw_receive(struct xrx200_chan *ch, int id)
-+{
-+      struct net_device *dev = ch->devs[id];
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
-+      struct sk_buff *skb = ch->skb[ch->dma.desc];
-+      int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - ETH_FCS_LEN;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->hw->lock, flags);
-+      if (xrx200_alloc_skb(ch)) {
-+              netdev_err(dev,
-+                      "failed to allocate new rx buffer, stopping DMA\n");
-+              ltq_dma_close(&ch->dma);
-+      }
-+
-+      ch->dma.desc++;
-+      ch->dma.desc %= LTQ_DESC_NUM;
-+      spin_unlock_irqrestore(&priv->hw->lock, flags);
-+
-+      skb_put(skb, len);
-+#ifdef SW_ROUTING
-+      skb_pull(skb, 8);
-+#endif
-+      skb->dev = dev;
-+      skb->protocol = eth_type_trans(skb, dev);
-+      netif_receive_skb(skb);
-+      priv->stats.rx_packets++;
-+      priv->stats.rx_bytes+=len;
-+}
-+
-+static int xrx200_poll_rx(struct napi_struct *napi, int budget)
-+{
-+      struct xrx200_chan *ch = container_of(napi,
-+                              struct xrx200_chan, napi);
-+      struct xrx200_priv *priv = netdev_priv(ch->devs[0]);
-+      int rx = 0;
-+      int complete = 0;
-+      unsigned long flags;
-+
-+      while ((rx < budget) && !complete) {
-+              struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
-+              if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
-+#ifdef SW_ROUTING
-+                      struct sk_buff *skb = ch->skb[ch->dma.desc];
-+                      u32 *special_tag = (u32*)skb->data;
-+                      int port = (special_tag[1] >> SPPID_SHIFT) & SPPID_MASK;
-+                      xrx200_hw_receive(ch, priv->hw->port_map[port]);
-+#else
-+                      xrx200_hw_receive(ch, 0);
-+#endif
-+                      rx++;
-+              } else {
-+                      complete = 1;
-+              }
-+      }
-+      if (complete || !rx) {
-+              napi_complete(&ch->napi);
-+              spin_lock_irqsave(&priv->hw->lock, flags);
-+              ltq_dma_ack_irq(&ch->dma);
-+              spin_unlock_irqrestore(&priv->hw->lock, flags);
-+      }
-+      return rx;
-+}
-+
-+static void xrx200_tx_housekeeping(unsigned long ptr)
-+{
-+      struct xrx200_hw *hw = (struct xrx200_hw *) ptr;
-+      struct xrx200_chan *ch = &hw->chan[XRX200_DMA_TX];
-+      unsigned long flags;
-+      int i;
-+
-+      spin_lock_irqsave(&hw->lock, flags);
-+      while ((ch->dma.desc_base[ch->tx_free].ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
-+              dev_kfree_skb_any(ch->skb[ch->tx_free]);
-+              ch->skb[ch->tx_free] = NULL;
-+              memset(&ch->dma.desc_base[ch->tx_free], 0,
-+                      sizeof(struct ltq_dma_desc));
-+              ch->tx_free++;
-+              ch->tx_free %= LTQ_DESC_NUM;
-+      }
-+      spin_unlock_irqrestore(&hw->lock, flags);
-+
-+      for (i = 0; i < XRX200_MAX_DEV && ch->devs[i]; i++) {
-+              struct netdev_queue *txq =
-+                      netdev_get_tx_queue(ch->devs[i], 0);
-+              if (netif_tx_queue_stopped(txq))
-+                      netif_tx_start_queue(txq);
-+      }
-+
-+      spin_lock_irqsave(&hw->lock, flags);
-+      ltq_dma_ack_irq(&ch->dma);
-+      spin_unlock_irqrestore(&hw->lock, flags);
-+}
-+
-+static struct net_device_stats *xrx200_get_stats (struct net_device *dev)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+
-+      return &priv->stats;
-+}
-+
-+static void xrx200_tx_timeout(struct net_device *dev)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+
-+      printk(KERN_ERR "%s: transmit timed out, disable the dma channel irq\n", dev->name);
-+
-+      priv->stats.tx_errors++;
-+      netif_wake_queue(dev);
-+}
-+
-+static int xrx200_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+      int queue = skb_get_queue_mapping(skb);
-+      struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      struct xrx200_chan *ch = &priv->hw->chan[XRX200_DMA_TX];
-+      struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
-+      unsigned long flags;
-+      u32 byte_offset;
-+      int len;
-+#ifdef SW_ROUTING
-+  #ifdef SW_PORTMAP
-+      u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | PORT_MAP_SEL | PORT_MAP_EN | DPID_ENABLE;
-+  #else
-+      u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | DPID_ENABLE;
-+  #endif
-+#endif
-+
-+      len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
-+
-+      if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
-+              netdev_err(dev, "tx ring full\n");
-+              netif_tx_stop_queue(txq);
-+              return NETDEV_TX_BUSY;
-+      }
-+#ifdef SW_ROUTING
-+  #ifdef SW_PORTMAP
-+      special_tag |= priv->port_map << PORT_MAP_SHIFT;
-+  #else
-+      if(priv->id)
-+              special_tag |= (1 << DPID_SHIFT);
-+  #endif
-+      if(skb_headroom(skb) < 4) {
-+              struct sk_buff *tmp = skb_realloc_headroom(skb, 4);
-+              dev_kfree_skb_any(skb);
-+              skb = tmp;
-+      }
-+      skb_push(skb, 4);
-+      memcpy(skb->data, &special_tag, sizeof(u32));
-+      len += 4;
-+#endif
-+
-+      /* dma needs to start on a 16 byte aligned address */
-+      byte_offset = CPHYSADDR(skb->data) % 16;
-+      ch->skb[ch->dma.desc] = skb;
-+
-+      dev->trans_start = jiffies;
-+
-+      spin_lock_irqsave(&priv->hw->lock, flags);
-+      desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
-+                                              DMA_TO_DEVICE)) - byte_offset;
-+      wmb();
-+      desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
-+              LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
-+      ch->dma.desc++;
-+      ch->dma.desc %= LTQ_DESC_NUM;
-+      spin_unlock_irqrestore(&priv->hw->lock, flags);
-+
-+      if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
-+              netif_tx_stop_queue(txq);
-+
-+      priv->stats.tx_packets++;
-+      priv->stats.tx_bytes+=len;
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static irqreturn_t xrx200_dma_irq(int irq, void *priv)
-+{
-+      struct xrx200_hw *hw = priv;
-+      int ch = irq - XRX200_DMA_IRQ;
-+
-+      if (ch % 2)
-+              tasklet_schedule(&hw->chan[ch].tasklet);
-+      else
-+              napi_schedule(&hw->chan[ch].napi);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int xrx200_dma_init(struct xrx200_hw *hw)
-+{
-+      int i, err = 0;
-+
-+      ltq_dma_init_port(DMA_PORT_ETOP);
-+
-+      for (i = 0; i < 8 && !err; i++) {
-+              int irq = XRX200_DMA_IRQ + i;
-+              struct xrx200_chan *ch = &hw->chan[i];
-+
-+              ch->idx = ch->dma.nr = i;
-+
-+              if (i == XRX200_DMA_TX) {
-+                      ltq_dma_alloc_tx(&ch->dma);
-+                      err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_tx", hw);
-+              } else if (i == XRX200_DMA_RX) {
-+                      ltq_dma_alloc_rx(&ch->dma);
-+                      for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
-+                                      ch->dma.desc++)
-+                              if (xrx200_alloc_skb(ch))
-+                                      err = -ENOMEM;
-+                      ch->dma.desc = 0;
-+                      err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_rx", hw);
-+              } else
-+                      continue;
-+
-+              if (!err)
-+                      ch->dma.irq = irq;
-+      }
-+
-+      return err;
-+}
-+
-+#ifdef SW_POLLING
-+static void xrx200_gmac_update(struct xrx200_port *port)
-+{
-+      u16 phyaddr = port->phydev->addr & MDIO_PHY_ADDR_MASK;
-+      u16 miimode = ltq_mii_r32(MII_CFG(port->num)) & MII_CFG_MODE_MASK;
-+      u16 miirate = 0;
-+
-+      switch (port->phydev->speed) {
-+      case SPEED_1000:
-+              phyaddr |= MDIO_PHY_SPEED_G1;
-+              miirate = MII_CFG_RATE_M125;
-+              break;
-+
-+      case SPEED_100:
-+              phyaddr |= MDIO_PHY_SPEED_M100;
-+              switch (miimode) {
-+              case MII_CFG_MODE_RMIIM:
-+              case MII_CFG_MODE_RMIIP:
-+                      miirate = MII_CFG_RATE_M50;
-+                      break;
-+              default:
-+                      miirate = MII_CFG_RATE_M25;
-+                      break;
-+              }
-+              break;
-+
-+      default:
-+              phyaddr |= MDIO_PHY_SPEED_M10;
-+              miirate = MII_CFG_RATE_M2P5;
-+              break;
-+      }
-+
-+      if (port->phydev->link)
-+              phyaddr |= MDIO_PHY_LINK_UP;
-+      else
-+              phyaddr |= MDIO_PHY_LINK_DOWN;
-+
-+      if (port->phydev->duplex == DUPLEX_FULL)
-+              phyaddr |= MDIO_PHY_FDUP_EN;
-+      else
-+              phyaddr |= MDIO_PHY_FDUP_DIS;
-+
-+      ltq_mdio_w32_mask(MDIO_UPDATE_MASK, phyaddr, MDIO_PHY(port->num));
-+      ltq_mii_w32_mask(MII_CFG_RATE_MASK, miirate, MII_CFG(port->num));
-+      udelay(1);
-+}
-+#else
-+static void xrx200_gmac_update(struct xrx200_port *port)
-+{
-+
-+}
-+#endif
-+
-+static void xrx200_mdio_link(struct net_device *dev)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      int i;
-+
-+      for (i = 0; i < priv->num_port; i++) {
-+              if (!priv->port[i].phydev)
-+                      continue;
-+
-+              if (priv->port[i].link != priv->port[i].phydev->link) {
-+                      xrx200_gmac_update(&priv->port[i]);
-+                      priv->port[i].link = priv->port[i].phydev->link;
-+                      netdev_info(dev, "port %d %s link\n",
-+                              priv->port[i].num,
-+                              (priv->port[i].link)?("got"):("lost"));
-+              }
-+      }
-+}
-+
-+static inline int xrx200_mdio_poll(struct mii_bus *bus)
-+{
-+      unsigned cnt = 10000;
-+
-+      while (likely(cnt--)) {
-+              unsigned ctrl = ltq_mdio_r32(MDIO_CTRL);
-+              if ((ctrl & MDIO_BUSY) == 0)
-+                      return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+static int xrx200_mdio_wr(struct mii_bus *bus, int addr, int reg, u16 val)
-+{
-+      if (xrx200_mdio_poll(bus))
-+              return 1;
-+
-+      ltq_mdio_w32(val, MDIO_WRITE);
-+      ltq_mdio_w32(MDIO_BUSY | MDIO_WR |
-+              ((addr & MDIO_MASK) << MDIO_ADDRSHIFT) |
-+              (reg & MDIO_MASK),
-+              MDIO_CTRL);
-+
-+      return 0;
-+}
-+
-+static int xrx200_mdio_rd(struct mii_bus *bus, int addr, int reg)
-+{
-+      if (xrx200_mdio_poll(bus))
-+              return -1;
-+
-+      ltq_mdio_w32(MDIO_BUSY | MDIO_RD |
-+              ((addr & MDIO_MASK) << MDIO_ADDRSHIFT) |
-+              (reg & MDIO_MASK),
-+              MDIO_CTRL);
-+
-+      if (xrx200_mdio_poll(bus))
-+              return -1;
-+
-+      return ltq_mdio_r32(MDIO_READ);
-+}
-+
-+static int xrx200_mdio_probe(struct net_device *dev, struct xrx200_port *port)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      struct phy_device *phydev = NULL;
-+      unsigned val;
-+
-+      phydev = priv->hw->mii_bus->phy_map[port->phy_addr];
-+
-+      if (!phydev) {
-+              netdev_err(dev, "no PHY found\n");
-+              return -ENODEV;
-+      }
-+
-+      phydev = phy_connect(dev, dev_name(&phydev->dev), &xrx200_mdio_link,
-+                              port->phy_if);
-+
-+      if (IS_ERR(phydev)) {
-+              netdev_err(dev, "Could not attach to PHY\n");
-+              return PTR_ERR(phydev);
-+      }
-+
-+      phydev->supported &= (SUPPORTED_10baseT_Half
-+                      | SUPPORTED_10baseT_Full
-+                      | SUPPORTED_100baseT_Half
-+                      | SUPPORTED_100baseT_Full
-+                      | SUPPORTED_1000baseT_Half
-+                      | SUPPORTED_1000baseT_Full
-+                      | SUPPORTED_Autoneg
-+                      | SUPPORTED_MII
-+                      | SUPPORTED_TP);
-+      phydev->advertising = phydev->supported;
-+      port->phydev = phydev;
-+
-+      pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
-+              dev->name, phydev->drv->name,
-+              dev_name(&phydev->dev), phydev->irq);
-+
-+#ifdef SW_POLLING
-+      phy_read_status(phydev);
-+
-+      val = xrx200_mdio_rd(priv->hw->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000);
-+      val |= ADVERTIZE_MPD;
-+      xrx200_mdio_wr(priv->hw->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000, val);
-+      xrx200_mdio_wr(priv->hw->mii_bus, 0, 0, 0x1040);
-+
-+      phy_start_aneg(phydev);
-+#endif
-+      return 0;
-+}
-+
-+static void xrx200_port_config(struct xrx200_priv *priv,
-+              const struct xrx200_port *port)
-+{
-+      u16 miimode = 0;
-+
-+      switch (port->num) {
-+      case 0: /* xMII0 */
-+      case 1: /* xMII1 */
-+              switch (port->phy_if) {
-+              case PHY_INTERFACE_MODE_MII:
-+                      if (port->flags & XRX200_PORT_TYPE_PHY)
-+                              /* MII MAC mode, connected to external PHY */
-+                              miimode = MII_CFG_MODE_MIIM;
-+                      else
-+                              /* MII PHY mode, connected to external MAC */
-+                              miimode = MII_CFG_MODE_MIIP;
-+                      break;
-+              case PHY_INTERFACE_MODE_RMII:
-+                      if (port->flags & XRX200_PORT_TYPE_PHY)
-+                              /* RMII MAC mode, connected to external PHY */
-+                              miimode = MII_CFG_MODE_RMIIM;
-+                      else
-+                              /* RMII PHY mode, connected to external MAC */
-+                              miimode = MII_CFG_MODE_RMIIP;
-+                      break;
-+              case PHY_INTERFACE_MODE_RGMII:
-+                      /* RGMII MAC mode, connected to external PHY */
-+                      miimode = MII_CFG_MODE_RGMII;
-+                      break;
-+              default:
-+                      break;
-+              }
-+              break;
-+      case 2: /* internal GPHY0 */
-+      case 3: /* internal GPHY0 */
-+      case 4: /* internal GPHY1 */
-+              switch (port->phy_if) {
-+                      case PHY_INTERFACE_MODE_MII:
-+                      case PHY_INTERFACE_MODE_GMII:
-+                              /* MII MAC mode, connected to internal GPHY */
-+                              miimode = MII_CFG_MODE_MIIM;
-+                              break;
-+                      default:
-+                              break;
-+              }
-+              break;
-+      case 5: /* internal GPHY1 or xMII2 */
-+              switch (port->phy_if) {
-+              case PHY_INTERFACE_MODE_MII:
-+                      /* MII MAC mode, connected to internal GPHY */
-+                      miimode = MII_CFG_MODE_MIIM;
-+                      break;
-+              case PHY_INTERFACE_MODE_RGMII:
-+                      /* RGMII MAC mode, connected to external PHY */
-+                      miimode = MII_CFG_MODE_RGMII;
-+                      break;
-+              default:
-+                      break;
-+              }
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      ltq_mii_w32_mask(MII_CFG_MODE_MASK, miimode | MII_CFG_EN,
-+              MII_CFG(port->num));
-+}
-+
-+static int xrx200_init(struct net_device *dev)
-+{
-+      struct xrx200_priv *priv = netdev_priv(dev);
-+      struct sockaddr mac;
-+      int err, i;
-+
-+#ifndef SW_POLLING
-+      unsigned int reg = 0;
-+
-+      /* enable auto polling */
-+      for (i = 0; i < priv->num_port; i++)
-+              reg |= BIT(priv->port[i].num);
-+      ltq_mdio_w32(reg, MDIO_CLK_CFG0);
-+      ltq_mdio_w32(MDIO1_25MHZ, MDIO_CLK_CFG1);
-+#endif
-+
-+      /* setup each port */
-+      for (i = 0; i < priv->num_port; i++)
-+              xrx200_port_config(priv, &priv->port[i]);
-+
-+      memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
-+      if (!is_valid_ether_addr(mac.sa_data)) {
-+              pr_warn("net-xrx200: invalid MAC, using random\n");
-+              eth_random_addr(mac.sa_data);
-+              dev->addr_assign_type |= NET_ADDR_RANDOM;
-+      }
-+
-+      err = eth_mac_addr(dev, &mac);
-+      if (err)
-+              goto err_netdev;
-+
-+      for (i = 0; i < priv->num_port; i++)
-+              if (xrx200_mdio_probe(dev, &priv->port[i]))
-+                      pr_warn("xrx200-mdio: probing phy of port %d failed\n",
-+                                       priv->port[i].num);
-+
-+      return 0;
-+
-+err_netdev:
-+      unregister_netdev(dev);
-+      free_netdev(dev);
-+      return err;
-+}
-+
-+static void xrx200_pci_microcode(void)
-+{
-+      int i;
-+
-+      ltq_switch_w32_mask(PCE_TBL_CFG_ADDR_MASK | PCE_TBL_CFG_ADWR_MASK,
-+              PCE_TBL_CFG_ADWR, PCE_TBL_CTRL);
-+      ltq_switch_w32(0, PCE_TBL_MASK);
-+
-+      for (i = 0; i < ARRAY_SIZE(pce_microcode); i++) {
-+              ltq_switch_w32(i, PCE_TBL_ADDR);
-+              ltq_switch_w32(pce_microcode[i].val[3], PCE_TBL_VAL(0));
-+              ltq_switch_w32(pce_microcode[i].val[2], PCE_TBL_VAL(1));
-+              ltq_switch_w32(pce_microcode[i].val[1], PCE_TBL_VAL(2));
-+              ltq_switch_w32(pce_microcode[i].val[0], PCE_TBL_VAL(3));
-+
-+              // start the table access:
-+              ltq_switch_w32_mask(0, PCE_TBL_BUSY, PCE_TBL_CTRL);
-+              while (ltq_switch_r32(PCE_TBL_CTRL) & PCE_TBL_BUSY);
-+      }
-+
-+      /* tell the switch that the microcode is loaded */
-+      ltq_switch_w32_mask(0, BIT(3), PCE_GCTRL_REG(0));
-+}
-+
-+static void xrx200_hw_init(struct xrx200_hw *hw)
-+{
-+      int i;
-+
-+      /* enable clock gate */
-+      clk_enable(hw->clk);
-+
-+      ltq_switch_w32(1, 0);
-+      mdelay(100);
-+      ltq_switch_w32(0, 0);
-+      /*
-+       * TODO: we should really disbale all phys/miis here and explicitly
-+       * enable them in the device secific init function
-+       */
-+
-+      /* disable port fetch/store dma */
-+      for (i = 0; i < 7; i++ ) {
-+              ltq_switch_w32(0, FDMA_PCTRLx(i));
-+              ltq_switch_w32(0, SDMA_PCTRLx(i));
-+      }
-+
-+      /* enable Switch */
-+      ltq_mdio_w32_mask(0, MDIO_GLOB_ENABLE, MDIO_GLOB);
-+
-+      /* load the pce microcode */
-+      xrx200_pci_microcode();
-+
-+      /* Default unknown Broadcat/Multicast/Unicast port maps */
-+      ltq_switch_w32(0x7f, PCE_PMAP1);
-+      ltq_switch_w32(0x7f, PCE_PMAP2);
-+      ltq_switch_w32(0x7f, PCE_PMAP3);
-+
-+      /* RMON Counter Enable for all physical ports */
-+      for (i = 0; i < 7; i++)
-+              ltq_switch_w32(0x1, BM_PCFG(i));
-+
-+      /* disable auto polling */
-+      ltq_mdio_w32(0x0, MDIO_CLK_CFG0);
-+
-+      /* enable port statistic counters */
-+      for (i = 0; i < 7; i++)
-+              ltq_switch_w32(0x1, BM_PCFGx(i));
-+
-+      /* set IPG to 12 */
-+      ltq_pmac_w32_mask(PMAC_IPG_MASK, 0xb, PMAC_RX_IPG);
-+
-+#ifdef SW_ROUTING
-+      /* enable status header, enable CRC */
-+      ltq_pmac_w32_mask(0,
-+              PMAC_HD_CTL_RST | PMAC_HD_CTL_AST | PMAC_HD_CTL_RXSH | PMAC_HD_CTL_AS | PMAC_HD_CTL_AC,
-+              PMAC_HD_CTL);
-+#else
-+      /* disable status header, enable CRC */
-+      ltq_pmac_w32_mask(PMAC_HD_CTL_AST | PMAC_HD_CTL_RXSH | PMAC_HD_CTL_AS,
-+              PMAC_HD_CTL_AC,
-+              PMAC_HD_CTL);
-+#endif
-+
-+      /* enable port fetch/store dma & VLAN Modification */
-+      for (i = 0; i < 7; i++ ) {
-+              ltq_switch_w32_mask(0, 0x19, FDMA_PCTRLx(i));
-+              ltq_switch_w32_mask(0, 0x01, SDMA_PCTRLx(i));
-+              ltq_switch_w32_mask(0, PCE_INGRESS, PCE_PCTRL_REG(i, 0));
-+      }
-+
-+      /* enable special tag insertion on cpu port */
-+      ltq_switch_w32_mask(0, 0x02, FDMA_PCTRLx(6));
-+      ltq_switch_w32_mask(0, PCE_INGRESS, PCE_PCTRL_REG(6, 0));
-+      ltq_switch_w32_mask(0, BIT(3), MAC_CTRL_REG(6, 2));
-+      ltq_switch_w32(1518 + 8 + 4 * 2, MAC_FLEN_REG);
-+}
-+
-+static void xrx200_hw_cleanup(struct xrx200_hw *hw)
-+{
-+      int i;
-+
-+      /* disable the switch */
-+      ltq_mdio_w32_mask(MDIO_GLOB_ENABLE, 0, MDIO_GLOB);
-+
-+      /* free the channels and IRQs */
-+      for (i = 0; i < 2; i++) {
-+              ltq_dma_free(&hw->chan[i].dma);
-+              if (hw->chan[i].dma.irq)
-+                      free_irq(hw->chan[i].dma.irq, hw);
-+      }
-+
-+      /* free the allocated RX ring */
-+      for (i = 0; i < LTQ_DESC_NUM; i++)
-+              dev_kfree_skb_any(hw->chan[XRX200_DMA_RX].skb[i]);
-+
-+      /* clear the mdio bus */
-+      mdiobus_unregister(hw->mii_bus);
-+      mdiobus_free(hw->mii_bus);
-+
-+      /* release the clock */
-+      clk_disable(hw->clk);
-+      clk_put(hw->clk);
-+}
-+
-+static int xrx200_of_mdio(struct xrx200_hw *hw, struct device_node *np)
-+{
-+      hw->mii_bus = mdiobus_alloc();
-+      if (!hw->mii_bus)
-+              return -ENOMEM;
-+
-+      hw->mii_bus->read = xrx200_mdio_rd;
-+      hw->mii_bus->write = xrx200_mdio_wr;
-+      hw->mii_bus->name = "lantiq,xrx200-mdio";
-+      snprintf(hw->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
-+
-+      if (of_mdiobus_register(hw->mii_bus, np)) {
-+              mdiobus_free(hw->mii_bus);
-+              return -ENXIO;
-+      }
-+
-+      return 0;
-+}
-+
-+static void xrx200_of_port(struct xrx200_priv *priv, struct device_node *port)
-+{
-+      const __be32 *addr, *id = of_get_property(port, "reg", NULL);
-+      struct xrx200_port *p = &priv->port[priv->num_port];
-+
-+      if (!id)
-+              return;
-+
-+      memset(p, 0, sizeof(struct xrx200_port));
-+      p->phy_node = of_parse_phandle(port, "phy-handle", 0);
-+      addr = of_get_property(p->phy_node, "reg", NULL);
-+      if (!addr)
-+              return;
-+
-+      p->num = *id;
-+      p->phy_addr = *addr;
-+      p->phy_if = of_get_phy_mode(port);
-+      if (p->phy_addr > 0x10)
-+              p->flags = XRX200_PORT_TYPE_MAC;
-+      else
-+              p->flags = XRX200_PORT_TYPE_PHY;
-+      priv->num_port++;
-+
-+      p->gpio = of_get_gpio_flags(port, 0, &p->gpio_flags);
-+      if (gpio_is_valid(p->gpio))
-+              if (!gpio_request(p->gpio, "phy-reset")) {
-+                      gpio_direction_output(p->gpio,
-+                              (p->gpio_flags & OF_GPIO_ACTIVE_LOW) ? (1) : (0));
-+                      udelay(100);
-+                      gpio_set_value(p->gpio, (p->gpio_flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1));
-+              }
-+      /* is this port a wan port ? */
-+      if (priv->wan)
-+              priv->hw->wan_map |= BIT(p->num);
-+
-+      priv->port_map |= BIT(p->num);
-+
-+      /* store the port id in the hw struct so we can map ports -> devices */
-+      priv->hw->port_map[p->num] = priv->hw->num_devs;
-+}
-+
-+static const struct net_device_ops xrx200_netdev_ops = {
-+      .ndo_init               = xrx200_init,
-+      .ndo_open               = xrx200_open,
-+      .ndo_stop               = xrx200_close,
-+      .ndo_start_xmit         = xrx200_start_xmit,
-+      .ndo_set_mac_address    = eth_mac_addr,
-+      .ndo_validate_addr      = eth_validate_addr,
-+      .ndo_change_mtu         = eth_change_mtu,
-+      .ndo_get_stats          = xrx200_get_stats,
-+      .ndo_tx_timeout         = xrx200_tx_timeout,
-+};
-+
-+static void xrx200_of_iface(struct xrx200_hw *hw, struct device_node *iface)
-+{
-+      struct xrx200_priv *priv;
-+      struct device_node *port;
-+      const __be32 *wan;
-+      const __be32 *sw;
-+
-+      /* alloc the network device */
-+      hw->devs[hw->num_devs] = alloc_etherdev(sizeof(struct xrx200_priv));
-+      if (!hw->devs[hw->num_devs])
-+              return;
-+
-+      /* setup the network device */
-+      strcpy(hw->devs[hw->num_devs]->name, "eth%d");
-+      hw->devs[hw->num_devs]->netdev_ops = &xrx200_netdev_ops;
-+      hw->devs[hw->num_devs]->watchdog_timeo = XRX200_TX_TIMEOUT;
-+      hw->devs[hw->num_devs]->needed_headroom = XRX200_HEADROOM;
-+
-+      /* setup our private data */
-+      priv = netdev_priv(hw->devs[hw->num_devs]);
-+      priv->hw = hw;
-+      of_get_mac_address_mtd(iface, priv->mac);
-+      priv->id = hw->num_devs;
-+
-+      /* is this the wan interface ? */
-+      wan = of_get_property(iface, "lantiq,wan", NULL);
-+      if (wan && (*wan == 1))
-+              priv->wan = 1;
-+
-+      /* should the switch be enabled on this interface ? */
-+      sw = of_get_property(iface, "lantiq,switch", NULL);
-+      if (sw && (*sw == 1))
-+              priv->sw = 1;
-+
-+      /* load the ports that are part of the interface */
-+      for_each_child_of_node(iface, port)
-+              if (of_device_is_compatible(port, "lantiq,xrx200-pdi-port"))
-+                      xrx200_of_port(priv, port);
-+
-+      /* register the actual device */
-+      if (!register_netdev(hw->devs[hw->num_devs]))
-+              hw->num_devs++;
-+}
-+
-+static struct xrx200_hw xrx200_hw;
-+
-+static int xrx200_probe(struct platform_device *pdev)
-+{
-+      struct resource *res[4];
-+      struct device_node *mdio_np, *iface_np;
-+      int i;
-+
-+      /* load the memory ranges */
-+      for (i = 0; i < 4; i++) {
-+              res[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
-+              if (!res[i]) {
-+                      dev_err(&pdev->dev, "failed to get resources\n");
-+                      return -ENOENT;
-+              }
-+      }
-+      xrx200_switch_membase = devm_request_and_ioremap(&pdev->dev, res[0]);
-+      xrx200_mdio_membase = devm_request_and_ioremap(&pdev->dev, res[1]);
-+      xrx200_mii_membase = devm_request_and_ioremap(&pdev->dev, res[2]);
-+      xrx200_pmac_membase = devm_request_and_ioremap(&pdev->dev, res[3]);
-+      if (!xrx200_switch_membase || !xrx200_mdio_membase ||
-+                      !xrx200_mii_membase || !xrx200_pmac_membase) {
-+              dev_err(&pdev->dev, "failed to request and remap io ranges \n");
-+              return -ENOMEM;
-+      }
-+
-+      /* get the clock */
-+      xrx200_hw.clk = clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(xrx200_hw.clk)) {
-+              dev_err(&pdev->dev, "failed to get clock\n");
-+              return PTR_ERR(xrx200_hw.clk);
-+      }
-+
-+      /* bring up the dma engine and IP core */
-+      spin_lock_init(&xrx200_hw.lock);
-+      xrx200_dma_init(&xrx200_hw);
-+      xrx200_hw_init(&xrx200_hw);
-+      tasklet_init(&xrx200_hw.chan[XRX200_DMA_TX].tasklet, xrx200_tx_housekeeping, (u32) &xrx200_hw);
-+
-+      /* bring up the mdio bus */
-+      mdio_np = of_find_compatible_node(pdev->dev.of_node, NULL,
-+                              "lantiq,xrx200-mdio");
-+      if (mdio_np)
-+              if (xrx200_of_mdio(&xrx200_hw, mdio_np))
-+                      dev_err(&pdev->dev, "mdio probe failed\n");
-+
-+      /* load the interfaces */
-+      for_each_child_of_node(pdev->dev.of_node, iface_np)
-+              if (of_device_is_compatible(iface_np, "lantiq,xrx200-pdi")) {
-+                      if (xrx200_hw.num_devs < XRX200_MAX_DEV)
-+                              xrx200_of_iface(&xrx200_hw, iface_np);
-+                      else
-+                              dev_err(&pdev->dev,
-+                                      "only %d interfaces allowed\n",
-+                                      XRX200_MAX_DEV);
-+              }
-+
-+      if (!xrx200_hw.num_devs) {
-+              xrx200_hw_cleanup(&xrx200_hw);
-+              dev_err(&pdev->dev, "failed to load interfaces\n");
-+              return -ENOENT;
-+      }
-+
-+      xrx200sw_init(&xrx200_hw);
-+
-+      /* set wan port mask */
-+      ltq_pmac_w32(xrx200_hw.wan_map, PMAC_EWAN);
-+
-+      for (i = 0; i < xrx200_hw.num_devs; i++) {
-+              xrx200_hw.chan[XRX200_DMA_RX].devs[i] = xrx200_hw.devs[i];
-+              xrx200_hw.chan[XRX200_DMA_TX].devs[i] = xrx200_hw.devs[i];
-+      }
-+
-+      /* setup NAPI */
-+      init_dummy_netdev(&xrx200_hw.chan[XRX200_DMA_RX].dummy_dev);
-+      netif_napi_add(&xrx200_hw.chan[XRX200_DMA_RX].dummy_dev,
-+                      &xrx200_hw.chan[XRX200_DMA_RX].napi, xrx200_poll_rx, 32);
-+
-+      platform_set_drvdata(pdev, &xrx200_hw);
-+
-+      return 0;
-+}
-+
-+static int xrx200_remove(struct platform_device *pdev)
-+{
-+      struct net_device *dev = platform_get_drvdata(pdev);
-+      struct xrx200_priv *priv;
-+
-+      if (!dev)
-+              return 0;
-+
-+      priv = netdev_priv(dev);
-+
-+      /* free stack related instances */
-+      netif_stop_queue(dev);
-+      netif_napi_del(&xrx200_hw.chan[XRX200_DMA_RX].napi);
-+
-+      /* shut down hardware */
-+      xrx200_hw_cleanup(&xrx200_hw);
-+
-+      /* remove the actual device */
-+      unregister_netdev(dev);
-+      free_netdev(dev);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id xrx200_match[] = {
-+      { .compatible = "lantiq,xrx200-net" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, xrx200_match);
-+
-+static struct platform_driver xrx200_driver = {
-+      .probe = xrx200_probe,
-+      .remove = xrx200_remove,
-+      .driver = {
-+              .name = "lantiq,xrx200-net",
-+              .of_match_table = xrx200_match,
-+              .owner = THIS_MODULE,
-+      },
-+};
-+
-+module_platform_driver(xrx200_driver);
-+
-+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-+MODULE_DESCRIPTION("Lantiq SoC XRX200 ethernet");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/net/ethernet/lantiq_xrx200_sw.h b/drivers/net/ethernet/lantiq_xrx200_sw.h
-new file mode 100644
-index 0000000..e7188a2
---- /dev/null
-+++ b/drivers/net/ethernet/lantiq_xrx200_sw.h
-@@ -0,0 +1,1328 @@
-+/*
-+ *   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.
-+ *
-+ *   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) 2010 Lantiq Deutschland GmbH
-+ *   Copyright (C) 2013 Antonios Vamporakis <vamporakis@yahoo.com>
-+ *
-+ *   VR9 switch registers extracted from 310TUJ0 switch api
-+ *   WARNING mult values of 0x00 may not be correct
-+ *
-+ */
-+
-+enum {
-+//    XRX200_ETHSW_SWRES,            /* Ethernet Switch ResetControl Register */
-+//    XRX200_ETHSW_SWRES_R1,         /* Hardware Reset */
-+//    XRX200_ETHSW_SWRES_R0,         /* Register Configuration */
-+//    XRX200_ETHSW_CLK_MAC_GAT,      /* Ethernet Switch Clock ControlRegister  */
-+//    XRX200_ETHSW_CLK_EXP_SLEEP,    /* Exponent to put system into sleep */
-+//    XRX200_ETHSW_CLK_EXP_WAKE,     /* Exponent to wake up system */
-+//    XRX200_ETHSW_CLK_CLK2_EN,      /* CLK2 Input for MAC */
-+//    XRX200_ETHSW_CLK_EXT_DIV_EN,   /* External Clock Divider Enable */
-+//    XRX200_ETHSW_CLK_RAM_DBG_EN,   /* Clock Gating Enable */
-+//    XRX200_ETHSW_CLK_REG_GAT_EN,   /* Clock Gating Enable */
-+//    XRX200_ETHSW_CLK_GAT_EN,       /* Clock Gating Enable */
-+//    XRX200_ETHSW_CLK_MAC_GAT_EN,   /* Clock Gating Enable */
-+//    XRX200_ETHSW_DBG_STEP,         /* Ethernet Switch Debug ControlRegister */
-+//    XRX200_ETHSW_DBG_CLK_SEL,      /* Trigger Enable */
-+//    XRX200_ETHSW_DBG_MON_EN,       /* Monitoring Enable */
-+//    XRX200_ETHSW_DBG_TRIG_EN,      /* Trigger Enable */
-+//    XRX200_ETHSW_DBG_MODE,         /* Debug Mode */
-+//    XRX200_ETHSW_DBG_STEP_TIME,    /* Clock Step Size */
-+//    XRX200_ETHSW_SSB_MODE,         /* Ethernet Switch SharedSegment Buffer Mode Register */
-+//    XRX200_ETHSW_SSB_MODE_ADDE,    /* Memory Address */
-+//    XRX200_ETHSW_SSB_MODE_MODE,    /* Memory Access Mode */
-+//    XRX200_ETHSW_SSB_ADDR,         /* Ethernet Switch SharedSegment Buffer Address Register */
-+//    XRX200_ETHSW_SSB_ADDR_ADDE,    /* Memory Address */
-+//    XRX200_ETHSW_SSB_DATA,         /* Ethernet Switch SharedSegment Buffer Data Register */
-+//    XRX200_ETHSW_SSB_DATA_DATA,    /* Data Value */
-+//    XRX200_ETHSW_CAP_0,            /* Ethernet Switch CapabilityRegister 0 */
-+//    XRX200_ETHSW_CAP_0_SPEED,      /* Clock frequency */
-+//    XRX200_ETHSW_CAP_1,            /* Ethernet Switch CapabilityRegister 1 */
-+//    XRX200_ETHSW_CAP_1_GMAC,       /* MAC operation mode */
-+//    XRX200_ETHSW_CAP_1_QUEUE,      /* Number of queues */
-+//    XRX200_ETHSW_CAP_1_VPORTS,     /* Number of virtual ports */
-+//    XRX200_ETHSW_CAP_1_PPORTS,     /* Number of physical ports */
-+//    XRX200_ETHSW_CAP_2,            /* Ethernet Switch CapabilityRegister 2 */
-+//    XRX200_ETHSW_CAP_2_PACKETS,    /* Number of packets */
-+//    XRX200_ETHSW_CAP_3,            /* Ethernet Switch CapabilityRegister 3 */
-+//    XRX200_ETHSW_CAP_3_METERS,     /* Number of traffic meters */
-+//    XRX200_ETHSW_CAP_3_SHAPERS,    /* Number of traffic shapers */
-+//    XRX200_ETHSW_CAP_4,            /* Ethernet Switch CapabilityRegister 4 */
-+//    XRX200_ETHSW_CAP_4_PPPOE,      /* PPPoE table size */
-+//    XRX200_ETHSW_CAP_4_VLAN,       /* Active VLAN table size */
-+//    XRX200_ETHSW_CAP_5,            /* Ethernet Switch CapabilityRegister 5 */
-+//    XRX200_ETHSW_CAP_5_IPPLEN,     /* IP packet length table size */
-+//    XRX200_ETHSW_CAP_5_PROT,       /* Protocol table size */
-+//    XRX200_ETHSW_CAP_6,            /* Ethernet Switch CapabilityRegister 6 */
-+//    XRX200_ETHSW_CAP_6_MACDASA,    /* MAC DA/SA table size */
-+//    XRX200_ETHSW_CAP_6_APPL,       /* Application table size */
-+//    XRX200_ETHSW_CAP_7,            /* Ethernet Switch CapabilityRegister 7 */
-+//    XRX200_ETHSW_CAP_7_IPDASAM,    /* IP DA/SA MSB table size */
-+//    XRX200_ETHSW_CAP_7_IPDASAL,    /* IP DA/SA LSB table size */
-+//    XRX200_ETHSW_CAP_8,            /* Ethernet Switch CapabilityRegister 8 */
-+//    XRX200_ETHSW_CAP_8_MCAST,      /* Multicast table size */
-+//    XRX200_ETHSW_CAP_9,            /* Ethernet Switch CapabilityRegister 9 */
-+//    XRX200_ETHSW_CAP_9_FLAGG,      /* Flow Aggregation table size */
-+//    XRX200_ETHSW_CAP_10,           /* Ethernet Switch CapabilityRegister 10 */
-+//    XRX200_ETHSW_CAP_10_MACBT,     /* MAC bridging table size */
-+//    XRX200_ETHSW_CAP_11,           /* Ethernet Switch CapabilityRegister 11 */
-+//    XRX200_ETHSW_CAP_11_BSIZEL,    /* Packet buffer size (lower part, in byte) */
-+//    XRX200_ETHSW_CAP_12,           /* Ethernet Switch CapabilityRegister 12 */
-+//    XRX200_ETHSW_CAP_12_BSIZEH,    /* Packet buffer size (higher part, in byte) */
-+//    XRX200_ETHSW_VERSION_REV,      /* Ethernet Switch VersionRegister */
-+//    XRX200_ETHSW_VERSION_MOD_ID,   /* Module Identification */
-+//    XRX200_ETHSW_VERSION_REV_ID,   /* Hardware Revision Identification */
-+//    XRX200_ETHSW_IER,              /* Interrupt Enable Register */
-+//    XRX200_ETHSW_IER_FDMAIE,       /* Fetch DMA Interrupt Enable */
-+//    XRX200_ETHSW_IER_SDMAIE,       /* Store DMA Interrupt Enable */
-+//    XRX200_ETHSW_IER_MACIE,        /* Ethernet MAC Interrupt Enable */
-+//    XRX200_ETHSW_IER_PCEIE,        /* Parser and Classification Engine Interrupt Enable */
-+//    XRX200_ETHSW_IER_BMIE,         /* Buffer Manager Interrupt Enable */
-+//    XRX200_ETHSW_ISR,              /* Interrupt Status Register */
-+//    XRX200_ETHSW_ISR_FDMAINT,      /* Fetch DMA Interrupt */
-+//    XRX200_ETHSW_ISR_SDMAINT,      /* Store DMA Interrupt */
-+//    XRX200_ETHSW_ISR_MACINT,       /* Ethernet MAC Interrupt */
-+//    XRX200_ETHSW_ISR_PCEINT,       /* Parser and Classification Engine Interrupt */
-+//    XRX200_ETHSW_ISR_BMINT,        /* Buffer Manager Interrupt */
-+//    XRX200_ETHSW_SPARE_0,          /* Ethernet Switch SpareCells 0 */
-+//    XRX200_ETHSW_SPARE_0_SPARE,    /* SPARE0  */
-+//    XRX200_ETHSW_SPARE_1,          /* Ethernet Switch SpareCells 1 */
-+//    XRX200_ETHSW_SPARE_1_SPARE,    /* SPARE1  */
-+//    XRX200_ETHSW_SPARE_2,          /* Ethernet Switch SpareCells 2 */
-+//    XRX200_ETHSW_SPARE_2_SPARE,    /* SPARE2  */
-+//    XRX200_ETHSW_SPARE_3,          /* Ethernet Switch SpareCells 3 */
-+//    XRX200_ETHSW_SPARE_3_SPARE,    /* SPARE3  */
-+//    XRX200_ETHSW_SPARE_4,          /* Ethernet Switch SpareCells 4 */
-+//    XRX200_ETHSW_SPARE_4_SPARE,    /* SPARE4  */
-+//    XRX200_ETHSW_SPARE_5,          /* Ethernet Switch SpareCells 5 */
-+//    XRX200_ETHSW_SPARE_5_SPARE,    /* SPARE5  */
-+//    XRX200_ETHSW_SPARE_6,          /* Ethernet Switch SpareCells 6 */
-+//    XRX200_ETHSW_SPARE_6_SPARE,    /* SPARE6  */
-+//    XRX200_ETHSW_SPARE_7,          /* Ethernet Switch SpareCells 7 */
-+//    XRX200_ETHSW_SPARE_7_SPARE,    /* SPARE7  */
-+//    XRX200_ETHSW_SPARE_8,          /* Ethernet Switch SpareCells 8 */
-+//    XRX200_ETHSW_SPARE_8_SPARE,    /* SPARE8  */
-+//    XRX200_ETHSW_SPARE_9,          /* Ethernet Switch SpareCells 9 */
-+//    XRX200_ETHSW_SPARE_9_SPARE,    /* SPARE9  */
-+//    XRX200_ETHSW_SPARE_10,         /* Ethernet Switch SpareCells 10 */
-+//    XRX200_ETHSW_SPARE_10_SPARE,   /* SPARE10  */
-+//    XRX200_ETHSW_SPARE_11,         /* Ethernet Switch SpareCells 11 */
-+//    XRX200_ETHSW_SPARE_11_SPARE,   /* SPARE11  */
-+//    XRX200_ETHSW_SPARE_12,         /* Ethernet Switch SpareCells 12 */
-+//    XRX200_ETHSW_SPARE_12_SPARE,   /* SPARE12  */
-+//    XRX200_ETHSW_SPARE_13,         /* Ethernet Switch SpareCells 13 */
-+//    XRX200_ETHSW_SPARE_13_SPARE,   /* SPARE13  */
-+//    XRX200_ETHSW_SPARE_14,         /* Ethernet Switch SpareCells 14 */
-+//    XRX200_ETHSW_SPARE_14_SPARE,   /* SPARE14  */
-+//    XRX200_ETHSW_SPARE_15,         /* Ethernet Switch SpareCells 15 */
-+//    XRX200_ETHSW_SPARE_15_SPARE,   /* SPARE15  */
-+//    XRX200_BM_RAM_VAL_3,           /* RAM Value Register 3 */
-+//    XRX200_BM_RAM_VAL_3_VAL3,      /* Data value [15:0] */
-+//    XRX200_BM_RAM_VAL_2,           /* RAM Value Register 2 */
-+//    XRX200_BM_RAM_VAL_2_VAL2,      /* Data value [15:0] */
-+//    XRX200_BM_RAM_VAL_1,           /* RAM Value Register 1 */
-+//    XRX200_BM_RAM_VAL_1_VAL1,      /* Data value [15:0] */
-+//    XRX200_BM_RAM_VAL_0,           /* RAM Value Register 0 */
-+//    XRX200_BM_RAM_VAL_0_VAL0,      /* Data value [15:0] */
-+//    XRX200_BM_RAM_ADDR,            /* RAM Address Register */
-+//    XRX200_BM_RAM_ADDR_ADDR,       /* RAM Address */
-+//    XRX200_BM_RAM_CTRL,            /* RAM Access Control Register */
-+//    XRX200_BM_RAM_CTRL_BAS,        /* Access Busy/Access Start */
-+//    XRX200_BM_RAM_CTRL_OPMOD,      /* Lookup Table Access Operation Mode */
-+//    XRX200_BM_RAM_CTRL_ADDR,       /* Address for RAM selection */
-+//    XRX200_BM_FSQM_GCTRL,          /* Free Segment Queue ManagerGlobal Control Register */
-+//    XRX200_BM_FSQM_GCTRL_SEGNUM,   /* Maximum Segment Number */
-+//    XRX200_BM_CONS_SEG,            /* Number of Consumed SegmentsRegister */
-+//    XRX200_BM_CONS_SEG_FSEG,       /* Number of Consumed Segments */
-+//    XRX200_BM_CONS_PKT,            /* Number of Consumed PacketPointers Register */
-+//    XRX200_BM_CONS_PKT_FQP,        /* Number of Consumed Packet Pointers */
-+//    XRX200_BM_GCTRL_F,             /* Buffer Manager Global ControlRegister 0 */
-+//    XRX200_BM_GCTRL_BM_STA,        /* Buffer Manager Initialization Status Bit */
-+//    XRX200_BM_GCTRL_SAT,           /* RMON Counter Update Mode */
-+//    XRX200_BM_GCTRL_FR_RBC,        /* Freeze RMON RX Bad Byte 64 Bit Counter */
-+//    XRX200_BM_GCTRL_FR_RGC,        /* Freeze RMON RX Good Byte 64 Bit Counter */
-+//    XRX200_BM_GCTRL_FR_TGC,        /* Freeze RMON TX Good Byte 64 Bit Counter */
-+//    XRX200_BM_GCTRL_I_FIN,         /* RAM initialization finished */
-+//    XRX200_BM_GCTRL_CX_INI,        /* PQM Context RAM initialization */
-+//    XRX200_BM_GCTRL_FP_INI,        /* FPQM RAM initialization */
-+//    XRX200_BM_GCTRL_FS_INI,        /* FSQM RAM initialization */
-+//    XRX200_BM_GCTRL_R_SRES,        /* Software Reset for RMON */
-+//    XRX200_BM_GCTRL_S_SRES,        /* Software Reset for Scheduler */
-+//    XRX200_BM_GCTRL_A_SRES,        /* Software Reset for AVG */
-+//    XRX200_BM_GCTRL_P_SRES,        /* Software Reset for PQM */
-+//    XRX200_BM_GCTRL_F_SRES,        /* Software Reset for FSQM */
-+//    XRX200_BM_QUEUE_GCTRL,         /* Queue Manager GlobalControl Register 0 */
-+//    XRX200_BM_QUEUE_GCTRL_GL_MOD,  /* WRED Mode Signal */
-+//    XRX200_BM_QUEUE_GCTRL_AQUI,    /* Average Queue Update Interval */
-+//    XRX200_BM_QUEUE_GCTRL_AQWF,    /* Average Queue Weight Factor */
-+//    XRX200_BM_QUEUE_GCTRL_QAVGEN,  /* Queue Average Calculation Enable */
-+//    XRX200_BM_QUEUE_GCTRL_DPROB,   /* Drop Probability Profile */
-+//    XRX200_BM_WRED_RTH_0,          /* WRED Red Threshold Register0 */
-+//    XRX200_BM_WRED_RTH_0_MINTH,    /* Minimum Threshold */
-+//    XRX200_BM_WRED_RTH_1,          /* WRED Red Threshold Register1 */
-+//    XRX200_BM_WRED_RTH_1_MAXTH,    /* Maximum Threshold */
-+//    XRX200_BM_WRED_YTH_0,          /* WRED Yellow ThresholdRegister 0 */
-+//    XRX200_BM_WRED_YTH_0_MINTH,    /* Minimum Threshold */
-+//    XRX200_BM_WRED_YTH_1,          /* WRED Yellow ThresholdRegister 1 */
-+//    XRX200_BM_WRED_YTH_1_MAXTH,    /* Maximum Threshold */
-+//    XRX200_BM_WRED_GTH_0,          /* WRED Green ThresholdRegister 0 */
-+//    XRX200_BM_WRED_GTH_0_MINTH,    /* Minimum Threshold */
-+//    XRX200_BM_WRED_GTH_1,          /* WRED Green ThresholdRegister 1 */
-+//    XRX200_BM_WRED_GTH_1_MAXTH,    /* Maximum Threshold */
-+//    XRX200_BM_DROP_GTH_0_THR,      /* Drop Threshold ConfigurationRegister 0 */
-+//    XRX200_BM_DROP_GTH_0_THR_FQ,   /* Threshold for frames marked red */
-+//    XRX200_BM_DROP_GTH_1_THY,      /* Drop Threshold ConfigurationRegister 1 */
-+//    XRX200_BM_DROP_GTH_1_THY_FQ,   /* Threshold for frames marked yellow */
-+//    XRX200_BM_DROP_GTH_2_THG,      /* Drop Threshold ConfigurationRegister 2 */
-+//    XRX200_BM_DROP_GTH_2_THG_FQ,   /* Threshold for frames marked green */
-+//    XRX200_BM_IER,                 /* Buffer Manager Global InterruptEnable Register */
-+//    XRX200_BM_IER_CNT4,            /* Counter Group 4 (RMON-CLASSIFICATION) Interrupt Enable */
-+//    XRX200_BM_IER_CNT3,            /* Counter Group 3 (RMON-PQM) Interrupt Enable */
-+//    XRX200_BM_IER_CNT2,            /* Counter Group 2 (RMON-SCHEDULER) Interrupt Enable */
-+//    XRX200_BM_IER_CNT1,            /* Counter Group 1 (RMON-QFETCH) Interrupt Enable */
-+//    XRX200_BM_IER_CNT0,            /* Counter Group 0 (RMON-QSTOR) Interrupt Enable */
-+//    XRX200_BM_IER_DEQ,             /* PQM dequeue Interrupt Enable */
-+//    XRX200_BM_IER_ENQ,             /* PQM Enqueue Interrupt Enable */
-+//    XRX200_BM_IER_FSQM,            /* Buffer Empty Interrupt Enable */
-+//    XRX200_BM_ISR,                 /* Buffer Manager Global InterruptStatus Register */
-+//    XRX200_BM_ISR_CNT4,            /* Counter Group 4 Interrupt */
-+//    XRX200_BM_ISR_CNT3,            /* Counter Group 3 Interrupt */
-+//    XRX200_BM_ISR_CNT2,            /* Counter Group 2 Interrupt */
-+//    XRX200_BM_ISR_CNT1,            /* Counter Group 1 Interrupt */
-+//    XRX200_BM_ISR_CNT0,            /* Counter Group 0 Interrupt */
-+//    XRX200_BM_ISR_DEQ,             /* PQM dequeue Interrupt Enable */
-+//    XRX200_BM_ISR_ENQ,             /* PQM Enqueue Interrupt */
-+//    XRX200_BM_ISR_FSQM,            /* Buffer Empty Interrupt */
-+//    XRX200_BM_CISEL,               /* Buffer Manager RMON CounterInterrupt Select Register */
-+//    XRX200_BM_CISEL_PORT,          /* Port Number */
-+//    XRX200_BM_DEBUG_CTRL_DBG,      /* Debug Control Register */
-+//    XRX200_BM_DEBUG_CTRL_DBG_SEL,  /* Select Signal for Debug Multiplexer */
-+//    XRX200_BM_DEBUG_VAL_DBG,       /* Debug Value Register */
-+//    XRX200_BM_DEBUG_VAL_DBG_DAT,   /* Debug Data Value */
-+//    XRX200_BM_PCFG,                /* Buffer Manager PortConfiguration Register */
-+//    XRX200_BM_PCFG_CNTEN,          /* RMON Counter Enable */
-+//    XRX200_BM_RMON_CTRL_RAM1,      /* Buffer ManagerRMON Control Register */
-+//    XRX200_BM_RMON_CTRL_RAM2_RES,  /* Software Reset for RMON RAM2 */
-+//    XRX200_BM_RMON_CTRL_RAM1_RES,  /* Software Reset for RMON RAM1 */
-+//    XRX200_PQM_DP,                 /* Packet Queue ManagerDrop Probability Register */
-+//    XRX200_PQM_DP_DPROB,           /* Drop Probability Profile */
-+//    XRX200_PQM_RS,                 /* Packet Queue ManagerRate Shaper Assignment Register */
-+//    XRX200_PQM_RS_EN2,             /* Rate Shaper 2 Enable */
-+//    XRX200_PQM_RS_RS2,             /* Rate Shaper 2 */
-+//    XRX200_PQM_RS_EN1,             /* Rate Shaper 1 Enable */
-+//    XRX200_PQM_RS_RS1,             /* Rate Shaper 1 */
-+//    XRX200_RS_CTRL,                /* Rate Shaper ControlRegister */
-+//    XRX200_RS_CTRL_RSEN,           /* Rate Shaper Enable */
-+//    XRX200_RS_CBS,                 /* Rate Shaper CommittedBurst Size Register */
-+//    XRX200_RS_CBS_CBS,             /* Committed Burst Size */
-+//    XRX200_RS_IBS,                 /* Rate Shaper InstantaneousBurst Size Register */
-+//    XRX200_RS_IBS_IBS,             /* Instantaneous Burst Size */
-+//    XRX200_RS_CIR_EXP,             /* Rate Shaper RateExponent Register */
-+//    XRX200_RS_CIR_EXP_EXP,         /* Exponent */
-+//    XRX200_RS_CIR_MANT,            /* Rate Shaper RateMantissa Register */
-+//    XRX200_RS_CIR_MANT_MANT,       /* Mantissa */
-+      XRX200_PCE_TBL_KEY_7,          /* Table Key Data 7 */
-+//    XRX200_PCE_TBL_KEY_7_KEY7,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_KEY_6,          /* Table Key Data 6 */
-+//    XRX200_PCE_TBL_KEY_6_KEY6,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_KEY_5,          /* Table Key Data 5 */
-+//    XRX200_PCE_TBL_KEY_5_KEY5,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_KEY_4,          /* Table Key Data 4 */
-+//    XRX200_PCE_TBL_KEY_4_KEY4,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_KEY_3,          /* Table Key Data 3 */
-+//    XRX200_PCE_TBL_KEY_3_KEY3,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_KEY_2,          /* Table Key Data 2 */
-+//    XRX200_PCE_TBL_KEY_2_KEY2,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_KEY_1,          /* Table Key Data 1 */
-+//    XRX200_PCE_TBL_KEY_1_KEY1,     /* Key Value[31:16] */
-+      XRX200_PCE_TBL_KEY_0,          /* Table Key Data 0 */
-+//    XRX200_PCE_TBL_KEY_0_KEY0,     /* Key Value[15:0] */
-+      XRX200_PCE_TBL_MASK_0,         /* Table Mask Write Register0 */
-+//    XRX200_PCE_TBL_MASK_0_MASK0,   /* Mask Pattern [15:0] */
-+      XRX200_PCE_TBL_VAL_4,          /* Table Value Register4 */
-+//    XRX200_PCE_TBL_VAL_4_VAL4,     /* Data value [15:0] */
-+      XRX200_PCE_TBL_VAL_3,          /* Table Value Register3 */
-+//    XRX200_PCE_TBL_VAL_3_VAL3,     /* Data value [15:0] */
-+      XRX200_PCE_TBL_VAL_2,          /* Table Value Register2 */
-+//    XRX200_PCE_TBL_VAL_2_VAL2,     /* Data value [15:0] */
-+      XRX200_PCE_TBL_VAL_1,          /* Table Value Register1 */
-+//    XRX200_PCE_TBL_VAL_1_VAL1,     /* Data value [15:0] */
-+      XRX200_PCE_TBL_VAL_0,          /* Table Value Register0 */
-+//    XRX200_PCE_TBL_VAL_0_VAL0,     /* Data value [15:0] */
-+//    XRX200_PCE_TBL_ADDR,           /* Table Entry AddressRegister */
-+      XRX200_PCE_TBL_ADDR_ADDR,      /* Table Address */
-+//    XRX200_PCE_TBL_CTRL,           /* Table Access ControlRegister */
-+      XRX200_PCE_TBL_CTRL_BAS,       /* Access Busy/Access Start */
-+      XRX200_PCE_TBL_CTRL_TYPE,      /* Lookup Entry Type */
-+      XRX200_PCE_TBL_CTRL_VLD,       /* Lookup Entry Valid */
-+      XRX200_PCE_TBL_CTRL_GMAP,      /* Group Map */
-+      XRX200_PCE_TBL_CTRL_OPMOD,     /* Lookup Table Access Operation Mode */
-+      XRX200_PCE_TBL_CTRL_ADDR,      /* Lookup Table Address */
-+//    XRX200_PCE_TBL_STAT,           /* Table General StatusRegister */
-+//    XRX200_PCE_TBL_STAT_TBUSY,     /* Table Access Busy */
-+//    XRX200_PCE_TBL_STAT_TEMPT,     /* Table Empty */
-+//    XRX200_PCE_TBL_STAT_TFUL,      /* Table Full */
-+//    XRX200_PCE_AGE_0,              /* Aging Counter ConfigurationRegister 0 */
-+//    XRX200_PCE_AGE_0_EXP,          /* Aging Counter Exponent Value  */
-+//    XRX200_PCE_AGE_1,              /* Aging Counter ConfigurationRegister 1 */
-+//    XRX200_PCE_AGE_1_MANT,         /* Aging Counter Mantissa Value  */
-+//    XRX200_PCE_PMAP_1,             /* Port Map Register 1 */
-+//    XRX200_PCE_PMAP_1_MPMAP,       /* Monitoring Port Map */
-+//    XRX200_PCE_PMAP_2,             /* Port Map Register 2 */
-+//    XRX200_PCE_PMAP_2_DMCPMAP,     /* Default Multicast Port Map */
-+//    XRX200_PCE_PMAP_3,             /* Port Map Register 3 */
-+//    XRX200_PCE_PMAP_3_UUCMAP,      /* Default Unknown Unicast Port Map */
-+//    XRX200_PCE_GCTRL_0,            /* PCE Global Control Register0 */
-+//    XRX200_PCE_GCTRL_0_IGMP,       /* IGMP Mode Selection */
-+      XRX200_PCE_GCTRL_0_VLAN,       /* VLAN-aware Switching */
-+//    XRX200_PCE_GCTRL_0_NOPM,       /* No Port Map Forwarding */
-+//    XRX200_PCE_GCTRL_0_SCONUC,     /* Unknown Unicast Storm Control */
-+//    XRX200_PCE_GCTRL_0_SCONMC,     /* Multicast Storm Control */
-+//    XRX200_PCE_GCTRL_0_SCONBC,     /* Broadcast Storm Control */
-+//    XRX200_PCE_GCTRL_0_SCONMOD,    /* Storm Control Mode */
-+//    XRX200_PCE_GCTRL_0_SCONMET,    /* Storm Control Metering Instance */
-+//    XRX200_PCE_GCTRL_0_MC_VALID,   /* Access Request */
-+//    XRX200_PCE_GCTRL_0_PLCKMOD,    /* Port Lock Mode */
-+//    XRX200_PCE_GCTRL_0_PLIMMOD,    /* MAC Address Learning Limitation Mode */
-+//    XRX200_PCE_GCTRL_0_MTFL,       /* MAC Table Flushing */
-+//    XRX200_PCE_GCTRL_1,            /* PCE Global Control Register1 */
-+//    XRX200_PCE_GCTRL_1_PCE_DIS,    /* PCE Disable after currently processed packet */
-+//    XRX200_PCE_GCTRL_1_LRNMOD,     /* MAC Address Learning Mode */
-+//    XRX200_PCE_TCM_GLOB_CTRL,      /* Three-color MarkerGlobal Control Register */
-+//    XRX200_PCE_TCM_GLOB_CTRL_DPRED, /* Re-marking Drop Precedence Red Encoding */
-+//    XRX200_PCE_TCM_GLOB_CTRL_DPYEL, /* Re-marking Drop Precedence Yellow Encoding */
-+//    XRX200_PCE_TCM_GLOB_CTRL_DPGRN, /* Re-marking Drop Precedence Green Encoding */
-+//    XRX200_PCE_IGMP_CTRL,          /* IGMP Control Register */
-+//    XRX200_PCE_IGMP_CTRL_FAGEEN,   /* Force Aging of Table Entries Enable */
-+//    XRX200_PCE_IGMP_CTRL_FLEAVE,   /* Fast Leave Enable */
-+//    XRX200_PCE_IGMP_CTRL_DMRTEN,   /* Default Maximum Response Time Enable */
-+//    XRX200_PCE_IGMP_CTRL_JASUP,    /* Join Aggregation Suppression Enable */
-+//    XRX200_PCE_IGMP_CTRL_REPSUP,   /* Report Suppression Enable */
-+//    XRX200_PCE_IGMP_CTRL_SRPEN,    /* Snooping of Router Port Enable */
-+//    XRX200_PCE_IGMP_CTRL_ROB,      /* Robustness Variable */
-+//    XRX200_PCE_IGMP_CTRL_DMRT,     /* IGMP Default Maximum Response Time */
-+//    XRX200_PCE_IGMP_DRPM,          /* IGMP Default RouterPort Map Register */
-+//    XRX200_PCE_IGMP_DRPM_DRPM,     /* IGMP Default Router Port Map */
-+//    XRX200_PCE_IGMP_AGE_0,         /* IGMP Aging Register0 */
-+//    XRX200_PCE_IGMP_AGE_0_MANT,    /* IGMP Group Aging Time Mantissa */
-+//    XRX200_PCE_IGMP_AGE_0_EXP,     /* IGMP Group Aging Time Exponent */
-+//    XRX200_PCE_IGMP_AGE_1,         /* IGMP Aging Register1 */
-+//    XRX200_PCE_IGMP_AGE_1_MANT,    /* IGMP Router Port Aging Time Mantissa */
-+//    XRX200_PCE_IGMP_STAT,          /* IGMP Status Register */
-+//    XRX200_PCE_IGMP_STAT_IGPM,     /* IGMP Port Map */
-+//    XRX200_WOL_GLB_CTRL,           /* Wake-on-LAN ControlRegister */
-+//    XRX200_WOL_GLB_CTRL_PASSEN,    /* WoL Password Enable */
-+//    XRX200_WOL_DA_0,               /* Wake-on-LAN DestinationAddress Register 0 */
-+//    XRX200_WOL_DA_0_DA0,           /* WoL Destination Address [15:0] */
-+//    XRX200_WOL_DA_1,               /* Wake-on-LAN DestinationAddress Register 1 */
-+//    XRX200_WOL_DA_1_DA1,           /* WoL Destination Address [31:16] */
-+//    XRX200_WOL_DA_2,               /* Wake-on-LAN DestinationAddress Register 2 */
-+//    XRX200_WOL_DA_2_DA2,           /* WoL Destination Address [47:32] */
-+//    XRX200_WOL_PW_0,               /* Wake-on-LAN Password Register0 */
-+//    XRX200_WOL_PW_0_PW0,           /* WoL Password [15:0] */
-+//    XRX200_WOL_PW_1,               /* Wake-on-LAN Password Register1 */
-+//    XRX200_WOL_PW_1_PW1,           /* WoL Password [31:16] */
-+//    XRX200_WOL_PW_2,               /* Wake-on-LAN Password Register2 */
-+//    XRX200_WOL_PW_2_PW2,           /* WoL Password [47:32] */
-+//    XRX200_PCE_IER_0_PINT,         /* Parser and ClassificationEngine Global Interrupt Enable Register 0 */
-+//    XRX200_PCE_IER_0_PINT_15,      /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_14,      /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_13,      /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_12,      /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_11,      /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_10,      /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_9,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_8,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_7,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_6,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_5,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_4,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_3,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_2,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_1,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_0_PINT_0,       /* Port Interrupt Enable */
-+//    XRX200_PCE_IER_1,              /* Parser and ClassificationEngine Global Interrupt Enable Register 1 */
-+//    XRX200_PCE_IER_1_FLOWINT,      /* Traffic Flow Table Interrupt Rule matched Interrupt Enable */
-+//    XRX200_PCE_IER_1_CPH2,         /* Classification Phase 2 Ready Interrupt Enable */
-+//    XRX200_PCE_IER_1_CPH1,         /* Classification Phase 1 Ready Interrupt Enable */
-+//    XRX200_PCE_IER_1_CPH0,         /* Classification Phase 0 Ready Interrupt Enable */
-+//    XRX200_PCE_IER_1_PRDY,         /* Parser Ready Interrupt Enable */
-+//    XRX200_PCE_IER_1_IGTF,         /* IGMP Table Full Interrupt Enable */
-+//    XRX200_PCE_IER_1_MTF,          /* MAC Table Full Interrupt Enable */
-+//    XRX200_PCE_ISR_0_PINT,         /* Parser and ClassificationEngine Global Interrupt Status Register 0 */
-+//    XRX200_PCE_ISR_0_PINT_15,      /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_14,      /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_13,      /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_12,      /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_11,      /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_10,      /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_9,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_8,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_7,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_6,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_5,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_4,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_3,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_2,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_1,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_0_PINT_0,       /* Port Interrupt */
-+//    XRX200_PCE_ISR_1,              /* Parser and ClassificationEngine Global Interrupt Status Register 1 */
-+//    XRX200_PCE_ISR_1_FLOWINT,      /* Traffic Flow Table Interrupt Rule matched */
-+//    XRX200_PCE_ISR_1_CPH2,         /* Classification Phase 2 Ready Interrupt */
-+//    XRX200_PCE_ISR_1_CPH1,         /* Classification Phase 1 Ready Interrupt */
-+//    XRX200_PCE_ISR_1_CPH0,         /* Classification Phase 0 Ready Interrupt */
-+//    XRX200_PCE_ISR_1_PRDY,         /* Parser Ready Interrupt */
-+//    XRX200_PCE_ISR_1_IGTF,         /* IGMP Table Full Interrupt */
-+//    XRX200_PCE_ISR_1_MTF,          /* MAC Table Full Interrupt */
-+//    XRX200_PARSER_STAT_FIFO,       /* Parser Status Register */
-+//    XRX200_PARSER_STAT_FSM_DAT_CNT, /* Parser FSM Data Counter */
-+//    XRX200_PARSER_STAT_FSM_STATE,  /* Parser FSM State */
-+//    XRX200_PARSER_STAT_PKT_ERR,    /* Packet error detected */
-+//    XRX200_PARSER_STAT_FSM_FIN,    /* Parser FSM finished */
-+//    XRX200_PARSER_STAT_FSM_START,  /* Parser FSM start */
-+//    XRX200_PARSER_STAT_FIFO_RDY,   /* Parser FIFO ready for read. */
-+//    XRX200_PARSER_STAT_FIFO_FULL,  /* Parser */
-+//    XRX200_PCE_PCTRL_0,            /* PCE Port ControlRegister 0 */
-+//    XRX200_PCE_PCTRL_0_MCST,       /* Multicast Forwarding Mode Selection */
-+//    XRX200_PCE_PCTRL_0_EGSTEN,     /* Table-based Egress Special Tag Enable */
-+//    XRX200_PCE_PCTRL_0_IGSTEN,     /* Ingress Special Tag Enable */
-+//    XRX200_PCE_PCTRL_0_PCPEN,      /* PCP Remarking Mode */
-+//    XRX200_PCE_PCTRL_0_CLPEN,      /* Class Remarking Mode */
-+//    XRX200_PCE_PCTRL_0_DPEN,       /* Drop Precedence Remarking Mode */
-+//    XRX200_PCE_PCTRL_0_CMOD,       /* Three-color Marker Color Mode */
-+//    XRX200_PCE_PCTRL_0_VREP,       /* VLAN Replacement Mode */
-+      XRX200_PCE_PCTRL_0_TVM,        /* Transparent VLAN Mode */
-+//    XRX200_PCE_PCTRL_0_PLOCK,      /* Port Locking Enable */
-+//    XRX200_PCE_PCTRL_0_AGEDIS,     /* Aging Disable */
-+//    XRX200_PCE_PCTRL_0_PSTATE,     /* Port State */
-+//    XRX200_PCE_PCTRL_1,            /* PCE Port ControlRegister 1 */
-+//    XRX200_PCE_PCTRL_1_LRNLIM,     /* MAC Address Learning Limit */
-+//    XRX200_PCE_PCTRL_2,            /* PCE Port ControlRegister 2 */
-+//    XRX200_PCE_PCTRL_2_DSCPMOD,    /* DSCP Mode Selection */
-+//    XRX200_PCE_PCTRL_2_DSCP,       /* Enable DSCP to select the Class of Service */
-+//    XRX200_PCE_PCTRL_2_PCP,        /* Enable VLAN PCP to select the Class of Service */
-+//    XRX200_PCE_PCTRL_2_PCLASS,     /* Port-based Traffic Class */
-+//    XRX200_PCE_PCTRL_3_VIO,        /* PCE Port ControlRegister 3 */
-+//    XRX200_PCE_PCTRL_3_EDIR,       /* Egress Redirection Mode */
-+//    XRX200_PCE_PCTRL_3_RXDMIR,     /* Receive Mirroring Enable for dropped frames */
-+//    XRX200_PCE_PCTRL_3_RXVMIR,     /* Receive Mirroring Enable for valid frames */
-+//    XRX200_PCE_PCTRL_3_TXMIR,      /* Transmit Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_7,      /* Violation Type 7 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_6,      /* Violation Type 6 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_5,      /* Violation Type 5 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_4,      /* Violation Type 4 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_3,      /* Violation Type 3 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_2,      /* Violation Type 2 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_1,      /* Violation Type 1 Mirroring Enable */
-+//    XRX200_PCE_PCTRL_3_VIO_0,      /* Violation Type 0 Mirroring Enable */
-+//    XRX200_WOL_CTRL,               /* Wake-on-LAN ControlRegister */
-+//    XRX200_WOL_CTRL_PORT,          /* WoL Enable */
-+//    XRX200_PCE_VCTRL,              /* PCE VLAN ControlRegister */
-+      XRX200_PCE_VCTRL_VSR,          /* VLAN Security Rule */
-+      XRX200_PCE_VCTRL_VEMR,         /* VLAN Egress Member Violation Rule */
-+      XRX200_PCE_VCTRL_VIMR,         /* VLAN Ingress Member Violation Rule */
-+      XRX200_PCE_VCTRL_VINR,         /* VLAN Ingress Tag Rule */
-+      XRX200_PCE_VCTRL_UVR,          /* Unknown VLAN Rule */
-+//    XRX200_PCE_DEFPVID,            /* PCE Default PortVID Register */
-+      XRX200_PCE_DEFPVID_PVID,       /* Default Port VID Index */
-+//    XRX200_PCE_PSTAT,              /* PCE Port StatusRegister */
-+//    XRX200_PCE_PSTAT_LRNCNT,       /* Learning Count */
-+//    XRX200_PCE_PIER,               /* Parser and ClassificationEngine Port Interrupt Enable Register */
-+//    XRX200_PCE_PIER_CLDRP,         /* Classification Drop Interrupt Enable */
-+//    XRX200_PCE_PIER_PTDRP,         /* Port Drop Interrupt Enable */
-+//    XRX200_PCE_PIER_VLAN,          /* VLAN Violation Interrupt Enable */
-+//    XRX200_PCE_PIER_WOL,           /* Wake-on-LAN Interrupt Enable */
-+//    XRX200_PCE_PIER_LOCK,          /* Port Limit Alert Interrupt Enable */
-+//    XRX200_PCE_PIER_LIM,           /* Port Lock Alert Interrupt Enable */
-+//    XRX200_PCE_PISR,               /* Parser and ClassificationEngine Port Interrupt Status Register */
-+//    XRX200_PCE_PISR_CLDRP,         /* Classification Drop Interrupt */
-+//    XRX200_PCE_PISR_PTDRP,         /* Port Drop Interrupt */
-+//    XRX200_PCE_PISR_VLAN,          /* VLAN Violation Interrupt */
-+//    XRX200_PCE_PISR_WOL,           /* Wake-on-LAN Interrupt */
-+//    XRX200_PCE_PISR_LOCK,          /* Port Lock Alert Interrupt */
-+//    XRX200_PCE_PISR_LIMIT,         /* Port Limitation Alert Interrupt */
-+//    XRX200_PCE_TCM_CTRL,           /* Three-colorMarker Control Register */
-+//    XRX200_PCE_TCM_CTRL_TCMEN,     /* Three-color Marker metering instance enable */
-+//    XRX200_PCE_TCM_STAT,           /* Three-colorMarker Status Register */
-+//    XRX200_PCE_TCM_STAT_AL1,       /* Three-color Marker Alert 1 Status */
-+//    XRX200_PCE_TCM_STAT_AL0,       /* Three-color Marker Alert 0 Status */
-+//    XRX200_PCE_TCM_CBS,            /* Three-color MarkerCommitted Burst Size Register */
-+//    XRX200_PCE_TCM_CBS_CBS,        /* Committed Burst Size */
-+//    XRX200_PCE_TCM_EBS,            /* Three-color MarkerExcess Burst Size Register */
-+//    XRX200_PCE_TCM_EBS_EBS,        /* Excess Burst Size */
-+//    XRX200_PCE_TCM_IBS,            /* Three-color MarkerInstantaneous Burst Size Register */
-+//    XRX200_PCE_TCM_IBS_IBS,        /* Instantaneous Burst Size */
-+//    XRX200_PCE_TCM_CIR_MANT,       /* Three-colorMarker Constant Information Rate Mantissa Register */
-+//    XRX200_PCE_TCM_CIR_MANT_MANT,  /* Rate Counter Mantissa */
-+//    XRX200_PCE_TCM_CIR_EXP,        /* Three-colorMarker Constant Information Rate Exponent Register */
-+//    XRX200_PCE_TCM_CIR_EXP_EXP,    /* Rate Counter Exponent */
-+//    XRX200_MAC_TEST,               /* MAC Test Register */
-+//    XRX200_MAC_TEST_JTP,           /* Jitter Test Pattern */
-+//    XRX200_MAC_PFAD_CFG,           /* MAC Pause FrameSource Address Configuration Register */
-+//    XRX200_MAC_PFAD_CFG_SAMOD,     /* Source Address Mode */
-+//    XRX200_MAC_PFSA_0,             /* Pause Frame SourceAddress Part 0  */
-+//    XRX200_MAC_PFSA_0_PFAD,        /* Pause Frame Source Address Part 0 */
-+//    XRX200_MAC_PFSA_1,             /* Pause Frame SourceAddress Part 1  */
-+//    XRX200_MAC_PFSA_1_PFAD,        /* Pause Frame Source Address Part 1 */
-+//    XRX200_MAC_PFSA_2,             /* Pause Frame SourceAddress Part 2  */
-+//    XRX200_MAC_PFSA_2_PFAD,        /* Pause Frame Source Address Part 2 */
-+//    XRX200_MAC_FLEN,               /* MAC Frame Length Register */
-+//    XRX200_MAC_FLEN_LEN,           /* Maximum Frame Length */
-+//    XRX200_MAC_VLAN_ETYPE_0,       /* MAC VLAN EthertypeRegister 0 */
-+//    XRX200_MAC_VLAN_ETYPE_0_OUTER, /* Ethertype */
-+//    XRX200_MAC_VLAN_ETYPE_1,       /* MAC VLAN EthertypeRegister 1 */
-+//    XRX200_MAC_VLAN_ETYPE_1_INNER, /* Ethertype */
-+//    XRX200_MAC_IER,                /* MAC Interrupt EnableRegister */
-+//    XRX200_MAC_IER_MACIEN,         /* MAC Interrupt Enable */
-+//    XRX200_MAC_ISR,                /* MAC Interrupt StatusRegister */
-+//    XRX200_MAC_ISR_MACINT,         /* MAC Interrupt */
-+//    XRX200_MAC_PSTAT,              /* MAC Port Status Register */
-+//    XRX200_MAC_PSTAT_PACT,         /* PHY Active Status */
-+      XRX200_MAC_PSTAT_GBIT,         /* Gigabit Speed Status */
-+      XRX200_MAC_PSTAT_MBIT,         /* Megabit Speed Status */
-+      XRX200_MAC_PSTAT_FDUP,         /* Full Duplex Status */
-+//    XRX200_MAC_PSTAT_RXPAU,        /* Receive Pause Status */
-+//    XRX200_MAC_PSTAT_TXPAU,        /* Transmit Pause Status */
-+//    XRX200_MAC_PSTAT_RXPAUEN,      /* Receive Pause Enable Status */
-+//    XRX200_MAC_PSTAT_TXPAUEN,      /* Transmit Pause Enable Status */
-+      XRX200_MAC_PSTAT_LSTAT,        /* Link Status */
-+//    XRX200_MAC_PSTAT_CRS,          /* Carrier Sense Status */
-+//    XRX200_MAC_PSTAT_TXLPI,        /* Transmit Low-power Idle Status */
-+//    XRX200_MAC_PSTAT_RXLPI,        /* Receive Low-power Idle Status */
-+//    XRX200_MAC_PISR,               /* MAC Interrupt Status Register */
-+//    XRX200_MAC_PISR_PACT,          /* PHY Active Status */
-+//    XRX200_MAC_PISR_SPEED,         /* Megabit Speed Status */
-+//    XRX200_MAC_PISR_FDUP,          /* Full Duplex Status */
-+//    XRX200_MAC_PISR_RXPAUEN,       /* Receive Pause Enable Status */
-+//    XRX200_MAC_PISR_TXPAUEN,       /* Transmit Pause Enable Status */
-+//    XRX200_MAC_PISR_LPIOFF,        /* Receive Low-power Idle Mode is left */
-+//    XRX200_MAC_PISR_LPION,         /* Receive Low-power Idle Mode is entered */
-+//    XRX200_MAC_PISR_JAM,           /* Jam Status Detected */
-+//    XRX200_MAC_PISR_TOOSHORT,      /* Too Short Frame Error Detected */
-+//    XRX200_MAC_PISR_TOOLONG,       /* Too Long Frame Error Detected */
-+//    XRX200_MAC_PISR_LENERR,        /* Length Mismatch Error Detected */
-+//    XRX200_MAC_PISR_FCSERR,        /* Frame Checksum Error Detected */
-+//    XRX200_MAC_PISR_TXPAUSE,       /* Pause Frame Transmitted */
-+//    XRX200_MAC_PISR_RXPAUSE,       /* Pause Frame Received */
-+//    XRX200_MAC_PIER,               /* MAC Interrupt Enable Register */
-+//    XRX200_MAC_PIER_PACT,          /* PHY Active Status */
-+//    XRX200_MAC_PIER_SPEED,         /* Megabit Speed Status */
-+//    XRX200_MAC_PIER_FDUP,          /* Full Duplex Status */
-+//    XRX200_MAC_PIER_RXPAUEN,       /* Receive Pause Enable Status */
-+//    XRX200_MAC_PIER_TXPAUEN,       /* Transmit Pause Enable Status */
-+//    XRX200_MAC_PIER_LPIOFF,        /* Low-power Idle Off Interrupt Mask */
-+//    XRX200_MAC_PIER_LPION,         /* Low-power Idle On Interrupt Mask */
-+//    XRX200_MAC_PIER_JAM,           /* Jam Status Interrupt Mask */
-+//    XRX200_MAC_PIER_TOOSHORT,      /* Too Short Frame Error Interrupt Mask */
-+//    XRX200_MAC_PIER_TOOLONG,       /* Too Long Frame Error Interrupt Mask */
-+//    XRX200_MAC_PIER_LENERR,        /* Length Mismatch Error Interrupt Mask */
-+//    XRX200_MAC_PIER_FCSERR,        /* Frame Checksum Error Interrupt Mask */
-+//    XRX200_MAC_PIER_TXPAUSE,       /* Transmit Pause Frame Interrupt Mask */
-+//    XRX200_MAC_PIER_RXPAUSE,       /* Receive Pause Frame Interrupt Mask */
-+//    XRX200_MAC_CTRL_0,             /* MAC Control Register0 */
-+//    XRX200_MAC_CTRL_0_LCOL,        /* Late Collision Control */
-+//    XRX200_MAC_CTRL_0_BM,          /* Burst Mode Control */
-+//    XRX200_MAC_CTRL_0_APADEN,      /* Automatic VLAN Padding Enable */
-+//    XRX200_MAC_CTRL_0_VPAD2EN,     /* Stacked VLAN Padding Enable */
-+//    XRX200_MAC_CTRL_0_VPADEN,      /* VLAN Padding Enable */
-+//    XRX200_MAC_CTRL_0_PADEN,       /* Padding Enable */
-+//    XRX200_MAC_CTRL_0_FCS,         /* Transmit FCS Control */
-+      XRX200_MAC_CTRL_0_FCON,        /* Flow Control Mode */
-+//    XRX200_MAC_CTRL_0_FDUP,        /* Full Duplex Control */
-+//    XRX200_MAC_CTRL_0_GMII,        /* GMII/MII interface mode selection */
-+//    XRX200_MAC_CTRL_1,             /* MAC Control Register1 */
-+//    XRX200_MAC_CTRL_1_SHORTPRE,    /* Short Preamble Control */
-+//    XRX200_MAC_CTRL_1_IPG,         /* Minimum Inter Packet Gap Size */
-+//    XRX200_MAC_CTRL_2,             /* MAC Control Register2 */
-+//    XRX200_MAC_CTRL_2_MLEN,        /* Maximum Untagged Frame Length */
-+//    XRX200_MAC_CTRL_2_LCHKL,       /* Frame Length Check Long Enable */
-+//    XRX200_MAC_CTRL_2_LCHKS,       /* Frame Length Check Short Enable */
-+//    XRX200_MAC_CTRL_3,             /* MAC Control Register3 */
-+//    XRX200_MAC_CTRL_3_RCNT,        /* Retry Count */
-+//    XRX200_MAC_CTRL_4,             /* MAC Control Register4 */
-+//    XRX200_MAC_CTRL_4_LPIEN,       /* LPI Mode Enable */
-+//    XRX200_MAC_CTRL_4_WAIT,        /* LPI Wait Time */
-+//    XRX200_MAC_CTRL_5_PJPS,        /* MAC Control Register5 */
-+//    XRX200_MAC_CTRL_5_PJPS_NOBP,   /* Prolonged Jam pattern size during no-backpressure state */
-+//    XRX200_MAC_CTRL_5_PJPS_BP,     /* Prolonged Jam pattern size during backpressure state */
-+//    XRX200_MAC_CTRL_6_XBUF,        /* Transmit and ReceiveBuffer Control Register */
-+//    XRX200_MAC_CTRL_6_RBUF_DLY_WP, /* Delay */
-+//    XRX200_MAC_CTRL_6_RBUF_INIT,   /* Receive Buffer Initialization */
-+//    XRX200_MAC_CTRL_6_RBUF_BYPASS, /* Bypass the Receive Buffer */
-+//    XRX200_MAC_CTRL_6_XBUF_DLY_WP, /* Delay */
-+//    XRX200_MAC_CTRL_6_XBUF_INIT,   /* Initialize the Transmit Buffer */
-+//    XRX200_MAC_CTRL_6_XBUF_BYPASS, /* Bypass the Transmit Buffer */
-+//    XRX200_MAC_BUFST_XBUF,         /* MAC Receive and TransmitBuffer Status Register */
-+//    XRX200_MAC_BUFST_RBUF_UFL,     /* Receive Buffer Underflow Indicator */
-+//    XRX200_MAC_BUFST_RBUF_OFL,     /* Receive Buffer Overflow Indicator */
-+//    XRX200_MAC_BUFST_XBUF_UFL,     /* Transmit Buffer Underflow Indicator */
-+//    XRX200_MAC_BUFST_XBUF_OFL,     /* Transmit Buffer Overflow Indicator */
-+//    XRX200_MAC_TESTEN,             /* MAC Test Enable Register */
-+//    XRX200_MAC_TESTEN_JTEN,        /* Jitter Test Enable */
-+//    XRX200_MAC_TESTEN_TXER,        /* Transmit Error Insertion */
-+//    XRX200_MAC_TESTEN_LOOP,        /* MAC Loopback Enable */
-+//    XRX200_FDMA_CTRL,              /* Ethernet Switch FetchDMA Control Register */
-+//    XRX200_FDMA_CTRL_LPI_THRESHOLD, /* Low Power Idle Threshold */
-+//    XRX200_FDMA_CTRL_LPI_MODE,     /* Low Power Idle Mode */
-+//    XRX200_FDMA_CTRL_EGSTAG,       /* Egress Special Tag Size */
-+//    XRX200_FDMA_CTRL_IGSTAG,       /* Ingress Special Tag Size */
-+//    XRX200_FDMA_CTRL_EXCOL,        /* Excessive Collision Handling */
-+//    XRX200_FDMA_STETYPE,           /* Special Tag EthertypeControl Register */
-+//    XRX200_FDMA_STETYPE_ETYPE,     /* Special Tag Ethertype */
-+//    XRX200_FDMA_VTETYPE,           /* VLAN Tag EthertypeControl Register */
-+//    XRX200_FDMA_VTETYPE_ETYPE,     /* VLAN Tag Ethertype */
-+//    XRX200_FDMA_STAT_0,            /* FDMA Status Register0 */
-+//    XRX200_FDMA_STAT_0_FSMS,       /* FSM states status */
-+//    XRX200_FDMA_IER,               /* Fetch DMA Global InterruptEnable Register */
-+//    XRX200_FDMA_IER_PCKD,          /* Packet Drop Interrupt Enable */
-+//    XRX200_FDMA_IER_PCKR,          /* Packet Ready Interrupt Enable */
-+//    XRX200_FDMA_IER_PCKT,          /* Packet Sent Interrupt Enable */
-+//    XRX200_FDMA_ISR,               /* Fetch DMA Global InterruptStatus Register */
-+//    XRX200_FDMA_ISR_PCKTD,         /* Packet Drop */
-+//    XRX200_FDMA_ISR_PCKR,          /* Packet is Ready for Transmission */
-+//    XRX200_FDMA_ISR_PCKT,          /* Packet Sent Event */
-+//    XRX200_FDMA_PCTRL,             /* Ethernet SwitchFetch DMA Port Control Register */
-+//    XRX200_FDMA_PCTRL_VLANMOD,     /* VLAN Modification Enable */
-+//    XRX200_FDMA_PCTRL_DSCPRM,      /* DSCP Re-marking Enable */
-+//    XRX200_FDMA_PCTRL_STEN,        /* Special Tag Insertion Enable */
-+//    XRX200_FDMA_PCTRL_EN,          /* FDMA Port Enable */
-+//    XRX200_FDMA_PRIO,              /* Ethernet SwitchFetch DMA Port Priority Register */
-+//    XRX200_FDMA_PRIO_PRIO,         /* FDMA PRIO */
-+//    XRX200_FDMA_PSTAT0,            /* Ethernet SwitchFetch DMA Port Status Register 0 */
-+//    XRX200_FDMA_PSTAT0_PKT_AVAIL,  /* Port Egress Packet Available */
-+//    XRX200_FDMA_PSTAT0_POK,        /* Port Status OK */
-+//    XRX200_FDMA_PSTAT0_PSEG,       /* Port Egress Segment Count */
-+//    XRX200_FDMA_PSTAT1_HDR,        /* Ethernet SwitchFetch DMA Port Status Register 1 */
-+//    XRX200_FDMA_PSTAT1_HDR_PTR,    /* Header Pointer */
-+//    XRX200_FDMA_TSTAMP0,           /* Egress TimeStamp Register 0 */
-+//    XRX200_FDMA_TSTAMP0_TSTL,      /* Time Stamp [15:0] */
-+//    XRX200_FDMA_TSTAMP1,           /* Egress TimeStamp Register 1 */
-+//    XRX200_FDMA_TSTAMP1_TSTH,      /* Time Stamp [31:16] */
-+//    XRX200_SDMA_CTRL,              /* Ethernet Switch StoreDMA Control Register */
-+//    XRX200_SDMA_CTRL_TSTEN,        /* Time Stamp Enable */
-+//    XRX200_SDMA_FCTHR1,            /* SDMA Flow Control Threshold1 Register */
-+//    XRX200_SDMA_FCTHR1_THR1,       /* Threshold 1 */
-+//    XRX200_SDMA_FCTHR2,            /* SDMA Flow Control Threshold2 Register */
-+//    XRX200_SDMA_FCTHR2_THR2,       /* Threshold 2 */
-+//    XRX200_SDMA_FCTHR3,            /* SDMA Flow Control Threshold3 Register */
-+//    XRX200_SDMA_FCTHR3_THR3,       /* Threshold 3 */
-+//    XRX200_SDMA_FCTHR4,            /* SDMA Flow Control Threshold4 Register */
-+//    XRX200_SDMA_FCTHR4_THR4,       /* Threshold 4 */
-+//    XRX200_SDMA_FCTHR5,            /* SDMA Flow Control Threshold5 Register */
-+//    XRX200_SDMA_FCTHR5_THR5,       /* Threshold 5 */
-+//    XRX200_SDMA_FCTHR6,            /* SDMA Flow Control Threshold6 Register */
-+//    XRX200_SDMA_FCTHR6_THR6,       /* Threshold 6 */
-+//    XRX200_SDMA_FCTHR7,            /* SDMA Flow Control Threshold7 Register */
-+//    XRX200_SDMA_FCTHR7_THR7,       /* Threshold 7 */
-+//    XRX200_SDMA_STAT_0,            /* SDMA Status Register0 */
-+//    XRX200_SDMA_STAT_0_BPS_FILL,   /* Back Pressure Status */
-+//    XRX200_SDMA_STAT_0_BPS_PNT,    /* Back Pressure Status */
-+//    XRX200_SDMA_STAT_0_DROP,       /* Back Pressure Status */
-+//    XRX200_SDMA_STAT_1,            /* SDMA Status Register1 */
-+//    XRX200_SDMA_STAT_1_FILL,       /* Buffer Filling Level */
-+//    XRX200_SDMA_STAT_2,            /* SDMA Status Register2 */
-+//    XRX200_SDMA_STAT_2_FSMS,       /* FSM states status */
-+//    XRX200_SDMA_IER,               /* SDMA Interrupt Enable Register */
-+//    XRX200_SDMA_IER_BPEX,          /* Buffer Pointers Exceeded */
-+//    XRX200_SDMA_IER_BFULL,         /* Buffer Full */
-+//    XRX200_SDMA_IER_FERR,          /* Frame Error */
-+//    XRX200_SDMA_IER_FRX,           /* Frame Received Successfully */
-+//    XRX200_SDMA_ISR,               /* SDMA Interrupt Status Register */
-+//    XRX200_SDMA_ISR_BPEX,          /* Packet Descriptors Exceeded */
-+//    XRX200_SDMA_ISR_BFULL,         /* Buffer Full */
-+//    XRX200_SDMA_ISR_FERR,          /* Frame Error */
-+//    XRX200_SDMA_ISR_FRX,           /* Frame Received Successfully */
-+//    XRX200_SDMA_PCTRL,             /* Ethernet SwitchStore DMA Port Control Register */
-+//    XRX200_SDMA_PCTRL_DTHR,        /* Drop Threshold Selection */
-+//    XRX200_SDMA_PCTRL_PTHR,        /* Pause Threshold Selection */
-+//    XRX200_SDMA_PCTRL_PHYEFWD,     /* Forward PHY Error Frames */
-+//    XRX200_SDMA_PCTRL_ALGFWD,      /* Forward Alignment Error Frames */
-+//    XRX200_SDMA_PCTRL_LENFWD,      /* Forward Length Errored Frames */
-+//    XRX200_SDMA_PCTRL_OSFWD,       /* Forward Oversized Frames */
-+//    XRX200_SDMA_PCTRL_USFWD,       /* Forward Undersized Frames */
-+//    XRX200_SDMA_PCTRL_FCSIGN,      /* Ignore FCS Errors */
-+//    XRX200_SDMA_PCTRL_FCSFWD,      /* Forward FCS Errored Frames */
-+//    XRX200_SDMA_PCTRL_PAUFWD,      /* Pause Frame Forwarding */
-+//    XRX200_SDMA_PCTRL_MFCEN,       /* Metering Flow Control Enable */
-+//    XRX200_SDMA_PCTRL_FCEN,        /* Flow Control Enable */
-+//    XRX200_SDMA_PCTRL_PEN,         /* Port Enable */
-+//    XRX200_SDMA_PRIO,              /* Ethernet SwitchStore DMA Port Priority Register */
-+//    XRX200_SDMA_PRIO_PRIO,         /* SDMA PRIO */
-+//    XRX200_SDMA_PSTAT0_HDR,        /* Ethernet SwitchStore DMA Port Status Register 0 */
-+//    XRX200_SDMA_PSTAT0_HDR_PTR,    /* Port Ingress Queue Header Pointer */
-+//    XRX200_SDMA_PSTAT1,            /* Ethernet SwitchStore DMA Port Status Register 1 */
-+//    XRX200_SDMA_PSTAT1_PPKT,       /* Port Ingress Packet Count */
-+//    XRX200_SDMA_TSTAMP0,           /* Ingress TimeStamp Register 0 */
-+//    XRX200_SDMA_TSTAMP0_TSTL,      /* Time Stamp [15:0] */
-+//    XRX200_SDMA_TSTAMP1,           /* Ingress TimeStamp Register 1 */
-+//    XRX200_SDMA_TSTAMP1_TSTH,      /* Time Stamp [31:16] */
-+};
-+
-+
-+struct xrx200sw_reg {
-+      int offset;
-+      int shift;
-+      int size;
-+      int mult;
-+} xrx200sw_reg[] = {
-+//    offeset      shift    size      mult
-+//    {0x0000,         0,     16,     0x00}, /* XRX200_ETHSW_SWRES             Ethernet Switch ResetControl Register */
-+//    {0x0000,         1,      1,     0x00}, /* XRX200_ETHSW_SWRES_R1          Hardware Reset */
-+//    {0x0000,         0,      1,     0x00}, /* XRX200_ETHSW_SWRES_R0          Register Configuration */
-+//    {0x0004,         0,     16,     0x00}, /* XRX200_ETHSW_CLK_MAC_GAT       Ethernet Switch Clock ControlRegister  */
-+//    {0x0004,        12,      4,     0x00}, /* XRX200_ETHSW_CLK_EXP_SLEEP     Exponent to put system into sleep */
-+//    {0x0004,         8,      4,     0x00}, /* XRX200_ETHSW_CLK_EXP_WAKE      Exponent to wake up system */
-+//    {0x0004,         7,      1,     0x00}, /* XRX200_ETHSW_CLK_CLK2_EN       CLK2 Input for MAC */
-+//    {0x0004,         6,      1,     0x00}, /* XRX200_ETHSW_CLK_EXT_DIV_EN    External Clock Divider Enable */
-+//    {0x0004,         5,      1,     0x00}, /* XRX200_ETHSW_CLK_RAM_DBG_EN    Clock Gating Enable */
-+//    {0x0004,         4,      1,     0x00}, /* XRX200_ETHSW_CLK_REG_GAT_EN    Clock Gating Enable */
-+//    {0x0004,         3,      1,     0x00}, /* XRX200_ETHSW_CLK_GAT_EN        Clock Gating Enable */
-+//    {0x0004,         2,      1,     0x00}, /* XRX200_ETHSW_CLK_MAC_GAT_EN    Clock Gating Enable */
-+//    {0x0008,         0,     16,     0x00}, /* XRX200_ETHSW_DBG_STEP          Ethernet Switch Debug ControlRegister */
-+//    {0x0008,        12,      4,     0x00}, /* XRX200_ETHSW_DBG_CLK_SEL       Trigger Enable */
-+//    {0x0008,        11,      1,     0x00}, /* XRX200_ETHSW_DBG_MON_EN        Monitoring Enable */
-+//    {0x0008,         9,      2,     0x00}, /* XRX200_ETHSW_DBG_TRIG_EN       Trigger Enable */
-+//    {0x0008,         8,      1,     0x00}, /* XRX200_ETHSW_DBG_MODE          Debug Mode */
-+//    {0x0008,         0,      8,     0x00}, /* XRX200_ETHSW_DBG_STEP_TIME     Clock Step Size */
-+//    {0x000C,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_MODE          Ethernet Switch SharedSegment Buffer Mode Register */
-+//    {0x000C,         2,      4,     0x00}, /* XRX200_ETHSW_SSB_MODE_ADDE     Memory Address */
-+//    {0x000C,         0,      2,     0x00}, /* XRX200_ETHSW_SSB_MODE_MODE     Memory Access Mode */
-+//    {0x0010,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_ADDR          Ethernet Switch SharedSegment Buffer Address Register */
-+//    {0x0010,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_ADDR_ADDE     Memory Address */
-+//    {0x0014,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_DATA          Ethernet Switch SharedSegment Buffer Data Register */
-+//    {0x0014,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_DATA_DATA     Data Value */
-+//    {0x0018,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_0             Ethernet Switch CapabilityRegister 0 */
-+//    {0x0018,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_0_SPEED       Clock frequency */
-+//    {0x001C,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_1             Ethernet Switch CapabilityRegister 1 */
-+//    {0x001C,        15,      1,     0x00}, /* XRX200_ETHSW_CAP_1_GMAC        MAC operation mode */
-+//    {0x001C,         8,      7,     0x00}, /* XRX200_ETHSW_CAP_1_QUEUE       Number of queues */
-+//    {0x001C,         4,      4,     0x00}, /* XRX200_ETHSW_CAP_1_VPORTS      Number of virtual ports */
-+//    {0x001C,         0,      4,     0x00}, /* XRX200_ETHSW_CAP_1_PPORTS      Number of physical ports */
-+//    {0x0020,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_2             Ethernet Switch CapabilityRegister 2 */
-+//    {0x0020,         0,     11,     0x00}, /* XRX200_ETHSW_CAP_2_PACKETS     Number of packets */
-+//    {0x0024,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_3             Ethernet Switch CapabilityRegister 3 */
-+//    {0x0024,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_3_METERS      Number of traffic meters */
-+//    {0x0024,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_3_SHAPERS     Number of traffic shapers */
-+//    {0x0028,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_4             Ethernet Switch CapabilityRegister 4 */
-+//    {0x0028,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_4_PPPOE       PPPoE table size */
-+//    {0x0028,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_4_VLAN        Active VLAN table size */
-+//    {0x002C,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_5             Ethernet Switch CapabilityRegister 5 */
-+//    {0x002C,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_5_IPPLEN      IP packet length table size */
-+//    {0x002C,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_5_PROT        Protocol table size */
-+//    {0x0030,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_6             Ethernet Switch CapabilityRegister 6 */
-+//    {0x0030,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_6_MACDASA     MAC DA/SA table size */
-+//    {0x0030,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_6_APPL        Application table size */
-+//    {0x0034,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_7             Ethernet Switch CapabilityRegister 7 */
-+//    {0x0034,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_7_IPDASAM     IP DA/SA MSB table size */
-+//    {0x0034,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_7_IPDASAL     IP DA/SA LSB table size */
-+//    {0x0038,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_8             Ethernet Switch CapabilityRegister 8 */
-+//    {0x0038,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_8_MCAST       Multicast table size */
-+//    {0x003C,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_9             Ethernet Switch CapabilityRegister 9 */
-+//    {0x003C,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_9_FLAGG       Flow Aggregation table size */
-+//    {0x0040,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_10            Ethernet Switch CapabilityRegister 10 */
-+//    {0x0040,         0,     13,     0x00}, /* XRX200_ETHSW_CAP_10_MACBT      MAC bridging table size */
-+//    {0x0044,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_11            Ethernet Switch CapabilityRegister 11 */
-+//    {0x0044,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_11_BSIZEL     Packet buffer size (lower part, in byte) */
-+//    {0x0048,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_12            Ethernet Switch CapabilityRegister 12 */
-+//    {0x0048,         0,      3,     0x00}, /* XRX200_ETHSW_CAP_12_BSIZEH     Packet buffer size (higher part, in byte) */
-+//    {0x004C,         0,     16,     0x00}, /* XRX200_ETHSW_VERSION_REV       Ethernet Switch VersionRegister */
-+//    {0x004C,         8,      8,     0x00}, /* XRX200_ETHSW_VERSION_MOD_ID    Module Identification */
-+//    {0x004C,         0,      8,     0x00}, /* XRX200_ETHSW_VERSION_REV_ID    Hardware Revision Identification */
-+//    {0x0050,         0,     16,     0x00}, /* XRX200_ETHSW_IER               Interrupt Enable Register */
-+//    {0x0050,         4,      1,     0x00}, /* XRX200_ETHSW_IER_FDMAIE        Fetch DMA Interrupt Enable */
-+//    {0x0050,         3,      1,     0x00}, /* XRX200_ETHSW_IER_SDMAIE        Store DMA Interrupt Enable */
-+//    {0x0050,         2,      1,     0x00}, /* XRX200_ETHSW_IER_MACIE         Ethernet MAC Interrupt Enable */
-+//    {0x0050,         1,      1,     0x00}, /* XRX200_ETHSW_IER_PCEIE         Parser and Classification Engine Interrupt Enable */
-+//    {0x0050,         0,      1,     0x00}, /* XRX200_ETHSW_IER_BMIE          Buffer Manager Interrupt Enable */
-+//    {0x0054,         0,     16,     0x00}, /* XRX200_ETHSW_ISR               Interrupt Status Register */
-+//    {0x0054,         4,      1,     0x00}, /* XRX200_ETHSW_ISR_FDMAINT       Fetch DMA Interrupt */
-+//    {0x0054,         3,      1,     0x00}, /* XRX200_ETHSW_ISR_SDMAINT       Store DMA Interrupt */
-+//    {0x0054,         2,      1,     0x00}, /* XRX200_ETHSW_ISR_MACINT        Ethernet MAC Interrupt */
-+//    {0x0054,         1,      1,     0x00}, /* XRX200_ETHSW_ISR_PCEINT        Parser and Classification Engine Interrupt */
-+//    {0x0054,         0,      1,     0x00}, /* XRX200_ETHSW_ISR_BMINT         Buffer Manager Interrupt */
-+//    {0x0058,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_0           Ethernet Switch SpareCells 0 */
-+//    {0x0058,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_0_SPARE     SPARE0  */
-+//    {0x005C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_1           Ethernet Switch SpareCells 1 */
-+//    {0x005C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_1_SPARE     SPARE1  */
-+//    {0x0060,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_2           Ethernet Switch SpareCells 2 */
-+//    {0x0060,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_2_SPARE     SPARE2  */
-+//    {0x0064,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_3           Ethernet Switch SpareCells 3 */
-+//    {0x0064,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_3_SPARE     SPARE3  */
-+//    {0x0068,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_4           Ethernet Switch SpareCells 4 */
-+//    {0x0068,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_4_SPARE     SPARE4  */
-+//    {0x006C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_5           Ethernet Switch SpareCells 5 */
-+//    {0x006C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_5_SPARE     SPARE5  */
-+//    {0x0070,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_6           Ethernet Switch SpareCells 6 */
-+//    {0x0070,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_6_SPARE     SPARE6  */
-+//    {0x0074,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_7           Ethernet Switch SpareCells 7 */
-+//    {0x0074,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_7_SPARE     SPARE7  */
-+//    {0x0078,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_8           Ethernet Switch SpareCells 8 */
-+//    {0x0078,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_8_SPARE     SPARE8  */
-+//    {0x007C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_9           Ethernet Switch SpareCells 9 */
-+//    {0x007C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_9_SPARE     SPARE9  */
-+//    {0x0080,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_10          Ethernet Switch SpareCells 10 */
-+//    {0x0080,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_10_SPARE    SPARE10  */
-+//    {0x0084,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_11          Ethernet Switch SpareCells 11 */
-+//    {0x0084,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_11_SPARE    SPARE11  */
-+//    {0x0088,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_12          Ethernet Switch SpareCells 12 */
-+//    {0x0088,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_12_SPARE    SPARE12  */
-+//    {0x008C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_13          Ethernet Switch SpareCells 13 */
-+//    {0x008C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_13_SPARE    SPARE13  */
-+//    {0x0090,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_14          Ethernet Switch SpareCells 14 */
-+//    {0x0090,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_14_SPARE    SPARE14  */
-+//    {0x0094,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_15          Ethernet Switch SpareCells 15 */
-+//    {0x0094,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_15_SPARE    SPARE15  */
-+//    {0x0100,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_3            RAM Value Register 3 */
-+//    {0x0100,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_3_VAL3       Data value [15:0] */
-+//    {0x0104,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_2            RAM Value Register 2 */
-+//    {0x0104,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_2_VAL2       Data value [15:0] */
-+//    {0x0108,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_1            RAM Value Register 1 */
-+//    {0x0108,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_1_VAL1       Data value [15:0] */
-+//    {0x010C,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_0            RAM Value Register 0 */
-+//    {0x010C,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_0_VAL0       Data value [15:0] */
-+//    {0x0110,         0,     16,     0x00}, /* XRX200_BM_RAM_ADDR             RAM Address Register */
-+//    {0x0110,         0,     11,     0x00}, /* XRX200_BM_RAM_ADDR_ADDR        RAM Address */
-+//    {0x0114,         0,     16,     0x00}, /* XRX200_BM_RAM_CTRL             RAM Access Control Register */
-+//    {0x0114,        15,      1,     0x00}, /* XRX200_BM_RAM_CTRL_BAS         Access Busy/Access Start */
-+//    {0x0114,         5,      1,     0x00}, /* XRX200_BM_RAM_CTRL_OPMOD       Lookup Table Access Operation Mode */
-+//    {0x0114,         0,      5,     0x00}, /* XRX200_BM_RAM_CTRL_ADDR        Address for RAM selection */
-+//    {0x0118,         0,     16,     0x00}, /* XRX200_BM_FSQM_GCTRL           Free Segment Queue ManagerGlobal Control Register */
-+//    {0x0118,         0,     10,     0x00}, /* XRX200_BM_FSQM_GCTRL_SEGNUM    Maximum Segment Number */
-+//    {0x011C,         0,     16,     0x00}, /* XRX200_BM_CONS_SEG             Number of Consumed SegmentsRegister */
-+//    {0x011C,         0,     10,     0x00}, /* XRX200_BM_CONS_SEG_FSEG        Number of Consumed Segments */
-+//    {0x0120,         0,     16,     0x00}, /* XRX200_BM_CONS_PKT             Number of Consumed PacketPointers Register */
-+//    {0x0120,         0,     11,     0x00}, /* XRX200_BM_CONS_PKT_FQP         Number of Consumed Packet Pointers */
-+//    {0x0124,         0,     16,     0x00}, /* XRX200_BM_GCTRL_F              Buffer Manager Global ControlRegister 0 */
-+//    {0x0124,        13,      1,     0x00}, /* XRX200_BM_GCTRL_BM_STA         Buffer Manager Initialization Status Bit */
-+//    {0x0124,        12,      1,     0x00}, /* XRX200_BM_GCTRL_SAT            RMON Counter Update Mode */
-+//    {0x0124,        11,      1,     0x00}, /* XRX200_BM_GCTRL_FR_RBC         Freeze RMON RX Bad Byte 64 Bit Counter */
-+//    {0x0124,        10,      1,     0x00}, /* XRX200_BM_GCTRL_FR_RGC         Freeze RMON RX Good Byte 64 Bit Counter */
-+//    {0x0124,         9,      1,     0x00}, /* XRX200_BM_GCTRL_FR_TGC         Freeze RMON TX Good Byte 64 Bit Counter */
-+//    {0x0124,         8,      1,     0x00}, /* XRX200_BM_GCTRL_I_FIN          RAM initialization finished */
-+//    {0x0124,         7,      1,     0x00}, /* XRX200_BM_GCTRL_CX_INI         PQM Context RAM initialization */
-+//    {0x0124,         6,      1,     0x00}, /* XRX200_BM_GCTRL_FP_INI         FPQM RAM initialization */
-+//    {0x0124,         5,      1,     0x00}, /* XRX200_BM_GCTRL_FS_INI         FSQM RAM initialization */
-+//    {0x0124,         4,      1,     0x00}, /* XRX200_BM_GCTRL_R_SRES         Software Reset for RMON */
-+//    {0x0124,         3,      1,     0x00}, /* XRX200_BM_GCTRL_S_SRES         Software Reset for Scheduler */
-+//    {0x0124,         2,      1,     0x00}, /* XRX200_BM_GCTRL_A_SRES         Software Reset for AVG */
-+//    {0x0124,         1,      1,     0x00}, /* XRX200_BM_GCTRL_P_SRES         Software Reset for PQM */
-+//    {0x0124,         0,      1,     0x00}, /* XRX200_BM_GCTRL_F_SRES         Software Reset for FSQM */
-+//    {0x0128,         0,     16,     0x00}, /* XRX200_BM_QUEUE_GCTRL          Queue Manager GlobalControl Register 0 */
-+//    {0x0128,        10,      1,     0x00}, /* XRX200_BM_QUEUE_GCTRL_GL_MOD   WRED Mode Signal */
-+//    {0x0128,         7,      3,     0x00}, /* XRX200_BM_QUEUE_GCTRL_AQUI     Average Queue Update Interval */
-+//    {0x0128,         3,      4,     0x00}, /* XRX200_BM_QUEUE_GCTRL_AQWF     Average Queue Weight Factor */
-+//    {0x0128,         2,      1,     0x00}, /* XRX200_BM_QUEUE_GCTRL_QAVGEN   Queue Average Calculation Enable */
-+//    {0x0128,         0,      2,     0x00}, /* XRX200_BM_QUEUE_GCTRL_DPROB    Drop Probability Profile */
-+//    {0x012C,         0,     16,     0x00}, /* XRX200_BM_WRED_RTH_0           WRED Red Threshold Register0 */
-+//    {0x012C,         0,     10,     0x00}, /* XRX200_BM_WRED_RTH_0_MINTH     Minimum Threshold */
-+//    {0x0130,         0,     16,     0x00}, /* XRX200_BM_WRED_RTH_1           WRED Red Threshold Register1 */
-+//    {0x0130,         0,     10,     0x00}, /* XRX200_BM_WRED_RTH_1_MAXTH     Maximum Threshold */
-+//    {0x0134,         0,     16,     0x00}, /* XRX200_BM_WRED_YTH_0           WRED Yellow ThresholdRegister 0 */
-+//    {0x0134,         0,     10,     0x00}, /* XRX200_BM_WRED_YTH_0_MINTH     Minimum Threshold */
-+//    {0x0138,         0,     16,     0x00}, /* XRX200_BM_WRED_YTH_1           WRED Yellow ThresholdRegister 1 */
-+//    {0x0138,         0,     10,     0x00}, /* XRX200_BM_WRED_YTH_1_MAXTH     Maximum Threshold */
-+//    {0x013C,         0,     16,     0x00}, /* XRX200_BM_WRED_GTH_0           WRED Green ThresholdRegister 0 */
-+//    {0x013C,         0,     10,     0x00}, /* XRX200_BM_WRED_GTH_0_MINTH     Minimum Threshold */
-+//    {0x0140,         0,     16,     0x00}, /* XRX200_BM_WRED_GTH_1           WRED Green ThresholdRegister 1 */
-+//    {0x0140,         0,     10,     0x00}, /* XRX200_BM_WRED_GTH_1_MAXTH     Maximum Threshold */
-+//    {0x0144,         0,     16,     0x00}, /* XRX200_BM_DROP_GTH_0_THR       Drop Threshold ConfigurationRegister 0 */
-+//    {0x0144,         0,     11,     0x00}, /* XRX200_BM_DROP_GTH_0_THR_FQ    Threshold for frames marked red */
-+//    {0x0148,         0,     16,     0x00}, /* XRX200_BM_DROP_GTH_1_THY       Drop Threshold ConfigurationRegister 1 */
-+//    {0x0148,         0,     11,     0x00}, /* XRX200_BM_DROP_GTH_1_THY_FQ    Threshold for frames marked yellow */
-+//    {0x014C,         0,     16,     0x00}, /* XRX200_BM_DROP_GTH_2_THG       Drop Threshold ConfigurationRegister 2 */
-+//    {0x014C,         0,     11,     0x00}, /* XRX200_BM_DROP_GTH_2_THG_FQ    Threshold for frames marked green */
-+//    {0x0150,         0,     16,     0x00}, /* XRX200_BM_IER                  Buffer Manager Global InterruptEnable Register */
-+//    {0x0150,         7,      1,     0x00}, /* XRX200_BM_IER_CNT4             Counter Group 4 (RMON-CLASSIFICATION) Interrupt Enable */
-+//    {0x0150,         6,      1,     0x00}, /* XRX200_BM_IER_CNT3             Counter Group 3 (RMON-PQM) Interrupt Enable */
-+//    {0x0150,         5,      1,     0x00}, /* XRX200_BM_IER_CNT2             Counter Group 2 (RMON-SCHEDULER) Interrupt Enable */
-+//    {0x0150,         4,      1,     0x00}, /* XRX200_BM_IER_CNT1             Counter Group 1 (RMON-QFETCH) Interrupt Enable */
-+//    {0x0150,         3,      1,     0x00}, /* XRX200_BM_IER_CNT0             Counter Group 0 (RMON-QSTOR) Interrupt Enable */
-+//    {0x0150,         2,      1,     0x00}, /* XRX200_BM_IER_DEQ              PQM dequeue Interrupt Enable */
-+//    {0x0150,         1,      1,     0x00}, /* XRX200_BM_IER_ENQ              PQM Enqueue Interrupt Enable */
-+//    {0x0150,         0,      1,     0x00}, /* XRX200_BM_IER_FSQM             Buffer Empty Interrupt Enable */
-+//    {0x0154,         0,     16,     0x00}, /* XRX200_BM_ISR                  Buffer Manager Global InterruptStatus Register */
-+//    {0x0154,         7,      1,     0x00}, /* XRX200_BM_ISR_CNT4             Counter Group 4 Interrupt */
-+//    {0x0154,         6,      1,     0x00}, /* XRX200_BM_ISR_CNT3             Counter Group 3 Interrupt */
-+//    {0x0154,         5,      1,     0x00}, /* XRX200_BM_ISR_CNT2             Counter Group 2 Interrupt */
-+//    {0x0154,         4,      1,     0x00}, /* XRX200_BM_ISR_CNT1             Counter Group 1 Interrupt */
-+//    {0x0154,         3,      1,     0x00}, /* XRX200_BM_ISR_CNT0             Counter Group 0 Interrupt */
-+//    {0x0154,         2,      1,     0x00}, /* XRX200_BM_ISR_DEQ              PQM dequeue Interrupt Enable */
-+//    {0x0154,         1,      1,     0x00}, /* XRX200_BM_ISR_ENQ              PQM Enqueue Interrupt */
-+//    {0x0154,         0,      1,     0x00}, /* XRX200_BM_ISR_FSQM             Buffer Empty Interrupt */
-+//    {0x0158,         0,     16,     0x00}, /* XRX200_BM_CISEL                Buffer Manager RMON CounterInterrupt Select Register */
-+//    {0x0158,         0,      3,     0x00}, /* XRX200_BM_CISEL_PORT           Port Number */
-+//    {0x015C,         0,     16,     0x00}, /* XRX200_BM_DEBUG_CTRL_DBG       Debug Control Register */
-+//    {0x015C,         0,      8,     0x00}, /* XRX200_BM_DEBUG_CTRL_DBG_SEL   Select Signal for Debug Multiplexer */
-+//    {0x0160,         0,     16,     0x00}, /* XRX200_BM_DEBUG_VAL_DBG        Debug Value Register */
-+//    {0x0160,         0,     16,     0x00}, /* XRX200_BM_DEBUG_VAL_DBG_DAT    Debug Data Value */
-+//    {0x0200,         0,     16,     0x08}, /* XRX200_BM_PCFG                 Buffer Manager PortConfiguration Register */
-+//    {0x0200,         0,      1,     0x08}, /* XRX200_BM_PCFG_CNTEN           RMON Counter Enable */
-+//    {0x0204,         0,     16,     0x08}, /* XRX200_BM_RMON_CTRL_RAM1       Buffer ManagerRMON Control Register */
-+//    {0x0204,         1,      1,     0x08}, /* XRX200_BM_RMON_CTRL_RAM2_RES   Software Reset for RMON RAM2 */
-+//    {0x0204,         0,      1,     0x08}, /* XRX200_BM_RMON_CTRL_RAM1_RES   Software Reset for RMON RAM1 */
-+//    {0x0400,         0,     16,     0x08}, /* XRX200_PQM_DP                  Packet Queue ManagerDrop Probability Register */
-+//    {0x0400,         0,      2,     0x08}, /* XRX200_PQM_DP_DPROB            Drop Probability Profile */
-+//    {0x0404,         0,     16,     0x08}, /* XRX200_PQM_RS                  Packet Queue ManagerRate Shaper Assignment Register */
-+//    {0x0404,        15,      1,     0x08}, /* XRX200_PQM_RS_EN2              Rate Shaper 2 Enable */
-+//    {0x0404,         8,      6,     0x08}, /* XRX200_PQM_RS_RS2              Rate Shaper 2 */
-+//    {0x0404,         7,      1,     0x08}, /* XRX200_PQM_RS_EN1              Rate Shaper 1 Enable */
-+//    {0x0404,         0,      6,     0x08}, /* XRX200_PQM_RS_RS1              Rate Shaper 1 */
-+//    {0x0500,         0,     16,     0x14}, /* XRX200_RS_CTRL                 Rate Shaper ControlRegister */
-+//    {0x0500,         0,      1,     0x14}, /* XRX200_RS_CTRL_RSEN            Rate Shaper Enable */
-+//    {0x0504,         0,     16,     0x14}, /* XRX200_RS_CBS                  Rate Shaper CommittedBurst Size Register */
-+//    {0x0504,         0,     10,     0x14}, /* XRX200_RS_CBS_CBS              Committed Burst Size */
-+//    {0x0508,         0,     16,     0x14}, /* XRX200_RS_IBS                  Rate Shaper InstantaneousBurst Size Register */
-+//    {0x0508,         0,      2,     0x14}, /* XRX200_RS_IBS_IBS              Instantaneous Burst Size */
-+//    {0x050C,         0,     16,     0x14}, /* XRX200_RS_CIR_EXP              Rate Shaper RateExponent Register */
-+//    {0x050C,         0,      4,     0x14}, /* XRX200_RS_CIR_EXP_EXP          Exponent */
-+//    {0x0510,         0,     16,     0x14}, /* XRX200_RS_CIR_MANT             Rate Shaper RateMantissa Register */
-+//    {0x0510,         0,     10,     0x14}, /* XRX200_RS_CIR_MANT_MANT        Mantissa */
-+      {0x1100,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_7           Table Key Data 7 */
-+//    {0x1100,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_7_KEY7      Key Value[15:0] */
-+      {0x1104,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_6           Table Key Data 6 */
-+//    {0x1104,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_6_KEY6      Key Value[15:0] */
-+      {0x1108,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_5           Table Key Data 5 */
-+//    {0x1108,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_5_KEY5      Key Value[15:0] */
-+      {0x110C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_4           Table Key Data 4 */
-+//    {0x110C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_4_KEY4      Key Value[15:0] */
-+      {0x1110,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_3           Table Key Data 3 */
-+//    {0x1110,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_3_KEY3      Key Value[15:0] */
-+      {0x1114,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_2           Table Key Data 2 */
-+//    {0x1114,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_2_KEY2      Key Value[15:0] */
-+      {0x1118,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_1           Table Key Data 1 */
-+//    {0x1118,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_1_KEY1      Key Value[31:16] */
-+      {0x111C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_0           Table Key Data 0 */
-+//    {0x111C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_0_KEY0      Key Value[15:0] */
-+      {0x1120,         0,     16,     0x00}, /* XRX200_PCE_TBL_MASK_0          Table Mask Write Register0 */
-+//    {0x1120,         0,     16,     0x00}, /* XRX200_PCE_TBL_MASK_0_MASK0    Mask Pattern [15:0] */
-+      {0x1124,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_4           Table Value Register4 */
-+//    {0x1124,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_4_VAL4      Data value [15:0] */
-+      {0x1128,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_3           Table Value Register3 */
-+//    {0x1128,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_3_VAL3      Data value [15:0] */
-+      {0x112C,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_2           Table Value Register2 */
-+//    {0x112C,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_2_VAL2      Data value [15:0] */
-+      {0x1130,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_1           Table Value Register1 */
-+//    {0x1130,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_1_VAL1      Data value [15:0] */
-+      {0x1134,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_0           Table Value Register0 */
-+//    {0x1134,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_0_VAL0      Data value [15:0] */
-+//    {0x1138,         0,     16,     0x00}, /* XRX200_PCE_TBL_ADDR            Table Entry AddressRegister */
-+      {0x1138,         0,     11,     0x00}, /* XRX200_PCE_TBL_ADDR_ADDR       Table Address */
-+//    {0x113C,         0,     16,     0x00}, /* XRX200_PCE_TBL_CTRL            Table Access ControlRegister */
-+      {0x113C,        15,      1,     0x00}, /* XRX200_PCE_TBL_CTRL_BAS        Access Busy/Access Start */
-+      {0x113C,        13,      1,     0x00}, /* XRX200_PCE_TBL_CTRL_TYPE       Lookup Entry Type */
-+      {0x113C,        12,      1,     0x00}, /* XRX200_PCE_TBL_CTRL_VLD        Lookup Entry Valid */
-+      {0x113C,         7,      4,     0x00}, /* XRX200_PCE_TBL_CTRL_GMAP       Group Map */
-+      {0x113C,         5,      2,     0x00}, /* XRX200_PCE_TBL_CTRL_OPMOD      Lookup Table Access Operation Mode */
-+      {0x113C,         0,      5,     0x00}, /* XRX200_PCE_TBL_CTRL_ADDR       Lookup Table Address */
-+//    {0x1140,         0,     16,     0x00}, /* XRX200_PCE_TBL_STAT            Table General StatusRegister */
-+//    {0x1140,         2,      1,     0x00}, /* XRX200_PCE_TBL_STAT_TBUSY      Table Access Busy */
-+//    {0x1140,         1,      1,     0x00}, /* XRX200_PCE_TBL_STAT_TEMPT      Table Empty */
-+//    {0x1140,         0,      1,     0x00}, /* XRX200_PCE_TBL_STAT_TFUL       Table Full */
-+//    {0x1144,         0,     16,     0x00}, /* XRX200_PCE_AGE_0               Aging Counter ConfigurationRegister 0 */
-+//    {0x1144,         0,      4,     0x00}, /* XRX200_PCE_AGE_0_EXP           Aging Counter Exponent Value  */
-+//    {0x1148,         0,     16,     0x00}, /* XRX200_PCE_AGE_1               Aging Counter ConfigurationRegister 1 */
-+//    {0x1148,         0,     16,     0x00}, /* XRX200_PCE_AGE_1_MANT          Aging Counter Mantissa Value  */
-+//    {0x114C,         0,     16,     0x00}, /* XRX200_PCE_PMAP_1              Port Map Register 1 */
-+//    {0x114C,         0,     16,     0x00}, /* XRX200_PCE_PMAP_1_MPMAP        Monitoring Port Map */
-+//    {0x1150,         0,     16,     0x00}, /* XRX200_PCE_PMAP_2              Port Map Register 2 */
-+//    {0x1150,         0,     16,     0x00}, /* XRX200_PCE_PMAP_2_DMCPMAP      Default Multicast Port Map */
-+//    {0x1154,         0,     16,     0x00}, /* XRX200_PCE_PMAP_3              Port Map Register 3 */
-+//    {0x1154,         0,     16,     0x00}, /* XRX200_PCE_PMAP_3_UUCMAP       Default Unknown Unicast Port Map */
-+//    {0x1158,         0,     16,     0x00}, /* XRX200_PCE_GCTRL_0             PCE Global Control Register0 */
-+//    {0x1158,        15,      1,     0x00}, /* XRX200_PCE_GCTRL_0_IGMP        IGMP Mode Selection */
-+      {0x1158,        14,      1,     0x00}, /* XRX200_PCE_GCTRL_0_VLAN        VLAN-aware Switching */
-+//    {0x1158,        13,      1,     0x00}, /* XRX200_PCE_GCTRL_0_NOPM        No Port Map Forwarding */
-+//    {0x1158,        12,      1,     0x00}, /* XRX200_PCE_GCTRL_0_SCONUC      Unknown Unicast Storm Control */
-+//    {0x1158,        11,      1,     0x00}, /* XRX200_PCE_GCTRL_0_SCONMC      Multicast Storm Control */
-+//    {0x1158,        10,      1,     0x00}, /* XRX200_PCE_GCTRL_0_SCONBC      Broadcast Storm Control */
-+//    {0x1158,         8,      2,     0x00}, /* XRX200_PCE_GCTRL_0_SCONMOD     Storm Control Mode */
-+//    {0x1158,         4,      4,     0x00}, /* XRX200_PCE_GCTRL_0_SCONMET     Storm Control Metering Instance */
-+//    {0x1158,         3,      1,     0x00}, /* XRX200_PCE_GCTRL_0_MC_VALID    Access Request */
-+//    {0x1158,         2,      1,     0x00}, /* XRX200_PCE_GCTRL_0_PLCKMOD     Port Lock Mode */
-+//    {0x1158,         1,      1,     0x00}, /* XRX200_PCE_GCTRL_0_PLIMMOD     MAC Address Learning Limitation Mode */
-+//    {0x1158,         0,      1,     0x00}, /* XRX200_PCE_GCTRL_0_MTFL        MAC Table Flushing */
-+//    {0x115C,         0,     16,     0x00}, /* XRX200_PCE_GCTRL_1             PCE Global Control Register1 */
-+//    {0x115C,         1,      1,     0x00}, /* XRX200_PCE_GCTRL_1_PCE_DIS     PCE Disable after currently processed packet */
-+//    {0x115C,         0,      1,     0x00}, /* XRX200_PCE_GCTRL_1_LRNMOD      MAC Address Learning Mode */
-+//    {0x1160,         0,     16,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL       Three-color MarkerGlobal Control Register */
-+//    {0x1160,         6,      3,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL_DPRED Re-marking Drop Precedence Red Encoding */
-+//    {0x1160,         3,      3,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL_DPYEL Re-marking Drop Precedence Yellow Encoding */
-+//    {0x1160,         0,      3,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL_DPGRN Re-marking Drop Precedence Green Encoding */
-+//    {0x1164,         0,     16,     0x00}, /* XRX200_PCE_IGMP_CTRL           IGMP Control Register */
-+//    {0x1164,        15,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_FAGEEN    Force Aging of Table Entries Enable */
-+//    {0x1164,        14,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_FLEAVE    Fast Leave Enable */
-+//    {0x1164,        13,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_DMRTEN    Default Maximum Response Time Enable */
-+//    {0x1164,        12,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_JASUP     Join Aggregation Suppression Enable */
-+//    {0x1164,        11,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_REPSUP    Report Suppression Enable */
-+//    {0x1164,        10,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_SRPEN     Snooping of Router Port Enable */
-+//    {0x1164,         8,      2,     0x00}, /* XRX200_PCE_IGMP_CTRL_ROB       Robustness Variable */
-+//    {0x1164,         0,      8,     0x00}, /* XRX200_PCE_IGMP_CTRL_DMRT      IGMP Default Maximum Response Time */
-+//    {0x1168,         0,     16,     0x00}, /* XRX200_PCE_IGMP_DRPM           IGMP Default RouterPort Map Register */
-+//    {0x1168,         0,     16,     0x00}, /* XRX200_PCE_IGMP_DRPM_DRPM      IGMP Default Router Port Map */
-+//    {0x116C,         0,     16,     0x00}, /* XRX200_PCE_IGMP_AGE_0          IGMP Aging Register0 */
-+//    {0x116C,         3,      8,     0x00}, /* XRX200_PCE_IGMP_AGE_0_MANT     IGMP Group Aging Time Mantissa */
-+//    {0x116C,         0,      3,     0x00}, /* XRX200_PCE_IGMP_AGE_0_EXP      IGMP Group Aging Time Exponent */
-+//    {0x1170,         0,     16,     0x00}, /* XRX200_PCE_IGMP_AGE_1          IGMP Aging Register1 */
-+//    {0x1170,         0,     12,     0x00}, /* XRX200_PCE_IGMP_AGE_1_MANT     IGMP Router Port Aging Time Mantissa */
-+//    {0x1174,         0,     16,     0x00}, /* XRX200_PCE_IGMP_STAT           IGMP Status Register */
-+//    {0x1174,         0,     16,     0x00}, /* XRX200_PCE_IGMP_STAT_IGPM      IGMP Port Map */
-+//    {0x1178,         0,     16,     0x00}, /* XRX200_WOL_GLB_CTRL            Wake-on-LAN ControlRegister */
-+//    {0x1178,         0,      1,     0x00}, /* XRX200_WOL_GLB_CTRL_PASSEN     WoL Password Enable */
-+//    {0x117C,         0,     16,     0x00}, /* XRX200_WOL_DA_0                Wake-on-LAN DestinationAddress Register 0 */
-+//    {0x117C,         0,     16,     0x00}, /* XRX200_WOL_DA_0_DA0            WoL Destination Address [15:0] */
-+//    {0x1180,         0,     16,     0x00}, /* XRX200_WOL_DA_1                Wake-on-LAN DestinationAddress Register 1 */
-+//    {0x1180,         0,     16,     0x00}, /* XRX200_WOL_DA_1_DA1            WoL Destination Address [31:16] */
-+//    {0x1184,         0,     16,     0x00}, /* XRX200_WOL_DA_2                Wake-on-LAN DestinationAddress Register 2 */
-+//    {0x1184,         0,     16,     0x00}, /* XRX200_WOL_DA_2_DA2            WoL Destination Address [47:32] */
-+//    {0x1188,         0,     16,     0x00}, /* XRX200_WOL_PW_0                Wake-on-LAN Password Register0 */
-+//    {0x1188,         0,     16,     0x00}, /* XRX200_WOL_PW_0_PW0            WoL Password [15:0] */
-+//    {0x118C,         0,     16,     0x00}, /* XRX200_WOL_PW_1                Wake-on-LAN Password Register1 */
-+//    {0x118C,         0,     16,     0x00}, /* XRX200_WOL_PW_1_PW1            WoL Password [31:16] */
-+//    {0x1190,         0,     16,     0x00}, /* XRX200_WOL_PW_2                Wake-on-LAN Password Register2 */
-+//    {0x1190,         0,     16,     0x00}, /* XRX200_WOL_PW_2_PW2            WoL Password [47:32] */
-+//    {0x1194,         0,     16,     0x00}, /* XRX200_PCE_IER_0_PINT          Parser and ClassificationEngine Global Interrupt Enable Register 0 */
-+//    {0x1194,        15,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_15       Port Interrupt Enable */
-+//    {0x1194,        14,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_14       Port Interrupt Enable */
-+//    {0x1194,        13,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_13       Port Interrupt Enable */
-+//    {0x1194,        12,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_12       Port Interrupt Enable */
-+//    {0x1194,        11,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_11       Port Interrupt Enable */
-+//    {0x1194,        10,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_10       Port Interrupt Enable */
-+//    {0x1194,         9,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_9        Port Interrupt Enable */
-+//    {0x1194,         8,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_8        Port Interrupt Enable */
-+//    {0x1194,         7,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_7        Port Interrupt Enable */
-+//    {0x1194,         6,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_6        Port Interrupt Enable */
-+//    {0x1194,         5,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_5        Port Interrupt Enable */
-+//    {0x1194,         4,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_4        Port Interrupt Enable */
-+//    {0x1194,         3,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_3        Port Interrupt Enable */
-+//    {0x1194,         2,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_2        Port Interrupt Enable */
-+//    {0x1194,         1,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_1        Port Interrupt Enable */
-+//    {0x1194,         0,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_0        Port Interrupt Enable */
-+//    {0x1198,         0,     16,     0x00}, /* XRX200_PCE_IER_1               Parser and ClassificationEngine Global Interrupt Enable Register 1 */
-+//    {0x1198,         6,      1,     0x00}, /* XRX200_PCE_IER_1_FLOWINT       Traffic Flow Table Interrupt Rule matched Interrupt Enable */
-+//    {0x1198,         5,      1,     0x00}, /* XRX200_PCE_IER_1_CPH2          Classification Phase 2 Ready Interrupt Enable */
-+//    {0x1198,         4,      1,     0x00}, /* XRX200_PCE_IER_1_CPH1          Classification Phase 1 Ready Interrupt Enable */
-+//    {0x1198,         3,      1,     0x00}, /* XRX200_PCE_IER_1_CPH0          Classification Phase 0 Ready Interrupt Enable */
-+//    {0x1198,         2,      1,     0x00}, /* XRX200_PCE_IER_1_PRDY          Parser Ready Interrupt Enable */
-+//    {0x1198,         1,      1,     0x00}, /* XRX200_PCE_IER_1_IGTF          IGMP Table Full Interrupt Enable */
-+//    {0x1198,         0,      1,     0x00}, /* XRX200_PCE_IER_1_MTF           MAC Table Full Interrupt Enable */
-+//    {0x119C,         0,     16,     0x00}, /* XRX200_PCE_ISR_0_PINT          Parser and ClassificationEngine Global Interrupt Status Register 0 */
-+//    {0x119C,        15,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_15       Port Interrupt */
-+//    {0x119C,        14,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_14       Port Interrupt */
-+//    {0x119C,        13,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_13       Port Interrupt */
-+//    {0x119C,        12,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_12       Port Interrupt */
-+//    {0x119C,        11,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_11       Port Interrupt */
-+//    {0x119C,        10,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_10       Port Interrupt */
-+//    {0x119C,         9,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_9        Port Interrupt */
-+//    {0x119C,         8,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_8        Port Interrupt */
-+//    {0x119C,         7,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_7        Port Interrupt */
-+//    {0x119C,         6,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_6        Port Interrupt */
-+//    {0x119C,         5,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_5        Port Interrupt */
-+//    {0x119C,         4,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_4        Port Interrupt */
-+//    {0x119C,         3,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_3        Port Interrupt */
-+//    {0x119C,         2,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_2        Port Interrupt */
-+//    {0x119C,         1,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_1        Port Interrupt */
-+//    {0x119C,         0,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_0        Port Interrupt */
-+//    {0x11A0,         0,     16,     0x00}, /* XRX200_PCE_ISR_1               Parser and ClassificationEngine Global Interrupt Status Register 1 */
-+//    {0x11A0,         6,      1,     0x00}, /* XRX200_PCE_ISR_1_FLOWINT       Traffic Flow Table Interrupt Rule matched */
-+//    {0x11A0,         5,      1,     0x00}, /* XRX200_PCE_ISR_1_CPH2          Classification Phase 2 Ready Interrupt */
-+//    {0x11A0,         4,      1,     0x00}, /* XRX200_PCE_ISR_1_CPH1          Classification Phase 1 Ready Interrupt */
-+//    {0x11A0,         3,      1,     0x00}, /* XRX200_PCE_ISR_1_CPH0          Classification Phase 0 Ready Interrupt */
-+//    {0x11A0,         2,      1,     0x00}, /* XRX200_PCE_ISR_1_PRDY          Parser Ready Interrupt */
-+//    {0x11A0,         1,      1,     0x00}, /* XRX200_PCE_ISR_1_IGTF          IGMP Table Full Interrupt */
-+//    {0x11A0,         0,      1,     0x00}, /* XRX200_PCE_ISR_1_MTF           MAC Table Full Interrupt */
-+//    {0x11A4,         0,     16,     0x00}, /* XRX200_PARSER_STAT_FIFO        Parser Status Register */
-+//    {0x11A4,         8,      8,     0x00}, /* XRX200_PARSER_STAT_FSM_DAT_CNT Parser FSM Data Counter */
-+//    {0x11A4,         5,      3,     0x00}, /* XRX200_PARSER_STAT_FSM_STATE   Parser FSM State */
-+//    {0x11A4,         4,      1,     0x00}, /* XRX200_PARSER_STAT_PKT_ERR     Packet error detected */
-+//    {0x11A4,         3,      1,     0x00}, /* XRX200_PARSER_STAT_FSM_FIN     Parser FSM finished */
-+//    {0x11A4,         2,      1,     0x00}, /* XRX200_PARSER_STAT_FSM_START   Parser FSM start */
-+//    {0x11A4,         1,      1,     0x00}, /* XRX200_PARSER_STAT_FIFO_RDY    Parser FIFO ready for read. */
-+//    {0x11A4,         0,      1,     0x00}, /* XRX200_PARSER_STAT_FIFO_FULL   Parser */
-+//    {0x1200,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_0             PCE Port ControlRegister 0 */
-+//    {0x1200,        13,      1,     0x28}, /* XRX200_PCE_PCTRL_0_MCST        Multicast Forwarding Mode Selection */
-+//    {0x1200,        12,      1,     0x28}, /* XRX200_PCE_PCTRL_0_EGSTEN      Table-based Egress Special Tag Enable */
-+//    {0x1200,        11,      1,     0x28}, /* XRX200_PCE_PCTRL_0_IGSTEN      Ingress Special Tag Enable */
-+//    {0x1200,        10,      1,     0x28}, /* XRX200_PCE_PCTRL_0_PCPEN       PCP Remarking Mode */
-+//    {0x1200,         9,      1,     0x28}, /* XRX200_PCE_PCTRL_0_CLPEN       Class Remarking Mode */
-+//    {0x1200,         8,      1,     0x28}, /* XRX200_PCE_PCTRL_0_DPEN        Drop Precedence Remarking Mode */
-+//    {0x1200,         7,      1,     0x28}, /* XRX200_PCE_PCTRL_0_CMOD        Three-color Marker Color Mode */
-+//    {0x1200,         6,      1,     0x28}, /* XRX200_PCE_PCTRL_0_VREP        VLAN Replacement Mode */
-+      {0x1200,         5,      1,     0x28}, /* XRX200_PCE_PCTRL_0_TVM         Transparent VLAN Mode */
-+//    {0x1200,         4,      1,     0x28}, /* XRX200_PCE_PCTRL_0_PLOCK       Port Locking Enable */
-+//    {0x1200,         3,      1,     0x28}, /* XRX200_PCE_PCTRL_0_AGEDIS      Aging Disable */
-+//    {0x1200,         0,      3,     0x28}, /* XRX200_PCE_PCTRL_0_PSTATE      Port State */
-+//    {0x1204,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_1             PCE Port ControlRegister 1 */
-+//    {0x1204,         0,      8,     0x28}, /* XRX200_PCE_PCTRL_1_LRNLIM      MAC Address Learning Limit */
-+//    {0x1208,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_2             PCE Port ControlRegister 2 */
-+//    {0x1208,         7,      1,     0x28}, /* XRX200_PCE_PCTRL_2_DSCPMOD     DSCP Mode Selection */
-+//    {0x1208,         5,      2,     0x28}, /* XRX200_PCE_PCTRL_2_DSCP        Enable DSCP to select the Class of Service */
-+//    {0x1208,         4,      1,     0x28}, /* XRX200_PCE_PCTRL_2_PCP         Enable VLAN PCP to select the Class of Service */
-+//    {0x1208,         0,      4,     0x28}, /* XRX200_PCE_PCTRL_2_PCLASS      Port-based Traffic Class */
-+//    {0x120C,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_3_VIO         PCE Port ControlRegister 3 */
-+//    {0x120C,        11,      1,     0x28}, /* XRX200_PCE_PCTRL_3_EDIR        Egress Redirection Mode */
-+//    {0x120C,        10,      1,     0x28}, /* XRX200_PCE_PCTRL_3_RXDMIR      Receive Mirroring Enable for dropped frames */
-+//    {0x120C,         9,      1,     0x28}, /* XRX200_PCE_PCTRL_3_RXVMIR      Receive Mirroring Enable for valid frames */
-+//    {0x120C,         8,      1,     0x28}, /* XRX200_PCE_PCTRL_3_TXMIR       Transmit Mirroring Enable */
-+//    {0x120C,         7,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_7       Violation Type 7 Mirroring Enable */
-+//    {0x120C,         6,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_6       Violation Type 6 Mirroring Enable */
-+//    {0x120C,         5,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_5       Violation Type 5 Mirroring Enable */
-+//    {0x120C,         4,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_4       Violation Type 4 Mirroring Enable */
-+//    {0x120C,         3,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_3       Violation Type 3 Mirroring Enable */
-+//    {0x120C,         2,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_2       Violation Type 2 Mirroring Enable */
-+//    {0x120C,         1,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_1       Violation Type 1 Mirroring Enable */
-+//    {0x120C,         0,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_0       Violation Type 0 Mirroring Enable */
-+//    {0x1210,         0,     16,     0x28}, /* XRX200_WOL_CTRL                Wake-on-LAN ControlRegister */
-+//    {0x1210,         0,      1,     0x28}, /* XRX200_WOL_CTRL_PORT           WoL Enable */
-+//    {0x1214,         0,     16,     0x28}, /* XRX200_PCE_VCTRL               PCE VLAN ControlRegister */
-+      {0x1214,         5,      1,     0x28}, /* XRX200_PCE_VCTRL_VSR           VLAN Security Rule */
-+      {0x1214,         4,      1,     0x28}, /* XRX200_PCE_VCTRL_VEMR          VLAN Egress Member Violation Rule */
-+      {0x1214,         3,      1,     0x28}, /* XRX200_PCE_VCTRL_VIMR          VLAN Ingress Member Violation Rule */
-+      {0x1214,         1,      2,     0x28}, /* XRX200_PCE_VCTRL_VINR          VLAN Ingress Tag Rule */
-+      {0x1214,         0,      1,     0x28}, /* XRX200_PCE_VCTRL_UVR           Unknown VLAN Rule */
-+//    {0x1218,         0,     16,     0x28}, /* XRX200_PCE_DEFPVID             PCE Default PortVID Register */
-+      {0x1218,         0,      6,     0x28}, /* XRX200_PCE_DEFPVID_PVID        Default Port VID Index */
-+//    {0x121C,         0,     16,     0x28}, /* XRX200_PCE_PSTAT               PCE Port StatusRegister */
-+//    {0x121C,         0,     16,     0x28}, /* XRX200_PCE_PSTAT_LRNCNT        Learning Count */
-+//    {0x1220,         0,     16,     0x28}, /* XRX200_PCE_PIER                Parser and ClassificationEngine Port Interrupt Enable Register */
-+//    {0x1220,         5,      1,     0x28}, /* XRX200_PCE_PIER_CLDRP          Classification Drop Interrupt Enable */
-+//    {0x1220,         4,      1,     0x28}, /* XRX200_PCE_PIER_PTDRP          Port Drop Interrupt Enable */
-+//    {0x1220,         3,      1,     0x28}, /* XRX200_PCE_PIER_VLAN           VLAN Violation Interrupt Enable */
-+//    {0x1220,         2,      1,     0x28}, /* XRX200_PCE_PIER_WOL            Wake-on-LAN Interrupt Enable */
-+//    {0x1220,         1,      1,     0x28}, /* XRX200_PCE_PIER_LOCK           Port Limit Alert Interrupt Enable */
-+//    {0x1220,         0,      1,     0x28}, /* XRX200_PCE_PIER_LIM            Port Lock Alert Interrupt Enable */
-+//    {0x1224,         0,     16,     0x28}, /* XRX200_PCE_PISR                Parser and ClassificationEngine Port Interrupt Status Register */
-+//    {0x1224,         5,      1,     0x28}, /* XRX200_PCE_PISR_CLDRP          Classification Drop Interrupt */
-+//    {0x1224,         4,      1,     0x28}, /* XRX200_PCE_PISR_PTDRP          Port Drop Interrupt */
-+//    {0x1224,         3,      1,     0x28}, /* XRX200_PCE_PISR_VLAN           VLAN Violation Interrupt */
-+//    {0x1224,         2,      1,     0x28}, /* XRX200_PCE_PISR_WOL            Wake-on-LAN Interrupt */
-+//    {0x1224,         1,      1,     0x28}, /* XRX200_PCE_PISR_LOCK           Port Lock Alert Interrupt */
-+//    {0x1224,         0,      1,     0x28}, /* XRX200_PCE_PISR_LIMIT          Port Limitation Alert Interrupt */
-+//    {0x1600,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CTRL            Three-colorMarker Control Register */
-+//    {0x1600,         0,      1,     0x1c}, /* XRX200_PCE_TCM_CTRL_TCMEN      Three-color Marker metering instance enable */
-+//    {0x1604,         0,     16,     0x1c}, /* XRX200_PCE_TCM_STAT            Three-colorMarker Status Register */
-+//    {0x1604,         1,      1,     0x1c}, /* XRX200_PCE_TCM_STAT_AL1        Three-color Marker Alert 1 Status */
-+//    {0x1604,         0,      1,     0x1c}, /* XRX200_PCE_TCM_STAT_AL0        Three-color Marker Alert 0 Status */
-+//    {0x1608,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CBS             Three-color MarkerCommitted Burst Size Register */
-+//    {0x1608,         0,     10,     0x1c}, /* XRX200_PCE_TCM_CBS_CBS         Committed Burst Size */
-+//    {0x160C,         0,     16,     0x1c}, /* XRX200_PCE_TCM_EBS             Three-color MarkerExcess Burst Size Register */
-+//    {0x160C,         0,     10,     0x1c}, /* XRX200_PCE_TCM_EBS_EBS         Excess Burst Size */
-+//    {0x1610,         0,     16,     0x1c}, /* XRX200_PCE_TCM_IBS             Three-color MarkerInstantaneous Burst Size Register */
-+//    {0x1610,         0,      2,     0x1c}, /* XRX200_PCE_TCM_IBS_IBS         Instantaneous Burst Size */
-+//    {0x1614,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CIR_MANT        Three-colorMarker Constant Information Rate Mantissa Register */
-+//    {0x1614,         0,     10,     0x1c}, /* XRX200_PCE_TCM_CIR_MANT_MANT   Rate Counter Mantissa */
-+//    {0x1618,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CIR_EXP         Three-colorMarker Constant Information Rate Exponent Register */
-+//    {0x1618,         0,      4,     0x1c}, /* XRX200_PCE_TCM_CIR_EXP_EXP     Rate Counter Exponent */
-+//    {0x2300,         0,     16,     0x00}, /* XRX200_MAC_TEST                MAC Test Register */
-+//    {0x2300,         0,     16,     0x00}, /* XRX200_MAC_TEST_JTP            Jitter Test Pattern */
-+//    {0x2304,         0,     16,     0x00}, /* XRX200_MAC_PFAD_CFG            MAC Pause FrameSource Address Configuration Register */
-+//    {0x2304,         0,      1,     0x00}, /* XRX200_MAC_PFAD_CFG_SAMOD      Source Address Mode */
-+//    {0x2308,         0,     16,     0x00}, /* XRX200_MAC_PFSA_0              Pause Frame SourceAddress Part 0  */
-+//    {0x2308,         0,     16,     0x00}, /* XRX200_MAC_PFSA_0_PFAD         Pause Frame Source Address Part 0 */
-+//    {0x230C,         0,     16,     0x00}, /* XRX200_MAC_PFSA_1              Pause Frame SourceAddress Part 1  */
-+//    {0x230C,         0,     16,     0x00}, /* XRX200_MAC_PFSA_1_PFAD         Pause Frame Source Address Part 1 */
-+//    {0x2310,         0,     16,     0x00}, /* XRX200_MAC_PFSA_2              Pause Frame SourceAddress Part 2  */
-+//    {0x2310,         0,     16,     0x00}, /* XRX200_MAC_PFSA_2_PFAD         Pause Frame Source Address Part 2 */
-+//    {0x2314,         0,     16,     0x00}, /* XRX200_MAC_FLEN                MAC Frame Length Register */
-+//    {0x2314,         0,     14,     0x00}, /* XRX200_MAC_FLEN_LEN            Maximum Frame Length */
-+//    {0x2318,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_0        MAC VLAN EthertypeRegister 0 */
-+//    {0x2318,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_0_OUTER  Ethertype */
-+//    {0x231C,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_1        MAC VLAN EthertypeRegister 1 */
-+//    {0x231C,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_1_INNER  Ethertype */
-+//    {0x2320,         0,     16,     0x00}, /* XRX200_MAC_IER                 MAC Interrupt EnableRegister */
-+//    {0x2320,         0,      8,     0x00}, /* XRX200_MAC_IER_MACIEN          MAC Interrupt Enable */
-+//    {0x2324,         0,     16,     0x00}, /* XRX200_MAC_ISR                 MAC Interrupt StatusRegister */
-+//    {0x2324,         0,      8,     0x00}, /* XRX200_MAC_ISR_MACINT          MAC Interrupt */
-+//    {0x2400,         0,     16,     0x30}, /* XRX200_MAC_PSTAT               MAC Port Status Register */
-+//    {0x2400,        11,      1,     0x30}, /* XRX200_MAC_PSTAT_PACT          PHY Active Status */
-+      {0x2400,        10,      1,     0x30}, /* XRX200_MAC_PSTAT_GBIT          Gigabit Speed Status */
-+      {0x2400,         9,      1,     0x30}, /* XRX200_MAC_PSTAT_MBIT          Megabit Speed Status */
-+      {0x2400,         8,      1,     0x30}, /* XRX200_MAC_PSTAT_FDUP          Full Duplex Status */
-+//    {0x2400,         7,      1,     0x30}, /* XRX200_MAC_PSTAT_RXPAU         Receive Pause Status */
-+//    {0x2400,         6,      1,     0x30}, /* XRX200_MAC_PSTAT_TXPAU         Transmit Pause Status */
-+//    {0x2400,         5,      1,     0x30}, /* XRX200_MAC_PSTAT_RXPAUEN       Receive Pause Enable Status */
-+//    {0x2400,         4,      1,     0x30}, /* XRX200_MAC_PSTAT_TXPAUEN       Transmit Pause Enable Status */
-+      {0x2400,         3,      1,     0x30}, /* XRX200_MAC_PSTAT_LSTAT         Link Status */
-+//    {0x2400,         2,      1,     0x30}, /* XRX200_MAC_PSTAT_CRS           Carrier Sense Status */
-+//    {0x2400,         1,      1,     0x30}, /* XRX200_MAC_PSTAT_TXLPI         Transmit Low-power Idle Status */
-+//    {0x2400,         0,      1,     0x30}, /* XRX200_MAC_PSTAT_RXLPI         Receive Low-power Idle Status */
-+//    {0x2404,         0,     16,     0x30}, /* XRX200_MAC_PISR                MAC Interrupt Status Register */
-+//    {0x2404,        13,      1,     0x30}, /* XRX200_MAC_PISR_PACT           PHY Active Status */
-+//    {0x2404,        12,      1,     0x30}, /* XRX200_MAC_PISR_SPEED          Megabit Speed Status */
-+//    {0x2404,        11,      1,     0x30}, /* XRX200_MAC_PISR_FDUP           Full Duplex Status */
-+//    {0x2404,        10,      1,     0x30}, /* XRX200_MAC_PISR_RXPAUEN        Receive Pause Enable Status */
-+//    {0x2404,         9,      1,     0x30}, /* XRX200_MAC_PISR_TXPAUEN        Transmit Pause Enable Status */
-+//    {0x2404,         8,      1,     0x30}, /* XRX200_MAC_PISR_LPIOFF         Receive Low-power Idle Mode is left */
-+//    {0x2404,         7,      1,     0x30}, /* XRX200_MAC_PISR_LPION          Receive Low-power Idle Mode is entered */
-+//    {0x2404,         6,      1,     0x30}, /* XRX200_MAC_PISR_JAM            Jam Status Detected */
-+//    {0x2404,         5,      1,     0x30}, /* XRX200_MAC_PISR_TOOSHORT       Too Short Frame Error Detected */
-+//    {0x2404,         4,      1,     0x30}, /* XRX200_MAC_PISR_TOOLONG        Too Long Frame Error Detected */
-+//    {0x2404,         3,      1,     0x30}, /* XRX200_MAC_PISR_LENERR         Length Mismatch Error Detected */
-+//    {0x2404,         2,      1,     0x30}, /* XRX200_MAC_PISR_FCSERR         Frame Checksum Error Detected */
-+//    {0x2404,         1,      1,     0x30}, /* XRX200_MAC_PISR_TXPAUSE        Pause Frame Transmitted */
-+//    {0x2404,         0,      1,     0x30}, /* XRX200_MAC_PISR_RXPAUSE        Pause Frame Received */
-+//    {0x2408,         0,     16,     0x30}, /* XRX200_MAC_PIER                MAC Interrupt Enable Register */
-+//    {0x2408,        13,      1,     0x30}, /* XRX200_MAC_PIER_PACT           PHY Active Status */
-+//    {0x2408,        12,      1,     0x30}, /* XRX200_MAC_PIER_SPEED          Megabit Speed Status */
-+//    {0x2408,        11,      1,     0x30}, /* XRX200_MAC_PIER_FDUP           Full Duplex Status */
-+//    {0x2408,        10,      1,     0x30}, /* XRX200_MAC_PIER_RXPAUEN        Receive Pause Enable Status */
-+//    {0x2408,         9,      1,     0x30}, /* XRX200_MAC_PIER_TXPAUEN        Transmit Pause Enable Status */
-+//    {0x2408,         8,      1,     0x30}, /* XRX200_MAC_PIER_LPIOFF         Low-power Idle Off Interrupt Mask */
-+//    {0x2408,         7,      1,     0x30}, /* XRX200_MAC_PIER_LPION          Low-power Idle On Interrupt Mask */
-+//    {0x2408,         6,      1,     0x30}, /* XRX200_MAC_PIER_JAM            Jam Status Interrupt Mask */
-+//    {0x2408,         5,      1,     0x30}, /* XRX200_MAC_PIER_TOOSHORT       Too Short Frame Error Interrupt Mask */
-+//    {0x2408,         4,      1,     0x30}, /* XRX200_MAC_PIER_TOOLONG        Too Long Frame Error Interrupt Mask */
-+//    {0x2408,         3,      1,     0x30}, /* XRX200_MAC_PIER_LENERR         Length Mismatch Error Interrupt Mask */
-+//    {0x2408,         2,      1,     0x30}, /* XRX200_MAC_PIER_FCSERR         Frame Checksum Error Interrupt Mask */
-+//    {0x2408,         1,      1,     0x30}, /* XRX200_MAC_PIER_TXPAUSE        Transmit Pause Frame Interrupt Mask */
-+//    {0x2408,         0,      1,     0x30}, /* XRX200_MAC_PIER_RXPAUSE        Receive Pause Frame Interrupt Mask */
-+//    {0x240C,         0,     16,     0x30}, /* XRX200_MAC_CTRL_0              MAC Control Register0 */
-+//    {0x240C,        13,      2,     0x30}, /* XRX200_MAC_CTRL_0_LCOL         Late Collision Control */
-+//    {0x240C,        12,      1,     0x30}, /* XRX200_MAC_CTRL_0_BM           Burst Mode Control */
-+//    {0x240C,        11,      1,     0x30}, /* XRX200_MAC_CTRL_0_APADEN       Automatic VLAN Padding Enable */
-+//    {0x240C,        10,      1,     0x30}, /* XRX200_MAC_CTRL_0_VPAD2EN      Stacked VLAN Padding Enable */
-+//    {0x240C,         9,      1,     0x30}, /* XRX200_MAC_CTRL_0_VPADEN       VLAN Padding Enable */
-+//    {0x240C,         8,      1,     0x30}, /* XRX200_MAC_CTRL_0_PADEN        Padding Enable */
-+//    {0x240C,         7,      1,     0x30}, /* XRX200_MAC_CTRL_0_FCS          Transmit FCS Control */
-+      {0x240C,         4,      3,     0x30}, /* XRX200_MAC_CTRL_0_FCON         Flow Control Mode */
-+//    {0x240C,         2,      2,     0x30}, /* XRX200_MAC_CTRL_0_FDUP         Full Duplex Control */
-+//    {0x240C,         0,      2,     0x30}, /* XRX200_MAC_CTRL_0_GMII         GMII/MII interface mode selection */
-+//    {0x2410,         0,     16,     0x30}, /* XRX200_MAC_CTRL_1              MAC Control Register1 */
-+//    {0x2410,         8,      1,     0x30}, /* XRX200_MAC_CTRL_1_SHORTPRE     Short Preamble Control */
-+//    {0x2410,         0,      4,     0x30}, /* XRX200_MAC_CTRL_1_IPG          Minimum Inter Packet Gap Size */
-+//    {0x2414,         0,     16,     0x30}, /* XRX200_MAC_CTRL_2              MAC Control Register2 */
-+//    {0x2414,         3,      1,     0x30}, /* XRX200_MAC_CTRL_2_MLEN         Maximum Untagged Frame Length */
-+//    {0x2414,         2,      1,     0x30}, /* XRX200_MAC_CTRL_2_LCHKL        Frame Length Check Long Enable */
-+//    {0x2414,         0,      2,     0x30}, /* XRX200_MAC_CTRL_2_LCHKS        Frame Length Check Short Enable */
-+//    {0x2418,         0,     16,     0x30}, /* XRX200_MAC_CTRL_3              MAC Control Register3 */
-+//    {0x2418,         0,      4,     0x30}, /* XRX200_MAC_CTRL_3_RCNT         Retry Count */
-+//    {0x241C,         0,     16,     0x30}, /* XRX200_MAC_CTRL_4              MAC Control Register4 */
-+//    {0x241C,         7,      1,     0x30}, /* XRX200_MAC_CTRL_4_LPIEN        LPI Mode Enable */
-+//    {0x241C,         0,      7,     0x30}, /* XRX200_MAC_CTRL_4_WAIT         LPI Wait Time */
-+//    {0x2420,         0,     16,     0x30}, /* XRX200_MAC_CTRL_5_PJPS         MAC Control Register5 */
-+//    {0x2420,         1,      1,     0x30}, /* XRX200_MAC_CTRL_5_PJPS_NOBP    Prolonged Jam pattern size during no-backpressure state */
-+//    {0x2420,         0,      1,     0x30}, /* XRX200_MAC_CTRL_5_PJPS_BP      Prolonged Jam pattern size during backpressure state */
-+//    {0x2424,         0,     16,     0x30}, /* XRX200_MAC_CTRL_6_XBUF         Transmit and ReceiveBuffer Control Register */
-+//    {0x2424,         9,      3,     0x30}, /* XRX200_MAC_CTRL_6_RBUF_DLY_WP  Delay */
-+//    {0x2424,         8,      1,     0x30}, /* XRX200_MAC_CTRL_6_RBUF_INIT    Receive Buffer Initialization */
-+//    {0x2424,         6,      1,     0x30}, /* XRX200_MAC_CTRL_6_RBUF_BYPASS  Bypass the Receive Buffer */
-+//    {0x2424,         3,      3,     0x30}, /* XRX200_MAC_CTRL_6_XBUF_DLY_WP  Delay */
-+//    {0x2424,         2,      1,     0x30}, /* XRX200_MAC_CTRL_6_XBUF_INIT    Initialize the Transmit Buffer */
-+//    {0x2424,         0,      1,     0x30}, /* XRX200_MAC_CTRL_6_XBUF_BYPASS  Bypass the Transmit Buffer */
-+//    {0x2428,         0,     16,     0x30}, /* XRX200_MAC_BUFST_XBUF          MAC Receive and TransmitBuffer Status Register */
-+//    {0x2428,         3,      1,     0x30}, /* XRX200_MAC_BUFST_RBUF_UFL      Receive Buffer Underflow Indicator */
-+//    {0x2428,         2,      1,     0x30}, /* XRX200_MAC_BUFST_RBUF_OFL      Receive Buffer Overflow Indicator */
-+//    {0x2428,         1,      1,     0x30}, /* XRX200_MAC_BUFST_XBUF_UFL      Transmit Buffer Underflow Indicator */
-+//    {0x2428,         0,      1,     0x30}, /* XRX200_MAC_BUFST_XBUF_OFL      Transmit Buffer Overflow Indicator */
-+//    {0x242C,         0,     16,     0x30}, /* XRX200_MAC_TESTEN              MAC Test Enable Register */
-+//    {0x242C,         2,      1,     0x30}, /* XRX200_MAC_TESTEN_JTEN         Jitter Test Enable */
-+//    {0x242C,         1,      1,     0x30}, /* XRX200_MAC_TESTEN_TXER         Transmit Error Insertion */
-+//    {0x242C,         0,      1,     0x30}, /* XRX200_MAC_TESTEN_LOOP         MAC Loopback Enable */
-+//    {0x2900,         0,     16,     0x00}, /* XRX200_FDMA_CTRL               Ethernet Switch FetchDMA Control Register */
-+//    {0x2900,         7,      5,     0x00}, /* XRX200_FDMA_CTRL_LPI_THRESHOLD Low Power Idle Threshold */
-+//    {0x2900,         4,      3,     0x00}, /* XRX200_FDMA_CTRL_LPI_MODE      Low Power Idle Mode */
-+//    {0x2900,         2,      2,     0x00}, /* XRX200_FDMA_CTRL_EGSTAG        Egress Special Tag Size */
-+//    {0x2900,         1,      1,     0x00}, /* XRX200_FDMA_CTRL_IGSTAG        Ingress Special Tag Size */
-+//    {0x2900,         0,      1,     0x00}, /* XRX200_FDMA_CTRL_EXCOL         Excessive Collision Handling */
-+//    {0x2904,         0,     16,     0x00}, /* XRX200_FDMA_STETYPE            Special Tag EthertypeControl Register */
-+//    {0x2904,         0,     16,     0x00}, /* XRX200_FDMA_STETYPE_ETYPE      Special Tag Ethertype */
-+//    {0x2908,         0,     16,     0x00}, /* XRX200_FDMA_VTETYPE            VLAN Tag EthertypeControl Register */
-+//    {0x2908,         0,     16,     0x00}, /* XRX200_FDMA_VTETYPE_ETYPE      VLAN Tag Ethertype */
-+//    {0x290C,         0,     16,     0x00}, /* XRX200_FDMA_STAT_0             FDMA Status Register0 */
-+//    {0x290C,         0,     16,     0x00}, /* XRX200_FDMA_STAT_0_FSMS        FSM states status */
-+//    {0x2910,         0,     16,     0x00}, /* XRX200_FDMA_IER                Fetch DMA Global InterruptEnable Register */
-+//    {0x2910,        14,      1,     0x00}, /* XRX200_FDMA_IER_PCKD           Packet Drop Interrupt Enable */
-+//    {0x2910,        13,      1,     0x00}, /* XRX200_FDMA_IER_PCKR           Packet Ready Interrupt Enable */
-+//    {0x2910,         0,      8,     0x00}, /* XRX200_FDMA_IER_PCKT           Packet Sent Interrupt Enable */
-+//    {0x2914,         0,     16,     0x00}, /* XRX200_FDMA_ISR                Fetch DMA Global InterruptStatus Register */
-+//    {0x2914,        14,      1,     0x00}, /* XRX200_FDMA_ISR_PCKTD          Packet Drop */
-+//    {0x2914,        13,      1,     0x00}, /* XRX200_FDMA_ISR_PCKR           Packet is Ready for Transmission */
-+//    {0x2914,         0,      8,     0x00}, /* XRX200_FDMA_ISR_PCKT           Packet Sent Event */
-+//    {0x2A00,         0,     16,     0x18}, /* XRX200_FDMA_PCTRL              Ethernet SwitchFetch DMA Port Control Register */
-+//    {0x2A00,         3,      2,     0x18}, /* XRX200_FDMA_PCTRL_VLANMOD      VLAN Modification Enable */
-+//    {0x2A00,         2,      1,     0x18}, /* XRX200_FDMA_PCTRL_DSCPRM       DSCP Re-marking Enable */
-+//    {0x2A00,         1,      1,     0x18}, /* XRX200_FDMA_PCTRL_STEN         Special Tag Insertion Enable */
-+//    {0x2A00,         0,      1,     0x18}, /* XRX200_FDMA_PCTRL_EN           FDMA Port Enable */
-+//    {0x2A04,         0,     16,     0x18}, /* XRX200_FDMA_PRIO               Ethernet SwitchFetch DMA Port Priority Register */
-+//    {0x2A04,         0,      2,     0x18}, /* XRX200_FDMA_PRIO_PRIO          FDMA PRIO */
-+//    {0x2A08,         0,     16,     0x18}, /* XRX200_FDMA_PSTAT0             Ethernet SwitchFetch DMA Port Status Register 0 */
-+//    {0x2A08,        15,      1,     0x18}, /* XRX200_FDMA_PSTAT0_PKT_AVAIL   Port Egress Packet Available */
-+//    {0x2A08,        14,      1,     0x18}, /* XRX200_FDMA_PSTAT0_POK         Port Status OK */
-+//    {0x2A08,         0,      6,     0x18}, /* XRX200_FDMA_PSTAT0_PSEG        Port Egress Segment Count */
-+//    {0x2A0C,         0,     16,     0x18}, /* XRX200_FDMA_PSTAT1_HDR         Ethernet SwitchFetch DMA Port Status Register 1 */
-+//    {0x2A0C,         0,     10,     0x18}, /* XRX200_FDMA_PSTAT1_HDR_PTR     Header Pointer */
-+//    {0x2A10,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP0            Egress TimeStamp Register 0 */
-+//    {0x2A10,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP0_TSTL       Time Stamp [15:0] */
-+//    {0x2A14,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP1            Egress TimeStamp Register 1 */
-+//    {0x2A14,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP1_TSTH       Time Stamp [31:16] */
-+//    {0x2D00,         0,     16,     0x00}, /* XRX200_SDMA_CTRL               Ethernet Switch StoreDMA Control Register */
-+//    {0x2D00,         0,      1,     0x00}, /* XRX200_SDMA_CTRL_TSTEN         Time Stamp Enable */
-+//    {0x2D04,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR1             SDMA Flow Control Threshold1 Register */
-+//    {0x2D04,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR1_THR1        Threshold 1 */
-+//    {0x2D08,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR2             SDMA Flow Control Threshold2 Register */
-+//    {0x2D08,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR2_THR2        Threshold 2 */
-+//    {0x2D0C,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR3             SDMA Flow Control Threshold3 Register */
-+//    {0x2D0C,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR3_THR3        Threshold 3 */
-+//    {0x2D10,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR4             SDMA Flow Control Threshold4 Register */
-+//    {0x2D10,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR4_THR4        Threshold 4 */
-+//    {0x2D14,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR5             SDMA Flow Control Threshold5 Register */
-+//    {0x2D14,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR5_THR5        Threshold 5 */
-+//    {0x2D18,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR6             SDMA Flow Control Threshold6 Register */
-+//    {0x2D18,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR6_THR6        Threshold 6 */
-+//    {0x2D1C,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR7             SDMA Flow Control Threshold7 Register */
-+//    {0x2D1C,         0,     11,     0x00}, /* XRX200_SDMA_FCTHR7_THR7        Threshold 7 */
-+//    {0x2D20,         0,     16,     0x00}, /* XRX200_SDMA_STAT_0             SDMA Status Register0 */
-+//    {0x2D20,         4,      3,     0x00}, /* XRX200_SDMA_STAT_0_BPS_FILL    Back Pressure Status */
-+//    {0x2D20,         2,      2,     0x00}, /* XRX200_SDMA_STAT_0_BPS_PNT     Back Pressure Status */
-+//    {0x2D20,         0,      2,     0x00}, /* XRX200_SDMA_STAT_0_DROP        Back Pressure Status */
-+//    {0x2D24,         0,     16,     0x00}, /* XRX200_SDMA_STAT_1             SDMA Status Register1 */
-+//    {0x2D24,         0,     10,     0x00}, /* XRX200_SDMA_STAT_1_FILL        Buffer Filling Level */
-+//    {0x2D28,         0,     16,     0x00}, /* XRX200_SDMA_STAT_2             SDMA Status Register2 */
-+//    {0x2D28,         0,     16,     0x00}, /* XRX200_SDMA_STAT_2_FSMS        FSM states status */
-+//    {0x2D2C,         0,     16,     0x00}, /* XRX200_SDMA_IER                SDMA Interrupt Enable Register */
-+//    {0x2D2C,        15,      1,     0x00}, /* XRX200_SDMA_IER_BPEX           Buffer Pointers Exceeded */
-+//    {0x2D2C,        14,      1,     0x00}, /* XRX200_SDMA_IER_BFULL          Buffer Full */
-+//    {0x2D2C,        13,      1,     0x00}, /* XRX200_SDMA_IER_FERR           Frame Error */
-+//    {0x2D2C,         0,      8,     0x00}, /* XRX200_SDMA_IER_FRX            Frame Received Successfully */
-+//    {0x2D30,         0,     16,     0x00}, /* XRX200_SDMA_ISR                SDMA Interrupt Status Register */
-+//    {0x2D30,        15,      1,     0x00}, /* XRX200_SDMA_ISR_BPEX           Packet Descriptors Exceeded */
-+//    {0x2D30,        14,      1,     0x00}, /* XRX200_SDMA_ISR_BFULL          Buffer Full */
-+//    {0x2D30,        13,      1,     0x00}, /* XRX200_SDMA_ISR_FERR           Frame Error */
-+//    {0x2D30,         0,      8,     0x00}, /* XRX200_SDMA_ISR_FRX            Frame Received Successfully */
-+//    {0x2F00,         0,     16,     0x18}, /* XRX200_SDMA_PCTRL              Ethernet SwitchStore DMA Port Control Register */
-+//    {0x2F00,        13,      2,     0x18}, /* XRX200_SDMA_PCTRL_DTHR         Drop Threshold Selection */
-+//    {0x2F00,        11,      2,     0x18}, /* XRX200_SDMA_PCTRL_PTHR         Pause Threshold Selection */
-+//    {0x2F00,        10,      1,     0x18}, /* XRX200_SDMA_PCTRL_PHYEFWD      Forward PHY Error Frames */
-+//    {0x2F00,         9,      1,     0x18}, /* XRX200_SDMA_PCTRL_ALGFWD       Forward Alignment Error Frames */
-+//    {0x2F00,         8,      1,     0x18}, /* XRX200_SDMA_PCTRL_LENFWD       Forward Length Errored Frames */
-+//    {0x2F00,         7,      1,     0x18}, /* XRX200_SDMA_PCTRL_OSFWD        Forward Oversized Frames */
-+//    {0x2F00,         6,      1,     0x18}, /* XRX200_SDMA_PCTRL_USFWD        Forward Undersized Frames */
-+//    {0x2F00,         5,      1,     0x18}, /* XRX200_SDMA_PCTRL_FCSIGN       Ignore FCS Errors */
-+//    {0x2F00,         4,      1,     0x18}, /* XRX200_SDMA_PCTRL_FCSFWD       Forward FCS Errored Frames */
-+//    {0x2F00,         3,      1,     0x18}, /* XRX200_SDMA_PCTRL_PAUFWD       Pause Frame Forwarding */
-+//    {0x2F00,         2,      1,     0x18}, /* XRX200_SDMA_PCTRL_MFCEN        Metering Flow Control Enable */
-+//    {0x2F00,         1,      1,     0x18}, /* XRX200_SDMA_PCTRL_FCEN         Flow Control Enable */
-+//    {0x2F00,         0,      1,     0x18}, /* XRX200_SDMA_PCTRL_PEN          Port Enable */
-+//    {0x2F04,         0,     16,     0x18}, /* XRX200_SDMA_PRIO               Ethernet SwitchStore DMA Port Priority Register */
-+//    {0x2F04,         0,      2,     0x18}, /* XRX200_SDMA_PRIO_PRIO          SDMA PRIO */
-+//    {0x2F08,         0,     16,     0x18}, /* XRX200_SDMA_PSTAT0_HDR         Ethernet SwitchStore DMA Port Status Register 0 */
-+//    {0x2F08,         0,     10,     0x18}, /* XRX200_SDMA_PSTAT0_HDR_PTR     Port Ingress Queue Header Pointer */
-+//    {0x2F0C,         0,     16,     0x18}, /* XRX200_SDMA_PSTAT1             Ethernet SwitchStore DMA Port Status Register 1 */
-+//    {0x2F0C,         0,     10,     0x18}, /* XRX200_SDMA_PSTAT1_PPKT        Port Ingress Packet Count */
-+//    {0x2F10,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP0            Ingress TimeStamp Register 0 */
-+//    {0x2F10,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP0_TSTL       Time Stamp [15:0] */
-+//    {0x2F14,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP1            Ingress TimeStamp Register 1 */
-+//    {0x2F14,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP1_TSTH       Time Stamp [31:16] */
-+};
-+
-+
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0023-NET-PHY-adds-driver-for-lantiq-PHY11G.patch b/target/linux/lantiq/patches-3.14/0023-NET-PHY-adds-driver-for-lantiq-PHY11G.patch
new file mode 100644 (file)
index 0000000..bd769e7
--- /dev/null
@@ -0,0 +1,281 @@
+From 0a63ab263725c427051a8bbaa0732b749627da27 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 7 Aug 2014 18:15:36 +0200
+Subject: [PATCH 23/36] NET: PHY: adds driver for lantiq PHY11G
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/phy/Kconfig  |    5 +
+ drivers/net/phy/Makefile |    1 +
+ drivers/net/phy/lantiq.c |  231 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 237 insertions(+)
+ create mode 100644 drivers/net/phy/lantiq.c
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index 9b5d46c..f3724b1 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -106,6 +106,11 @@ config MICREL_PHY
+       ---help---
+         Supports the KSZ9021, VSC8201, KS8001 PHYs.
++config LANTIQ_PHY
++      tristate "Driver for Lantiq PHYs"
++      ---help---
++        Supports the 11G and 22E PHYs.
++
+ config FIXED_PHY
+       bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
+       depends on PHYLIB=y
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 9013dfa..b5e030f 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -23,6 +23,7 @@ obj-$(CONFIG_NATIONAL_PHY)   += national.o
+ obj-$(CONFIG_DP83640_PHY)     += dp83640.o
+ obj-$(CONFIG_STE10XP)         += ste10Xp.o
+ obj-$(CONFIG_MICREL_PHY)      += micrel.o
++obj-$(CONFIG_LANTIQ_PHY)        += lantiq.o
+ obj-$(CONFIG_MDIO_OCTEON)     += mdio-octeon.o
+ obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
+ obj-$(CONFIG_AT803X_PHY)      += at803x.o
+diff --git a/drivers/net/phy/lantiq.c b/drivers/net/phy/lantiq.c
+new file mode 100644
+index 0000000..f109bb9
+--- /dev/null
++++ b/drivers/net/phy/lantiq.c
+@@ -0,0 +1,231 @@
++/*
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation; either version 2 of the License, or
++ *   (at your option) any later version.
++ *
++ *   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) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
++ */
++
++#include <linux/module.h>
++#include <linux/phy.h>
++
++#define MII_MMDCTRL           0x0d
++#define MII_MMDDATA           0x0e
++
++#define MII_VR9_11G_IMASK     0x19    /* interrupt mask */
++#define MII_VR9_11G_ISTAT     0x1a    /* interrupt status */
++
++#define INT_VR9_11G_WOL               BIT(15) /* Wake-On-LAN */
++#define INT_VR9_11G_ANE               BIT(11) /* Auto-Neg error */
++#define INT_VR9_11G_ANC               BIT(10) /* Auto-Neg complete */
++#define INT_VR9_11G_ADSC      BIT(5)  /* Link auto-downspeed detect */
++#define INT_VR9_11G_DXMC      BIT(2)  /* Duplex mode change */
++#define INT_VR9_11G_LSPC      BIT(1)  /* Link speed change */
++#define INT_VR9_11G_LSTC      BIT(0)  /* Link state change */
++#define INT_VR9_11G_MASK      (INT_VR9_11G_LSTC | INT_VR9_11G_ADSC)
++
++#define ADVERTISED_MPD                BIT(10) /* Multi-port device */
++
++#define MMD_DEVAD             0x1f
++#define MMD_ACTYPE_SHIFT      14
++#define MMD_ACTYPE_ADDRESS    (0 << MMD_ACTYPE_SHIFT)
++#define MMD_ACTYPE_DATA               (1 << MMD_ACTYPE_SHIFT)
++#define MMD_ACTYPE_DATA_PI    (2 << MMD_ACTYPE_SHIFT)
++#define MMD_ACTYPE_DATA_PIWR  (3 << MMD_ACTYPE_SHIFT)
++
++static __maybe_unused int vr9_gphy_mmd_read(struct phy_device *phydev,
++                                              u16 regnum)
++{
++      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
++      phy_write(phydev, MII_MMDDATA, regnum);
++      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
++
++      return phy_read(phydev, MII_MMDDATA);
++}
++
++static __maybe_unused int vr9_gphy_mmd_write(struct phy_device *phydev,
++                                              u16 regnum, u16 val)
++{
++      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_ADDRESS | MMD_DEVAD);
++      phy_write(phydev, MII_MMDDATA, regnum);
++      phy_write(phydev, MII_MMDCTRL, MMD_ACTYPE_DATA | MMD_DEVAD);
++      phy_write(phydev, MII_MMDDATA, val);
++
++      return 0;
++}
++
++static int vr9_gphy_config_init(struct phy_device *phydev)
++{
++      int err;
++
++      dev_dbg(&phydev->dev, "%s\n", __func__);
++
++      /* Mask all interrupts */
++      err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
++      if (err)
++              return err;
++
++      /* Clear all pending interrupts */
++      phy_read(phydev, MII_VR9_11G_ISTAT);
++
++      vr9_gphy_mmd_write(phydev, 0x1e0, 0xc5);
++      vr9_gphy_mmd_write(phydev, 0x1e1, 0x67);
++      vr9_gphy_mmd_write(phydev, 0x1e2, 0x42);
++      vr9_gphy_mmd_write(phydev, 0x1e3, 0x10);
++      vr9_gphy_mmd_write(phydev, 0x1e4, 0x70);
++      vr9_gphy_mmd_write(phydev, 0x1e5, 0x03);
++      vr9_gphy_mmd_write(phydev, 0x1e6, 0x20);
++      vr9_gphy_mmd_write(phydev, 0x1e7, 0x00);
++      vr9_gphy_mmd_write(phydev, 0x1e8, 0x40);
++      vr9_gphy_mmd_write(phydev, 0x1e9, 0x20);
++
++      return 0;
++}
++
++static int vr9_gphy_config_aneg(struct phy_device *phydev)
++{
++      int reg, err;
++
++      /* Advertise as multi-port device */
++      reg = phy_read(phydev, MII_CTRL1000);
++      reg |= ADVERTISED_MPD;
++      err = phy_write(phydev, MII_CTRL1000, reg);
++      if (err)
++              return err;
++
++      return genphy_config_aneg(phydev);
++}
++
++static int vr9_gphy_ack_interrupt(struct phy_device *phydev)
++{
++      int reg;
++
++      /*
++       * Possible IRQ numbers:
++       * - IM3_IRL18 for GPHY0
++       * - IM3_IRL17 for GPHY1
++       *
++       * Due to a silicon bug IRQ lines are not really independent from
++       * each other. Sometimes the two lines are driven at the same time
++       * if only one GPHY core raises the interrupt.
++       */
++
++      reg = phy_read(phydev, MII_VR9_11G_ISTAT);
++
++      return (reg < 0) ? reg : 0;
++}
++
++static int vr9_gphy_did_interrupt(struct phy_device *phydev)
++{
++      int reg;
++
++      reg = phy_read(phydev, MII_VR9_11G_ISTAT);
++
++      return reg > 0;
++}
++
++static int vr9_gphy_config_intr(struct phy_device *phydev)
++{
++      int err;
++
++      if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
++              err = phy_write(phydev, MII_VR9_11G_IMASK, INT_VR9_11G_MASK);
++      else
++              err = phy_write(phydev, MII_VR9_11G_IMASK, 0);
++
++      return err;
++}
++
++static struct phy_driver lantiq_phy[] = {
++      {
++              .phy_id         = 0xd565a400,
++              .phy_id_mask    = 0xffffffff,
++              .name           = "Lantiq XWAY PEF7071",
++              .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
++              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
++              .config_init    = vr9_gphy_config_init,
++              .config_aneg    = vr9_gphy_config_aneg,
++              .read_status    = genphy_read_status,
++              .ack_interrupt  = vr9_gphy_ack_interrupt,
++              .did_interrupt  = vr9_gphy_did_interrupt,
++              .config_intr    = vr9_gphy_config_intr,
++              .driver         = { .owner = THIS_MODULE },
++      }, {
++              .phy_id         = 0x030260D0,
++              .phy_id_mask    = 0xfffffff0,
++              .name           = "Lantiq XWAY VR9 GPHY 11G v1.3",
++              .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
++              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
++              .config_init    = vr9_gphy_config_init,
++              .config_aneg    = vr9_gphy_config_aneg,
++              .read_status    = genphy_read_status,
++              .ack_interrupt  = vr9_gphy_ack_interrupt,
++              .did_interrupt  = vr9_gphy_did_interrupt,
++              .config_intr    = vr9_gphy_config_intr,
++              .driver         = { .owner = THIS_MODULE },
++      }, {
++              .phy_id         = 0xd565a408,
++              .phy_id_mask    = 0xfffffff8,
++              .name           = "Lantiq XWAY VR9 GPHY 11G v1.4",
++              .features       = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
++              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
++              .config_init    = vr9_gphy_config_init,
++              .config_aneg    = vr9_gphy_config_aneg,
++              .read_status    = genphy_read_status,
++              .ack_interrupt  = vr9_gphy_ack_interrupt,
++              .did_interrupt  = vr9_gphy_did_interrupt,
++              .config_intr    = vr9_gphy_config_intr,
++              .driver         = { .owner = THIS_MODULE },
++      }, {
++              .phy_id         = 0xd565a418,
++              .phy_id_mask    = 0xfffffff8,
++              .name           = "Lantiq XWAY XRX PHY22F v1.4",
++              .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
++              .flags          = 0, /*PHY_HAS_INTERRUPT,*/
++              .config_init    = vr9_gphy_config_init,
++              .config_aneg    = vr9_gphy_config_aneg,
++              .read_status    = genphy_read_status,
++              .ack_interrupt  = vr9_gphy_ack_interrupt,
++              .did_interrupt  = vr9_gphy_did_interrupt,
++              .config_intr    = vr9_gphy_config_intr,
++              .driver         = { .owner = THIS_MODULE },
++      },
++};
++
++static int __init ltq_phy_init(void)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(lantiq_phy); i++) {
++              int err = phy_driver_register(&lantiq_phy[i]);
++              if (err)
++                      pr_err("lantiq_phy: failed to load %s\n", lantiq_phy[i].name);
++      }
++
++      return 0;
++}
++
++static void __exit ltq_phy_exit(void)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(lantiq_phy); i++)
++              phy_driver_unregister(&lantiq_phy[i]);
++}
++
++module_init(ltq_phy_init);
++module_exit(ltq_phy_exit);
++
++MODULE_DESCRIPTION("Lantiq PHY drivers");
++MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
++MODULE_LICENSE("GPL");
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0023-NET-multi-phy-support.patch b/target/linux/lantiq/patches-3.14/0023-NET-multi-phy-support.patch
deleted file mode 100644 (file)
index dcda21f..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From 2e265bc5154636daecf941acfea3087e7820877d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 27 Jul 2014 09:38:50 +0100
-Subject: [PATCH 23/31] NET: multi phy support
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/net/phy/phy.c |    9 ++++++---
- include/linux/phy.h   |    1 +
- 2 files changed, 7 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
-index 76d96b9..371f0b6 100644
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -715,7 +715,8 @@ void phy_state_machine(struct work_struct *work)
-               /* If the link is down, give up on 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;
-               }
-@@ -781,7 +782,8 @@ void phy_state_machine(struct work_struct *work)
-                       netif_carrier_on(phydev->attached_dev);
-               } else {
-                       phydev->state = PHY_NOLINK;
--                      netif_carrier_off(phydev->attached_dev);
-+                      if (!phydev->no_auto_carrier_off)
-+                              netif_carrier_off(phydev->attached_dev);
-               }
-               phydev->adjust_link(phydev->attached_dev);
-@@ -793,7 +795,8 @@ void phy_state_machine(struct work_struct *work)
-       case PHY_HALTED:
-               if (phydev->link) {
-                       phydev->link = 0;
--                      netif_carrier_off(phydev->attached_dev);
-+                      if (!phydev->no_auto_carrier_off)
-+                              netif_carrier_off(phydev->attached_dev);
-                       phydev->adjust_link(phydev->attached_dev);
-                       do_suspend = 1;
-               }
-diff --git a/include/linux/phy.h b/include/linux/phy.h
-index 565188c..91b93f7 100644
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -308,6 +308,7 @@ struct phy_device {
-       struct phy_c45_device_ids c45_ids;
-       bool is_c45;
-       bool is_internal;
-+      bool no_auto_carrier_off;
-       enum phy_state state;
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0024-NET-add-of_get_mac_address_mtd.patch b/target/linux/lantiq/patches-3.14/0024-NET-add-of_get_mac_address_mtd.patch
deleted file mode 100644 (file)
index 7024278..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-From c4f036afb2016d21433c0214c55c01b8b9b7f4ee Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 27 Jul 2014 09:40:01 +0100
-Subject: [PATCH 24/31] 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(+)
-
-diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
-index a208a45..de93111 100644
---- 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
-@@ -94,3 +95,39 @@ const void *of_get_mac_address(struct device_node *np)
-       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);
-diff --git a/include/linux/of_net.h b/include/linux/of_net.h
-index 34597c8..cdfbc60 100644
---- a/include/linux/of_net.h
-+++ b/include/linux/of_net.h
-@@ -11,6 +11,7 @@
- #include <linux/of.h>
- extern 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 int of_get_phy_mode(struct device_node *np)
- {
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0024-NET-lantiq-adds-PHY11G-firmware-blobs.patch b/target/linux/lantiq/patches-3.14/0024-NET-lantiq-adds-PHY11G-firmware-blobs.patch
new file mode 100644 (file)
index 0000000..e4c221c
--- /dev/null
@@ -0,0 +1,375 @@
+From 77e89d5a28be35058041c79e9874ab26f222c603 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Oct 2012 09:26:24 +0200
+Subject: [PATCH 24/36] NET: lantiq: adds PHY11G firmware blobs
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ firmware/Makefile       |    4 +
+ firmware/lantiq/COPYING |  286 +++++++++++++++++++++++++++++++++++++++++++++++
+ firmware/lantiq/README  |   45 ++++++++
+ 3 files changed, 335 insertions(+)
+ create mode 100644 firmware/lantiq/COPYING
+ create mode 100644 firmware/lantiq/README
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index cbb09ce..171ebab 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -134,6 +134,10 @@ fw-shipped-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda/keyspan_pda.fw
+ fw-shipped-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda/xircom_pgs.fw
+ fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw
+ fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin
++fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy11g_a1x.bin
++fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy11g_a2x.bin
++fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy22f_a1x.bin
++fw-shipped-$(CONFIG_LANTIQ_XRX200) += lantiq/vr9_phy22f_a2x.bin
+ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+diff --git a/firmware/lantiq/COPYING b/firmware/lantiq/COPYING
+new file mode 100644
+index 0000000..5ec70b2
+--- /dev/null
++++ b/firmware/lantiq/COPYING
+@@ -0,0 +1,286 @@
++All firmware files are copyrighted by Lantiq Deutschland GmbH.
++The files have been extracted from header files found in Lantiq BSPs.
++If not stated otherwise all files are licensed under GPL.
++
++=======================================================================
++
++                  GNU GENERAL PUBLIC LICENSE
++                     Version 2, June 1991
++
++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
++     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ Everyone is permitted to copy and distribute verbatim copies
++ of this license document, but changing it is not allowed.
++
++                          Preamble
++
++  The licenses for most software are designed to take away your
++freedom to share and change it.  By contrast, the GNU General Public
++License is intended to guarantee your freedom to share and change free
++software--to make sure the software is free for all its users.  This
++General Public License applies to most of the Free Software
++Foundation's software and to any other program whose authors commit to
++using it.  (Some other Free Software Foundation software is covered by
++the GNU Library General Public License instead.)  You can apply it to
++your programs, too.
++
++  When we speak of free software, we are referring to freedom, not
++price.  Our General Public Licenses are designed to make sure that you
++have the freedom to distribute copies of free software (and charge for
++this service if you wish), that you receive source code or can get it
++if you want it, that you can change the software or use pieces of it
++in new free programs; and that you know you can do these things.
++
++  To protect your rights, we need to make restrictions that forbid
++anyone to deny you these rights or to ask you to surrender the rights.
++These restrictions translate to certain responsibilities for you if you
++distribute copies of the software, or if you modify it.
++
++  For example, if you distribute copies of such a program, whether
++gratis or for a fee, you must give the recipients all the rights that
++you have.  You must make sure that they, too, receive or can get the
++source code.  And you must show them these terms so they know their
++rights.
++
++  We protect your rights with two steps: (1) copyright the software, and
++(2) offer you this license which gives you legal permission to copy,
++distribute and/or modify the software.
++
++  Also, for each author's protection and ours, we want to make certain
++that everyone understands that there is no warranty for this free
++software.  If the software is modified by someone else and passed on, we
++want its recipients to know that what they have is not the original, so
++that any problems introduced by others will not reflect on the original
++authors' reputations.
++
++  Finally, any free program is threatened constantly by software
++patents.  We wish to avoid the danger that redistributors of a free
++program will individually obtain patent licenses, in effect making the
++program proprietary.  To prevent this, we have made it clear that any
++patent must be licensed for everyone's free use or not licensed at all.
++
++  The precise terms and conditions for copying, distribution and
++modification follow.
++\f
++                  GNU GENERAL PUBLIC LICENSE
++   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
++
++  0. This License applies to any program or other work which contains
++a notice placed by the copyright holder saying it may be distributed
++under the terms of this General Public License.  The "Program", below,
++refers to any such program or work, and a "work based on the Program"
++means either the Program or any derivative work under copyright law:
++that is to say, a work containing the Program or a portion of it,
++either verbatim or with modifications and/or translated into another
++language.  (Hereinafter, translation is included without limitation in
++the term "modification".)  Each licensee is addressed as "you".
++
++Activities other than copying, distribution and modification are not
++covered by this License; they are outside its scope.  The act of
++running the Program is not restricted, and the output from the Program
++is covered only if its contents constitute a work based on the
++Program (independent of having been made by running the Program).
++Whether that is true depends on what the Program does.
++
++  1. You may copy and distribute verbatim copies of the Program's
++source code as you receive it, in any medium, provided that you
++conspicuously and appropriately publish on each copy an appropriate
++copyright notice and disclaimer of warranty; keep intact all the
++notices that refer to this License and to the absence of any warranty;
++and give any other recipients of the Program a copy of this License
++along with the Program.
++
++You may charge a fee for the physical act of transferring a copy, and
++you may at your option offer warranty protection in exchange for a fee.
++
++  2. You may modify your copy or copies of the Program or any portion
++of it, thus forming a work based on the Program, and copy and
++distribute such modifications or work under the terms of Section 1
++above, provided that you also meet all of these conditions:
++
++    a) You must cause the modified files to carry prominent notices
++    stating that you changed the files and the date of any change.
++
++    b) You must cause any work that you distribute or publish, that in
++    whole or in part contains or is derived from the Program or any
++    part thereof, to be licensed as a whole at no charge to all third
++    parties under the terms of this License.
++
++    c) If the modified program normally reads commands interactively
++    when run, you must cause it, when started running for such
++    interactive use in the most ordinary way, to print or display an
++    announcement including an appropriate copyright notice and a
++    notice that there is no warranty (or else, saying that you provide
++    a warranty) and that users may redistribute the program under
++    these conditions, and telling the user how to view a copy of this
++    License.  (Exception: if the Program itself is interactive but
++    does not normally print such an announcement, your work based on
++    the Program is not required to print an announcement.)
++\f
++These requirements apply to the modified work as a whole.  If
++identifiable sections of that work are not derived from the Program,
++and can be reasonably considered independent and separate works in
++themselves, then this License, and its terms, do not apply to those
++sections when you distribute them as separate works.  But when you
++distribute the same sections as part of a whole which is a work based
++on the Program, the distribution of the whole must be on the terms of
++this License, whose permissions for other licensees extend to the
++entire whole, and thus to each and every part regardless of who wrote it.
++
++Thus, it is not the intent of this section to claim rights or contest
++your rights to work written entirely by you; rather, the intent is to
++exercise the right to control the distribution of derivative or
++collective works based on the Program.
++
++In addition, mere aggregation of another work not based on the Program
++with the Program (or with a work based on the Program) on a volume of
++a storage or distribution medium does not bring the other work under
++the scope of this License.
++
++  3. You may copy and distribute the Program (or a work based on it,
++under Section 2) in object code or executable form under the terms of
++Sections 1 and 2 above provided that you also do one of the following:
++
++    a) Accompany it with the complete corresponding machine-readable
++    source code, which must be distributed under the terms of Sections
++    1 and 2 above on a medium customarily used for software interchange; or,
++
++    b) Accompany it with a written offer, valid for at least three
++    years, to give any third party, for a charge no more than your
++    cost of physically performing source distribution, a complete
++    machine-readable copy of the corresponding source code, to be
++    distributed under the terms of Sections 1 and 2 above on a medium
++    customarily used for software interchange; or,
++
++    c) Accompany it with the information you received as to the offer
++    to distribute corresponding source code.  (This alternative is
++    allowed only for noncommercial distribution and only if you
++    received the program in object code or executable form with such
++    an offer, in accord with Subsection b above.)
++
++The source code for a work means the preferred form of the work for
++making modifications to it.  For an executable work, complete source
++code means all the source code for all modules it contains, plus any
++associated interface definition files, plus the scripts used to
++control compilation and installation of the executable.  However, as a
++special exception, the source code distributed need not include
++anything that is normally distributed (in either source or binary
++form) with the major components (compiler, kernel, and so on) of the
++operating system on which the executable runs, unless that component
++itself accompanies the executable.
++
++If distribution of executable or object code is made by offering
++access to copy from a designated place, then offering equivalent
++access to copy the source code from the same place counts as
++distribution of the source code, even though third parties are not
++compelled to copy the source along with the object code.
++\f
++  4. You may not copy, modify, sublicense, or distribute the Program
++except as expressly provided under this License.  Any attempt
++otherwise to copy, modify, sublicense or distribute the Program is
++void, and will automatically terminate your rights under this License.
++However, parties who have received copies, or rights, from you under
++this License will not have their licenses terminated so long as such
++parties remain in full compliance.
++
++  5. You are not required to accept this License, since you have not
++signed it.  However, nothing else grants you permission to modify or
++distribute the Program or its derivative works.  These actions are
++prohibited by law if you do not accept this License.  Therefore, by
++modifying or distributing the Program (or any work based on the
++Program), you indicate your acceptance of this License to do so, and
++all its terms and conditions for copying, distributing or modifying
++the Program or works based on it.
++
++  6. Each time you redistribute the Program (or any work based on the
++Program), the recipient automatically receives a license from the
++original licensor to copy, distribute or modify the Program subject to
++these terms and conditions.  You may not impose any further
++restrictions on the recipients' exercise of the rights granted herein.
++You are not responsible for enforcing compliance by third parties to
++this License.
++
++  7. If, as a consequence of a court judgment or allegation of patent
++infringement or for any other reason (not limited to patent issues),
++conditions are imposed on you (whether by court order, agreement or
++otherwise) that contradict the conditions of this License, they do not
++excuse you from the conditions of this License.  If you cannot
++distribute so as to satisfy simultaneously your obligations under this
++License and any other pertinent obligations, then as a consequence you
++may not distribute the Program at all.  For example, if a patent
++license would not permit royalty-free redistribution of the Program by
++all those who receive copies directly or indirectly through you, then
++the only way you could satisfy both it and this License would be to
++refrain entirely from distribution of the Program.
++
++If any portion of this section is held invalid or unenforceable under
++any particular circumstance, the balance of the section is intended to
++apply and the section as a whole is intended to apply in other
++circumstances.
++
++It is not the purpose of this section to induce you to infringe any
++patents or other property right claims or to contest validity of any
++such claims; this section has the sole purpose of protecting the
++integrity of the free software distribution system, which is
++implemented by public license practices.  Many people have made
++generous contributions to the wide range of software distributed
++through that system in reliance on consistent application of that
++system; it is up to the author/donor to decide if he or she is willing
++to distribute software through any other system and a licensee cannot
++impose that choice.
++
++This section is intended to make thoroughly clear what is believed to
++be a consequence of the rest of this License.
++\f
++  8. If the distribution and/or use of the Program is restricted in
++certain countries either by patents or by copyrighted interfaces, the
++original copyright holder who places the Program under this License
++may add an explicit geographical distribution limitation excluding
++those countries, so that distribution is permitted only in or among
++countries not thus excluded.  In such case, this License incorporates
++the limitation as if written in the body of this License.
++
++  9. The Free Software Foundation may publish revised and/or new versions
++of the General Public License from time to time.  Such new versions will
++be similar in spirit to the present version, but may differ in detail to
++address new problems or concerns.
++
++Each version is given a distinguishing version number.  If the Program
++specifies a version number of this License which applies to it and "any
++later version", you have the option of following the terms and conditions
++either of that version or of any later version published by the Free
++Software Foundation.  If the Program does not specify a version number of
++this License, you may choose any version ever published by the Free Software
++Foundation.
++
++  10. If you wish to incorporate parts of the Program into other free
++programs whose distribution conditions are different, write to the author
++to ask for permission.  For software which is copyrighted by the Free
++Software Foundation, write to the Free Software Foundation; we sometimes
++make exceptions for this.  Our decision will be guided by the two goals
++of preserving the free status of all derivatives of our free software and
++of promoting the sharing and reuse of software generally.
++
++                          NO WARRANTY
++
++  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
++REPAIR OR CORRECTION.
++
++  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
++POSSIBILITY OF SUCH DAMAGES.
++
++                   END OF TERMS AND CONDITIONS
+diff --git a/firmware/lantiq/README b/firmware/lantiq/README
+new file mode 100644
+index 0000000..1b666d4
+--- /dev/null
++++ b/firmware/lantiq/README
+@@ -0,0 +1,45 @@
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# 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
++#
++# (C) Copyright 2007 - 2012
++# Lantiq Deutschland GmbH
++#
++# (C) Copyright 2012
++# Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
++#
++
++#
++# How to use
++#
++Configure kernel with:
++CONFIG_FW_LOADER=y
++CONFIG_EXTRA_FIRMWARE_DIR="FIRMWARE_DIR"
++CONFIG_EXTRA_FIRMWARE="FIRMWARE_FILES"
++
++where FIRMWARE_DIR should point to this git tree and FIRMWARE_FILES is a list
++of space separated files from list below.
++
++#
++# Firmware files
++#
++
++# GPHY core on Lantiq XWAY VR9 v1.1
++lantiq/vr9_phy11g_a1x.bin
++lantiq/vr9_phy22f_a1x.bin
++
++# GPHY core on Lantiq XWAY VR9 v1.2
++lantiq/vr9_phy11g_a2x.bin
++lantiq/vr9_phy22f_a2x.bin
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0025-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch b/target/linux/lantiq/patches-3.14/0025-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch
deleted file mode 100644 (file)
index 841401f..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-From 8d45ea02fc0e9b5edd7deaf564663f1ffe8bed64 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 7 Aug 2014 18:22:19 +0200
-Subject: [PATCH 25/31] GPIO: MIPS: lantiq: add gpio driver for falcon SoC
-
-Add driver for GPIO blocks found on Lantiq FALCON SoC. The SoC has 5 banks of
-up to 32 pads. The GPIO blocks have a per pin IRQs.
-
-Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
-Acked-by: John Crispin <blogic@openwrt.org>
-Cc: linux-mips@linux-mips.org
-Cc: linux-gpio@vger.kernel.org
----
- drivers/gpio/Kconfig       |    5 +
- drivers/gpio/Makefile      |    1 +
- drivers/gpio/gpio-falcon.c |  348 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 354 insertions(+)
- create mode 100644 drivers/gpio/gpio-falcon.c
-
-diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
-index 903f24d..670c064 100644
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -145,6 +145,11 @@ config GPIO_EP93XX
-       depends on ARCH_EP93XX
-       select GPIO_GENERIC
-+config GPIO_FALCON
-+      def_bool y
-+      depends on MIPS && SOC_FALCON
-+      select GPIO_GENERIC
-+
- config GPIO_MM_LANTIQ
-       bool "Lantiq Memory mapped GPIOs"
-       depends on LANTIQ && SOC_XWAY
-diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
-index 5d50179..c92db39 100644
---- a/drivers/gpio/Makefile
-+++ b/drivers/gpio/Makefile
-@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_DAVINCI)   += gpio-davinci.o
- obj-$(CONFIG_GPIO_EM)         += gpio-em.o
- obj-$(CONFIG_GPIO_EP93XX)     += gpio-ep93xx.o
- obj-$(CONFIG_GPIO_F7188X)     += gpio-f7188x.o
-+obj-$(CONFIG_GPIO_FALCON)     += gpio-falcon.o
- obj-$(CONFIG_GPIO_GE_FPGA)    += gpio-ge.o
- obj-$(CONFIG_GPIO_GRGPIO)     += gpio-grgpio.o
- obj-$(CONFIG_GPIO_ICH)                += gpio-ich.o
-diff --git a/drivers/gpio/gpio-falcon.c b/drivers/gpio/gpio-falcon.c
-new file mode 100644
-index 0000000..ae3bdfb
---- /dev/null
-+++ b/drivers/gpio/gpio-falcon.c
-@@ -0,0 +1,348 @@
-+/*
-+ *  This program is free software; you can redistribute it and/or modify it
-+ *  under the terms of the GNU General Public License version 2 as published
-+ *  by the Free Software Foundation.
-+ *
-+ *  Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
-+ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/gpio.h>
-+#include <linux/interrupt.h>
-+#include <linux/slab.h>
-+#include <linux/export.h>
-+#include <linux/err.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+#include <linux/pinctrl/pinctrl.h>
-+#include <linux/pinctrl/consumer.h>
-+#include <linux/platform_device.h>
-+
-+#include <lantiq_soc.h>
-+
-+/* Data Output Register */
-+#define GPIO_OUT            0x00000000
-+/* Data Input Register */
-+#define GPIO_IN             0x00000004
-+/* Direction Register */
-+#define GPIO_DIR            0x00000008
-+/* External Interrupt Control Register 0 */
-+#define GPIO_EXINTCR0       0x00000018
-+/* External Interrupt Control Register 1 */
-+#define GPIO_EXINTCR1       0x0000001C
-+/* IRN Capture Register */
-+#define GPIO_IRNCR          0x00000020
-+/* IRN Interrupt Configuration Register */
-+#define GPIO_IRNCFG           0x0000002C
-+/* IRN Interrupt Enable Set Register */
-+#define GPIO_IRNRNSET       0x00000030
-+/* IRN Interrupt Enable Clear Register */
-+#define GPIO_IRNENCLR       0x00000034
-+/* Output Set Register */
-+#define GPIO_OUTSET         0x00000040
-+/* Output Cler Register */
-+#define GPIO_OUTCLR         0x00000044
-+/* Direction Clear Register */
-+#define GPIO_DIRSET         0x00000048
-+/* Direction Set Register */
-+#define GPIO_DIRCLR         0x0000004C
-+
-+/* turn a gpio_chip into a falcon_gpio_port */
-+#define ctop(c)               container_of(c, struct falcon_gpio_port, gpio_chip)
-+/* turn a irq_data into a falcon_gpio_port */
-+#define itop(i)               ((struct falcon_gpio_port *) irq_get_chip_data(i->irq))
-+
-+#define port_r32(p, reg)      ltq_r32(p->port + reg)
-+#define port_w32(p, val, reg) ltq_w32(val, p->port + reg)
-+#define port_w32_mask(p, clear, set, reg) \
-+              port_w32(p, (port_r32(p, reg) & ~(clear)) | (set), reg)
-+
-+#define MAX_BANKS             5
-+#define PINS_PER_PORT         32
-+
-+struct falcon_gpio_port {
-+      struct gpio_chip gpio_chip;
-+      void __iomem *port;
-+      unsigned int irq_base;
-+      unsigned int chained_irq;
-+      struct clk *clk;
-+      char name[6];
-+};
-+
-+static struct irq_chip falcon_gpio_irq_chip;
-+
-+static int falcon_gpio_direction_input(struct gpio_chip *chip,
-+                                      unsigned int offset)
-+{
-+      port_w32(ctop(chip), 1 << offset, GPIO_DIRCLR);
-+
-+      return 0;
-+}
-+
-+static void falcon_gpio_set(struct gpio_chip *chip, unsigned int offset,
-+                                      int value)
-+{
-+      if (value)
-+              port_w32(ctop(chip), 1 << offset, GPIO_OUTSET);
-+      else
-+              port_w32(ctop(chip), 1 << offset, GPIO_OUTCLR);
-+}
-+
-+static int falcon_gpio_direction_output(struct gpio_chip *chip,
-+                                      unsigned int offset, int value)
-+{
-+      falcon_gpio_set(chip, offset, value);
-+      port_w32(ctop(chip), 1 << offset, GPIO_DIRSET);
-+
-+      return 0;
-+}
-+
-+static int falcon_gpio_get(struct gpio_chip *chip, unsigned int offset)
-+{
-+      if ((port_r32(ctop(chip), GPIO_DIR) >> offset) & 1)
-+              return (port_r32(ctop(chip), GPIO_OUT) >> offset) & 1;
-+      else
-+              return (port_r32(ctop(chip), GPIO_IN) >> offset) & 1;
-+}
-+
-+static int falcon_gpio_request(struct gpio_chip *chip, unsigned offset)
-+{
-+      int gpio = chip->base + offset;
-+
-+      return pinctrl_request_gpio(gpio);
-+}
-+
-+static void falcon_gpio_free(struct gpio_chip *chip, unsigned offset)
-+{
-+      int gpio = chip->base + offset;
-+
-+      pinctrl_free_gpio(gpio);
-+}
-+
-+static int falcon_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-+{
-+      return ctop(chip)->irq_base + offset;
-+}
-+
-+static void falcon_gpio_disable_irq(struct irq_data *d)
-+{
-+      unsigned int offset = d->irq - itop(d)->irq_base;
-+
-+      port_w32(itop(d), 1 << offset, GPIO_IRNENCLR);
-+}
-+
-+static void falcon_gpio_enable_irq(struct irq_data *d)
-+{
-+      unsigned int offset = d->irq - itop(d)->irq_base;
-+
-+      port_w32(itop(d), 1 << offset, GPIO_IRNRNSET);
-+}
-+
-+static void falcon_gpio_ack_irq(struct irq_data *d)
-+{
-+      unsigned int offset = d->irq - itop(d)->irq_base;
-+
-+      port_w32(itop(d), 1 << offset, GPIO_IRNCR);
-+}
-+
-+static void falcon_gpio_mask_and_ack_irq(struct irq_data *d)
-+{
-+      unsigned int offset = d->irq - itop(d)->irq_base;
-+
-+      port_w32(itop(d), 1 << offset, GPIO_IRNENCLR);
-+      port_w32(itop(d), 1 << offset, GPIO_IRNCR);
-+}
-+
-+static int falcon_gpio_irq_type(struct irq_data *d, unsigned int type)
-+{
-+      unsigned int offset = d->irq - itop(d)->irq_base;
-+      unsigned int mask = 1 << offset;
-+
-+      if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE)
-+              return 0;
-+
-+      if ((type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) != 0) {
-+              /* level triggered */
-+              port_w32_mask(itop(d), 0, mask, GPIO_IRNCFG);
-+              irq_set_chip_and_handler_name(d->irq,
-+                      &falcon_gpio_irq_chip, handle_level_irq, "mux");
-+      } else {
-+              /* edge triggered */
-+              port_w32_mask(itop(d), mask, 0, GPIO_IRNCFG);
-+              irq_set_chip_and_handler_name(d->irq,
-+                      &falcon_gpio_irq_chip, handle_simple_irq, "mux");
-+      }
-+
-+      if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
-+              port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR0);
-+              port_w32_mask(itop(d), 0, mask, GPIO_EXINTCR1);
-+      } else {
-+              if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) != 0)
-+                      /* positive logic: rising edge, high level */
-+                      port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR0);
-+              else
-+                      /* negative logic: falling edge, low level */
-+                      port_w32_mask(itop(d), 0, mask, GPIO_EXINTCR0);
-+              port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR1);
-+      }
-+
-+      return gpio_direction_input(itop(d)->gpio_chip.base + offset);
-+}
-+
-+static void falcon_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-+{
-+      struct falcon_gpio_port *gpio_port = irq_desc_get_handler_data(desc);
-+      unsigned long irncr;
-+      int offset;
-+
-+      /* acknowledge interrupt */
-+      irncr = port_r32(gpio_port, GPIO_IRNCR);
-+      port_w32(gpio_port, irncr, GPIO_IRNCR);
-+
-+      desc->irq_data.chip->irq_ack(&desc->irq_data);
-+
-+      for_each_set_bit(offset, &irncr, gpio_port->gpio_chip.ngpio)
-+              generic_handle_irq(gpio_port->irq_base + offset);
-+}
-+
-+static int falcon_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-+                              irq_hw_number_t hw)
-+{
-+      struct falcon_gpio_port *port = d->host_data;
-+
-+      irq_set_chip_and_handler_name(irq, &falcon_gpio_irq_chip,
-+                      handle_simple_irq, "mux");
-+      irq_set_chip_data(irq, port);
-+
-+      /* set to negative logic (falling edge, low level) */
-+      port_w32_mask(port, 0, 1 << hw, GPIO_EXINTCR0);
-+      return 0;
-+}
-+
-+static struct irq_chip falcon_gpio_irq_chip = {
-+      .name = "gpio_irq_mux",
-+      .irq_mask = falcon_gpio_disable_irq,
-+      .irq_unmask = falcon_gpio_enable_irq,
-+      .irq_ack = falcon_gpio_ack_irq,
-+      .irq_mask_ack = falcon_gpio_mask_and_ack_irq,
-+      .irq_set_type = falcon_gpio_irq_type,
-+};
-+
-+static const struct irq_domain_ops irq_domain_ops = {
-+      .xlate = irq_domain_xlate_onetwocell,
-+      .map = falcon_gpio_irq_map,
-+};
-+
-+static struct irqaction gpio_cascade = {
-+      .handler = no_action,
-+      .flags = IRQF_DISABLED,
-+      .name = "gpio_cascade",
-+};
-+
-+static int falcon_gpio_probe(struct platform_device *pdev)
-+{
-+      struct pinctrl_gpio_range *gpio_range;
-+      struct device_node *node = pdev->dev.of_node;
-+      const __be32 *bank = of_get_property(node, "lantiq,bank", NULL);
-+      struct falcon_gpio_port *gpio_port;
-+      struct resource *gpiores, irqres;
-+      int ret, size;
-+
-+      if (!bank || *bank >= MAX_BANKS)
-+              return -ENODEV;
-+
-+      size = pinctrl_falcon_get_range_size(*bank);
-+      if (size < 1) {
-+              dev_err(&pdev->dev, "pad not loaded for bank %d\n", *bank);
-+              return size;
-+      }
-+
-+      gpio_range = devm_kzalloc(&pdev->dev, sizeof(struct pinctrl_gpio_range),
-+                              GFP_KERNEL);
-+      if (!gpio_range)
-+              return -ENOMEM;
-+
-+      gpio_port = devm_kzalloc(&pdev->dev, sizeof(struct falcon_gpio_port),
-+                              GFP_KERNEL);
-+      if (!gpio_port)
-+              return -ENOMEM;
-+
-+      snprintf(gpio_port->name, 6, "gpio%d", *bank);
-+      gpio_port->gpio_chip.label = gpio_port->name;
-+      gpio_port->gpio_chip.direction_input = falcon_gpio_direction_input;
-+      gpio_port->gpio_chip.direction_output = falcon_gpio_direction_output;
-+      gpio_port->gpio_chip.get = falcon_gpio_get;
-+      gpio_port->gpio_chip.set = falcon_gpio_set;
-+      gpio_port->gpio_chip.request = falcon_gpio_request;
-+      gpio_port->gpio_chip.free = falcon_gpio_free;
-+      gpio_port->gpio_chip.base = *bank * PINS_PER_PORT;
-+      gpio_port->gpio_chip.ngpio = size;
-+      gpio_port->gpio_chip.dev = &pdev->dev;
-+
-+      gpiores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      gpio_port->port = devm_request_and_ioremap(&pdev->dev, gpiores);
-+      if (IS_ERR(gpio_port->port))
-+              return PTR_ERR(gpio_port->port);
-+
-+      gpio_port->clk = devm_clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(gpio_port->clk))
-+              return PTR_ERR(gpio_port->clk);
-+      clk_activate(gpio_port->clk);
-+
-+      if (of_irq_to_resource_table(node, &irqres, 1) == 1) {
-+              gpio_port->irq_base = INT_NUM_EXTRA_START + (32 * *bank);
-+              gpio_port->gpio_chip.to_irq = falcon_gpio_to_irq;
-+              gpio_port->chained_irq = irqres.start;
-+              irq_domain_add_legacy(node, size, gpio_port->irq_base, 0,
-+                                      &irq_domain_ops, gpio_port);
-+              setup_irq(irqres.start, &gpio_cascade);
-+              irq_set_handler_data(irqres.start, gpio_port);
-+              irq_set_chained_handler(irqres.start, falcon_gpio_irq_handler);
-+      }
-+
-+      ret = gpiochip_add(&gpio_port->gpio_chip);
-+      if (ret)
-+              return ret;
-+
-+      platform_set_drvdata(pdev, gpio_port);
-+
-+      gpio_range->name = "FALCON GPIO";
-+      gpio_range->id = *bank;
-+      gpio_range->base = gpio_port->gpio_chip.base;
-+      gpio_range->pin_base = gpio_port->gpio_chip.base;
-+      gpio_range->npins = gpio_port->gpio_chip.ngpio;
-+      gpio_range->gc = &gpio_port->gpio_chip;
-+
-+      pinctrl_falcon_add_gpio_range(gpio_range);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id falcon_gpio_match[] = {
-+      { .compatible = "lantiq,falcon-gpio" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, falcon_gpio_match);
-+
-+static struct platform_driver falcon_gpio_driver = {
-+      .probe = falcon_gpio_probe,
-+      .driver = {
-+              .name = "gpio-falcon",
-+              .owner = THIS_MODULE,
-+              .of_match_table = falcon_gpio_match,
-+      },
-+};
-+
-+int __init falcon_gpio_init(void)
-+{
-+      int ret;
-+
-+      pr_info("FALC(tm) ON GPIO Driver, (C) 2012 Lantiq Deutschland Gmbh\n");
-+      ret = platform_driver_register(&falcon_gpio_driver);
-+      if (ret)
-+              pr_err("falcon_gpio: Error registering platform driver!");
-+      return ret;
-+}
-+
-+subsys_initcall(falcon_gpio_init);
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0025-NET-MIPS-lantiq-adds-xrx200-net.patch b/target/linux/lantiq/patches-3.14/0025-NET-MIPS-lantiq-adds-xrx200-net.patch
new file mode 100644 (file)
index 0000000..705430e
--- /dev/null
@@ -0,0 +1,3357 @@
+From fb0c9601f4414c39ff68e26b88681bef0bb04954 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 22 Oct 2012 12:22:23 +0200
+Subject: [PATCH 25/36] NET: MIPS: lantiq: adds xrx200-net
+
+---
+ drivers/net/ethernet/Kconfig            |    8 +-
+ drivers/net/ethernet/Makefile           |    1 +
+ drivers/net/ethernet/lantiq_pce.h       |  163 +++
+ drivers/net/ethernet/lantiq_xrx200.c    | 1798 +++++++++++++++++++++++++++++++
+ drivers/net/ethernet/lantiq_xrx200_sw.h | 1328 +++++++++++++++++++++++
+ 5 files changed, 3297 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/ethernet/lantiq_pce.h
+ create mode 100644 drivers/net/ethernet/lantiq_xrx200.c
+ create mode 100644 drivers/net/ethernet/lantiq_xrx200_sw.h
+
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index 506b024..0a0dbe6 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -84,7 +84,13 @@ config LANTIQ_ETOP
+       tristate "Lantiq SoC ETOP driver"
+       depends on SOC_TYPE_XWAY
+       ---help---
+-        Support for the MII0 inside the Lantiq SoC
++        Support for the MII0 inside the Lantiq ADSL SoC
++
++config LANTIQ_XRX200
++      tristate "Lantiq SoC XRX200 driver"
++      depends on SOC_TYPE_XWAY
++      ---help---
++        Support for the MII0 inside the Lantiq VDSL SoC
+ source "drivers/net/ethernet/marvell/Kconfig"
+ source "drivers/net/ethernet/mellanox/Kconfig"
+diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
+index c0b8789..459cce8 100644
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -38,6 +38,7 @@ obj-$(CONFIG_IP1000) += icplus/
+ obj-$(CONFIG_JME) += jme.o
+ obj-$(CONFIG_KORINA) += korina.o
+ obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
++obj-$(CONFIG_LANTIQ_XRX200) += lantiq_xrx200.o
+ obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
+ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
+ obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
+diff --git a/drivers/net/ethernet/lantiq_pce.h b/drivers/net/ethernet/lantiq_pce.h
+new file mode 100644
+index 0000000..0c38efe
+--- /dev/null
++++ b/drivers/net/ethernet/lantiq_pce.h
+@@ -0,0 +1,163 @@
++/*
++ *   This program is free software; you can redistribute it and/or modify it
++ *   under the terms of the GNU General Public License version 2 as published
++ *   by the Free Software Foundation.
++ *
++ *   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) 2010 Lantiq Deutschland GmbH
++ *   Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ *
++ *   PCE microcode extracted from UGW5.2 switch api
++ */
++
++/* Switch API Micro Code V0.3 */
++enum {
++      OUT_MAC0 = 0,
++      OUT_MAC1,
++      OUT_MAC2,
++      OUT_MAC3,
++      OUT_MAC4,
++      OUT_MAC5,
++      OUT_ETHTYP,
++      OUT_VTAG0,
++      OUT_VTAG1,
++      OUT_ITAG0,
++      OUT_ITAG1,      /*10 */
++      OUT_ITAG2,
++      OUT_ITAG3,
++      OUT_IP0,
++      OUT_IP1,
++      OUT_IP2,
++      OUT_IP3,
++      OUT_SIP0,
++      OUT_SIP1,
++      OUT_SIP2,
++      OUT_SIP3,       /*20*/
++      OUT_SIP4,
++      OUT_SIP5,
++      OUT_SIP6,
++      OUT_SIP7,
++      OUT_DIP0,
++      OUT_DIP1,
++      OUT_DIP2,
++      OUT_DIP3,
++      OUT_DIP4,
++      OUT_DIP5,       /*30*/
++      OUT_DIP6,
++      OUT_DIP7,
++      OUT_SESID,
++      OUT_PROT,
++      OUT_APP0,
++      OUT_APP1,
++      OUT_IGMP0,
++      OUT_IGMP1,
++      OUT_IPOFF,      /*39*/
++      OUT_NONE =  63
++};
++
++/* parser's microcode length type */
++#define INSTR         0
++#define IPV6          1
++#define LENACCU               2
++
++/* parser's microcode flag type */
++enum {
++      FLAG_ITAG =  0,
++      FLAG_VLAN,
++      FLAG_SNAP,
++      FLAG_PPPOE,
++      FLAG_IPV6,
++      FLAG_IPV6FL,
++      FLAG_IPV4,
++      FLAG_IGMP,
++      FLAG_TU,
++      FLAG_HOP,
++      FLAG_NN1,       /*10 */
++      FLAG_NN2,
++      FLAG_END,
++      FLAG_NO,        /*13*/
++};
++
++/* Micro code version V2_11 (extension for parsing IPv6 in PPPoE) */
++#define MC_ENTRY(val, msk, ns, out, len, type, flags, ipv4_len) \
++      { {val, msk, (ns<<10 | out<<4 | len>>1), (len&1)<<15 | type<<13 | flags<<9 | ipv4_len<<8 }}
++struct pce_microcode {
++      unsigned short val[4];
++/*    unsigned short val_2;
++      unsigned short val_1;
++      unsigned short val_0;*/
++} pce_microcode[] = {
++      /*      value    mask    ns  fields      L  type     flags       ipv4_len */
++      MC_ENTRY(0x88c3, 0xFFFF,  1, OUT_ITAG0,  4, INSTR,   FLAG_ITAG,  0),
++      MC_ENTRY(0x8100, 0xFFFF,  2, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
++      MC_ENTRY(0x88A8, 0xFFFF,  1, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
++      MC_ENTRY(0x8100, 0xFFFF,  1, OUT_VTAG0,  2, INSTR,   FLAG_VLAN,  0),
++      MC_ENTRY(0x8864, 0xFFFF, 17, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0800, 0xFFFF, 21, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x86DD, 0xFFFF, 22, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x8863, 0xFFFF, 16, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0xF800, 10, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 38, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0600, 0x0600, 38, OUT_ETHTYP, 1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 12, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0xAAAA, 0xFFFF, 14, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0300, 0xFF00, 39, OUT_NONE,   0, INSTR,   FLAG_SNAP,  0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_DIP7,   3, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 18, OUT_DIP7,   3, INSTR,   FLAG_PPPOE, 0),
++      MC_ENTRY(0x0021, 0xFFFF, 21, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0057, 0xFFFF, 22, OUT_NONE,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x4000, 0xF000, 24, OUT_IP0,    4, INSTR,   FLAG_IPV4,  1),
++      MC_ENTRY(0x6000, 0xF000, 27, OUT_IP0,    3, INSTR,   FLAG_IPV6,  0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 25, OUT_IP3,    2, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 26, OUT_SIP0,   4, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 38, OUT_NONE,   0, LENACCU, FLAG_NO,    0),
++      MC_ENTRY(0x1100, 0xFF00, 37, OUT_PROT,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0600, 0xFF00, 37, OUT_PROT,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_HOP,   0),
++      MC_ENTRY(0x2B00, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_NN1,   0),
++      MC_ENTRY(0x3C00, 0xFF00, 33, OUT_IP3,   17, INSTR,   FLAG_NN2,   0),
++      MC_ENTRY(0x0000, 0x0000, 37, OUT_PROT,   1, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0xFF00, 33, OUT_NONE,   0, IPV6,    FLAG_HOP,   0),
++      MC_ENTRY(0x2B00, 0xFF00, 33, OUT_NONE,   0, IPV6,    FLAG_NN1,   0),
++      MC_ENTRY(0x3C00, 0xFF00, 33, OUT_NONE,   0, IPV6,    FLAG_NN2,   0),
++      MC_ENTRY(0x0000, 0x0000, 38, OUT_PROT,   1, IPV6,    FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 38, OUT_SIP0,  16, INSTR,   FLAG_NO,    0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_APP0,   4, INSTR,   FLAG_IGMP,  0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++      MC_ENTRY(0x0000, 0x0000, 39, OUT_NONE,   0, INSTR,   FLAG_END,   0),
++};
+diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c
+new file mode 100644
+index 0000000..2da9d47
+--- /dev/null
++++ b/drivers/net/ethernet/lantiq_xrx200.c
+@@ -0,0 +1,1798 @@
++/*
++ *   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.
++ *
++ *   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) 2010 Lantiq Deutschland
++ *   Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/switch.h>
++#include <linux/etherdevice.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <asm/delay.h>
++
++#include <linux/of_net.h>
++#include <linux/of_mdio.h>
++#include <linux/of_gpio.h>
++
++#include <xway_dma.h>
++#include <lantiq_soc.h>
++
++#include "lantiq_pce.h"
++#include "lantiq_xrx200_sw.h"
++
++#define SW_POLLING
++#define SW_ROUTING
++#define SW_PORTMAP
++
++#ifdef SW_ROUTING
++  #ifdef SW_PORTMAP
++#define XRX200_MAX_DEV                2
++  #else
++#define XRX200_MAX_DEV                2
++  #endif
++#else
++#define XRX200_MAX_DEV                1
++#endif
++
++#define XRX200_MAX_VLAN               64
++#define XRX200_PCE_ACTVLAN_IDX        0x01
++#define XRX200_PCE_VLANMAP_IDX        0x02
++
++#define XRX200_MAX_PORT               7
++#define XRX200_MAX_DMA                8
++
++#define XRX200_HEADROOM               4
++
++#define XRX200_TX_TIMEOUT     (10 * HZ)
++
++/* port type */
++#define XRX200_PORT_TYPE_PHY  1
++#define XRX200_PORT_TYPE_MAC  2
++
++/* DMA */
++#define XRX200_DMA_DATA_LEN   0x600
++#define XRX200_DMA_IRQ                INT_NUM_IM2_IRL0
++#define XRX200_DMA_RX         0
++#define XRX200_DMA_TX         1
++#define XRX200_DMA_IS_TX(x)   (x%2)
++#define XRX200_DMA_IS_RX(x)   (!XRX200_DMA_IS_TX(x))
++
++/* fetch / store dma */
++#define FDMA_PCTRL0           0x2A00
++#define FDMA_PCTRLx(x)                (FDMA_PCTRL0 + (x * 0x18))
++#define SDMA_PCTRL0           0x2F00
++#define SDMA_PCTRLx(x)                (SDMA_PCTRL0 + (x * 0x18))
++
++/* buffer management */
++#define BM_PCFG0              0x200
++#define BM_PCFGx(x)           (BM_PCFG0 + (x * 8))
++
++/* MDIO */
++#define MDIO_GLOB             0x0000
++#define MDIO_CTRL             0x0020
++#define MDIO_READ             0x0024
++#define MDIO_WRITE            0x0028
++#define MDIO_PHY0             0x0054
++#define MDIO_PHY(x)           (0x0054 - (x * sizeof(unsigned)))
++#define MDIO_CLK_CFG0         0x002C
++#define MDIO_CLK_CFG1         0x0030
++
++#define MDIO_GLOB_ENABLE      0x8000
++#define MDIO_BUSY             BIT(12)
++#define MDIO_RD                       BIT(11)
++#define MDIO_WR                       BIT(10)
++#define MDIO_MASK             0x1f
++#define MDIO_ADDRSHIFT                5
++#define MDIO1_25MHZ           9
++
++#define MDIO_PHY_LINK_DOWN    0x4000
++#define MDIO_PHY_LINK_UP      0x2000
++
++#define MDIO_PHY_SPEED_M10    0x0000
++#define MDIO_PHY_SPEED_M100   0x0800
++#define MDIO_PHY_SPEED_G1     0x1000
++
++#define MDIO_PHY_FDUP_EN      0x0200
++#define MDIO_PHY_FDUP_DIS     0x0600
++
++#define MDIO_PHY_LINK_MASK    0x6000
++#define MDIO_PHY_SPEED_MASK   0x1800
++#define MDIO_PHY_FDUP_MASK    0x0600
++#define MDIO_PHY_ADDR_MASK    0x001f
++#define MDIO_UPDATE_MASK      MDIO_PHY_ADDR_MASK | MDIO_PHY_LINK_MASK | \
++                                      MDIO_PHY_SPEED_MASK | MDIO_PHY_FDUP_MASK
++
++/* MII */
++#define MII_CFG(p)            (p * 8)
++
++#define MII_CFG_EN            BIT(14)
++
++#define MII_CFG_MODE_MIIP     0x0
++#define MII_CFG_MODE_MIIM     0x1
++#define MII_CFG_MODE_RMIIP    0x2
++#define MII_CFG_MODE_RMIIM    0x3
++#define MII_CFG_MODE_RGMII    0x4
++#define MII_CFG_MODE_MASK     0xf
++
++#define MII_CFG_RATE_M2P5     0x00
++#define MII_CFG_RATE_M25      0x10
++#define MII_CFG_RATE_M125     0x20
++#define MII_CFG_RATE_M50      0x30
++#define MII_CFG_RATE_AUTO     0x40
++#define MII_CFG_RATE_MASK     0x70
++
++/* cpu port mac */
++#define PMAC_HD_CTL           0x0000
++#define PMAC_RX_IPG           0x0024
++#define PMAC_EWAN             0x002c
++
++#define PMAC_IPG_MASK         0xf
++#define PMAC_HD_CTL_AS                0x0008
++#define PMAC_HD_CTL_AC                0x0004
++#define PMAC_HD_CTL_RXSH      0x0040
++#define PMAC_HD_CTL_AST               0x0080
++#define PMAC_HD_CTL_RST               0x0100
++
++/* PCE */
++#define PCE_TBL_KEY(x)                (0x1100 + ((7 - x) * 4))
++#define PCE_TBL_MASK          0x1120
++#define PCE_TBL_VAL(x)                (0x1124 + ((4 - x) * 4))
++#define PCE_TBL_ADDR          0x1138
++#define PCE_TBL_CTRL          0x113c
++#define PCE_PMAP1             0x114c
++#define PCE_PMAP2             0x1150
++#define PCE_PMAP3             0x1154
++#define PCE_GCTRL_REG(x)      (0x1158 + (x * 4))
++#define PCE_PCTRL_REG(p, x)   (0x1200 + (((p * 0xa) + x) * 4))
++
++#define PCE_TBL_BUSY          BIT(15)
++#define PCE_TBL_CFG_ADDR_MASK 0x1f
++#define PCE_TBL_CFG_ADWR      0x20
++#define PCE_TBL_CFG_ADWR_MASK 0x60
++#define PCE_INGRESS           BIT(11)
++
++/* MAC */
++#define MAC_FLEN_REG          (0x2314)
++#define MAC_CTRL_REG(p, x)    (0x240c + (((p * 0xc) + x) * 4))
++
++/* buffer management */
++#define BM_PCFG(p)            (0x200 + (p * 8))
++
++/* special tag in TX path header */
++#define SPID_SHIFT            24
++#define DPID_SHIFT            16
++#define DPID_ENABLE           1
++#define SPID_CPU_PORT         2
++#define PORT_MAP_SEL          BIT(15)
++#define PORT_MAP_EN           BIT(14)
++#define PORT_MAP_SHIFT                1
++#define PORT_MAP_MASK         0x3f
++
++#define SPPID_MASK            0x7
++#define SPPID_SHIFT           4
++
++/* MII regs not yet in linux */
++#define MDIO_DEVAD_NONE               (-1)
++#define ADVERTIZE_MPD         (1 << 10)
++
++struct xrx200_port {
++      u8 num;
++      u8 phy_addr;
++      u16 flags;
++      phy_interface_t phy_if;
++
++      int link;
++      int gpio;
++      enum of_gpio_flags gpio_flags;
++
++      struct phy_device *phydev;
++      struct device_node *phy_node;
++};
++
++struct xrx200_chan {
++      int idx;
++      int refcount;
++      int tx_free;
++
++      struct net_device dummy_dev;
++      struct net_device *devs[XRX200_MAX_DEV];
++
++      struct tasklet_struct tasklet;
++      struct napi_struct napi;
++      struct ltq_dma_channel dma;
++      struct sk_buff *skb[LTQ_DESC_NUM];
++};
++
++struct xrx200_hw {
++      struct clk *clk;
++      struct mii_bus *mii_bus;
++
++      struct xrx200_chan chan[XRX200_MAX_DMA];
++
++      struct net_device *devs[XRX200_MAX_DEV];
++      int num_devs;
++
++      int port_map[XRX200_MAX_PORT];
++      unsigned short wan_map;
++
++      spinlock_t lock;
++
++      struct switch_dev swdev;
++};
++
++struct xrx200_priv {
++      struct net_device_stats stats;
++      int id;
++
++      struct xrx200_port port[XRX200_MAX_PORT];
++      int num_port;
++      bool wan;
++      bool sw;
++      unsigned short port_map;
++      unsigned char mac[6];
++
++      struct xrx200_hw *hw;
++};
++
++static __iomem void *xrx200_switch_membase;
++static __iomem void *xrx200_mii_membase;
++static __iomem void *xrx200_mdio_membase;
++static __iomem void *xrx200_pmac_membase;
++
++#define ltq_switch_r32(x)     ltq_r32(xrx200_switch_membase + (x))
++#define ltq_switch_w32(x, y)  ltq_w32(x, xrx200_switch_membase + (y))
++#define ltq_switch_w32_mask(x, y, z) \
++                      ltq_w32_mask(x, y, xrx200_switch_membase + (z))
++
++#define ltq_mdio_r32(x)               ltq_r32(xrx200_mdio_membase + (x))
++#define ltq_mdio_w32(x, y)    ltq_w32(x, xrx200_mdio_membase + (y))
++#define ltq_mdio_w32_mask(x, y, z) \
++                      ltq_w32_mask(x, y, xrx200_mdio_membase + (z))
++
++#define ltq_mii_r32(x)                ltq_r32(xrx200_mii_membase + (x))
++#define ltq_mii_w32(x, y)     ltq_w32(x, xrx200_mii_membase + (y))
++#define ltq_mii_w32_mask(x, y, z) \
++                      ltq_w32_mask(x, y, xrx200_mii_membase + (z))
++
++#define ltq_pmac_r32(x)               ltq_r32(xrx200_pmac_membase + (x))
++#define ltq_pmac_w32(x, y)    ltq_w32(x, xrx200_pmac_membase + (y))
++#define ltq_pmac_w32_mask(x, y, z) \
++                      ltq_w32_mask(x, y, xrx200_pmac_membase + (z))
++
++#define XRX200_GLOBAL_REGATTR(reg) \
++      .id = reg, \
++      .type = SWITCH_TYPE_INT, \
++      .set = xrx200_set_global_attr, \
++      .get = xrx200_get_global_attr
++
++#define XRX200_PORT_REGATTR(reg) \
++      .id = reg, \
++      .type = SWITCH_TYPE_INT, \
++      .set = xrx200_set_port_attr, \
++      .get = xrx200_get_port_attr
++
++static int xrx200sw_read_x(int reg, int x)
++{
++      int value, mask, addr;
++
++      addr = xrx200sw_reg[reg].offset + (xrx200sw_reg[reg].mult * x);
++      value = ltq_switch_r32(addr);
++      mask = (1 << xrx200sw_reg[reg].size) - 1;
++      value = (value >> xrx200sw_reg[reg].shift);
++
++      return (value & mask);
++}
++
++static int xrx200sw_read(int reg)
++{
++      return xrx200sw_read_x(reg, 0);
++}
++
++static void xrx200sw_write_x(int value, int reg, int x)
++{
++      int mask, addr;
++
++      addr = xrx200sw_reg[reg].offset + (xrx200sw_reg[reg].mult * x);
++      mask = (1 << xrx200sw_reg[reg].size) - 1;
++      mask = (mask << xrx200sw_reg[reg].shift);
++      value = (value << xrx200sw_reg[reg].shift) & mask;
++
++      ltq_switch_w32_mask(mask, value, addr);
++}
++
++static void xrx200sw_write(int value, int reg)
++{
++      xrx200sw_write_x(value, reg, 0);
++}
++
++struct xrx200_pce_table_entry {
++      int index;      // PCE_TBL_ADDR.ADDR = pData->table_index
++      int table;      // PCE_TBL_CTRL.ADDR = pData->table
++      unsigned short key[8];
++      unsigned short val[5];
++      unsigned short mask;
++      unsigned short type;
++      unsigned short valid;
++      unsigned short gmap;
++};
++
++static int xrx200_pce_table_entry_read(struct xrx200_pce_table_entry *tbl)
++{
++      // wait until hardware is ready
++      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
++
++      // prepare the table access:
++      // PCE_TBL_ADDR.ADDR = pData->table_index
++      xrx200sw_write(tbl->index, XRX200_PCE_TBL_ADDR_ADDR);
++      // PCE_TBL_CTRL.ADDR = pData->table
++      xrx200sw_write(tbl->table, XRX200_PCE_TBL_CTRL_ADDR);
++
++      //(address-based read)
++      xrx200sw_write(0, XRX200_PCE_TBL_CTRL_OPMOD); // OPMOD_ADRD
++
++      xrx200sw_write(1, XRX200_PCE_TBL_CTRL_BAS); // start access
++
++      // wait until hardware is ready
++      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
++
++      // read the keys
++      tbl->key[7] = xrx200sw_read(XRX200_PCE_TBL_KEY_7);
++      tbl->key[6] = xrx200sw_read(XRX200_PCE_TBL_KEY_6);
++      tbl->key[5] = xrx200sw_read(XRX200_PCE_TBL_KEY_5);
++      tbl->key[4] = xrx200sw_read(XRX200_PCE_TBL_KEY_4);
++      tbl->key[3] = xrx200sw_read(XRX200_PCE_TBL_KEY_3);
++      tbl->key[2] = xrx200sw_read(XRX200_PCE_TBL_KEY_2);
++      tbl->key[1] = xrx200sw_read(XRX200_PCE_TBL_KEY_1);
++      tbl->key[0] = xrx200sw_read(XRX200_PCE_TBL_KEY_0);
++
++      // read the values
++      tbl->val[4] = xrx200sw_read(XRX200_PCE_TBL_VAL_4);
++      tbl->val[3] = xrx200sw_read(XRX200_PCE_TBL_VAL_3);
++      tbl->val[2] = xrx200sw_read(XRX200_PCE_TBL_VAL_2);
++      tbl->val[1] = xrx200sw_read(XRX200_PCE_TBL_VAL_1);
++      tbl->val[0] = xrx200sw_read(XRX200_PCE_TBL_VAL_0);
++
++      // read the mask
++      tbl->mask = xrx200sw_read(XRX200_PCE_TBL_MASK_0);
++      // read the type
++      tbl->type = xrx200sw_read(XRX200_PCE_TBL_CTRL_TYPE);
++      // read the valid flag
++      tbl->valid = xrx200sw_read(XRX200_PCE_TBL_CTRL_VLD);
++      // read the group map
++      tbl->gmap = xrx200sw_read(XRX200_PCE_TBL_CTRL_GMAP);
++
++      return 0;
++}
++
++static int xrx200_pce_table_entry_write(struct xrx200_pce_table_entry *tbl)
++{
++      // wait until hardware is ready
++      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
++
++      // prepare the table access:
++      // PCE_TBL_ADDR.ADDR = pData->table_index
++      xrx200sw_write(tbl->index, XRX200_PCE_TBL_ADDR_ADDR);
++      // PCE_TBL_CTRL.ADDR = pData->table
++      xrx200sw_write(tbl->table, XRX200_PCE_TBL_CTRL_ADDR);
++
++      //(address-based write)
++      xrx200sw_write(1, XRX200_PCE_TBL_CTRL_OPMOD); // OPMOD_ADRD
++
++      // read the keys
++      xrx200sw_write(tbl->key[7], XRX200_PCE_TBL_KEY_7);
++      xrx200sw_write(tbl->key[6], XRX200_PCE_TBL_KEY_6);
++      xrx200sw_write(tbl->key[5], XRX200_PCE_TBL_KEY_5);
++      xrx200sw_write(tbl->key[4], XRX200_PCE_TBL_KEY_4);
++      xrx200sw_write(tbl->key[3], XRX200_PCE_TBL_KEY_3);
++      xrx200sw_write(tbl->key[2], XRX200_PCE_TBL_KEY_2);
++      xrx200sw_write(tbl->key[1], XRX200_PCE_TBL_KEY_1);
++      xrx200sw_write(tbl->key[0], XRX200_PCE_TBL_KEY_0);
++
++      // read the values
++      xrx200sw_write(tbl->val[4], XRX200_PCE_TBL_VAL_4);
++      xrx200sw_write(tbl->val[3], XRX200_PCE_TBL_VAL_3);
++      xrx200sw_write(tbl->val[2], XRX200_PCE_TBL_VAL_2);
++      xrx200sw_write(tbl->val[1], XRX200_PCE_TBL_VAL_1);
++      xrx200sw_write(tbl->val[0], XRX200_PCE_TBL_VAL_0);
++
++      // read the mask
++      xrx200sw_write(tbl->mask, XRX200_PCE_TBL_MASK_0);
++      // read the type
++      xrx200sw_write(tbl->type, XRX200_PCE_TBL_CTRL_TYPE);
++      // read the valid flag
++      xrx200sw_write(tbl->valid, XRX200_PCE_TBL_CTRL_VLD);
++      // read the group map
++      xrx200sw_write(tbl->gmap, XRX200_PCE_TBL_CTRL_GMAP);
++
++      xrx200sw_write(1, XRX200_PCE_TBL_CTRL_BAS); // start access
++
++      // wait until hardware is ready
++      while (xrx200sw_read(XRX200_PCE_TBL_CTRL_BAS)) {};
++
++      return 0;
++}
++
++static void xrx200sw_fixup_pvids(void)
++{
++      int index, p, portmap, untagged;
++      struct xrx200_pce_table_entry tem;
++      struct xrx200_pce_table_entry tev;
++
++      portmap = 0;
++      for (p = 0; p < XRX200_MAX_PORT; p++)
++              portmap |= BIT(p);
++
++      tem.table = XRX200_PCE_VLANMAP_IDX;
++      tev.table = XRX200_PCE_ACTVLAN_IDX;
++
++      for (index = XRX200_MAX_VLAN; index-- > 0;)
++      {
++              tev.index = index;
++              xrx200_pce_table_entry_read(&tev);
++
++              if (tev.valid == 0)
++                      continue;
++
++              tem.index = index;
++              xrx200_pce_table_entry_read(&tem);
++
++              if (tem.val[0] == 0)
++                      continue;
++
++              untagged = portmap & (tem.val[1] ^ tem.val[2]);
++
++              for (p = 0; p < XRX200_MAX_PORT; p++)
++                      if (untagged & BIT(p))
++                      {
++                              portmap &= ~BIT(p);
++                              xrx200sw_write_x(index, XRX200_PCE_DEFPVID_PVID, p);
++                      }
++
++              for (p = 0; p < XRX200_MAX_PORT; p++)
++                      if (portmap & BIT(p))
++                              xrx200sw_write_x(index, XRX200_PCE_DEFPVID_PVID, p);
++      }
++}
++
++// swconfig interface
++static void xrx200_hw_init(struct xrx200_hw *hw);
++
++// global
++static int xrx200sw_reset_switch(struct switch_dev *dev)
++{
++      struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev);
++
++      xrx200_hw_init(hw);
++
++      return 0;
++}
++
++static int xrx200_set_vlan_mode_enable(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
++{
++      int p;
++
++      if ((attr->max > 0) && (val->value.i > attr->max))
++              return -EINVAL;
++
++      for (p = 0; p < XRX200_MAX_PORT; p++) {
++              xrx200sw_write_x(val->value.i, XRX200_PCE_VCTRL_VEMR, p);
++              xrx200sw_write_x(val->value.i, XRX200_PCE_VCTRL_VIMR, p);
++      }
++
++      xrx200sw_write(val->value.i, XRX200_PCE_GCTRL_0_VLAN);
++      return 0;
++}
++
++static int xrx200_get_vlan_mode_enable(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
++{
++      val->value.i = xrx200sw_read(attr->id);
++      return 0;
++}
++
++static int xrx200_set_global_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
++{
++      if ((attr->max > 0) && (val->value.i > attr->max))
++              return -EINVAL;
++
++      xrx200sw_write(val->value.i, attr->id);
++      return 0;
++}
++
++static int xrx200_get_global_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
++{
++      val->value.i = xrx200sw_read(attr->id);
++      return 0;
++}
++
++// vlan
++static int xrx200sw_set_vlan_vid(struct switch_dev *dev, const struct switch_attr *attr,
++                               struct switch_val *val)
++{
++      int i;
++      struct xrx200_pce_table_entry tev;
++      struct xrx200_pce_table_entry tem;
++
++      tev.table = XRX200_PCE_ACTVLAN_IDX;
++
++      for (i = 0; i < XRX200_MAX_VLAN; i++)
++      {
++              tev.index = i;
++              xrx200_pce_table_entry_read(&tev);
++              if (tev.key[0] == val->value.i && i != val->port_vlan)
++                      return -EINVAL;
++      }
++
++      tev.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&tev);
++      tev.key[0] = val->value.i;
++      tev.valid = val->value.i > 0;
++      xrx200_pce_table_entry_write(&tev);
++
++      tem.table = XRX200_PCE_VLANMAP_IDX;
++      tem.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&tem);
++      tem.val[0] = val->value.i;
++      xrx200_pce_table_entry_write(&tem);
++
++      xrx200sw_fixup_pvids();
++      return 0;
++}
++
++static int xrx200sw_get_vlan_vid(struct switch_dev *dev, const struct switch_attr *attr,
++                               struct switch_val *val)
++{
++      struct xrx200_pce_table_entry te;
++
++      te.table = XRX200_PCE_ACTVLAN_IDX;
++      te.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&te);
++      val->value.i = te.key[0];
++
++      return 0;
++}
++
++static int xrx200sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
++{
++      int i, portmap, tagmap, untagged;
++      struct xrx200_pce_table_entry tem;
++
++      portmap = 0;
++      tagmap = 0;
++      for (i = 0; i < val->len; i++)
++      {
++              struct switch_port *p = &val->value.ports[i];
++
++              portmap |= (1 << p->id);
++              if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
++                      tagmap |= (1 << p->id);
++      }
++
++      tem.table = XRX200_PCE_VLANMAP_IDX;
++
++      untagged = portmap ^ tagmap;
++      for (i = 0; i < XRX200_MAX_VLAN; i++)
++      {
++              tem.index = i;
++              xrx200_pce_table_entry_read(&tem);
++
++              if (tem.val[0] == 0)
++                      continue;
++
++              if ((untagged & (tem.val[1] ^ tem.val[2])) && (val->port_vlan != i))
++                      return -EINVAL;
++      }
++
++      tem.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&tem);
++
++      // auto-enable this vlan if not enabled already
++      if (tem.val[0] == 0)
++      {
++              struct switch_val v;
++              v.port_vlan = val->port_vlan;
++              v.value.i = val->port_vlan;
++              if(xrx200sw_set_vlan_vid(dev, NULL, &v))
++                      return -EINVAL;
++
++              //read updated tem
++              tem.index = val->port_vlan;
++              xrx200_pce_table_entry_read(&tem);
++      }
++
++      tem.val[1] = portmap;
++      tem.val[2] = tagmap;
++      xrx200_pce_table_entry_write(&tem);
++
++      xrx200sw_fixup_pvids();
++
++      return 0;
++}
++
++static int xrx200sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
++{
++      int i;
++      unsigned short ports, tags;
++      struct xrx200_pce_table_entry tem;
++
++      tem.table = XRX200_PCE_VLANMAP_IDX;
++      tem.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&tem);
++
++      ports = tem.val[1];
++      tags = tem.val[2];
++
++      for (i = 0; i < XRX200_MAX_PORT; i++) {
++              struct switch_port *p;
++
++              if (!(ports & (1 << i)))
++                      continue;
++
++              p = &val->value.ports[val->len++];
++              p->id = i;
++              if (tags & (1 << i))
++                      p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
++              else
++                      p->flags = 0;
++      }
++
++      return 0;
++}
++
++static int xrx200sw_set_vlan_enable(struct switch_dev *dev, const struct switch_attr *attr,
++                               struct switch_val *val)
++{
++      struct xrx200_pce_table_entry tev;
++
++      tev.table = XRX200_PCE_ACTVLAN_IDX;
++      tev.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&tev);
++
++      if (tev.key[0] == 0)
++              return -EINVAL;
++
++      tev.valid = val->value.i;
++      xrx200_pce_table_entry_write(&tev);
++
++      xrx200sw_fixup_pvids();
++      return 0;
++}
++
++static int xrx200sw_get_vlan_enable(struct switch_dev *dev, const struct switch_attr *attr,
++                               struct switch_val *val)
++{
++      struct xrx200_pce_table_entry tev;
++
++      tev.table = XRX200_PCE_ACTVLAN_IDX;
++      tev.index = val->port_vlan;
++      xrx200_pce_table_entry_read(&tev);
++      val->value.i = tev.valid;
++
++      return 0;
++}
++
++// port
++static int xrx200sw_get_port_pvid(struct switch_dev *dev, int port, int *val)
++{
++      struct xrx200_pce_table_entry tev;
++
++      if (port >= XRX200_MAX_PORT)
++              return -EINVAL;
++
++      tev.table = XRX200_PCE_ACTVLAN_IDX;
++      tev.index = xrx200sw_read_x(XRX200_PCE_DEFPVID_PVID, port);
++      xrx200_pce_table_entry_read(&tev);
++
++      *val = tev.key[0];
++      return 0;
++}
++
++static int xrx200sw_get_port_link(struct switch_dev *dev,
++                                int port,
++                                struct switch_port_link *link)
++{
++      if (port >= XRX200_MAX_PORT)
++              return -EINVAL;
++
++      link->link = xrx200sw_read_x(XRX200_MAC_PSTAT_LSTAT, port);
++      if (!link->link)
++              return 0;
++
++      link->duplex = xrx200sw_read_x(XRX200_MAC_PSTAT_FDUP, port);
++
++      link->rx_flow = !!(xrx200sw_read_x(XRX200_MAC_CTRL_0_FCON, port) && 0x0010);
++      link->tx_flow = !!(xrx200sw_read_x(XRX200_MAC_CTRL_0_FCON, port) && 0x0020);
++      link->aneg = !(xrx200sw_read_x(XRX200_MAC_CTRL_0_FCON, port));
++
++      link->speed = SWITCH_PORT_SPEED_10;
++      if (xrx200sw_read_x(XRX200_MAC_PSTAT_MBIT, port))
++              link->speed = SWITCH_PORT_SPEED_100;
++      if (xrx200sw_read_x(XRX200_MAC_PSTAT_GBIT, port))
++              link->speed = SWITCH_PORT_SPEED_1000;
++
++      return 0;
++}
++
++static int xrx200_set_port_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
++{
++      printk("%s %s(%d)\n", __FILE__, __func__, __LINE__);
++      if (val->port_vlan >= XRX200_MAX_PORT)
++              return -EINVAL;
++
++      if ((attr->max > 0) && (val->value.i > attr->max))
++              return -EINVAL;
++
++      xrx200sw_write_x(val->value.i, attr->id, val->port_vlan);
++      return 0;
++}
++
++static int xrx200_get_port_attr(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
++{
++      if (val->port_vlan >= XRX200_MAX_PORT)
++              return -EINVAL;
++
++      val->value.i = xrx200sw_read_x(attr->id, val->port_vlan);
++      return 0;
++}
++
++// attributes
++static struct switch_attr xrx200sw_globals[] = {
++      {
++              .type = SWITCH_TYPE_INT,
++              .set = xrx200_set_vlan_mode_enable,
++              .get = xrx200_get_vlan_mode_enable,
++              .name = "enable_vlan",
++              .description = "Enable VLAN mode",
++              .max = 1},
++};
++
++static struct switch_attr xrx200sw_port[] = {
++      {
++      XRX200_PORT_REGATTR(XRX200_PCE_VCTRL_UVR),
++      .name = "uvr",
++      .description = "Unknown VLAN Rule",
++      .max = 1,
++      },
++      {
++      XRX200_PORT_REGATTR(XRX200_PCE_VCTRL_VSR),
++      .name = "vsr",
++      .description = "VLAN Security Rule",
++      .max = 1,
++      },
++      {
++      XRX200_PORT_REGATTR(XRX200_PCE_VCTRL_VINR),
++      .name = "vinr",
++      .description = "VLAN Ingress Tag Rule",
++      .max = 2,
++      },
++      {
++      XRX200_PORT_REGATTR(XRX200_PCE_PCTRL_0_TVM),
++      .name = "tvm",
++      .description = "Transparent VLAN Mode",
++      .max = 1,
++      },
++};
++
++static struct switch_attr xrx200sw_vlan[] = {
++      {
++              .type = SWITCH_TYPE_INT,
++              .name = "vid",
++              .description = "VLAN ID (0-4094)",
++              .set = xrx200sw_set_vlan_vid,
++              .get = xrx200sw_get_vlan_vid,
++              .max = 4094,
++      },
++      {
++              .type = SWITCH_TYPE_INT,
++              .name = "enable",
++              .description = "Enable VLAN",
++              .set = xrx200sw_set_vlan_enable,
++              .get = xrx200sw_get_vlan_enable,
++              .max = 1,
++      },
++};
++
++static const struct switch_dev_ops xrx200sw_ops = {
++      .attr_global = {
++              .attr = xrx200sw_globals,
++              .n_attr = ARRAY_SIZE(xrx200sw_globals),
++      },
++      .attr_port = {
++              .attr = xrx200sw_port,
++              .n_attr = ARRAY_SIZE(xrx200sw_port),
++      },
++      .attr_vlan = {
++              .attr = xrx200sw_vlan,
++              .n_attr = ARRAY_SIZE(xrx200sw_vlan),
++      },
++      .get_vlan_ports = xrx200sw_get_vlan_ports,
++      .set_vlan_ports = xrx200sw_set_vlan_ports,
++      .get_port_pvid = xrx200sw_get_port_pvid,
++      .reset_switch = xrx200sw_reset_switch,
++      .get_port_link = xrx200sw_get_port_link,
++//    .get_port_stats = xrx200sw_get_port_stats, //TODO
++};
++
++static int xrx200sw_init(struct xrx200_hw *hw)
++{
++      int netdev_num;
++
++      for (netdev_num = 0; netdev_num < hw->num_devs; netdev_num++)
++      {
++              struct switch_dev *swdev;
++              struct net_device *dev = hw->devs[netdev_num];
++              struct xrx200_priv *priv = netdev_priv(dev);
++              if (!priv->sw)
++                      continue;
++
++              swdev = &hw->swdev;
++
++              swdev->name = "Lantiq XRX200 Switch";
++              swdev->vlans = XRX200_MAX_VLAN;
++              swdev->ports = XRX200_MAX_PORT;
++              swdev->cpu_port = 6;
++              swdev->ops = &xrx200sw_ops;
++
++              register_switch(swdev, dev);
++              return 0; // enough switches
++      }
++      return 0;
++}
++
++static int xrx200_open(struct net_device *dev)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++      unsigned long flags;
++      int i;
++
++      for (i = 0; i < XRX200_MAX_DMA; i++) {
++              if (!priv->hw->chan[i].dma.irq)
++                      continue;
++              spin_lock_irqsave(&priv->hw->lock, flags);
++              if (!priv->hw->chan[i].refcount) {
++                      if (XRX200_DMA_IS_RX(i))
++                              napi_enable(&priv->hw->chan[i].napi);
++                      ltq_dma_open(&priv->hw->chan[i].dma);
++              }
++              priv->hw->chan[i].refcount++;
++              spin_unlock_irqrestore(&priv->hw->lock, flags);
++      }
++      for (i = 0; i < priv->num_port; i++)
++              if (priv->port[i].phydev)
++                      phy_start(priv->port[i].phydev);
++      netif_start_queue(dev);
++
++      return 0;
++}
++
++static int xrx200_close(struct net_device *dev)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++      unsigned long flags;
++      int i;
++
++      netif_stop_queue(dev);
++
++      for (i = 0; i < priv->num_port; i++)
++              if (priv->port[i].phydev)
++                      phy_stop(priv->port[i].phydev);
++
++      for (i = 0; i < XRX200_MAX_DMA; i++) {
++              if (!priv->hw->chan[i].dma.irq)
++                      continue;
++              spin_lock_irqsave(&priv->hw->lock, flags);
++              priv->hw->chan[i].refcount--;
++              if (!priv->hw->chan[i].refcount) {
++                      if (XRX200_DMA_IS_RX(i))
++                              napi_disable(&priv->hw->chan[i].napi);
++                      ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma);
++              }
++              spin_unlock_irqrestore(&priv->hw->lock, flags);
++      }
++
++      return 0;
++}
++
++static int xrx200_alloc_skb(struct xrx200_chan *ch)
++{
++#define DMA_PAD       (NET_IP_ALIGN + NET_SKB_PAD)
++      ch->skb[ch->dma.desc] = dev_alloc_skb(XRX200_DMA_DATA_LEN + DMA_PAD);
++      if (!ch->skb[ch->dma.desc])
++              return -ENOMEM;
++
++      skb_reserve(ch->skb[ch->dma.desc], NET_SKB_PAD);
++      ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
++              ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN,
++                      DMA_FROM_DEVICE);
++      ch->dma.desc_base[ch->dma.desc].addr =
++              CPHYSADDR(ch->skb[ch->dma.desc]->data);
++      ch->dma.desc_base[ch->dma.desc].ctl =
++              LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
++              XRX200_DMA_DATA_LEN;
++      skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
++
++      return 0;
++}
++
++static void xrx200_hw_receive(struct xrx200_chan *ch, int id)
++{
++      struct net_device *dev = ch->devs[id];
++      struct xrx200_priv *priv = netdev_priv(dev);
++      struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++      struct sk_buff *skb = ch->skb[ch->dma.desc];
++      int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - ETH_FCS_LEN;
++      unsigned long flags;
++
++      spin_lock_irqsave(&priv->hw->lock, flags);
++      if (xrx200_alloc_skb(ch)) {
++              netdev_err(dev,
++                      "failed to allocate new rx buffer, stopping DMA\n");
++              ltq_dma_close(&ch->dma);
++      }
++
++      ch->dma.desc++;
++      ch->dma.desc %= LTQ_DESC_NUM;
++      spin_unlock_irqrestore(&priv->hw->lock, flags);
++
++      skb_put(skb, len);
++#ifdef SW_ROUTING
++      skb_pull(skb, 8);
++#endif
++      skb->dev = dev;
++      skb->protocol = eth_type_trans(skb, dev);
++      netif_receive_skb(skb);
++      priv->stats.rx_packets++;
++      priv->stats.rx_bytes+=len;
++}
++
++static int xrx200_poll_rx(struct napi_struct *napi, int budget)
++{
++      struct xrx200_chan *ch = container_of(napi,
++                              struct xrx200_chan, napi);
++      struct xrx200_priv *priv = netdev_priv(ch->devs[0]);
++      int rx = 0;
++      int complete = 0;
++      unsigned long flags;
++
++      while ((rx < budget) && !complete) {
++              struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++              if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
++#ifdef SW_ROUTING
++                      struct sk_buff *skb = ch->skb[ch->dma.desc];
++                      u32 *special_tag = (u32*)skb->data;
++                      int port = (special_tag[1] >> SPPID_SHIFT) & SPPID_MASK;
++                      xrx200_hw_receive(ch, priv->hw->port_map[port]);
++#else
++                      xrx200_hw_receive(ch, 0);
++#endif
++                      rx++;
++              } else {
++                      complete = 1;
++              }
++      }
++      if (complete || !rx) {
++              napi_complete(&ch->napi);
++              spin_lock_irqsave(&priv->hw->lock, flags);
++              ltq_dma_ack_irq(&ch->dma);
++              spin_unlock_irqrestore(&priv->hw->lock, flags);
++      }
++      return rx;
++}
++
++static void xrx200_tx_housekeeping(unsigned long ptr)
++{
++      struct xrx200_hw *hw = (struct xrx200_hw *) ptr;
++      struct xrx200_chan *ch = &hw->chan[XRX200_DMA_TX];
++      unsigned long flags;
++      int i;
++
++      spin_lock_irqsave(&hw->lock, flags);
++      while ((ch->dma.desc_base[ch->tx_free].ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
++              dev_kfree_skb_any(ch->skb[ch->tx_free]);
++              ch->skb[ch->tx_free] = NULL;
++              memset(&ch->dma.desc_base[ch->tx_free], 0,
++                      sizeof(struct ltq_dma_desc));
++              ch->tx_free++;
++              ch->tx_free %= LTQ_DESC_NUM;
++      }
++      spin_unlock_irqrestore(&hw->lock, flags);
++
++      for (i = 0; i < XRX200_MAX_DEV && ch->devs[i]; i++) {
++              struct netdev_queue *txq =
++                      netdev_get_tx_queue(ch->devs[i], 0);
++              if (netif_tx_queue_stopped(txq))
++                      netif_tx_start_queue(txq);
++      }
++
++      spin_lock_irqsave(&hw->lock, flags);
++      ltq_dma_ack_irq(&ch->dma);
++      spin_unlock_irqrestore(&hw->lock, flags);
++}
++
++static struct net_device_stats *xrx200_get_stats (struct net_device *dev)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++
++      return &priv->stats;
++}
++
++static void xrx200_tx_timeout(struct net_device *dev)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++
++      printk(KERN_ERR "%s: transmit timed out, disable the dma channel irq\n", dev->name);
++
++      priv->stats.tx_errors++;
++      netif_wake_queue(dev);
++}
++
++static int xrx200_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++      int queue = skb_get_queue_mapping(skb);
++      struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
++      struct xrx200_priv *priv = netdev_priv(dev);
++      struct xrx200_chan *ch = &priv->hw->chan[XRX200_DMA_TX];
++      struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++      unsigned long flags;
++      u32 byte_offset;
++      int len;
++#ifdef SW_ROUTING
++  #ifdef SW_PORTMAP
++      u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | PORT_MAP_SEL | PORT_MAP_EN | DPID_ENABLE;
++  #else
++      u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | DPID_ENABLE;
++  #endif
++#endif
++
++      len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
++
++      if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
++              netdev_err(dev, "tx ring full\n");
++              netif_tx_stop_queue(txq);
++              return NETDEV_TX_BUSY;
++      }
++#ifdef SW_ROUTING
++  #ifdef SW_PORTMAP
++      special_tag |= priv->port_map << PORT_MAP_SHIFT;
++  #else
++      if(priv->id)
++              special_tag |= (1 << DPID_SHIFT);
++  #endif
++      if(skb_headroom(skb) < 4) {
++              struct sk_buff *tmp = skb_realloc_headroom(skb, 4);
++              dev_kfree_skb_any(skb);
++              skb = tmp;
++      }
++      skb_push(skb, 4);
++      memcpy(skb->data, &special_tag, sizeof(u32));
++      len += 4;
++#endif
++
++      /* dma needs to start on a 16 byte aligned address */
++      byte_offset = CPHYSADDR(skb->data) % 16;
++      ch->skb[ch->dma.desc] = skb;
++
++      dev->trans_start = jiffies;
++
++      spin_lock_irqsave(&priv->hw->lock, flags);
++      desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
++                                              DMA_TO_DEVICE)) - byte_offset;
++      wmb();
++      desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
++              LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
++      ch->dma.desc++;
++      ch->dma.desc %= LTQ_DESC_NUM;
++      spin_unlock_irqrestore(&priv->hw->lock, flags);
++
++      if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
++              netif_tx_stop_queue(txq);
++
++      priv->stats.tx_packets++;
++      priv->stats.tx_bytes+=len;
++
++      return NETDEV_TX_OK;
++}
++
++static irqreturn_t xrx200_dma_irq(int irq, void *priv)
++{
++      struct xrx200_hw *hw = priv;
++      int ch = irq - XRX200_DMA_IRQ;
++
++      if (ch % 2)
++              tasklet_schedule(&hw->chan[ch].tasklet);
++      else
++              napi_schedule(&hw->chan[ch].napi);
++
++      return IRQ_HANDLED;
++}
++
++static int xrx200_dma_init(struct xrx200_hw *hw)
++{
++      int i, err = 0;
++
++      ltq_dma_init_port(DMA_PORT_ETOP);
++
++      for (i = 0; i < 8 && !err; i++) {
++              int irq = XRX200_DMA_IRQ + i;
++              struct xrx200_chan *ch = &hw->chan[i];
++
++              ch->idx = ch->dma.nr = i;
++
++              if (i == XRX200_DMA_TX) {
++                      ltq_dma_alloc_tx(&ch->dma);
++                      err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_tx", hw);
++              } else if (i == XRX200_DMA_RX) {
++                      ltq_dma_alloc_rx(&ch->dma);
++                      for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
++                                      ch->dma.desc++)
++                              if (xrx200_alloc_skb(ch))
++                                      err = -ENOMEM;
++                      ch->dma.desc = 0;
++                      err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_rx", hw);
++              } else
++                      continue;
++
++              if (!err)
++                      ch->dma.irq = irq;
++      }
++
++      return err;
++}
++
++#ifdef SW_POLLING
++static void xrx200_gmac_update(struct xrx200_port *port)
++{
++      u16 phyaddr = port->phydev->addr & MDIO_PHY_ADDR_MASK;
++      u16 miimode = ltq_mii_r32(MII_CFG(port->num)) & MII_CFG_MODE_MASK;
++      u16 miirate = 0;
++
++      switch (port->phydev->speed) {
++      case SPEED_1000:
++              phyaddr |= MDIO_PHY_SPEED_G1;
++              miirate = MII_CFG_RATE_M125;
++              break;
++
++      case SPEED_100:
++              phyaddr |= MDIO_PHY_SPEED_M100;
++              switch (miimode) {
++              case MII_CFG_MODE_RMIIM:
++              case MII_CFG_MODE_RMIIP:
++                      miirate = MII_CFG_RATE_M50;
++                      break;
++              default:
++                      miirate = MII_CFG_RATE_M25;
++                      break;
++              }
++              break;
++
++      default:
++              phyaddr |= MDIO_PHY_SPEED_M10;
++              miirate = MII_CFG_RATE_M2P5;
++              break;
++      }
++
++      if (port->phydev->link)
++              phyaddr |= MDIO_PHY_LINK_UP;
++      else
++              phyaddr |= MDIO_PHY_LINK_DOWN;
++
++      if (port->phydev->duplex == DUPLEX_FULL)
++              phyaddr |= MDIO_PHY_FDUP_EN;
++      else
++              phyaddr |= MDIO_PHY_FDUP_DIS;
++
++      ltq_mdio_w32_mask(MDIO_UPDATE_MASK, phyaddr, MDIO_PHY(port->num));
++      ltq_mii_w32_mask(MII_CFG_RATE_MASK, miirate, MII_CFG(port->num));
++      udelay(1);
++}
++#else
++static void xrx200_gmac_update(struct xrx200_port *port)
++{
++
++}
++#endif
++
++static void xrx200_mdio_link(struct net_device *dev)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++      int i;
++
++      for (i = 0; i < priv->num_port; i++) {
++              if (!priv->port[i].phydev)
++                      continue;
++
++              if (priv->port[i].link != priv->port[i].phydev->link) {
++                      xrx200_gmac_update(&priv->port[i]);
++                      priv->port[i].link = priv->port[i].phydev->link;
++                      netdev_info(dev, "port %d %s link\n",
++                              priv->port[i].num,
++                              (priv->port[i].link)?("got"):("lost"));
++              }
++      }
++}
++
++static inline int xrx200_mdio_poll(struct mii_bus *bus)
++{
++      unsigned cnt = 10000;
++
++      while (likely(cnt--)) {
++              unsigned ctrl = ltq_mdio_r32(MDIO_CTRL);
++              if ((ctrl & MDIO_BUSY) == 0)
++                      return 0;
++      }
++
++      return 1;
++}
++
++static int xrx200_mdio_wr(struct mii_bus *bus, int addr, int reg, u16 val)
++{
++      if (xrx200_mdio_poll(bus))
++              return 1;
++
++      ltq_mdio_w32(val, MDIO_WRITE);
++      ltq_mdio_w32(MDIO_BUSY | MDIO_WR |
++              ((addr & MDIO_MASK) << MDIO_ADDRSHIFT) |
++              (reg & MDIO_MASK),
++              MDIO_CTRL);
++
++      return 0;
++}
++
++static int xrx200_mdio_rd(struct mii_bus *bus, int addr, int reg)
++{
++      if (xrx200_mdio_poll(bus))
++              return -1;
++
++      ltq_mdio_w32(MDIO_BUSY | MDIO_RD |
++              ((addr & MDIO_MASK) << MDIO_ADDRSHIFT) |
++              (reg & MDIO_MASK),
++              MDIO_CTRL);
++
++      if (xrx200_mdio_poll(bus))
++              return -1;
++
++      return ltq_mdio_r32(MDIO_READ);
++}
++
++static int xrx200_mdio_probe(struct net_device *dev, struct xrx200_port *port)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++      struct phy_device *phydev = NULL;
++      unsigned val;
++
++      phydev = priv->hw->mii_bus->phy_map[port->phy_addr];
++
++      if (!phydev) {
++              netdev_err(dev, "no PHY found\n");
++              return -ENODEV;
++      }
++
++      phydev = phy_connect(dev, dev_name(&phydev->dev), &xrx200_mdio_link,
++                              port->phy_if);
++
++      if (IS_ERR(phydev)) {
++              netdev_err(dev, "Could not attach to PHY\n");
++              return PTR_ERR(phydev);
++      }
++
++      phydev->supported &= (SUPPORTED_10baseT_Half
++                      | SUPPORTED_10baseT_Full
++                      | SUPPORTED_100baseT_Half
++                      | SUPPORTED_100baseT_Full
++                      | SUPPORTED_1000baseT_Half
++                      | SUPPORTED_1000baseT_Full
++                      | SUPPORTED_Autoneg
++                      | SUPPORTED_MII
++                      | SUPPORTED_TP);
++      phydev->advertising = phydev->supported;
++      port->phydev = phydev;
++
++      pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
++              dev->name, phydev->drv->name,
++              dev_name(&phydev->dev), phydev->irq);
++
++#ifdef SW_POLLING
++      phy_read_status(phydev);
++
++      val = xrx200_mdio_rd(priv->hw->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000);
++      val |= ADVERTIZE_MPD;
++      xrx200_mdio_wr(priv->hw->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000, val);
++      xrx200_mdio_wr(priv->hw->mii_bus, 0, 0, 0x1040);
++
++      phy_start_aneg(phydev);
++#endif
++      return 0;
++}
++
++static void xrx200_port_config(struct xrx200_priv *priv,
++              const struct xrx200_port *port)
++{
++      u16 miimode = 0;
++
++      switch (port->num) {
++      case 0: /* xMII0 */
++      case 1: /* xMII1 */
++              switch (port->phy_if) {
++              case PHY_INTERFACE_MODE_MII:
++                      if (port->flags & XRX200_PORT_TYPE_PHY)
++                              /* MII MAC mode, connected to external PHY */
++                              miimode = MII_CFG_MODE_MIIM;
++                      else
++                              /* MII PHY mode, connected to external MAC */
++                              miimode = MII_CFG_MODE_MIIP;
++                      break;
++              case PHY_INTERFACE_MODE_RMII:
++                      if (port->flags & XRX200_PORT_TYPE_PHY)
++                              /* RMII MAC mode, connected to external PHY */
++                              miimode = MII_CFG_MODE_RMIIM;
++                      else
++                              /* RMII PHY mode, connected to external MAC */
++                              miimode = MII_CFG_MODE_RMIIP;
++                      break;
++              case PHY_INTERFACE_MODE_RGMII:
++                      /* RGMII MAC mode, connected to external PHY */
++                      miimode = MII_CFG_MODE_RGMII;
++                      break;
++              default:
++                      break;
++              }
++              break;
++      case 2: /* internal GPHY0 */
++      case 3: /* internal GPHY0 */
++      case 4: /* internal GPHY1 */
++              switch (port->phy_if) {
++                      case PHY_INTERFACE_MODE_MII:
++                      case PHY_INTERFACE_MODE_GMII:
++                              /* MII MAC mode, connected to internal GPHY */
++                              miimode = MII_CFG_MODE_MIIM;
++                              break;
++                      default:
++                              break;
++              }
++              break;
++      case 5: /* internal GPHY1 or xMII2 */
++              switch (port->phy_if) {
++              case PHY_INTERFACE_MODE_MII:
++                      /* MII MAC mode, connected to internal GPHY */
++                      miimode = MII_CFG_MODE_MIIM;
++                      break;
++              case PHY_INTERFACE_MODE_RGMII:
++                      /* RGMII MAC mode, connected to external PHY */
++                      miimode = MII_CFG_MODE_RGMII;
++                      break;
++              default:
++                      break;
++              }
++              break;
++      default:
++              break;
++      }
++
++      ltq_mii_w32_mask(MII_CFG_MODE_MASK, miimode | MII_CFG_EN,
++              MII_CFG(port->num));
++}
++
++static int xrx200_init(struct net_device *dev)
++{
++      struct xrx200_priv *priv = netdev_priv(dev);
++      struct sockaddr mac;
++      int err, i;
++
++#ifndef SW_POLLING
++      unsigned int reg = 0;
++
++      /* enable auto polling */
++      for (i = 0; i < priv->num_port; i++)
++              reg |= BIT(priv->port[i].num);
++      ltq_mdio_w32(reg, MDIO_CLK_CFG0);
++      ltq_mdio_w32(MDIO1_25MHZ, MDIO_CLK_CFG1);
++#endif
++
++      /* setup each port */
++      for (i = 0; i < priv->num_port; i++)
++              xrx200_port_config(priv, &priv->port[i]);
++
++      memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
++      if (!is_valid_ether_addr(mac.sa_data)) {
++              pr_warn("net-xrx200: invalid MAC, using random\n");
++              eth_random_addr(mac.sa_data);
++              dev->addr_assign_type |= NET_ADDR_RANDOM;
++      }
++
++      err = eth_mac_addr(dev, &mac);
++      if (err)
++              goto err_netdev;
++
++      for (i = 0; i < priv->num_port; i++)
++              if (xrx200_mdio_probe(dev, &priv->port[i]))
++                      pr_warn("xrx200-mdio: probing phy of port %d failed\n",
++                                       priv->port[i].num);
++
++      return 0;
++
++err_netdev:
++      unregister_netdev(dev);
++      free_netdev(dev);
++      return err;
++}
++
++static void xrx200_pci_microcode(void)
++{
++      int i;
++
++      ltq_switch_w32_mask(PCE_TBL_CFG_ADDR_MASK | PCE_TBL_CFG_ADWR_MASK,
++              PCE_TBL_CFG_ADWR, PCE_TBL_CTRL);
++      ltq_switch_w32(0, PCE_TBL_MASK);
++
++      for (i = 0; i < ARRAY_SIZE(pce_microcode); i++) {
++              ltq_switch_w32(i, PCE_TBL_ADDR);
++              ltq_switch_w32(pce_microcode[i].val[3], PCE_TBL_VAL(0));
++              ltq_switch_w32(pce_microcode[i].val[2], PCE_TBL_VAL(1));
++              ltq_switch_w32(pce_microcode[i].val[1], PCE_TBL_VAL(2));
++              ltq_switch_w32(pce_microcode[i].val[0], PCE_TBL_VAL(3));
++
++              // start the table access:
++              ltq_switch_w32_mask(0, PCE_TBL_BUSY, PCE_TBL_CTRL);
++              while (ltq_switch_r32(PCE_TBL_CTRL) & PCE_TBL_BUSY);
++      }
++
++      /* tell the switch that the microcode is loaded */
++      ltq_switch_w32_mask(0, BIT(3), PCE_GCTRL_REG(0));
++}
++
++static void xrx200_hw_init(struct xrx200_hw *hw)
++{
++      int i;
++
++      /* enable clock gate */
++      clk_enable(hw->clk);
++
++      ltq_switch_w32(1, 0);
++      mdelay(100);
++      ltq_switch_w32(0, 0);
++      /*
++       * TODO: we should really disbale all phys/miis here and explicitly
++       * enable them in the device secific init function
++       */
++
++      /* disable port fetch/store dma */
++      for (i = 0; i < 7; i++ ) {
++              ltq_switch_w32(0, FDMA_PCTRLx(i));
++              ltq_switch_w32(0, SDMA_PCTRLx(i));
++      }
++
++      /* enable Switch */
++      ltq_mdio_w32_mask(0, MDIO_GLOB_ENABLE, MDIO_GLOB);
++
++      /* load the pce microcode */
++      xrx200_pci_microcode();
++
++      /* Default unknown Broadcat/Multicast/Unicast port maps */
++      ltq_switch_w32(0x7f, PCE_PMAP1);
++      ltq_switch_w32(0x7f, PCE_PMAP2);
++      ltq_switch_w32(0x7f, PCE_PMAP3);
++
++      /* RMON Counter Enable for all physical ports */
++      for (i = 0; i < 7; i++)
++              ltq_switch_w32(0x1, BM_PCFG(i));
++
++      /* disable auto polling */
++      ltq_mdio_w32(0x0, MDIO_CLK_CFG0);
++
++      /* enable port statistic counters */
++      for (i = 0; i < 7; i++)
++              ltq_switch_w32(0x1, BM_PCFGx(i));
++
++      /* set IPG to 12 */
++      ltq_pmac_w32_mask(PMAC_IPG_MASK, 0xb, PMAC_RX_IPG);
++
++#ifdef SW_ROUTING
++      /* enable status header, enable CRC */
++      ltq_pmac_w32_mask(0,
++              PMAC_HD_CTL_RST | PMAC_HD_CTL_AST | PMAC_HD_CTL_RXSH | PMAC_HD_CTL_AS | PMAC_HD_CTL_AC,
++              PMAC_HD_CTL);
++#else
++      /* disable status header, enable CRC */
++      ltq_pmac_w32_mask(PMAC_HD_CTL_AST | PMAC_HD_CTL_RXSH | PMAC_HD_CTL_AS,
++              PMAC_HD_CTL_AC,
++              PMAC_HD_CTL);
++#endif
++
++      /* enable port fetch/store dma & VLAN Modification */
++      for (i = 0; i < 7; i++ ) {
++              ltq_switch_w32_mask(0, 0x19, FDMA_PCTRLx(i));
++              ltq_switch_w32_mask(0, 0x01, SDMA_PCTRLx(i));
++              ltq_switch_w32_mask(0, PCE_INGRESS, PCE_PCTRL_REG(i, 0));
++      }
++
++      /* enable special tag insertion on cpu port */
++      ltq_switch_w32_mask(0, 0x02, FDMA_PCTRLx(6));
++      ltq_switch_w32_mask(0, PCE_INGRESS, PCE_PCTRL_REG(6, 0));
++      ltq_switch_w32_mask(0, BIT(3), MAC_CTRL_REG(6, 2));
++      ltq_switch_w32(1518 + 8 + 4 * 2, MAC_FLEN_REG);
++}
++
++static void xrx200_hw_cleanup(struct xrx200_hw *hw)
++{
++      int i;
++
++      /* disable the switch */
++      ltq_mdio_w32_mask(MDIO_GLOB_ENABLE, 0, MDIO_GLOB);
++
++      /* free the channels and IRQs */
++      for (i = 0; i < 2; i++) {
++              ltq_dma_free(&hw->chan[i].dma);
++              if (hw->chan[i].dma.irq)
++                      free_irq(hw->chan[i].dma.irq, hw);
++      }
++
++      /* free the allocated RX ring */
++      for (i = 0; i < LTQ_DESC_NUM; i++)
++              dev_kfree_skb_any(hw->chan[XRX200_DMA_RX].skb[i]);
++
++      /* clear the mdio bus */
++      mdiobus_unregister(hw->mii_bus);
++      mdiobus_free(hw->mii_bus);
++
++      /* release the clock */
++      clk_disable(hw->clk);
++      clk_put(hw->clk);
++}
++
++static int xrx200_of_mdio(struct xrx200_hw *hw, struct device_node *np)
++{
++      hw->mii_bus = mdiobus_alloc();
++      if (!hw->mii_bus)
++              return -ENOMEM;
++
++      hw->mii_bus->read = xrx200_mdio_rd;
++      hw->mii_bus->write = xrx200_mdio_wr;
++      hw->mii_bus->name = "lantiq,xrx200-mdio";
++      snprintf(hw->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
++
++      if (of_mdiobus_register(hw->mii_bus, np)) {
++              mdiobus_free(hw->mii_bus);
++              return -ENXIO;
++      }
++
++      return 0;
++}
++
++static void xrx200_of_port(struct xrx200_priv *priv, struct device_node *port)
++{
++      const __be32 *addr, *id = of_get_property(port, "reg", NULL);
++      struct xrx200_port *p = &priv->port[priv->num_port];
++
++      if (!id)
++              return;
++
++      memset(p, 0, sizeof(struct xrx200_port));
++      p->phy_node = of_parse_phandle(port, "phy-handle", 0);
++      addr = of_get_property(p->phy_node, "reg", NULL);
++      if (!addr)
++              return;
++
++      p->num = *id;
++      p->phy_addr = *addr;
++      p->phy_if = of_get_phy_mode(port);
++      if (p->phy_addr > 0x10)
++              p->flags = XRX200_PORT_TYPE_MAC;
++      else
++              p->flags = XRX200_PORT_TYPE_PHY;
++      priv->num_port++;
++
++      p->gpio = of_get_gpio_flags(port, 0, &p->gpio_flags);
++      if (gpio_is_valid(p->gpio))
++              if (!gpio_request(p->gpio, "phy-reset")) {
++                      gpio_direction_output(p->gpio,
++                              (p->gpio_flags & OF_GPIO_ACTIVE_LOW) ? (1) : (0));
++                      udelay(100);
++                      gpio_set_value(p->gpio, (p->gpio_flags & OF_GPIO_ACTIVE_LOW) ? (0) : (1));
++              }
++      /* is this port a wan port ? */
++      if (priv->wan)
++              priv->hw->wan_map |= BIT(p->num);
++
++      priv->port_map |= BIT(p->num);
++
++      /* store the port id in the hw struct so we can map ports -> devices */
++      priv->hw->port_map[p->num] = priv->hw->num_devs;
++}
++
++static const struct net_device_ops xrx200_netdev_ops = {
++      .ndo_init               = xrx200_init,
++      .ndo_open               = xrx200_open,
++      .ndo_stop               = xrx200_close,
++      .ndo_start_xmit         = xrx200_start_xmit,
++      .ndo_set_mac_address    = eth_mac_addr,
++      .ndo_validate_addr      = eth_validate_addr,
++      .ndo_change_mtu         = eth_change_mtu,
++      .ndo_get_stats          = xrx200_get_stats,
++      .ndo_tx_timeout         = xrx200_tx_timeout,
++};
++
++static void xrx200_of_iface(struct xrx200_hw *hw, struct device_node *iface)
++{
++      struct xrx200_priv *priv;
++      struct device_node *port;
++      const __be32 *wan;
++      const __be32 *sw;
++
++      /* alloc the network device */
++      hw->devs[hw->num_devs] = alloc_etherdev(sizeof(struct xrx200_priv));
++      if (!hw->devs[hw->num_devs])
++              return;
++
++      /* setup the network device */
++      strcpy(hw->devs[hw->num_devs]->name, "eth%d");
++      hw->devs[hw->num_devs]->netdev_ops = &xrx200_netdev_ops;
++      hw->devs[hw->num_devs]->watchdog_timeo = XRX200_TX_TIMEOUT;
++      hw->devs[hw->num_devs]->needed_headroom = XRX200_HEADROOM;
++
++      /* setup our private data */
++      priv = netdev_priv(hw->devs[hw->num_devs]);
++      priv->hw = hw;
++      of_get_mac_address_mtd(iface, priv->mac);
++      priv->id = hw->num_devs;
++
++      /* is this the wan interface ? */
++      wan = of_get_property(iface, "lantiq,wan", NULL);
++      if (wan && (*wan == 1))
++              priv->wan = 1;
++
++      /* should the switch be enabled on this interface ? */
++      sw = of_get_property(iface, "lantiq,switch", NULL);
++      if (sw && (*sw == 1))
++              priv->sw = 1;
++
++      /* load the ports that are part of the interface */
++      for_each_child_of_node(iface, port)
++              if (of_device_is_compatible(port, "lantiq,xrx200-pdi-port"))
++                      xrx200_of_port(priv, port);
++
++      /* register the actual device */
++      if (!register_netdev(hw->devs[hw->num_devs]))
++              hw->num_devs++;
++}
++
++static struct xrx200_hw xrx200_hw;
++
++static int xrx200_probe(struct platform_device *pdev)
++{
++      struct resource *res[4];
++      struct device_node *mdio_np, *iface_np;
++      int i;
++
++      /* load the memory ranges */
++      for (i = 0; i < 4; i++) {
++              res[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
++              if (!res[i]) {
++                      dev_err(&pdev->dev, "failed to get resources\n");
++                      return -ENOENT;
++              }
++      }
++      xrx200_switch_membase = devm_request_and_ioremap(&pdev->dev, res[0]);
++      xrx200_mdio_membase = devm_request_and_ioremap(&pdev->dev, res[1]);
++      xrx200_mii_membase = devm_request_and_ioremap(&pdev->dev, res[2]);
++      xrx200_pmac_membase = devm_request_and_ioremap(&pdev->dev, res[3]);
++      if (!xrx200_switch_membase || !xrx200_mdio_membase ||
++                      !xrx200_mii_membase || !xrx200_pmac_membase) {
++              dev_err(&pdev->dev, "failed to request and remap io ranges \n");
++              return -ENOMEM;
++      }
++
++      /* get the clock */
++      xrx200_hw.clk = clk_get(&pdev->dev, NULL);
++      if (IS_ERR(xrx200_hw.clk)) {
++              dev_err(&pdev->dev, "failed to get clock\n");
++              return PTR_ERR(xrx200_hw.clk);
++      }
++
++      /* bring up the dma engine and IP core */
++      spin_lock_init(&xrx200_hw.lock);
++      xrx200_dma_init(&xrx200_hw);
++      xrx200_hw_init(&xrx200_hw);
++      tasklet_init(&xrx200_hw.chan[XRX200_DMA_TX].tasklet, xrx200_tx_housekeeping, (u32) &xrx200_hw);
++
++      /* bring up the mdio bus */
++      mdio_np = of_find_compatible_node(pdev->dev.of_node, NULL,
++                              "lantiq,xrx200-mdio");
++      if (mdio_np)
++              if (xrx200_of_mdio(&xrx200_hw, mdio_np))
++                      dev_err(&pdev->dev, "mdio probe failed\n");
++
++      /* load the interfaces */
++      for_each_child_of_node(pdev->dev.of_node, iface_np)
++              if (of_device_is_compatible(iface_np, "lantiq,xrx200-pdi")) {
++                      if (xrx200_hw.num_devs < XRX200_MAX_DEV)
++                              xrx200_of_iface(&xrx200_hw, iface_np);
++                      else
++                              dev_err(&pdev->dev,
++                                      "only %d interfaces allowed\n",
++                                      XRX200_MAX_DEV);
++              }
++
++      if (!xrx200_hw.num_devs) {
++              xrx200_hw_cleanup(&xrx200_hw);
++              dev_err(&pdev->dev, "failed to load interfaces\n");
++              return -ENOENT;
++      }
++
++      xrx200sw_init(&xrx200_hw);
++
++      /* set wan port mask */
++      ltq_pmac_w32(xrx200_hw.wan_map, PMAC_EWAN);
++
++      for (i = 0; i < xrx200_hw.num_devs; i++) {
++              xrx200_hw.chan[XRX200_DMA_RX].devs[i] = xrx200_hw.devs[i];
++              xrx200_hw.chan[XRX200_DMA_TX].devs[i] = xrx200_hw.devs[i];
++      }
++
++      /* setup NAPI */
++      init_dummy_netdev(&xrx200_hw.chan[XRX200_DMA_RX].dummy_dev);
++      netif_napi_add(&xrx200_hw.chan[XRX200_DMA_RX].dummy_dev,
++                      &xrx200_hw.chan[XRX200_DMA_RX].napi, xrx200_poll_rx, 32);
++
++      platform_set_drvdata(pdev, &xrx200_hw);
++
++      return 0;
++}
++
++static int xrx200_remove(struct platform_device *pdev)
++{
++      struct net_device *dev = platform_get_drvdata(pdev);
++      struct xrx200_priv *priv;
++
++      if (!dev)
++              return 0;
++
++      priv = netdev_priv(dev);
++
++      /* free stack related instances */
++      netif_stop_queue(dev);
++      netif_napi_del(&xrx200_hw.chan[XRX200_DMA_RX].napi);
++
++      /* shut down hardware */
++      xrx200_hw_cleanup(&xrx200_hw);
++
++      /* remove the actual device */
++      unregister_netdev(dev);
++      free_netdev(dev);
++
++      return 0;
++}
++
++static const struct of_device_id xrx200_match[] = {
++      { .compatible = "lantiq,xrx200-net" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, xrx200_match);
++
++static struct platform_driver xrx200_driver = {
++      .probe = xrx200_probe,
++      .remove = xrx200_remove,
++      .driver = {
++              .name = "lantiq,xrx200-net",
++              .of_match_table = xrx200_match,
++              .owner = THIS_MODULE,
++      },
++};
++
++module_platform_driver(xrx200_driver);
++
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
++MODULE_DESCRIPTION("Lantiq SoC XRX200 ethernet");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ethernet/lantiq_xrx200_sw.h b/drivers/net/ethernet/lantiq_xrx200_sw.h
+new file mode 100644
+index 0000000..e7188a2
+--- /dev/null
++++ b/drivers/net/ethernet/lantiq_xrx200_sw.h
+@@ -0,0 +1,1328 @@
++/*
++ *   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.
++ *
++ *   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) 2010 Lantiq Deutschland GmbH
++ *   Copyright (C) 2013 Antonios Vamporakis <vamporakis@yahoo.com>
++ *
++ *   VR9 switch registers extracted from 310TUJ0 switch api
++ *   WARNING mult values of 0x00 may not be correct
++ *
++ */
++
++enum {
++//    XRX200_ETHSW_SWRES,            /* Ethernet Switch ResetControl Register */
++//    XRX200_ETHSW_SWRES_R1,         /* Hardware Reset */
++//    XRX200_ETHSW_SWRES_R0,         /* Register Configuration */
++//    XRX200_ETHSW_CLK_MAC_GAT,      /* Ethernet Switch Clock ControlRegister  */
++//    XRX200_ETHSW_CLK_EXP_SLEEP,    /* Exponent to put system into sleep */
++//    XRX200_ETHSW_CLK_EXP_WAKE,     /* Exponent to wake up system */
++//    XRX200_ETHSW_CLK_CLK2_EN,      /* CLK2 Input for MAC */
++//    XRX200_ETHSW_CLK_EXT_DIV_EN,   /* External Clock Divider Enable */
++//    XRX200_ETHSW_CLK_RAM_DBG_EN,   /* Clock Gating Enable */
++//    XRX200_ETHSW_CLK_REG_GAT_EN,   /* Clock Gating Enable */
++//    XRX200_ETHSW_CLK_GAT_EN,       /* Clock Gating Enable */
++//    XRX200_ETHSW_CLK_MAC_GAT_EN,   /* Clock Gating Enable */
++//    XRX200_ETHSW_DBG_STEP,         /* Ethernet Switch Debug ControlRegister */
++//    XRX200_ETHSW_DBG_CLK_SEL,      /* Trigger Enable */
++//    XRX200_ETHSW_DBG_MON_EN,       /* Monitoring Enable */
++//    XRX200_ETHSW_DBG_TRIG_EN,      /* Trigger Enable */
++//    XRX200_ETHSW_DBG_MODE,         /* Debug Mode */
++//    XRX200_ETHSW_DBG_STEP_TIME,    /* Clock Step Size */
++//    XRX200_ETHSW_SSB_MODE,         /* Ethernet Switch SharedSegment Buffer Mode Register */
++//    XRX200_ETHSW_SSB_MODE_ADDE,    /* Memory Address */
++//    XRX200_ETHSW_SSB_MODE_MODE,    /* Memory Access Mode */
++//    XRX200_ETHSW_SSB_ADDR,         /* Ethernet Switch SharedSegment Buffer Address Register */
++//    XRX200_ETHSW_SSB_ADDR_ADDE,    /* Memory Address */
++//    XRX200_ETHSW_SSB_DATA,         /* Ethernet Switch SharedSegment Buffer Data Register */
++//    XRX200_ETHSW_SSB_DATA_DATA,    /* Data Value */
++//    XRX200_ETHSW_CAP_0,            /* Ethernet Switch CapabilityRegister 0 */
++//    XRX200_ETHSW_CAP_0_SPEED,      /* Clock frequency */
++//    XRX200_ETHSW_CAP_1,            /* Ethernet Switch CapabilityRegister 1 */
++//    XRX200_ETHSW_CAP_1_GMAC,       /* MAC operation mode */
++//    XRX200_ETHSW_CAP_1_QUEUE,      /* Number of queues */
++//    XRX200_ETHSW_CAP_1_VPORTS,     /* Number of virtual ports */
++//    XRX200_ETHSW_CAP_1_PPORTS,     /* Number of physical ports */
++//    XRX200_ETHSW_CAP_2,            /* Ethernet Switch CapabilityRegister 2 */
++//    XRX200_ETHSW_CAP_2_PACKETS,    /* Number of packets */
++//    XRX200_ETHSW_CAP_3,            /* Ethernet Switch CapabilityRegister 3 */
++//    XRX200_ETHSW_CAP_3_METERS,     /* Number of traffic meters */
++//    XRX200_ETHSW_CAP_3_SHAPERS,    /* Number of traffic shapers */
++//    XRX200_ETHSW_CAP_4,            /* Ethernet Switch CapabilityRegister 4 */
++//    XRX200_ETHSW_CAP_4_PPPOE,      /* PPPoE table size */
++//    XRX200_ETHSW_CAP_4_VLAN,       /* Active VLAN table size */
++//    XRX200_ETHSW_CAP_5,            /* Ethernet Switch CapabilityRegister 5 */
++//    XRX200_ETHSW_CAP_5_IPPLEN,     /* IP packet length table size */
++//    XRX200_ETHSW_CAP_5_PROT,       /* Protocol table size */
++//    XRX200_ETHSW_CAP_6,            /* Ethernet Switch CapabilityRegister 6 */
++//    XRX200_ETHSW_CAP_6_MACDASA,    /* MAC DA/SA table size */
++//    XRX200_ETHSW_CAP_6_APPL,       /* Application table size */
++//    XRX200_ETHSW_CAP_7,            /* Ethernet Switch CapabilityRegister 7 */
++//    XRX200_ETHSW_CAP_7_IPDASAM,    /* IP DA/SA MSB table size */
++//    XRX200_ETHSW_CAP_7_IPDASAL,    /* IP DA/SA LSB table size */
++//    XRX200_ETHSW_CAP_8,            /* Ethernet Switch CapabilityRegister 8 */
++//    XRX200_ETHSW_CAP_8_MCAST,      /* Multicast table size */
++//    XRX200_ETHSW_CAP_9,            /* Ethernet Switch CapabilityRegister 9 */
++//    XRX200_ETHSW_CAP_9_FLAGG,      /* Flow Aggregation table size */
++//    XRX200_ETHSW_CAP_10,           /* Ethernet Switch CapabilityRegister 10 */
++//    XRX200_ETHSW_CAP_10_MACBT,     /* MAC bridging table size */
++//    XRX200_ETHSW_CAP_11,           /* Ethernet Switch CapabilityRegister 11 */
++//    XRX200_ETHSW_CAP_11_BSIZEL,    /* Packet buffer size (lower part, in byte) */
++//    XRX200_ETHSW_CAP_12,           /* Ethernet Switch CapabilityRegister 12 */
++//    XRX200_ETHSW_CAP_12_BSIZEH,    /* Packet buffer size (higher part, in byte) */
++//    XRX200_ETHSW_VERSION_REV,      /* Ethernet Switch VersionRegister */
++//    XRX200_ETHSW_VERSION_MOD_ID,   /* Module Identification */
++//    XRX200_ETHSW_VERSION_REV_ID,   /* Hardware Revision Identification */
++//    XRX200_ETHSW_IER,              /* Interrupt Enable Register */
++//    XRX200_ETHSW_IER_FDMAIE,       /* Fetch DMA Interrupt Enable */
++//    XRX200_ETHSW_IER_SDMAIE,       /* Store DMA Interrupt Enable */
++//    XRX200_ETHSW_IER_MACIE,        /* Ethernet MAC Interrupt Enable */
++//    XRX200_ETHSW_IER_PCEIE,        /* Parser and Classification Engine Interrupt Enable */
++//    XRX200_ETHSW_IER_BMIE,         /* Buffer Manager Interrupt Enable */
++//    XRX200_ETHSW_ISR,              /* Interrupt Status Register */
++//    XRX200_ETHSW_ISR_FDMAINT,      /* Fetch DMA Interrupt */
++//    XRX200_ETHSW_ISR_SDMAINT,      /* Store DMA Interrupt */
++//    XRX200_ETHSW_ISR_MACINT,       /* Ethernet MAC Interrupt */
++//    XRX200_ETHSW_ISR_PCEINT,       /* Parser and Classification Engine Interrupt */
++//    XRX200_ETHSW_ISR_BMINT,        /* Buffer Manager Interrupt */
++//    XRX200_ETHSW_SPARE_0,          /* Ethernet Switch SpareCells 0 */
++//    XRX200_ETHSW_SPARE_0_SPARE,    /* SPARE0  */
++//    XRX200_ETHSW_SPARE_1,          /* Ethernet Switch SpareCells 1 */
++//    XRX200_ETHSW_SPARE_1_SPARE,    /* SPARE1  */
++//    XRX200_ETHSW_SPARE_2,          /* Ethernet Switch SpareCells 2 */
++//    XRX200_ETHSW_SPARE_2_SPARE,    /* SPARE2  */
++//    XRX200_ETHSW_SPARE_3,          /* Ethernet Switch SpareCells 3 */
++//    XRX200_ETHSW_SPARE_3_SPARE,    /* SPARE3  */
++//    XRX200_ETHSW_SPARE_4,          /* Ethernet Switch SpareCells 4 */
++//    XRX200_ETHSW_SPARE_4_SPARE,    /* SPARE4  */
++//    XRX200_ETHSW_SPARE_5,          /* Ethernet Switch SpareCells 5 */
++//    XRX200_ETHSW_SPARE_5_SPARE,    /* SPARE5  */
++//    XRX200_ETHSW_SPARE_6,          /* Ethernet Switch SpareCells 6 */
++//    XRX200_ETHSW_SPARE_6_SPARE,    /* SPARE6  */
++//    XRX200_ETHSW_SPARE_7,          /* Ethernet Switch SpareCells 7 */
++//    XRX200_ETHSW_SPARE_7_SPARE,    /* SPARE7  */
++//    XRX200_ETHSW_SPARE_8,          /* Ethernet Switch SpareCells 8 */
++//    XRX200_ETHSW_SPARE_8_SPARE,    /* SPARE8  */
++//    XRX200_ETHSW_SPARE_9,          /* Ethernet Switch SpareCells 9 */
++//    XRX200_ETHSW_SPARE_9_SPARE,    /* SPARE9  */
++//    XRX200_ETHSW_SPARE_10,         /* Ethernet Switch SpareCells 10 */
++//    XRX200_ETHSW_SPARE_10_SPARE,   /* SPARE10  */
++//    XRX200_ETHSW_SPARE_11,         /* Ethernet Switch SpareCells 11 */
++//    XRX200_ETHSW_SPARE_11_SPARE,   /* SPARE11  */
++//    XRX200_ETHSW_SPARE_12,         /* Ethernet Switch SpareCells 12 */
++//    XRX200_ETHSW_SPARE_12_SPARE,   /* SPARE12  */
++//    XRX200_ETHSW_SPARE_13,         /* Ethernet Switch SpareCells 13 */
++//    XRX200_ETHSW_SPARE_13_SPARE,   /* SPARE13  */
++//    XRX200_ETHSW_SPARE_14,         /* Ethernet Switch SpareCells 14 */
++//    XRX200_ETHSW_SPARE_14_SPARE,   /* SPARE14  */
++//    XRX200_ETHSW_SPARE_15,         /* Ethernet Switch SpareCells 15 */
++//    XRX200_ETHSW_SPARE_15_SPARE,   /* SPARE15  */
++//    XRX200_BM_RAM_VAL_3,           /* RAM Value Register 3 */
++//    XRX200_BM_RAM_VAL_3_VAL3,      /* Data value [15:0] */
++//    XRX200_BM_RAM_VAL_2,           /* RAM Value Register 2 */
++//    XRX200_BM_RAM_VAL_2_VAL2,      /* Data value [15:0] */
++//    XRX200_BM_RAM_VAL_1,           /* RAM Value Register 1 */
++//    XRX200_BM_RAM_VAL_1_VAL1,      /* Data value [15:0] */
++//    XRX200_BM_RAM_VAL_0,           /* RAM Value Register 0 */
++//    XRX200_BM_RAM_VAL_0_VAL0,      /* Data value [15:0] */
++//    XRX200_BM_RAM_ADDR,            /* RAM Address Register */
++//    XRX200_BM_RAM_ADDR_ADDR,       /* RAM Address */
++//    XRX200_BM_RAM_CTRL,            /* RAM Access Control Register */
++//    XRX200_BM_RAM_CTRL_BAS,        /* Access Busy/Access Start */
++//    XRX200_BM_RAM_CTRL_OPMOD,      /* Lookup Table Access Operation Mode */
++//    XRX200_BM_RAM_CTRL_ADDR,       /* Address for RAM selection */
++//    XRX200_BM_FSQM_GCTRL,          /* Free Segment Queue ManagerGlobal Control Register */
++//    XRX200_BM_FSQM_GCTRL_SEGNUM,   /* Maximum Segment Number */
++//    XRX200_BM_CONS_SEG,            /* Number of Consumed SegmentsRegister */
++//    XRX200_BM_CONS_SEG_FSEG,       /* Number of Consumed Segments */
++//    XRX200_BM_CONS_PKT,            /* Number of Consumed PacketPointers Register */
++//    XRX200_BM_CONS_PKT_FQP,        /* Number of Consumed Packet Pointers */
++//    XRX200_BM_GCTRL_F,             /* Buffer Manager Global ControlRegister 0 */
++//    XRX200_BM_GCTRL_BM_STA,        /* Buffer Manager Initialization Status Bit */
++//    XRX200_BM_GCTRL_SAT,           /* RMON Counter Update Mode */
++//    XRX200_BM_GCTRL_FR_RBC,        /* Freeze RMON RX Bad Byte 64 Bit Counter */
++//    XRX200_BM_GCTRL_FR_RGC,        /* Freeze RMON RX Good Byte 64 Bit Counter */
++//    XRX200_BM_GCTRL_FR_TGC,        /* Freeze RMON TX Good Byte 64 Bit Counter */
++//    XRX200_BM_GCTRL_I_FIN,         /* RAM initialization finished */
++//    XRX200_BM_GCTRL_CX_INI,        /* PQM Context RAM initialization */
++//    XRX200_BM_GCTRL_FP_INI,        /* FPQM RAM initialization */
++//    XRX200_BM_GCTRL_FS_INI,        /* FSQM RAM initialization */
++//    XRX200_BM_GCTRL_R_SRES,        /* Software Reset for RMON */
++//    XRX200_BM_GCTRL_S_SRES,        /* Software Reset for Scheduler */
++//    XRX200_BM_GCTRL_A_SRES,        /* Software Reset for AVG */
++//    XRX200_BM_GCTRL_P_SRES,        /* Software Reset for PQM */
++//    XRX200_BM_GCTRL_F_SRES,        /* Software Reset for FSQM */
++//    XRX200_BM_QUEUE_GCTRL,         /* Queue Manager GlobalControl Register 0 */
++//    XRX200_BM_QUEUE_GCTRL_GL_MOD,  /* WRED Mode Signal */
++//    XRX200_BM_QUEUE_GCTRL_AQUI,    /* Average Queue Update Interval */
++//    XRX200_BM_QUEUE_GCTRL_AQWF,    /* Average Queue Weight Factor */
++//    XRX200_BM_QUEUE_GCTRL_QAVGEN,  /* Queue Average Calculation Enable */
++//    XRX200_BM_QUEUE_GCTRL_DPROB,   /* Drop Probability Profile */
++//    XRX200_BM_WRED_RTH_0,          /* WRED Red Threshold Register0 */
++//    XRX200_BM_WRED_RTH_0_MINTH,    /* Minimum Threshold */
++//    XRX200_BM_WRED_RTH_1,          /* WRED Red Threshold Register1 */
++//    XRX200_BM_WRED_RTH_1_MAXTH,    /* Maximum Threshold */
++//    XRX200_BM_WRED_YTH_0,          /* WRED Yellow ThresholdRegister 0 */
++//    XRX200_BM_WRED_YTH_0_MINTH,    /* Minimum Threshold */
++//    XRX200_BM_WRED_YTH_1,          /* WRED Yellow ThresholdRegister 1 */
++//    XRX200_BM_WRED_YTH_1_MAXTH,    /* Maximum Threshold */
++//    XRX200_BM_WRED_GTH_0,          /* WRED Green ThresholdRegister 0 */
++//    XRX200_BM_WRED_GTH_0_MINTH,    /* Minimum Threshold */
++//    XRX200_BM_WRED_GTH_1,          /* WRED Green ThresholdRegister 1 */
++//    XRX200_BM_WRED_GTH_1_MAXTH,    /* Maximum Threshold */
++//    XRX200_BM_DROP_GTH_0_THR,      /* Drop Threshold ConfigurationRegister 0 */
++//    XRX200_BM_DROP_GTH_0_THR_FQ,   /* Threshold for frames marked red */
++//    XRX200_BM_DROP_GTH_1_THY,      /* Drop Threshold ConfigurationRegister 1 */
++//    XRX200_BM_DROP_GTH_1_THY_FQ,   /* Threshold for frames marked yellow */
++//    XRX200_BM_DROP_GTH_2_THG,      /* Drop Threshold ConfigurationRegister 2 */
++//    XRX200_BM_DROP_GTH_2_THG_FQ,   /* Threshold for frames marked green */
++//    XRX200_BM_IER,                 /* Buffer Manager Global InterruptEnable Register */
++//    XRX200_BM_IER_CNT4,            /* Counter Group 4 (RMON-CLASSIFICATION) Interrupt Enable */
++//    XRX200_BM_IER_CNT3,            /* Counter Group 3 (RMON-PQM) Interrupt Enable */
++//    XRX200_BM_IER_CNT2,            /* Counter Group 2 (RMON-SCHEDULER) Interrupt Enable */
++//    XRX200_BM_IER_CNT1,            /* Counter Group 1 (RMON-QFETCH) Interrupt Enable */
++//    XRX200_BM_IER_CNT0,            /* Counter Group 0 (RMON-QSTOR) Interrupt Enable */
++//    XRX200_BM_IER_DEQ,             /* PQM dequeue Interrupt Enable */
++//    XRX200_BM_IER_ENQ,             /* PQM Enqueue Interrupt Enable */
++//    XRX200_BM_IER_FSQM,            /* Buffer Empty Interrupt Enable */
++//    XRX200_BM_ISR,                 /* Buffer Manager Global InterruptStatus Register */
++//    XRX200_BM_ISR_CNT4,            /* Counter Group 4 Interrupt */
++//    XRX200_BM_ISR_CNT3,            /* Counter Group 3 Interrupt */
++//    XRX200_BM_ISR_CNT2,            /* Counter Group 2 Interrupt */
++//    XRX200_BM_ISR_CNT1,            /* Counter Group 1 Interrupt */
++//    XRX200_BM_ISR_CNT0,            /* Counter Group 0 Interrupt */
++//    XRX200_BM_ISR_DEQ,             /* PQM dequeue Interrupt Enable */
++//    XRX200_BM_ISR_ENQ,             /* PQM Enqueue Interrupt */
++//    XRX200_BM_ISR_FSQM,            /* Buffer Empty Interrupt */
++//    XRX200_BM_CISEL,               /* Buffer Manager RMON CounterInterrupt Select Register */
++//    XRX200_BM_CISEL_PORT,          /* Port Number */
++//    XRX200_BM_DEBUG_CTRL_DBG,      /* Debug Control Register */
++//    XRX200_BM_DEBUG_CTRL_DBG_SEL,  /* Select Signal for Debug Multiplexer */
++//    XRX200_BM_DEBUG_VAL_DBG,       /* Debug Value Register */
++//    XRX200_BM_DEBUG_VAL_DBG_DAT,   /* Debug Data Value */
++//    XRX200_BM_PCFG,                /* Buffer Manager PortConfiguration Register */
++//    XRX200_BM_PCFG_CNTEN,          /* RMON Counter Enable */
++//    XRX200_BM_RMON_CTRL_RAM1,      /* Buffer ManagerRMON Control Register */
++//    XRX200_BM_RMON_CTRL_RAM2_RES,  /* Software Reset for RMON RAM2 */
++//    XRX200_BM_RMON_CTRL_RAM1_RES,  /* Software Reset for RMON RAM1 */
++//    XRX200_PQM_DP,                 /* Packet Queue ManagerDrop Probability Register */
++//    XRX200_PQM_DP_DPROB,           /* Drop Probability Profile */
++//    XRX200_PQM_RS,                 /* Packet Queue ManagerRate Shaper Assignment Register */
++//    XRX200_PQM_RS_EN2,             /* Rate Shaper 2 Enable */
++//    XRX200_PQM_RS_RS2,             /* Rate Shaper 2 */
++//    XRX200_PQM_RS_EN1,             /* Rate Shaper 1 Enable */
++//    XRX200_PQM_RS_RS1,             /* Rate Shaper 1 */
++//    XRX200_RS_CTRL,                /* Rate Shaper ControlRegister */
++//    XRX200_RS_CTRL_RSEN,           /* Rate Shaper Enable */
++//    XRX200_RS_CBS,                 /* Rate Shaper CommittedBurst Size Register */
++//    XRX200_RS_CBS_CBS,             /* Committed Burst Size */
++//    XRX200_RS_IBS,                 /* Rate Shaper InstantaneousBurst Size Register */
++//    XRX200_RS_IBS_IBS,             /* Instantaneous Burst Size */
++//    XRX200_RS_CIR_EXP,             /* Rate Shaper RateExponent Register */
++//    XRX200_RS_CIR_EXP_EXP,         /* Exponent */
++//    XRX200_RS_CIR_MANT,            /* Rate Shaper RateMantissa Register */
++//    XRX200_RS_CIR_MANT_MANT,       /* Mantissa */
++      XRX200_PCE_TBL_KEY_7,          /* Table Key Data 7 */
++//    XRX200_PCE_TBL_KEY_7_KEY7,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_KEY_6,          /* Table Key Data 6 */
++//    XRX200_PCE_TBL_KEY_6_KEY6,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_KEY_5,          /* Table Key Data 5 */
++//    XRX200_PCE_TBL_KEY_5_KEY5,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_KEY_4,          /* Table Key Data 4 */
++//    XRX200_PCE_TBL_KEY_4_KEY4,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_KEY_3,          /* Table Key Data 3 */
++//    XRX200_PCE_TBL_KEY_3_KEY3,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_KEY_2,          /* Table Key Data 2 */
++//    XRX200_PCE_TBL_KEY_2_KEY2,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_KEY_1,          /* Table Key Data 1 */
++//    XRX200_PCE_TBL_KEY_1_KEY1,     /* Key Value[31:16] */
++      XRX200_PCE_TBL_KEY_0,          /* Table Key Data 0 */
++//    XRX200_PCE_TBL_KEY_0_KEY0,     /* Key Value[15:0] */
++      XRX200_PCE_TBL_MASK_0,         /* Table Mask Write Register0 */
++//    XRX200_PCE_TBL_MASK_0_MASK0,   /* Mask Pattern [15:0] */
++      XRX200_PCE_TBL_VAL_4,          /* Table Value Register4 */
++//    XRX200_PCE_TBL_VAL_4_VAL4,     /* Data value [15:0] */
++      XRX200_PCE_TBL_VAL_3,          /* Table Value Register3 */
++//    XRX200_PCE_TBL_VAL_3_VAL3,     /* Data value [15:0] */
++      XRX200_PCE_TBL_VAL_2,          /* Table Value Register2 */
++//    XRX200_PCE_TBL_VAL_2_VAL2,     /* Data value [15:0] */
++      XRX200_PCE_TBL_VAL_1,          /* Table Value Register1 */
++//    XRX200_PCE_TBL_VAL_1_VAL1,     /* Data value [15:0] */
++      XRX200_PCE_TBL_VAL_0,          /* Table Value Register0 */
++//    XRX200_PCE_TBL_VAL_0_VAL0,     /* Data value [15:0] */
++//    XRX200_PCE_TBL_ADDR,           /* Table Entry AddressRegister */
++      XRX200_PCE_TBL_ADDR_ADDR,      /* Table Address */
++//    XRX200_PCE_TBL_CTRL,           /* Table Access ControlRegister */
++      XRX200_PCE_TBL_CTRL_BAS,       /* Access Busy/Access Start */
++      XRX200_PCE_TBL_CTRL_TYPE,      /* Lookup Entry Type */
++      XRX200_PCE_TBL_CTRL_VLD,       /* Lookup Entry Valid */
++      XRX200_PCE_TBL_CTRL_GMAP,      /* Group Map */
++      XRX200_PCE_TBL_CTRL_OPMOD,     /* Lookup Table Access Operation Mode */
++      XRX200_PCE_TBL_CTRL_ADDR,      /* Lookup Table Address */
++//    XRX200_PCE_TBL_STAT,           /* Table General StatusRegister */
++//    XRX200_PCE_TBL_STAT_TBUSY,     /* Table Access Busy */
++//    XRX200_PCE_TBL_STAT_TEMPT,     /* Table Empty */
++//    XRX200_PCE_TBL_STAT_TFUL,      /* Table Full */
++//    XRX200_PCE_AGE_0,              /* Aging Counter ConfigurationRegister 0 */
++//    XRX200_PCE_AGE_0_EXP,          /* Aging Counter Exponent Value  */
++//    XRX200_PCE_AGE_1,              /* Aging Counter ConfigurationRegister 1 */
++//    XRX200_PCE_AGE_1_MANT,         /* Aging Counter Mantissa Value  */
++//    XRX200_PCE_PMAP_1,             /* Port Map Register 1 */
++//    XRX200_PCE_PMAP_1_MPMAP,       /* Monitoring Port Map */
++//    XRX200_PCE_PMAP_2,             /* Port Map Register 2 */
++//    XRX200_PCE_PMAP_2_DMCPMAP,     /* Default Multicast Port Map */
++//    XRX200_PCE_PMAP_3,             /* Port Map Register 3 */
++//    XRX200_PCE_PMAP_3_UUCMAP,      /* Default Unknown Unicast Port Map */
++//    XRX200_PCE_GCTRL_0,            /* PCE Global Control Register0 */
++//    XRX200_PCE_GCTRL_0_IGMP,       /* IGMP Mode Selection */
++      XRX200_PCE_GCTRL_0_VLAN,       /* VLAN-aware Switching */
++//    XRX200_PCE_GCTRL_0_NOPM,       /* No Port Map Forwarding */
++//    XRX200_PCE_GCTRL_0_SCONUC,     /* Unknown Unicast Storm Control */
++//    XRX200_PCE_GCTRL_0_SCONMC,     /* Multicast Storm Control */
++//    XRX200_PCE_GCTRL_0_SCONBC,     /* Broadcast Storm Control */
++//    XRX200_PCE_GCTRL_0_SCONMOD,    /* Storm Control Mode */
++//    XRX200_PCE_GCTRL_0_SCONMET,    /* Storm Control Metering Instance */
++//    XRX200_PCE_GCTRL_0_MC_VALID,   /* Access Request */
++//    XRX200_PCE_GCTRL_0_PLCKMOD,    /* Port Lock Mode */
++//    XRX200_PCE_GCTRL_0_PLIMMOD,    /* MAC Address Learning Limitation Mode */
++//    XRX200_PCE_GCTRL_0_MTFL,       /* MAC Table Flushing */
++//    XRX200_PCE_GCTRL_1,            /* PCE Global Control Register1 */
++//    XRX200_PCE_GCTRL_1_PCE_DIS,    /* PCE Disable after currently processed packet */
++//    XRX200_PCE_GCTRL_1_LRNMOD,     /* MAC Address Learning Mode */
++//    XRX200_PCE_TCM_GLOB_CTRL,      /* Three-color MarkerGlobal Control Register */
++//    XRX200_PCE_TCM_GLOB_CTRL_DPRED, /* Re-marking Drop Precedence Red Encoding */
++//    XRX200_PCE_TCM_GLOB_CTRL_DPYEL, /* Re-marking Drop Precedence Yellow Encoding */
++//    XRX200_PCE_TCM_GLOB_CTRL_DPGRN, /* Re-marking Drop Precedence Green Encoding */
++//    XRX200_PCE_IGMP_CTRL,          /* IGMP Control Register */
++//    XRX200_PCE_IGMP_CTRL_FAGEEN,   /* Force Aging of Table Entries Enable */
++//    XRX200_PCE_IGMP_CTRL_FLEAVE,   /* Fast Leave Enable */
++//    XRX200_PCE_IGMP_CTRL_DMRTEN,   /* Default Maximum Response Time Enable */
++//    XRX200_PCE_IGMP_CTRL_JASUP,    /* Join Aggregation Suppression Enable */
++//    XRX200_PCE_IGMP_CTRL_REPSUP,   /* Report Suppression Enable */
++//    XRX200_PCE_IGMP_CTRL_SRPEN,    /* Snooping of Router Port Enable */
++//    XRX200_PCE_IGMP_CTRL_ROB,      /* Robustness Variable */
++//    XRX200_PCE_IGMP_CTRL_DMRT,     /* IGMP Default Maximum Response Time */
++//    XRX200_PCE_IGMP_DRPM,          /* IGMP Default RouterPort Map Register */
++//    XRX200_PCE_IGMP_DRPM_DRPM,     /* IGMP Default Router Port Map */
++//    XRX200_PCE_IGMP_AGE_0,         /* IGMP Aging Register0 */
++//    XRX200_PCE_IGMP_AGE_0_MANT,    /* IGMP Group Aging Time Mantissa */
++//    XRX200_PCE_IGMP_AGE_0_EXP,     /* IGMP Group Aging Time Exponent */
++//    XRX200_PCE_IGMP_AGE_1,         /* IGMP Aging Register1 */
++//    XRX200_PCE_IGMP_AGE_1_MANT,    /* IGMP Router Port Aging Time Mantissa */
++//    XRX200_PCE_IGMP_STAT,          /* IGMP Status Register */
++//    XRX200_PCE_IGMP_STAT_IGPM,     /* IGMP Port Map */
++//    XRX200_WOL_GLB_CTRL,           /* Wake-on-LAN ControlRegister */
++//    XRX200_WOL_GLB_CTRL_PASSEN,    /* WoL Password Enable */
++//    XRX200_WOL_DA_0,               /* Wake-on-LAN DestinationAddress Register 0 */
++//    XRX200_WOL_DA_0_DA0,           /* WoL Destination Address [15:0] */
++//    XRX200_WOL_DA_1,               /* Wake-on-LAN DestinationAddress Register 1 */
++//    XRX200_WOL_DA_1_DA1,           /* WoL Destination Address [31:16] */
++//    XRX200_WOL_DA_2,               /* Wake-on-LAN DestinationAddress Register 2 */
++//    XRX200_WOL_DA_2_DA2,           /* WoL Destination Address [47:32] */
++//    XRX200_WOL_PW_0,               /* Wake-on-LAN Password Register0 */
++//    XRX200_WOL_PW_0_PW0,           /* WoL Password [15:0] */
++//    XRX200_WOL_PW_1,               /* Wake-on-LAN Password Register1 */
++//    XRX200_WOL_PW_1_PW1,           /* WoL Password [31:16] */
++//    XRX200_WOL_PW_2,               /* Wake-on-LAN Password Register2 */
++//    XRX200_WOL_PW_2_PW2,           /* WoL Password [47:32] */
++//    XRX200_PCE_IER_0_PINT,         /* Parser and ClassificationEngine Global Interrupt Enable Register 0 */
++//    XRX200_PCE_IER_0_PINT_15,      /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_14,      /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_13,      /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_12,      /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_11,      /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_10,      /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_9,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_8,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_7,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_6,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_5,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_4,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_3,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_2,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_1,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_0_PINT_0,       /* Port Interrupt Enable */
++//    XRX200_PCE_IER_1,              /* Parser and ClassificationEngine Global Interrupt Enable Register 1 */
++//    XRX200_PCE_IER_1_FLOWINT,      /* Traffic Flow Table Interrupt Rule matched Interrupt Enable */
++//    XRX200_PCE_IER_1_CPH2,         /* Classification Phase 2 Ready Interrupt Enable */
++//    XRX200_PCE_IER_1_CPH1,         /* Classification Phase 1 Ready Interrupt Enable */
++//    XRX200_PCE_IER_1_CPH0,         /* Classification Phase 0 Ready Interrupt Enable */
++//    XRX200_PCE_IER_1_PRDY,         /* Parser Ready Interrupt Enable */
++//    XRX200_PCE_IER_1_IGTF,         /* IGMP Table Full Interrupt Enable */
++//    XRX200_PCE_IER_1_MTF,          /* MAC Table Full Interrupt Enable */
++//    XRX200_PCE_ISR_0_PINT,         /* Parser and ClassificationEngine Global Interrupt Status Register 0 */
++//    XRX200_PCE_ISR_0_PINT_15,      /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_14,      /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_13,      /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_12,      /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_11,      /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_10,      /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_9,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_8,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_7,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_6,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_5,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_4,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_3,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_2,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_1,       /* Port Interrupt */
++//    XRX200_PCE_ISR_0_PINT_0,       /* Port Interrupt */
++//    XRX200_PCE_ISR_1,              /* Parser and ClassificationEngine Global Interrupt Status Register 1 */
++//    XRX200_PCE_ISR_1_FLOWINT,      /* Traffic Flow Table Interrupt Rule matched */
++//    XRX200_PCE_ISR_1_CPH2,         /* Classification Phase 2 Ready Interrupt */
++//    XRX200_PCE_ISR_1_CPH1,         /* Classification Phase 1 Ready Interrupt */
++//    XRX200_PCE_ISR_1_CPH0,         /* Classification Phase 0 Ready Interrupt */
++//    XRX200_PCE_ISR_1_PRDY,         /* Parser Ready Interrupt */
++//    XRX200_PCE_ISR_1_IGTF,         /* IGMP Table Full Interrupt */
++//    XRX200_PCE_ISR_1_MTF,          /* MAC Table Full Interrupt */
++//    XRX200_PARSER_STAT_FIFO,       /* Parser Status Register */
++//    XRX200_PARSER_STAT_FSM_DAT_CNT, /* Parser FSM Data Counter */
++//    XRX200_PARSER_STAT_FSM_STATE,  /* Parser FSM State */
++//    XRX200_PARSER_STAT_PKT_ERR,    /* Packet error detected */
++//    XRX200_PARSER_STAT_FSM_FIN,    /* Parser FSM finished */
++//    XRX200_PARSER_STAT_FSM_START,  /* Parser FSM start */
++//    XRX200_PARSER_STAT_FIFO_RDY,   /* Parser FIFO ready for read. */
++//    XRX200_PARSER_STAT_FIFO_FULL,  /* Parser */
++//    XRX200_PCE_PCTRL_0,            /* PCE Port ControlRegister 0 */
++//    XRX200_PCE_PCTRL_0_MCST,       /* Multicast Forwarding Mode Selection */
++//    XRX200_PCE_PCTRL_0_EGSTEN,     /* Table-based Egress Special Tag Enable */
++//    XRX200_PCE_PCTRL_0_IGSTEN,     /* Ingress Special Tag Enable */
++//    XRX200_PCE_PCTRL_0_PCPEN,      /* PCP Remarking Mode */
++//    XRX200_PCE_PCTRL_0_CLPEN,      /* Class Remarking Mode */
++//    XRX200_PCE_PCTRL_0_DPEN,       /* Drop Precedence Remarking Mode */
++//    XRX200_PCE_PCTRL_0_CMOD,       /* Three-color Marker Color Mode */
++//    XRX200_PCE_PCTRL_0_VREP,       /* VLAN Replacement Mode */
++      XRX200_PCE_PCTRL_0_TVM,        /* Transparent VLAN Mode */
++//    XRX200_PCE_PCTRL_0_PLOCK,      /* Port Locking Enable */
++//    XRX200_PCE_PCTRL_0_AGEDIS,     /* Aging Disable */
++//    XRX200_PCE_PCTRL_0_PSTATE,     /* Port State */
++//    XRX200_PCE_PCTRL_1,            /* PCE Port ControlRegister 1 */
++//    XRX200_PCE_PCTRL_1_LRNLIM,     /* MAC Address Learning Limit */
++//    XRX200_PCE_PCTRL_2,            /* PCE Port ControlRegister 2 */
++//    XRX200_PCE_PCTRL_2_DSCPMOD,    /* DSCP Mode Selection */
++//    XRX200_PCE_PCTRL_2_DSCP,       /* Enable DSCP to select the Class of Service */
++//    XRX200_PCE_PCTRL_2_PCP,        /* Enable VLAN PCP to select the Class of Service */
++//    XRX200_PCE_PCTRL_2_PCLASS,     /* Port-based Traffic Class */
++//    XRX200_PCE_PCTRL_3_VIO,        /* PCE Port ControlRegister 3 */
++//    XRX200_PCE_PCTRL_3_EDIR,       /* Egress Redirection Mode */
++//    XRX200_PCE_PCTRL_3_RXDMIR,     /* Receive Mirroring Enable for dropped frames */
++//    XRX200_PCE_PCTRL_3_RXVMIR,     /* Receive Mirroring Enable for valid frames */
++//    XRX200_PCE_PCTRL_3_TXMIR,      /* Transmit Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_7,      /* Violation Type 7 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_6,      /* Violation Type 6 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_5,      /* Violation Type 5 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_4,      /* Violation Type 4 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_3,      /* Violation Type 3 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_2,      /* Violation Type 2 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_1,      /* Violation Type 1 Mirroring Enable */
++//    XRX200_PCE_PCTRL_3_VIO_0,      /* Violation Type 0 Mirroring Enable */
++//    XRX200_WOL_CTRL,               /* Wake-on-LAN ControlRegister */
++//    XRX200_WOL_CTRL_PORT,          /* WoL Enable */
++//    XRX200_PCE_VCTRL,              /* PCE VLAN ControlRegister */
++      XRX200_PCE_VCTRL_VSR,          /* VLAN Security Rule */
++      XRX200_PCE_VCTRL_VEMR,         /* VLAN Egress Member Violation Rule */
++      XRX200_PCE_VCTRL_VIMR,         /* VLAN Ingress Member Violation Rule */
++      XRX200_PCE_VCTRL_VINR,         /* VLAN Ingress Tag Rule */
++      XRX200_PCE_VCTRL_UVR,          /* Unknown VLAN Rule */
++//    XRX200_PCE_DEFPVID,            /* PCE Default PortVID Register */
++      XRX200_PCE_DEFPVID_PVID,       /* Default Port VID Index */
++//    XRX200_PCE_PSTAT,              /* PCE Port StatusRegister */
++//    XRX200_PCE_PSTAT_LRNCNT,       /* Learning Count */
++//    XRX200_PCE_PIER,               /* Parser and ClassificationEngine Port Interrupt Enable Register */
++//    XRX200_PCE_PIER_CLDRP,         /* Classification Drop Interrupt Enable */
++//    XRX200_PCE_PIER_PTDRP,         /* Port Drop Interrupt Enable */
++//    XRX200_PCE_PIER_VLAN,          /* VLAN Violation Interrupt Enable */
++//    XRX200_PCE_PIER_WOL,           /* Wake-on-LAN Interrupt Enable */
++//    XRX200_PCE_PIER_LOCK,          /* Port Limit Alert Interrupt Enable */
++//    XRX200_PCE_PIER_LIM,           /* Port Lock Alert Interrupt Enable */
++//    XRX200_PCE_PISR,               /* Parser and ClassificationEngine Port Interrupt Status Register */
++//    XRX200_PCE_PISR_CLDRP,         /* Classification Drop Interrupt */
++//    XRX200_PCE_PISR_PTDRP,         /* Port Drop Interrupt */
++//    XRX200_PCE_PISR_VLAN,          /* VLAN Violation Interrupt */
++//    XRX200_PCE_PISR_WOL,           /* Wake-on-LAN Interrupt */
++//    XRX200_PCE_PISR_LOCK,          /* Port Lock Alert Interrupt */
++//    XRX200_PCE_PISR_LIMIT,         /* Port Limitation Alert Interrupt */
++//    XRX200_PCE_TCM_CTRL,           /* Three-colorMarker Control Register */
++//    XRX200_PCE_TCM_CTRL_TCMEN,     /* Three-color Marker metering instance enable */
++//    XRX200_PCE_TCM_STAT,           /* Three-colorMarker Status Register */
++//    XRX200_PCE_TCM_STAT_AL1,       /* Three-color Marker Alert 1 Status */
++//    XRX200_PCE_TCM_STAT_AL0,       /* Three-color Marker Alert 0 Status */
++//    XRX200_PCE_TCM_CBS,            /* Three-color MarkerCommitted Burst Size Register */
++//    XRX200_PCE_TCM_CBS_CBS,        /* Committed Burst Size */
++//    XRX200_PCE_TCM_EBS,            /* Three-color MarkerExcess Burst Size Register */
++//    XRX200_PCE_TCM_EBS_EBS,        /* Excess Burst Size */
++//    XRX200_PCE_TCM_IBS,            /* Three-color MarkerInstantaneous Burst Size Register */
++//    XRX200_PCE_TCM_IBS_IBS,        /* Instantaneous Burst Size */
++//    XRX200_PCE_TCM_CIR_MANT,       /* Three-colorMarker Constant Information Rate Mantissa Register */
++//    XRX200_PCE_TCM_CIR_MANT_MANT,  /* Rate Counter Mantissa */
++//    XRX200_PCE_TCM_CIR_EXP,        /* Three-colorMarker Constant Information Rate Exponent Register */
++//    XRX200_PCE_TCM_CIR_EXP_EXP,    /* Rate Counter Exponent */
++//    XRX200_MAC_TEST,               /* MAC Test Register */
++//    XRX200_MAC_TEST_JTP,           /* Jitter Test Pattern */
++//    XRX200_MAC_PFAD_CFG,           /* MAC Pause FrameSource Address Configuration Register */
++//    XRX200_MAC_PFAD_CFG_SAMOD,     /* Source Address Mode */
++//    XRX200_MAC_PFSA_0,             /* Pause Frame SourceAddress Part 0  */
++//    XRX200_MAC_PFSA_0_PFAD,        /* Pause Frame Source Address Part 0 */
++//    XRX200_MAC_PFSA_1,             /* Pause Frame SourceAddress Part 1  */
++//    XRX200_MAC_PFSA_1_PFAD,        /* Pause Frame Source Address Part 1 */
++//    XRX200_MAC_PFSA_2,             /* Pause Frame SourceAddress Part 2  */
++//    XRX200_MAC_PFSA_2_PFAD,        /* Pause Frame Source Address Part 2 */
++//    XRX200_MAC_FLEN,               /* MAC Frame Length Register */
++//    XRX200_MAC_FLEN_LEN,           /* Maximum Frame Length */
++//    XRX200_MAC_VLAN_ETYPE_0,       /* MAC VLAN EthertypeRegister 0 */
++//    XRX200_MAC_VLAN_ETYPE_0_OUTER, /* Ethertype */
++//    XRX200_MAC_VLAN_ETYPE_1,       /* MAC VLAN EthertypeRegister 1 */
++//    XRX200_MAC_VLAN_ETYPE_1_INNER, /* Ethertype */
++//    XRX200_MAC_IER,                /* MAC Interrupt EnableRegister */
++//    XRX200_MAC_IER_MACIEN,         /* MAC Interrupt Enable */
++//    XRX200_MAC_ISR,                /* MAC Interrupt StatusRegister */
++//    XRX200_MAC_ISR_MACINT,         /* MAC Interrupt */
++//    XRX200_MAC_PSTAT,              /* MAC Port Status Register */
++//    XRX200_MAC_PSTAT_PACT,         /* PHY Active Status */
++      XRX200_MAC_PSTAT_GBIT,         /* Gigabit Speed Status */
++      XRX200_MAC_PSTAT_MBIT,         /* Megabit Speed Status */
++      XRX200_MAC_PSTAT_FDUP,         /* Full Duplex Status */
++//    XRX200_MAC_PSTAT_RXPAU,        /* Receive Pause Status */
++//    XRX200_MAC_PSTAT_TXPAU,        /* Transmit Pause Status */
++//    XRX200_MAC_PSTAT_RXPAUEN,      /* Receive Pause Enable Status */
++//    XRX200_MAC_PSTAT_TXPAUEN,      /* Transmit Pause Enable Status */
++      XRX200_MAC_PSTAT_LSTAT,        /* Link Status */
++//    XRX200_MAC_PSTAT_CRS,          /* Carrier Sense Status */
++//    XRX200_MAC_PSTAT_TXLPI,        /* Transmit Low-power Idle Status */
++//    XRX200_MAC_PSTAT_RXLPI,        /* Receive Low-power Idle Status */
++//    XRX200_MAC_PISR,               /* MAC Interrupt Status Register */
++//    XRX200_MAC_PISR_PACT,          /* PHY Active Status */
++//    XRX200_MAC_PISR_SPEED,         /* Megabit Speed Status */
++//    XRX200_MAC_PISR_FDUP,          /* Full Duplex Status */
++//    XRX200_MAC_PISR_RXPAUEN,       /* Receive Pause Enable Status */
++//    XRX200_MAC_PISR_TXPAUEN,       /* Transmit Pause Enable Status */
++//    XRX200_MAC_PISR_LPIOFF,        /* Receive Low-power Idle Mode is left */
++//    XRX200_MAC_PISR_LPION,         /* Receive Low-power Idle Mode is entered */
++//    XRX200_MAC_PISR_JAM,           /* Jam Status Detected */
++//    XRX200_MAC_PISR_TOOSHORT,      /* Too Short Frame Error Detected */
++//    XRX200_MAC_PISR_TOOLONG,       /* Too Long Frame Error Detected */
++//    XRX200_MAC_PISR_LENERR,        /* Length Mismatch Error Detected */
++//    XRX200_MAC_PISR_FCSERR,        /* Frame Checksum Error Detected */
++//    XRX200_MAC_PISR_TXPAUSE,       /* Pause Frame Transmitted */
++//    XRX200_MAC_PISR_RXPAUSE,       /* Pause Frame Received */
++//    XRX200_MAC_PIER,               /* MAC Interrupt Enable Register */
++//    XRX200_MAC_PIER_PACT,          /* PHY Active Status */
++//    XRX200_MAC_PIER_SPEED,         /* Megabit Speed Status */
++//    XRX200_MAC_PIER_FDUP,          /* Full Duplex Status */
++//    XRX200_MAC_PIER_RXPAUEN,       /* Receive Pause Enable Status */
++//    XRX200_MAC_PIER_TXPAUEN,       /* Transmit Pause Enable Status */
++//    XRX200_MAC_PIER_LPIOFF,        /* Low-power Idle Off Interrupt Mask */
++//    XRX200_MAC_PIER_LPION,         /* Low-power Idle On Interrupt Mask */
++//    XRX200_MAC_PIER_JAM,           /* Jam Status Interrupt Mask */
++//    XRX200_MAC_PIER_TOOSHORT,      /* Too Short Frame Error Interrupt Mask */
++//    XRX200_MAC_PIER_TOOLONG,       /* Too Long Frame Error Interrupt Mask */
++//    XRX200_MAC_PIER_LENERR,        /* Length Mismatch Error Interrupt Mask */
++//    XRX200_MAC_PIER_FCSERR,        /* Frame Checksum Error Interrupt Mask */
++//    XRX200_MAC_PIER_TXPAUSE,       /* Transmit Pause Frame Interrupt Mask */
++//    XRX200_MAC_PIER_RXPAUSE,       /* Receive Pause Frame Interrupt Mask */
++//    XRX200_MAC_CTRL_0,             /* MAC Control Register0 */
++//    XRX200_MAC_CTRL_0_LCOL,        /* Late Collision Control */
++//    XRX200_MAC_CTRL_0_BM,          /* Burst Mode Control */
++//    XRX200_MAC_CTRL_0_APADEN,      /* Automatic VLAN Padding Enable */
++//    XRX200_MAC_CTRL_0_VPAD2EN,     /* Stacked VLAN Padding Enable */
++//    XRX200_MAC_CTRL_0_VPADEN,      /* VLAN Padding Enable */
++//    XRX200_MAC_CTRL_0_PADEN,       /* Padding Enable */
++//    XRX200_MAC_CTRL_0_FCS,         /* Transmit FCS Control */
++      XRX200_MAC_CTRL_0_FCON,        /* Flow Control Mode */
++//    XRX200_MAC_CTRL_0_FDUP,        /* Full Duplex Control */
++//    XRX200_MAC_CTRL_0_GMII,        /* GMII/MII interface mode selection */
++//    XRX200_MAC_CTRL_1,             /* MAC Control Register1 */
++//    XRX200_MAC_CTRL_1_SHORTPRE,    /* Short Preamble Control */
++//    XRX200_MAC_CTRL_1_IPG,         /* Minimum Inter Packet Gap Size */
++//    XRX200_MAC_CTRL_2,             /* MAC Control Register2 */
++//    XRX200_MAC_CTRL_2_MLEN,        /* Maximum Untagged Frame Length */
++//    XRX200_MAC_CTRL_2_LCHKL,       /* Frame Length Check Long Enable */
++//    XRX200_MAC_CTRL_2_LCHKS,       /* Frame Length Check Short Enable */
++//    XRX200_MAC_CTRL_3,             /* MAC Control Register3 */
++//    XRX200_MAC_CTRL_3_RCNT,        /* Retry Count */
++//    XRX200_MAC_CTRL_4,             /* MAC Control Register4 */
++//    XRX200_MAC_CTRL_4_LPIEN,       /* LPI Mode Enable */
++//    XRX200_MAC_CTRL_4_WAIT,        /* LPI Wait Time */
++//    XRX200_MAC_CTRL_5_PJPS,        /* MAC Control Register5 */
++//    XRX200_MAC_CTRL_5_PJPS_NOBP,   /* Prolonged Jam pattern size during no-backpressure state */
++//    XRX200_MAC_CTRL_5_PJPS_BP,     /* Prolonged Jam pattern size during backpressure state */
++//    XRX200_MAC_CTRL_6_XBUF,        /* Transmit and ReceiveBuffer Control Register */
++//    XRX200_MAC_CTRL_6_RBUF_DLY_WP, /* Delay */
++//    XRX200_MAC_CTRL_6_RBUF_INIT,   /* Receive Buffer Initialization */
++//    XRX200_MAC_CTRL_6_RBUF_BYPASS, /* Bypass the Receive Buffer */
++//    XRX200_MAC_CTRL_6_XBUF_DLY_WP, /* Delay */
++//    XRX200_MAC_CTRL_6_XBUF_INIT,   /* Initialize the Transmit Buffer */
++//    XRX200_MAC_CTRL_6_XBUF_BYPASS, /* Bypass the Transmit Buffer */
++//    XRX200_MAC_BUFST_XBUF,         /* MAC Receive and TransmitBuffer Status Register */
++//    XRX200_MAC_BUFST_RBUF_UFL,     /* Receive Buffer Underflow Indicator */
++//    XRX200_MAC_BUFST_RBUF_OFL,     /* Receive Buffer Overflow Indicator */
++//    XRX200_MAC_BUFST_XBUF_UFL,     /* Transmit Buffer Underflow Indicator */
++//    XRX200_MAC_BUFST_XBUF_OFL,     /* Transmit Buffer Overflow Indicator */
++//    XRX200_MAC_TESTEN,             /* MAC Test Enable Register */
++//    XRX200_MAC_TESTEN_JTEN,        /* Jitter Test Enable */
++//    XRX200_MAC_TESTEN_TXER,        /* Transmit Error Insertion */
++//    XRX200_MAC_TESTEN_LOOP,        /* MAC Loopback Enable */
++//    XRX200_FDMA_CTRL,              /* Ethernet Switch FetchDMA Control Register */
++//    XRX200_FDMA_CTRL_LPI_THRESHOLD, /* Low Power Idle Threshold */
++//    XRX200_FDMA_CTRL_LPI_MODE,     /* Low Power Idle Mode */
++//    XRX200_FDMA_CTRL_EGSTAG,       /* Egress Special Tag Size */
++//    XRX200_FDMA_CTRL_IGSTAG,       /* Ingress Special Tag Size */
++//    XRX200_FDMA_CTRL_EXCOL,        /* Excessive Collision Handling */
++//    XRX200_FDMA_STETYPE,           /* Special Tag EthertypeControl Register */
++//    XRX200_FDMA_STETYPE_ETYPE,     /* Special Tag Ethertype */
++//    XRX200_FDMA_VTETYPE,           /* VLAN Tag EthertypeControl Register */
++//    XRX200_FDMA_VTETYPE_ETYPE,     /* VLAN Tag Ethertype */
++//    XRX200_FDMA_STAT_0,            /* FDMA Status Register0 */
++//    XRX200_FDMA_STAT_0_FSMS,       /* FSM states status */
++//    XRX200_FDMA_IER,               /* Fetch DMA Global InterruptEnable Register */
++//    XRX200_FDMA_IER_PCKD,          /* Packet Drop Interrupt Enable */
++//    XRX200_FDMA_IER_PCKR,          /* Packet Ready Interrupt Enable */
++//    XRX200_FDMA_IER_PCKT,          /* Packet Sent Interrupt Enable */
++//    XRX200_FDMA_ISR,               /* Fetch DMA Global InterruptStatus Register */
++//    XRX200_FDMA_ISR_PCKTD,         /* Packet Drop */
++//    XRX200_FDMA_ISR_PCKR,          /* Packet is Ready for Transmission */
++//    XRX200_FDMA_ISR_PCKT,          /* Packet Sent Event */
++//    XRX200_FDMA_PCTRL,             /* Ethernet SwitchFetch DMA Port Control Register */
++//    XRX200_FDMA_PCTRL_VLANMOD,     /* VLAN Modification Enable */
++//    XRX200_FDMA_PCTRL_DSCPRM,      /* DSCP Re-marking Enable */
++//    XRX200_FDMA_PCTRL_STEN,        /* Special Tag Insertion Enable */
++//    XRX200_FDMA_PCTRL_EN,          /* FDMA Port Enable */
++//    XRX200_FDMA_PRIO,              /* Ethernet SwitchFetch DMA Port Priority Register */
++//    XRX200_FDMA_PRIO_PRIO,         /* FDMA PRIO */
++//    XRX200_FDMA_PSTAT0,            /* Ethernet SwitchFetch DMA Port Status Register 0 */
++//    XRX200_FDMA_PSTAT0_PKT_AVAIL,  /* Port Egress Packet Available */
++//    XRX200_FDMA_PSTAT0_POK,        /* Port Status OK */
++//    XRX200_FDMA_PSTAT0_PSEG,       /* Port Egress Segment Count */
++//    XRX200_FDMA_PSTAT1_HDR,        /* Ethernet SwitchFetch DMA Port Status Register 1 */
++//    XRX200_FDMA_PSTAT1_HDR_PTR,    /* Header Pointer */
++//    XRX200_FDMA_TSTAMP0,           /* Egress TimeStamp Register 0 */
++//    XRX200_FDMA_TSTAMP0_TSTL,      /* Time Stamp [15:0] */
++//    XRX200_FDMA_TSTAMP1,           /* Egress TimeStamp Register 1 */
++//    XRX200_FDMA_TSTAMP1_TSTH,      /* Time Stamp [31:16] */
++//    XRX200_SDMA_CTRL,              /* Ethernet Switch StoreDMA Control Register */
++//    XRX200_SDMA_CTRL_TSTEN,        /* Time Stamp Enable */
++//    XRX200_SDMA_FCTHR1,            /* SDMA Flow Control Threshold1 Register */
++//    XRX200_SDMA_FCTHR1_THR1,       /* Threshold 1 */
++//    XRX200_SDMA_FCTHR2,            /* SDMA Flow Control Threshold2 Register */
++//    XRX200_SDMA_FCTHR2_THR2,       /* Threshold 2 */
++//    XRX200_SDMA_FCTHR3,            /* SDMA Flow Control Threshold3 Register */
++//    XRX200_SDMA_FCTHR3_THR3,       /* Threshold 3 */
++//    XRX200_SDMA_FCTHR4,            /* SDMA Flow Control Threshold4 Register */
++//    XRX200_SDMA_FCTHR4_THR4,       /* Threshold 4 */
++//    XRX200_SDMA_FCTHR5,            /* SDMA Flow Control Threshold5 Register */
++//    XRX200_SDMA_FCTHR5_THR5,       /* Threshold 5 */
++//    XRX200_SDMA_FCTHR6,            /* SDMA Flow Control Threshold6 Register */
++//    XRX200_SDMA_FCTHR6_THR6,       /* Threshold 6 */
++//    XRX200_SDMA_FCTHR7,            /* SDMA Flow Control Threshold7 Register */
++//    XRX200_SDMA_FCTHR7_THR7,       /* Threshold 7 */
++//    XRX200_SDMA_STAT_0,            /* SDMA Status Register0 */
++//    XRX200_SDMA_STAT_0_BPS_FILL,   /* Back Pressure Status */
++//    XRX200_SDMA_STAT_0_BPS_PNT,    /* Back Pressure Status */
++//    XRX200_SDMA_STAT_0_DROP,       /* Back Pressure Status */
++//    XRX200_SDMA_STAT_1,            /* SDMA Status Register1 */
++//    XRX200_SDMA_STAT_1_FILL,       /* Buffer Filling Level */
++//    XRX200_SDMA_STAT_2,            /* SDMA Status Register2 */
++//    XRX200_SDMA_STAT_2_FSMS,       /* FSM states status */
++//    XRX200_SDMA_IER,               /* SDMA Interrupt Enable Register */
++//    XRX200_SDMA_IER_BPEX,          /* Buffer Pointers Exceeded */
++//    XRX200_SDMA_IER_BFULL,         /* Buffer Full */
++//    XRX200_SDMA_IER_FERR,          /* Frame Error */
++//    XRX200_SDMA_IER_FRX,           /* Frame Received Successfully */
++//    XRX200_SDMA_ISR,               /* SDMA Interrupt Status Register */
++//    XRX200_SDMA_ISR_BPEX,          /* Packet Descriptors Exceeded */
++//    XRX200_SDMA_ISR_BFULL,         /* Buffer Full */
++//    XRX200_SDMA_ISR_FERR,          /* Frame Error */
++//    XRX200_SDMA_ISR_FRX,           /* Frame Received Successfully */
++//    XRX200_SDMA_PCTRL,             /* Ethernet SwitchStore DMA Port Control Register */
++//    XRX200_SDMA_PCTRL_DTHR,        /* Drop Threshold Selection */
++//    XRX200_SDMA_PCTRL_PTHR,        /* Pause Threshold Selection */
++//    XRX200_SDMA_PCTRL_PHYEFWD,     /* Forward PHY Error Frames */
++//    XRX200_SDMA_PCTRL_ALGFWD,      /* Forward Alignment Error Frames */
++//    XRX200_SDMA_PCTRL_LENFWD,      /* Forward Length Errored Frames */
++//    XRX200_SDMA_PCTRL_OSFWD,       /* Forward Oversized Frames */
++//    XRX200_SDMA_PCTRL_USFWD,       /* Forward Undersized Frames */
++//    XRX200_SDMA_PCTRL_FCSIGN,      /* Ignore FCS Errors */
++//    XRX200_SDMA_PCTRL_FCSFWD,      /* Forward FCS Errored Frames */
++//    XRX200_SDMA_PCTRL_PAUFWD,      /* Pause Frame Forwarding */
++//    XRX200_SDMA_PCTRL_MFCEN,       /* Metering Flow Control Enable */
++//    XRX200_SDMA_PCTRL_FCEN,        /* Flow Control Enable */
++//    XRX200_SDMA_PCTRL_PEN,         /* Port Enable */
++//    XRX200_SDMA_PRIO,              /* Ethernet SwitchStore DMA Port Priority Register */
++//    XRX200_SDMA_PRIO_PRIO,         /* SDMA PRIO */
++//    XRX200_SDMA_PSTAT0_HDR,        /* Ethernet SwitchStore DMA Port Status Register 0 */
++//    XRX200_SDMA_PSTAT0_HDR_PTR,    /* Port Ingress Queue Header Pointer */
++//    XRX200_SDMA_PSTAT1,            /* Ethernet SwitchStore DMA Port Status Register 1 */
++//    XRX200_SDMA_PSTAT1_PPKT,       /* Port Ingress Packet Count */
++//    XRX200_SDMA_TSTAMP0,           /* Ingress TimeStamp Register 0 */
++//    XRX200_SDMA_TSTAMP0_TSTL,      /* Time Stamp [15:0] */
++//    XRX200_SDMA_TSTAMP1,           /* Ingress TimeStamp Register 1 */
++//    XRX200_SDMA_TSTAMP1_TSTH,      /* Time Stamp [31:16] */
++};
++
++
++struct xrx200sw_reg {
++      int offset;
++      int shift;
++      int size;
++      int mult;
++} xrx200sw_reg[] = {
++//    offeset      shift    size      mult
++//    {0x0000,         0,     16,     0x00}, /* XRX200_ETHSW_SWRES             Ethernet Switch ResetControl Register */
++//    {0x0000,         1,      1,     0x00}, /* XRX200_ETHSW_SWRES_R1          Hardware Reset */
++//    {0x0000,         0,      1,     0x00}, /* XRX200_ETHSW_SWRES_R0          Register Configuration */
++//    {0x0004,         0,     16,     0x00}, /* XRX200_ETHSW_CLK_MAC_GAT       Ethernet Switch Clock ControlRegister  */
++//    {0x0004,        12,      4,     0x00}, /* XRX200_ETHSW_CLK_EXP_SLEEP     Exponent to put system into sleep */
++//    {0x0004,         8,      4,     0x00}, /* XRX200_ETHSW_CLK_EXP_WAKE      Exponent to wake up system */
++//    {0x0004,         7,      1,     0x00}, /* XRX200_ETHSW_CLK_CLK2_EN       CLK2 Input for MAC */
++//    {0x0004,         6,      1,     0x00}, /* XRX200_ETHSW_CLK_EXT_DIV_EN    External Clock Divider Enable */
++//    {0x0004,         5,      1,     0x00}, /* XRX200_ETHSW_CLK_RAM_DBG_EN    Clock Gating Enable */
++//    {0x0004,         4,      1,     0x00}, /* XRX200_ETHSW_CLK_REG_GAT_EN    Clock Gating Enable */
++//    {0x0004,         3,      1,     0x00}, /* XRX200_ETHSW_CLK_GAT_EN        Clock Gating Enable */
++//    {0x0004,         2,      1,     0x00}, /* XRX200_ETHSW_CLK_MAC_GAT_EN    Clock Gating Enable */
++//    {0x0008,         0,     16,     0x00}, /* XRX200_ETHSW_DBG_STEP          Ethernet Switch Debug ControlRegister */
++//    {0x0008,        12,      4,     0x00}, /* XRX200_ETHSW_DBG_CLK_SEL       Trigger Enable */
++//    {0x0008,        11,      1,     0x00}, /* XRX200_ETHSW_DBG_MON_EN        Monitoring Enable */
++//    {0x0008,         9,      2,     0x00}, /* XRX200_ETHSW_DBG_TRIG_EN       Trigger Enable */
++//    {0x0008,         8,      1,     0x00}, /* XRX200_ETHSW_DBG_MODE          Debug Mode */
++//    {0x0008,         0,      8,     0x00}, /* XRX200_ETHSW_DBG_STEP_TIME     Clock Step Size */
++//    {0x000C,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_MODE          Ethernet Switch SharedSegment Buffer Mode Register */
++//    {0x000C,         2,      4,     0x00}, /* XRX200_ETHSW_SSB_MODE_ADDE     Memory Address */
++//    {0x000C,         0,      2,     0x00}, /* XRX200_ETHSW_SSB_MODE_MODE     Memory Access Mode */
++//    {0x0010,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_ADDR          Ethernet Switch SharedSegment Buffer Address Register */
++//    {0x0010,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_ADDR_ADDE     Memory Address */
++//    {0x0014,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_DATA          Ethernet Switch SharedSegment Buffer Data Register */
++//    {0x0014,         0,     16,     0x00}, /* XRX200_ETHSW_SSB_DATA_DATA     Data Value */
++//    {0x0018,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_0             Ethernet Switch CapabilityRegister 0 */
++//    {0x0018,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_0_SPEED       Clock frequency */
++//    {0x001C,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_1             Ethernet Switch CapabilityRegister 1 */
++//    {0x001C,        15,      1,     0x00}, /* XRX200_ETHSW_CAP_1_GMAC        MAC operation mode */
++//    {0x001C,         8,      7,     0x00}, /* XRX200_ETHSW_CAP_1_QUEUE       Number of queues */
++//    {0x001C,         4,      4,     0x00}, /* XRX200_ETHSW_CAP_1_VPORTS      Number of virtual ports */
++//    {0x001C,         0,      4,     0x00}, /* XRX200_ETHSW_CAP_1_PPORTS      Number of physical ports */
++//    {0x0020,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_2             Ethernet Switch CapabilityRegister 2 */
++//    {0x0020,         0,     11,     0x00}, /* XRX200_ETHSW_CAP_2_PACKETS     Number of packets */
++//    {0x0024,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_3             Ethernet Switch CapabilityRegister 3 */
++//    {0x0024,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_3_METERS      Number of traffic meters */
++//    {0x0024,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_3_SHAPERS     Number of traffic shapers */
++//    {0x0028,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_4             Ethernet Switch CapabilityRegister 4 */
++//    {0x0028,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_4_PPPOE       PPPoE table size */
++//    {0x0028,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_4_VLAN        Active VLAN table size */
++//    {0x002C,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_5             Ethernet Switch CapabilityRegister 5 */
++//    {0x002C,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_5_IPPLEN      IP packet length table size */
++//    {0x002C,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_5_PROT        Protocol table size */
++//    {0x0030,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_6             Ethernet Switch CapabilityRegister 6 */
++//    {0x0030,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_6_MACDASA     MAC DA/SA table size */
++//    {0x0030,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_6_APPL        Application table size */
++//    {0x0034,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_7             Ethernet Switch CapabilityRegister 7 */
++//    {0x0034,         8,      8,     0x00}, /* XRX200_ETHSW_CAP_7_IPDASAM     IP DA/SA MSB table size */
++//    {0x0034,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_7_IPDASAL     IP DA/SA LSB table size */
++//    {0x0038,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_8             Ethernet Switch CapabilityRegister 8 */
++//    {0x0038,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_8_MCAST       Multicast table size */
++//    {0x003C,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_9             Ethernet Switch CapabilityRegister 9 */
++//    {0x003C,         0,      8,     0x00}, /* XRX200_ETHSW_CAP_9_FLAGG       Flow Aggregation table size */
++//    {0x0040,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_10            Ethernet Switch CapabilityRegister 10 */
++//    {0x0040,         0,     13,     0x00}, /* XRX200_ETHSW_CAP_10_MACBT      MAC bridging table size */
++//    {0x0044,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_11            Ethernet Switch CapabilityRegister 11 */
++//    {0x0044,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_11_BSIZEL     Packet buffer size (lower part, in byte) */
++//    {0x0048,         0,     16,     0x00}, /* XRX200_ETHSW_CAP_12            Ethernet Switch CapabilityRegister 12 */
++//    {0x0048,         0,      3,     0x00}, /* XRX200_ETHSW_CAP_12_BSIZEH     Packet buffer size (higher part, in byte) */
++//    {0x004C,         0,     16,     0x00}, /* XRX200_ETHSW_VERSION_REV       Ethernet Switch VersionRegister */
++//    {0x004C,         8,      8,     0x00}, /* XRX200_ETHSW_VERSION_MOD_ID    Module Identification */
++//    {0x004C,         0,      8,     0x00}, /* XRX200_ETHSW_VERSION_REV_ID    Hardware Revision Identification */
++//    {0x0050,         0,     16,     0x00}, /* XRX200_ETHSW_IER               Interrupt Enable Register */
++//    {0x0050,         4,      1,     0x00}, /* XRX200_ETHSW_IER_FDMAIE        Fetch DMA Interrupt Enable */
++//    {0x0050,         3,      1,     0x00}, /* XRX200_ETHSW_IER_SDMAIE        Store DMA Interrupt Enable */
++//    {0x0050,         2,      1,     0x00}, /* XRX200_ETHSW_IER_MACIE         Ethernet MAC Interrupt Enable */
++//    {0x0050,         1,      1,     0x00}, /* XRX200_ETHSW_IER_PCEIE         Parser and Classification Engine Interrupt Enable */
++//    {0x0050,         0,      1,     0x00}, /* XRX200_ETHSW_IER_BMIE          Buffer Manager Interrupt Enable */
++//    {0x0054,         0,     16,     0x00}, /* XRX200_ETHSW_ISR               Interrupt Status Register */
++//    {0x0054,         4,      1,     0x00}, /* XRX200_ETHSW_ISR_FDMAINT       Fetch DMA Interrupt */
++//    {0x0054,         3,      1,     0x00}, /* XRX200_ETHSW_ISR_SDMAINT       Store DMA Interrupt */
++//    {0x0054,         2,      1,     0x00}, /* XRX200_ETHSW_ISR_MACINT        Ethernet MAC Interrupt */
++//    {0x0054,         1,      1,     0x00}, /* XRX200_ETHSW_ISR_PCEINT        Parser and Classification Engine Interrupt */
++//    {0x0054,         0,      1,     0x00}, /* XRX200_ETHSW_ISR_BMINT         Buffer Manager Interrupt */
++//    {0x0058,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_0           Ethernet Switch SpareCells 0 */
++//    {0x0058,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_0_SPARE     SPARE0  */
++//    {0x005C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_1           Ethernet Switch SpareCells 1 */
++//    {0x005C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_1_SPARE     SPARE1  */
++//    {0x0060,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_2           Ethernet Switch SpareCells 2 */
++//    {0x0060,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_2_SPARE     SPARE2  */
++//    {0x0064,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_3           Ethernet Switch SpareCells 3 */
++//    {0x0064,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_3_SPARE     SPARE3  */
++//    {0x0068,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_4           Ethernet Switch SpareCells 4 */
++//    {0x0068,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_4_SPARE     SPARE4  */
++//    {0x006C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_5           Ethernet Switch SpareCells 5 */
++//    {0x006C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_5_SPARE     SPARE5  */
++//    {0x0070,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_6           Ethernet Switch SpareCells 6 */
++//    {0x0070,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_6_SPARE     SPARE6  */
++//    {0x0074,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_7           Ethernet Switch SpareCells 7 */
++//    {0x0074,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_7_SPARE     SPARE7  */
++//    {0x0078,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_8           Ethernet Switch SpareCells 8 */
++//    {0x0078,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_8_SPARE     SPARE8  */
++//    {0x007C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_9           Ethernet Switch SpareCells 9 */
++//    {0x007C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_9_SPARE     SPARE9  */
++//    {0x0080,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_10          Ethernet Switch SpareCells 10 */
++//    {0x0080,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_10_SPARE    SPARE10  */
++//    {0x0084,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_11          Ethernet Switch SpareCells 11 */
++//    {0x0084,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_11_SPARE    SPARE11  */
++//    {0x0088,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_12          Ethernet Switch SpareCells 12 */
++//    {0x0088,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_12_SPARE    SPARE12  */
++//    {0x008C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_13          Ethernet Switch SpareCells 13 */
++//    {0x008C,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_13_SPARE    SPARE13  */
++//    {0x0090,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_14          Ethernet Switch SpareCells 14 */
++//    {0x0090,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_14_SPARE    SPARE14  */
++//    {0x0094,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_15          Ethernet Switch SpareCells 15 */
++//    {0x0094,         0,     16,     0x00}, /* XRX200_ETHSW_SPARE_15_SPARE    SPARE15  */
++//    {0x0100,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_3            RAM Value Register 3 */
++//    {0x0100,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_3_VAL3       Data value [15:0] */
++//    {0x0104,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_2            RAM Value Register 2 */
++//    {0x0104,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_2_VAL2       Data value [15:0] */
++//    {0x0108,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_1            RAM Value Register 1 */
++//    {0x0108,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_1_VAL1       Data value [15:0] */
++//    {0x010C,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_0            RAM Value Register 0 */
++//    {0x010C,         0,     16,     0x00}, /* XRX200_BM_RAM_VAL_0_VAL0       Data value [15:0] */
++//    {0x0110,         0,     16,     0x00}, /* XRX200_BM_RAM_ADDR             RAM Address Register */
++//    {0x0110,         0,     11,     0x00}, /* XRX200_BM_RAM_ADDR_ADDR        RAM Address */
++//    {0x0114,         0,     16,     0x00}, /* XRX200_BM_RAM_CTRL             RAM Access Control Register */
++//    {0x0114,        15,      1,     0x00}, /* XRX200_BM_RAM_CTRL_BAS         Access Busy/Access Start */
++//    {0x0114,         5,      1,     0x00}, /* XRX200_BM_RAM_CTRL_OPMOD       Lookup Table Access Operation Mode */
++//    {0x0114,         0,      5,     0x00}, /* XRX200_BM_RAM_CTRL_ADDR        Address for RAM selection */
++//    {0x0118,         0,     16,     0x00}, /* XRX200_BM_FSQM_GCTRL           Free Segment Queue ManagerGlobal Control Register */
++//    {0x0118,         0,     10,     0x00}, /* XRX200_BM_FSQM_GCTRL_SEGNUM    Maximum Segment Number */
++//    {0x011C,         0,     16,     0x00}, /* XRX200_BM_CONS_SEG             Number of Consumed SegmentsRegister */
++//    {0x011C,         0,     10,     0x00}, /* XRX200_BM_CONS_SEG_FSEG        Number of Consumed Segments */
++//    {0x0120,         0,     16,     0x00}, /* XRX200_BM_CONS_PKT             Number of Consumed PacketPointers Register */
++//    {0x0120,         0,     11,     0x00}, /* XRX200_BM_CONS_PKT_FQP         Number of Consumed Packet Pointers */
++//    {0x0124,         0,     16,     0x00}, /* XRX200_BM_GCTRL_F              Buffer Manager Global ControlRegister 0 */
++//    {0x0124,        13,      1,     0x00}, /* XRX200_BM_GCTRL_BM_STA         Buffer Manager Initialization Status Bit */
++//    {0x0124,        12,      1,     0x00}, /* XRX200_BM_GCTRL_SAT            RMON Counter Update Mode */
++//    {0x0124,        11,      1,     0x00}, /* XRX200_BM_GCTRL_FR_RBC         Freeze RMON RX Bad Byte 64 Bit Counter */
++//    {0x0124,        10,      1,     0x00}, /* XRX200_BM_GCTRL_FR_RGC         Freeze RMON RX Good Byte 64 Bit Counter */
++//    {0x0124,         9,      1,     0x00}, /* XRX200_BM_GCTRL_FR_TGC         Freeze RMON TX Good Byte 64 Bit Counter */
++//    {0x0124,         8,      1,     0x00}, /* XRX200_BM_GCTRL_I_FIN          RAM initialization finished */
++//    {0x0124,         7,      1,     0x00}, /* XRX200_BM_GCTRL_CX_INI         PQM Context RAM initialization */
++//    {0x0124,         6,      1,     0x00}, /* XRX200_BM_GCTRL_FP_INI         FPQM RAM initialization */
++//    {0x0124,         5,      1,     0x00}, /* XRX200_BM_GCTRL_FS_INI         FSQM RAM initialization */
++//    {0x0124,         4,      1,     0x00}, /* XRX200_BM_GCTRL_R_SRES         Software Reset for RMON */
++//    {0x0124,         3,      1,     0x00}, /* XRX200_BM_GCTRL_S_SRES         Software Reset for Scheduler */
++//    {0x0124,         2,      1,     0x00}, /* XRX200_BM_GCTRL_A_SRES         Software Reset for AVG */
++//    {0x0124,         1,      1,     0x00}, /* XRX200_BM_GCTRL_P_SRES         Software Reset for PQM */
++//    {0x0124,         0,      1,     0x00}, /* XRX200_BM_GCTRL_F_SRES         Software Reset for FSQM */
++//    {0x0128,         0,     16,     0x00}, /* XRX200_BM_QUEUE_GCTRL          Queue Manager GlobalControl Register 0 */
++//    {0x0128,        10,      1,     0x00}, /* XRX200_BM_QUEUE_GCTRL_GL_MOD   WRED Mode Signal */
++//    {0x0128,         7,      3,     0x00}, /* XRX200_BM_QUEUE_GCTRL_AQUI     Average Queue Update Interval */
++//    {0x0128,         3,      4,     0x00}, /* XRX200_BM_QUEUE_GCTRL_AQWF     Average Queue Weight Factor */
++//    {0x0128,         2,      1,     0x00}, /* XRX200_BM_QUEUE_GCTRL_QAVGEN   Queue Average Calculation Enable */
++//    {0x0128,         0,      2,     0x00}, /* XRX200_BM_QUEUE_GCTRL_DPROB    Drop Probability Profile */
++//    {0x012C,         0,     16,     0x00}, /* XRX200_BM_WRED_RTH_0           WRED Red Threshold Register0 */
++//    {0x012C,         0,     10,     0x00}, /* XRX200_BM_WRED_RTH_0_MINTH     Minimum Threshold */
++//    {0x0130,         0,     16,     0x00}, /* XRX200_BM_WRED_RTH_1           WRED Red Threshold Register1 */
++//    {0x0130,         0,     10,     0x00}, /* XRX200_BM_WRED_RTH_1_MAXTH     Maximum Threshold */
++//    {0x0134,         0,     16,     0x00}, /* XRX200_BM_WRED_YTH_0           WRED Yellow ThresholdRegister 0 */
++//    {0x0134,         0,     10,     0x00}, /* XRX200_BM_WRED_YTH_0_MINTH     Minimum Threshold */
++//    {0x0138,         0,     16,     0x00}, /* XRX200_BM_WRED_YTH_1           WRED Yellow ThresholdRegister 1 */
++//    {0x0138,         0,     10,     0x00}, /* XRX200_BM_WRED_YTH_1_MAXTH     Maximum Threshold */
++//    {0x013C,         0,     16,     0x00}, /* XRX200_BM_WRED_GTH_0           WRED Green ThresholdRegister 0 */
++//    {0x013C,         0,     10,     0x00}, /* XRX200_BM_WRED_GTH_0_MINTH     Minimum Threshold */
++//    {0x0140,         0,     16,     0x00}, /* XRX200_BM_WRED_GTH_1           WRED Green ThresholdRegister 1 */
++//    {0x0140,         0,     10,     0x00}, /* XRX200_BM_WRED_GTH_1_MAXTH     Maximum Threshold */
++//    {0x0144,         0,     16,     0x00}, /* XRX200_BM_DROP_GTH_0_THR       Drop Threshold ConfigurationRegister 0 */
++//    {0x0144,         0,     11,     0x00}, /* XRX200_BM_DROP_GTH_0_THR_FQ    Threshold for frames marked red */
++//    {0x0148,         0,     16,     0x00}, /* XRX200_BM_DROP_GTH_1_THY       Drop Threshold ConfigurationRegister 1 */
++//    {0x0148,         0,     11,     0x00}, /* XRX200_BM_DROP_GTH_1_THY_FQ    Threshold for frames marked yellow */
++//    {0x014C,         0,     16,     0x00}, /* XRX200_BM_DROP_GTH_2_THG       Drop Threshold ConfigurationRegister 2 */
++//    {0x014C,         0,     11,     0x00}, /* XRX200_BM_DROP_GTH_2_THG_FQ    Threshold for frames marked green */
++//    {0x0150,         0,     16,     0x00}, /* XRX200_BM_IER                  Buffer Manager Global InterruptEnable Register */
++//    {0x0150,         7,      1,     0x00}, /* XRX200_BM_IER_CNT4             Counter Group 4 (RMON-CLASSIFICATION) Interrupt Enable */
++//    {0x0150,         6,      1,     0x00}, /* XRX200_BM_IER_CNT3             Counter Group 3 (RMON-PQM) Interrupt Enable */
++//    {0x0150,         5,      1,     0x00}, /* XRX200_BM_IER_CNT2             Counter Group 2 (RMON-SCHEDULER) Interrupt Enable */
++//    {0x0150,         4,      1,     0x00}, /* XRX200_BM_IER_CNT1             Counter Group 1 (RMON-QFETCH) Interrupt Enable */
++//    {0x0150,         3,      1,     0x00}, /* XRX200_BM_IER_CNT0             Counter Group 0 (RMON-QSTOR) Interrupt Enable */
++//    {0x0150,         2,      1,     0x00}, /* XRX200_BM_IER_DEQ              PQM dequeue Interrupt Enable */
++//    {0x0150,         1,      1,     0x00}, /* XRX200_BM_IER_ENQ              PQM Enqueue Interrupt Enable */
++//    {0x0150,         0,      1,     0x00}, /* XRX200_BM_IER_FSQM             Buffer Empty Interrupt Enable */
++//    {0x0154,         0,     16,     0x00}, /* XRX200_BM_ISR                  Buffer Manager Global InterruptStatus Register */
++//    {0x0154,         7,      1,     0x00}, /* XRX200_BM_ISR_CNT4             Counter Group 4 Interrupt */
++//    {0x0154,         6,      1,     0x00}, /* XRX200_BM_ISR_CNT3             Counter Group 3 Interrupt */
++//    {0x0154,         5,      1,     0x00}, /* XRX200_BM_ISR_CNT2             Counter Group 2 Interrupt */
++//    {0x0154,         4,      1,     0x00}, /* XRX200_BM_ISR_CNT1             Counter Group 1 Interrupt */
++//    {0x0154,         3,      1,     0x00}, /* XRX200_BM_ISR_CNT0             Counter Group 0 Interrupt */
++//    {0x0154,         2,      1,     0x00}, /* XRX200_BM_ISR_DEQ              PQM dequeue Interrupt Enable */
++//    {0x0154,         1,      1,     0x00}, /* XRX200_BM_ISR_ENQ              PQM Enqueue Interrupt */
++//    {0x0154,         0,      1,     0x00}, /* XRX200_BM_ISR_FSQM             Buffer Empty Interrupt */
++//    {0x0158,         0,     16,     0x00}, /* XRX200_BM_CISEL                Buffer Manager RMON CounterInterrupt Select Register */
++//    {0x0158,         0,      3,     0x00}, /* XRX200_BM_CISEL_PORT           Port Number */
++//    {0x015C,         0,     16,     0x00}, /* XRX200_BM_DEBUG_CTRL_DBG       Debug Control Register */
++//    {0x015C,         0,      8,     0x00}, /* XRX200_BM_DEBUG_CTRL_DBG_SEL   Select Signal for Debug Multiplexer */
++//    {0x0160,         0,     16,     0x00}, /* XRX200_BM_DEBUG_VAL_DBG        Debug Value Register */
++//    {0x0160,         0,     16,     0x00}, /* XRX200_BM_DEBUG_VAL_DBG_DAT    Debug Data Value */
++//    {0x0200,         0,     16,     0x08}, /* XRX200_BM_PCFG                 Buffer Manager PortConfiguration Register */
++//    {0x0200,         0,      1,     0x08}, /* XRX200_BM_PCFG_CNTEN           RMON Counter Enable */
++//    {0x0204,         0,     16,     0x08}, /* XRX200_BM_RMON_CTRL_RAM1       Buffer ManagerRMON Control Register */
++//    {0x0204,         1,      1,     0x08}, /* XRX200_BM_RMON_CTRL_RAM2_RES   Software Reset for RMON RAM2 */
++//    {0x0204,         0,      1,     0x08}, /* XRX200_BM_RMON_CTRL_RAM1_RES   Software Reset for RMON RAM1 */
++//    {0x0400,         0,     16,     0x08}, /* XRX200_PQM_DP                  Packet Queue ManagerDrop Probability Register */
++//    {0x0400,         0,      2,     0x08}, /* XRX200_PQM_DP_DPROB            Drop Probability Profile */
++//    {0x0404,         0,     16,     0x08}, /* XRX200_PQM_RS                  Packet Queue ManagerRate Shaper Assignment Register */
++//    {0x0404,        15,      1,     0x08}, /* XRX200_PQM_RS_EN2              Rate Shaper 2 Enable */
++//    {0x0404,         8,      6,     0x08}, /* XRX200_PQM_RS_RS2              Rate Shaper 2 */
++//    {0x0404,         7,      1,     0x08}, /* XRX200_PQM_RS_EN1              Rate Shaper 1 Enable */
++//    {0x0404,         0,      6,     0x08}, /* XRX200_PQM_RS_RS1              Rate Shaper 1 */
++//    {0x0500,         0,     16,     0x14}, /* XRX200_RS_CTRL                 Rate Shaper ControlRegister */
++//    {0x0500,         0,      1,     0x14}, /* XRX200_RS_CTRL_RSEN            Rate Shaper Enable */
++//    {0x0504,         0,     16,     0x14}, /* XRX200_RS_CBS                  Rate Shaper CommittedBurst Size Register */
++//    {0x0504,         0,     10,     0x14}, /* XRX200_RS_CBS_CBS              Committed Burst Size */
++//    {0x0508,         0,     16,     0x14}, /* XRX200_RS_IBS                  Rate Shaper InstantaneousBurst Size Register */
++//    {0x0508,         0,      2,     0x14}, /* XRX200_RS_IBS_IBS              Instantaneous Burst Size */
++//    {0x050C,         0,     16,     0x14}, /* XRX200_RS_CIR_EXP              Rate Shaper RateExponent Register */
++//    {0x050C,         0,      4,     0x14}, /* XRX200_RS_CIR_EXP_EXP          Exponent */
++//    {0x0510,         0,     16,     0x14}, /* XRX200_RS_CIR_MANT             Rate Shaper RateMantissa Register */
++//    {0x0510,         0,     10,     0x14}, /* XRX200_RS_CIR_MANT_MANT        Mantissa */
++      {0x1100,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_7           Table Key Data 7 */
++//    {0x1100,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_7_KEY7      Key Value[15:0] */
++      {0x1104,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_6           Table Key Data 6 */
++//    {0x1104,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_6_KEY6      Key Value[15:0] */
++      {0x1108,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_5           Table Key Data 5 */
++//    {0x1108,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_5_KEY5      Key Value[15:0] */
++      {0x110C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_4           Table Key Data 4 */
++//    {0x110C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_4_KEY4      Key Value[15:0] */
++      {0x1110,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_3           Table Key Data 3 */
++//    {0x1110,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_3_KEY3      Key Value[15:0] */
++      {0x1114,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_2           Table Key Data 2 */
++//    {0x1114,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_2_KEY2      Key Value[15:0] */
++      {0x1118,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_1           Table Key Data 1 */
++//    {0x1118,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_1_KEY1      Key Value[31:16] */
++      {0x111C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_0           Table Key Data 0 */
++//    {0x111C,         0,     16,     0x00}, /* XRX200_PCE_TBL_KEY_0_KEY0      Key Value[15:0] */
++      {0x1120,         0,     16,     0x00}, /* XRX200_PCE_TBL_MASK_0          Table Mask Write Register0 */
++//    {0x1120,         0,     16,     0x00}, /* XRX200_PCE_TBL_MASK_0_MASK0    Mask Pattern [15:0] */
++      {0x1124,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_4           Table Value Register4 */
++//    {0x1124,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_4_VAL4      Data value [15:0] */
++      {0x1128,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_3           Table Value Register3 */
++//    {0x1128,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_3_VAL3      Data value [15:0] */
++      {0x112C,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_2           Table Value Register2 */
++//    {0x112C,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_2_VAL2      Data value [15:0] */
++      {0x1130,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_1           Table Value Register1 */
++//    {0x1130,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_1_VAL1      Data value [15:0] */
++      {0x1134,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_0           Table Value Register0 */
++//    {0x1134,         0,     16,     0x00}, /* XRX200_PCE_TBL_VAL_0_VAL0      Data value [15:0] */
++//    {0x1138,         0,     16,     0x00}, /* XRX200_PCE_TBL_ADDR            Table Entry AddressRegister */
++      {0x1138,         0,     11,     0x00}, /* XRX200_PCE_TBL_ADDR_ADDR       Table Address */
++//    {0x113C,         0,     16,     0x00}, /* XRX200_PCE_TBL_CTRL            Table Access ControlRegister */
++      {0x113C,        15,      1,     0x00}, /* XRX200_PCE_TBL_CTRL_BAS        Access Busy/Access Start */
++      {0x113C,        13,      1,     0x00}, /* XRX200_PCE_TBL_CTRL_TYPE       Lookup Entry Type */
++      {0x113C,        12,      1,     0x00}, /* XRX200_PCE_TBL_CTRL_VLD        Lookup Entry Valid */
++      {0x113C,         7,      4,     0x00}, /* XRX200_PCE_TBL_CTRL_GMAP       Group Map */
++      {0x113C,         5,      2,     0x00}, /* XRX200_PCE_TBL_CTRL_OPMOD      Lookup Table Access Operation Mode */
++      {0x113C,         0,      5,     0x00}, /* XRX200_PCE_TBL_CTRL_ADDR       Lookup Table Address */
++//    {0x1140,         0,     16,     0x00}, /* XRX200_PCE_TBL_STAT            Table General StatusRegister */
++//    {0x1140,         2,      1,     0x00}, /* XRX200_PCE_TBL_STAT_TBUSY      Table Access Busy */
++//    {0x1140,         1,      1,     0x00}, /* XRX200_PCE_TBL_STAT_TEMPT      Table Empty */
++//    {0x1140,         0,      1,     0x00}, /* XRX200_PCE_TBL_STAT_TFUL       Table Full */
++//    {0x1144,         0,     16,     0x00}, /* XRX200_PCE_AGE_0               Aging Counter ConfigurationRegister 0 */
++//    {0x1144,         0,      4,     0x00}, /* XRX200_PCE_AGE_0_EXP           Aging Counter Exponent Value  */
++//    {0x1148,         0,     16,     0x00}, /* XRX200_PCE_AGE_1               Aging Counter ConfigurationRegister 1 */
++//    {0x1148,         0,     16,     0x00}, /* XRX200_PCE_AGE_1_MANT          Aging Counter Mantissa Value  */
++//    {0x114C,         0,     16,     0x00}, /* XRX200_PCE_PMAP_1              Port Map Register 1 */
++//    {0x114C,         0,     16,     0x00}, /* XRX200_PCE_PMAP_1_MPMAP        Monitoring Port Map */
++//    {0x1150,         0,     16,     0x00}, /* XRX200_PCE_PMAP_2              Port Map Register 2 */
++//    {0x1150,         0,     16,     0x00}, /* XRX200_PCE_PMAP_2_DMCPMAP      Default Multicast Port Map */
++//    {0x1154,         0,     16,     0x00}, /* XRX200_PCE_PMAP_3              Port Map Register 3 */
++//    {0x1154,         0,     16,     0x00}, /* XRX200_PCE_PMAP_3_UUCMAP       Default Unknown Unicast Port Map */
++//    {0x1158,         0,     16,     0x00}, /* XRX200_PCE_GCTRL_0             PCE Global Control Register0 */
++//    {0x1158,        15,      1,     0x00}, /* XRX200_PCE_GCTRL_0_IGMP        IGMP Mode Selection */
++      {0x1158,        14,      1,     0x00}, /* XRX200_PCE_GCTRL_0_VLAN        VLAN-aware Switching */
++//    {0x1158,        13,      1,     0x00}, /* XRX200_PCE_GCTRL_0_NOPM        No Port Map Forwarding */
++//    {0x1158,        12,      1,     0x00}, /* XRX200_PCE_GCTRL_0_SCONUC      Unknown Unicast Storm Control */
++//    {0x1158,        11,      1,     0x00}, /* XRX200_PCE_GCTRL_0_SCONMC      Multicast Storm Control */
++//    {0x1158,        10,      1,     0x00}, /* XRX200_PCE_GCTRL_0_SCONBC      Broadcast Storm Control */
++//    {0x1158,         8,      2,     0x00}, /* XRX200_PCE_GCTRL_0_SCONMOD     Storm Control Mode */
++//    {0x1158,         4,      4,     0x00}, /* XRX200_PCE_GCTRL_0_SCONMET     Storm Control Metering Instance */
++//    {0x1158,         3,      1,     0x00}, /* XRX200_PCE_GCTRL_0_MC_VALID    Access Request */
++//    {0x1158,         2,      1,     0x00}, /* XRX200_PCE_GCTRL_0_PLCKMOD     Port Lock Mode */
++//    {0x1158,         1,      1,     0x00}, /* XRX200_PCE_GCTRL_0_PLIMMOD     MAC Address Learning Limitation Mode */
++//    {0x1158,         0,      1,     0x00}, /* XRX200_PCE_GCTRL_0_MTFL        MAC Table Flushing */
++//    {0x115C,         0,     16,     0x00}, /* XRX200_PCE_GCTRL_1             PCE Global Control Register1 */
++//    {0x115C,         1,      1,     0x00}, /* XRX200_PCE_GCTRL_1_PCE_DIS     PCE Disable after currently processed packet */
++//    {0x115C,         0,      1,     0x00}, /* XRX200_PCE_GCTRL_1_LRNMOD      MAC Address Learning Mode */
++//    {0x1160,         0,     16,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL       Three-color MarkerGlobal Control Register */
++//    {0x1160,         6,      3,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL_DPRED Re-marking Drop Precedence Red Encoding */
++//    {0x1160,         3,      3,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL_DPYEL Re-marking Drop Precedence Yellow Encoding */
++//    {0x1160,         0,      3,     0x00}, /* XRX200_PCE_TCM_GLOB_CTRL_DPGRN Re-marking Drop Precedence Green Encoding */
++//    {0x1164,         0,     16,     0x00}, /* XRX200_PCE_IGMP_CTRL           IGMP Control Register */
++//    {0x1164,        15,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_FAGEEN    Force Aging of Table Entries Enable */
++//    {0x1164,        14,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_FLEAVE    Fast Leave Enable */
++//    {0x1164,        13,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_DMRTEN    Default Maximum Response Time Enable */
++//    {0x1164,        12,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_JASUP     Join Aggregation Suppression Enable */
++//    {0x1164,        11,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_REPSUP    Report Suppression Enable */
++//    {0x1164,        10,      1,     0x00}, /* XRX200_PCE_IGMP_CTRL_SRPEN     Snooping of Router Port Enable */
++//    {0x1164,         8,      2,     0x00}, /* XRX200_PCE_IGMP_CTRL_ROB       Robustness Variable */
++//    {0x1164,         0,      8,     0x00}, /* XRX200_PCE_IGMP_CTRL_DMRT      IGMP Default Maximum Response Time */
++//    {0x1168,         0,     16,     0x00}, /* XRX200_PCE_IGMP_DRPM           IGMP Default RouterPort Map Register */
++//    {0x1168,         0,     16,     0x00}, /* XRX200_PCE_IGMP_DRPM_DRPM      IGMP Default Router Port Map */
++//    {0x116C,         0,     16,     0x00}, /* XRX200_PCE_IGMP_AGE_0          IGMP Aging Register0 */
++//    {0x116C,         3,      8,     0x00}, /* XRX200_PCE_IGMP_AGE_0_MANT     IGMP Group Aging Time Mantissa */
++//    {0x116C,         0,      3,     0x00}, /* XRX200_PCE_IGMP_AGE_0_EXP      IGMP Group Aging Time Exponent */
++//    {0x1170,         0,     16,     0x00}, /* XRX200_PCE_IGMP_AGE_1          IGMP Aging Register1 */
++//    {0x1170,         0,     12,     0x00}, /* XRX200_PCE_IGMP_AGE_1_MANT     IGMP Router Port Aging Time Mantissa */
++//    {0x1174,         0,     16,     0x00}, /* XRX200_PCE_IGMP_STAT           IGMP Status Register */
++//    {0x1174,         0,     16,     0x00}, /* XRX200_PCE_IGMP_STAT_IGPM      IGMP Port Map */
++//    {0x1178,         0,     16,     0x00}, /* XRX200_WOL_GLB_CTRL            Wake-on-LAN ControlRegister */
++//    {0x1178,         0,      1,     0x00}, /* XRX200_WOL_GLB_CTRL_PASSEN     WoL Password Enable */
++//    {0x117C,         0,     16,     0x00}, /* XRX200_WOL_DA_0                Wake-on-LAN DestinationAddress Register 0 */
++//    {0x117C,         0,     16,     0x00}, /* XRX200_WOL_DA_0_DA0            WoL Destination Address [15:0] */
++//    {0x1180,         0,     16,     0x00}, /* XRX200_WOL_DA_1                Wake-on-LAN DestinationAddress Register 1 */
++//    {0x1180,         0,     16,     0x00}, /* XRX200_WOL_DA_1_DA1            WoL Destination Address [31:16] */
++//    {0x1184,         0,     16,     0x00}, /* XRX200_WOL_DA_2                Wake-on-LAN DestinationAddress Register 2 */
++//    {0x1184,         0,     16,     0x00}, /* XRX200_WOL_DA_2_DA2            WoL Destination Address [47:32] */
++//    {0x1188,         0,     16,     0x00}, /* XRX200_WOL_PW_0                Wake-on-LAN Password Register0 */
++//    {0x1188,         0,     16,     0x00}, /* XRX200_WOL_PW_0_PW0            WoL Password [15:0] */
++//    {0x118C,         0,     16,     0x00}, /* XRX200_WOL_PW_1                Wake-on-LAN Password Register1 */
++//    {0x118C,         0,     16,     0x00}, /* XRX200_WOL_PW_1_PW1            WoL Password [31:16] */
++//    {0x1190,         0,     16,     0x00}, /* XRX200_WOL_PW_2                Wake-on-LAN Password Register2 */
++//    {0x1190,         0,     16,     0x00}, /* XRX200_WOL_PW_2_PW2            WoL Password [47:32] */
++//    {0x1194,         0,     16,     0x00}, /* XRX200_PCE_IER_0_PINT          Parser and ClassificationEngine Global Interrupt Enable Register 0 */
++//    {0x1194,        15,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_15       Port Interrupt Enable */
++//    {0x1194,        14,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_14       Port Interrupt Enable */
++//    {0x1194,        13,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_13       Port Interrupt Enable */
++//    {0x1194,        12,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_12       Port Interrupt Enable */
++//    {0x1194,        11,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_11       Port Interrupt Enable */
++//    {0x1194,        10,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_10       Port Interrupt Enable */
++//    {0x1194,         9,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_9        Port Interrupt Enable */
++//    {0x1194,         8,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_8        Port Interrupt Enable */
++//    {0x1194,         7,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_7        Port Interrupt Enable */
++//    {0x1194,         6,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_6        Port Interrupt Enable */
++//    {0x1194,         5,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_5        Port Interrupt Enable */
++//    {0x1194,         4,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_4        Port Interrupt Enable */
++//    {0x1194,         3,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_3        Port Interrupt Enable */
++//    {0x1194,         2,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_2        Port Interrupt Enable */
++//    {0x1194,         1,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_1        Port Interrupt Enable */
++//    {0x1194,         0,      1,     0x00}, /* XRX200_PCE_IER_0_PINT_0        Port Interrupt Enable */
++//    {0x1198,         0,     16,     0x00}, /* XRX200_PCE_IER_1               Parser and ClassificationEngine Global Interrupt Enable Register 1 */
++//    {0x1198,         6,      1,     0x00}, /* XRX200_PCE_IER_1_FLOWINT       Traffic Flow Table Interrupt Rule matched Interrupt Enable */
++//    {0x1198,         5,      1,     0x00}, /* XRX200_PCE_IER_1_CPH2          Classification Phase 2 Ready Interrupt Enable */
++//    {0x1198,         4,      1,     0x00}, /* XRX200_PCE_IER_1_CPH1          Classification Phase 1 Ready Interrupt Enable */
++//    {0x1198,         3,      1,     0x00}, /* XRX200_PCE_IER_1_CPH0          Classification Phase 0 Ready Interrupt Enable */
++//    {0x1198,         2,      1,     0x00}, /* XRX200_PCE_IER_1_PRDY          Parser Ready Interrupt Enable */
++//    {0x1198,         1,      1,     0x00}, /* XRX200_PCE_IER_1_IGTF          IGMP Table Full Interrupt Enable */
++//    {0x1198,         0,      1,     0x00}, /* XRX200_PCE_IER_1_MTF           MAC Table Full Interrupt Enable */
++//    {0x119C,         0,     16,     0x00}, /* XRX200_PCE_ISR_0_PINT          Parser and ClassificationEngine Global Interrupt Status Register 0 */
++//    {0x119C,        15,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_15       Port Interrupt */
++//    {0x119C,        14,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_14       Port Interrupt */
++//    {0x119C,        13,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_13       Port Interrupt */
++//    {0x119C,        12,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_12       Port Interrupt */
++//    {0x119C,        11,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_11       Port Interrupt */
++//    {0x119C,        10,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_10       Port Interrupt */
++//    {0x119C,         9,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_9        Port Interrupt */
++//    {0x119C,         8,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_8        Port Interrupt */
++//    {0x119C,         7,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_7        Port Interrupt */
++//    {0x119C,         6,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_6        Port Interrupt */
++//    {0x119C,         5,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_5        Port Interrupt */
++//    {0x119C,         4,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_4        Port Interrupt */
++//    {0x119C,         3,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_3        Port Interrupt */
++//    {0x119C,         2,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_2        Port Interrupt */
++//    {0x119C,         1,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_1        Port Interrupt */
++//    {0x119C,         0,      1,     0x00}, /* XRX200_PCE_ISR_0_PINT_0        Port Interrupt */
++//    {0x11A0,         0,     16,     0x00}, /* XRX200_PCE_ISR_1               Parser and ClassificationEngine Global Interrupt Status Register 1 */
++//    {0x11A0,         6,      1,     0x00}, /* XRX200_PCE_ISR_1_FLOWINT       Traffic Flow Table Interrupt Rule matched */
++//    {0x11A0,         5,      1,     0x00}, /* XRX200_PCE_ISR_1_CPH2          Classification Phase 2 Ready Interrupt */
++//    {0x11A0,         4,      1,     0x00}, /* XRX200_PCE_ISR_1_CPH1          Classification Phase 1 Ready Interrupt */
++//    {0x11A0,         3,      1,     0x00}, /* XRX200_PCE_ISR_1_CPH0          Classification Phase 0 Ready Interrupt */
++//    {0x11A0,         2,      1,     0x00}, /* XRX200_PCE_ISR_1_PRDY          Parser Ready Interrupt */
++//    {0x11A0,         1,      1,     0x00}, /* XRX200_PCE_ISR_1_IGTF          IGMP Table Full Interrupt */
++//    {0x11A0,         0,      1,     0x00}, /* XRX200_PCE_ISR_1_MTF           MAC Table Full Interrupt */
++//    {0x11A4,         0,     16,     0x00}, /* XRX200_PARSER_STAT_FIFO        Parser Status Register */
++//    {0x11A4,         8,      8,     0x00}, /* XRX200_PARSER_STAT_FSM_DAT_CNT Parser FSM Data Counter */
++//    {0x11A4,         5,      3,     0x00}, /* XRX200_PARSER_STAT_FSM_STATE   Parser FSM State */
++//    {0x11A4,         4,      1,     0x00}, /* XRX200_PARSER_STAT_PKT_ERR     Packet error detected */
++//    {0x11A4,         3,      1,     0x00}, /* XRX200_PARSER_STAT_FSM_FIN     Parser FSM finished */
++//    {0x11A4,         2,      1,     0x00}, /* XRX200_PARSER_STAT_FSM_START   Parser FSM start */
++//    {0x11A4,         1,      1,     0x00}, /* XRX200_PARSER_STAT_FIFO_RDY    Parser FIFO ready for read. */
++//    {0x11A4,         0,      1,     0x00}, /* XRX200_PARSER_STAT_FIFO_FULL   Parser */
++//    {0x1200,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_0             PCE Port ControlRegister 0 */
++//    {0x1200,        13,      1,     0x28}, /* XRX200_PCE_PCTRL_0_MCST        Multicast Forwarding Mode Selection */
++//    {0x1200,        12,      1,     0x28}, /* XRX200_PCE_PCTRL_0_EGSTEN      Table-based Egress Special Tag Enable */
++//    {0x1200,        11,      1,     0x28}, /* XRX200_PCE_PCTRL_0_IGSTEN      Ingress Special Tag Enable */
++//    {0x1200,        10,      1,     0x28}, /* XRX200_PCE_PCTRL_0_PCPEN       PCP Remarking Mode */
++//    {0x1200,         9,      1,     0x28}, /* XRX200_PCE_PCTRL_0_CLPEN       Class Remarking Mode */
++//    {0x1200,         8,      1,     0x28}, /* XRX200_PCE_PCTRL_0_DPEN        Drop Precedence Remarking Mode */
++//    {0x1200,         7,      1,     0x28}, /* XRX200_PCE_PCTRL_0_CMOD        Three-color Marker Color Mode */
++//    {0x1200,         6,      1,     0x28}, /* XRX200_PCE_PCTRL_0_VREP        VLAN Replacement Mode */
++      {0x1200,         5,      1,     0x28}, /* XRX200_PCE_PCTRL_0_TVM         Transparent VLAN Mode */
++//    {0x1200,         4,      1,     0x28}, /* XRX200_PCE_PCTRL_0_PLOCK       Port Locking Enable */
++//    {0x1200,         3,      1,     0x28}, /* XRX200_PCE_PCTRL_0_AGEDIS      Aging Disable */
++//    {0x1200,         0,      3,     0x28}, /* XRX200_PCE_PCTRL_0_PSTATE      Port State */
++//    {0x1204,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_1             PCE Port ControlRegister 1 */
++//    {0x1204,         0,      8,     0x28}, /* XRX200_PCE_PCTRL_1_LRNLIM      MAC Address Learning Limit */
++//    {0x1208,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_2             PCE Port ControlRegister 2 */
++//    {0x1208,         7,      1,     0x28}, /* XRX200_PCE_PCTRL_2_DSCPMOD     DSCP Mode Selection */
++//    {0x1208,         5,      2,     0x28}, /* XRX200_PCE_PCTRL_2_DSCP        Enable DSCP to select the Class of Service */
++//    {0x1208,         4,      1,     0x28}, /* XRX200_PCE_PCTRL_2_PCP         Enable VLAN PCP to select the Class of Service */
++//    {0x1208,         0,      4,     0x28}, /* XRX200_PCE_PCTRL_2_PCLASS      Port-based Traffic Class */
++//    {0x120C,         0,     16,     0x28}, /* XRX200_PCE_PCTRL_3_VIO         PCE Port ControlRegister 3 */
++//    {0x120C,        11,      1,     0x28}, /* XRX200_PCE_PCTRL_3_EDIR        Egress Redirection Mode */
++//    {0x120C,        10,      1,     0x28}, /* XRX200_PCE_PCTRL_3_RXDMIR      Receive Mirroring Enable for dropped frames */
++//    {0x120C,         9,      1,     0x28}, /* XRX200_PCE_PCTRL_3_RXVMIR      Receive Mirroring Enable for valid frames */
++//    {0x120C,         8,      1,     0x28}, /* XRX200_PCE_PCTRL_3_TXMIR       Transmit Mirroring Enable */
++//    {0x120C,         7,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_7       Violation Type 7 Mirroring Enable */
++//    {0x120C,         6,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_6       Violation Type 6 Mirroring Enable */
++//    {0x120C,         5,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_5       Violation Type 5 Mirroring Enable */
++//    {0x120C,         4,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_4       Violation Type 4 Mirroring Enable */
++//    {0x120C,         3,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_3       Violation Type 3 Mirroring Enable */
++//    {0x120C,         2,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_2       Violation Type 2 Mirroring Enable */
++//    {0x120C,         1,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_1       Violation Type 1 Mirroring Enable */
++//    {0x120C,         0,      1,     0x28}, /* XRX200_PCE_PCTRL_3_VIO_0       Violation Type 0 Mirroring Enable */
++//    {0x1210,         0,     16,     0x28}, /* XRX200_WOL_CTRL                Wake-on-LAN ControlRegister */
++//    {0x1210,         0,      1,     0x28}, /* XRX200_WOL_CTRL_PORT           WoL Enable */
++//    {0x1214,         0,     16,     0x28}, /* XRX200_PCE_VCTRL               PCE VLAN ControlRegister */
++      {0x1214,         5,      1,     0x28}, /* XRX200_PCE_VCTRL_VSR           VLAN Security Rule */
++      {0x1214,         4,      1,     0x28}, /* XRX200_PCE_VCTRL_VEMR          VLAN Egress Member Violation Rule */
++      {0x1214,         3,      1,     0x28}, /* XRX200_PCE_VCTRL_VIMR          VLAN Ingress Member Violation Rule */
++      {0x1214,         1,      2,     0x28}, /* XRX200_PCE_VCTRL_VINR          VLAN Ingress Tag Rule */
++      {0x1214,         0,      1,     0x28}, /* XRX200_PCE_VCTRL_UVR           Unknown VLAN Rule */
++//    {0x1218,         0,     16,     0x28}, /* XRX200_PCE_DEFPVID             PCE Default PortVID Register */
++      {0x1218,         0,      6,     0x28}, /* XRX200_PCE_DEFPVID_PVID        Default Port VID Index */
++//    {0x121C,         0,     16,     0x28}, /* XRX200_PCE_PSTAT               PCE Port StatusRegister */
++//    {0x121C,         0,     16,     0x28}, /* XRX200_PCE_PSTAT_LRNCNT        Learning Count */
++//    {0x1220,         0,     16,     0x28}, /* XRX200_PCE_PIER                Parser and ClassificationEngine Port Interrupt Enable Register */
++//    {0x1220,         5,      1,     0x28}, /* XRX200_PCE_PIER_CLDRP          Classification Drop Interrupt Enable */
++//    {0x1220,         4,      1,     0x28}, /* XRX200_PCE_PIER_PTDRP          Port Drop Interrupt Enable */
++//    {0x1220,         3,      1,     0x28}, /* XRX200_PCE_PIER_VLAN           VLAN Violation Interrupt Enable */
++//    {0x1220,         2,      1,     0x28}, /* XRX200_PCE_PIER_WOL            Wake-on-LAN Interrupt Enable */
++//    {0x1220,         1,      1,     0x28}, /* XRX200_PCE_PIER_LOCK           Port Limit Alert Interrupt Enable */
++//    {0x1220,         0,      1,     0x28}, /* XRX200_PCE_PIER_LIM            Port Lock Alert Interrupt Enable */
++//    {0x1224,         0,     16,     0x28}, /* XRX200_PCE_PISR                Parser and ClassificationEngine Port Interrupt Status Register */
++//    {0x1224,         5,      1,     0x28}, /* XRX200_PCE_PISR_CLDRP          Classification Drop Interrupt */
++//    {0x1224,         4,      1,     0x28}, /* XRX200_PCE_PISR_PTDRP          Port Drop Interrupt */
++//    {0x1224,         3,      1,     0x28}, /* XRX200_PCE_PISR_VLAN           VLAN Violation Interrupt */
++//    {0x1224,         2,      1,     0x28}, /* XRX200_PCE_PISR_WOL            Wake-on-LAN Interrupt */
++//    {0x1224,         1,      1,     0x28}, /* XRX200_PCE_PISR_LOCK           Port Lock Alert Interrupt */
++//    {0x1224,         0,      1,     0x28}, /* XRX200_PCE_PISR_LIMIT          Port Limitation Alert Interrupt */
++//    {0x1600,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CTRL            Three-colorMarker Control Register */
++//    {0x1600,         0,      1,     0x1c}, /* XRX200_PCE_TCM_CTRL_TCMEN      Three-color Marker metering instance enable */
++//    {0x1604,         0,     16,     0x1c}, /* XRX200_PCE_TCM_STAT            Three-colorMarker Status Register */
++//    {0x1604,         1,      1,     0x1c}, /* XRX200_PCE_TCM_STAT_AL1        Three-color Marker Alert 1 Status */
++//    {0x1604,         0,      1,     0x1c}, /* XRX200_PCE_TCM_STAT_AL0        Three-color Marker Alert 0 Status */
++//    {0x1608,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CBS             Three-color MarkerCommitted Burst Size Register */
++//    {0x1608,         0,     10,     0x1c}, /* XRX200_PCE_TCM_CBS_CBS         Committed Burst Size */
++//    {0x160C,         0,     16,     0x1c}, /* XRX200_PCE_TCM_EBS             Three-color MarkerExcess Burst Size Register */
++//    {0x160C,         0,     10,     0x1c}, /* XRX200_PCE_TCM_EBS_EBS         Excess Burst Size */
++//    {0x1610,         0,     16,     0x1c}, /* XRX200_PCE_TCM_IBS             Three-color MarkerInstantaneous Burst Size Register */
++//    {0x1610,         0,      2,     0x1c}, /* XRX200_PCE_TCM_IBS_IBS         Instantaneous Burst Size */
++//    {0x1614,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CIR_MANT        Three-colorMarker Constant Information Rate Mantissa Register */
++//    {0x1614,         0,     10,     0x1c}, /* XRX200_PCE_TCM_CIR_MANT_MANT   Rate Counter Mantissa */
++//    {0x1618,         0,     16,     0x1c}, /* XRX200_PCE_TCM_CIR_EXP         Three-colorMarker Constant Information Rate Exponent Register */
++//    {0x1618,         0,      4,     0x1c}, /* XRX200_PCE_TCM_CIR_EXP_EXP     Rate Counter Exponent */
++//    {0x2300,         0,     16,     0x00}, /* XRX200_MAC_TEST                MAC Test Register */
++//    {0x2300,         0,     16,     0x00}, /* XRX200_MAC_TEST_JTP            Jitter Test Pattern */
++//    {0x2304,         0,     16,     0x00}, /* XRX200_MAC_PFAD_CFG            MAC Pause FrameSource Address Configuration Register */
++//    {0x2304,         0,      1,     0x00}, /* XRX200_MAC_PFAD_CFG_SAMOD      Source Address Mode */
++//    {0x2308,         0,     16,     0x00}, /* XRX200_MAC_PFSA_0              Pause Frame SourceAddress Part 0  */
++//    {0x2308,         0,     16,     0x00}, /* XRX200_MAC_PFSA_0_PFAD         Pause Frame Source Address Part 0 */
++//    {0x230C,         0,     16,     0x00}, /* XRX200_MAC_PFSA_1              Pause Frame SourceAddress Part 1  */
++//    {0x230C,         0,     16,     0x00}, /* XRX200_MAC_PFSA_1_PFAD         Pause Frame Source Address Part 1 */
++//    {0x2310,         0,     16,     0x00}, /* XRX200_MAC_PFSA_2              Pause Frame SourceAddress Part 2  */
++//    {0x2310,         0,     16,     0x00}, /* XRX200_MAC_PFSA_2_PFAD         Pause Frame Source Address Part 2 */
++//    {0x2314,         0,     16,     0x00}, /* XRX200_MAC_FLEN                MAC Frame Length Register */
++//    {0x2314,         0,     14,     0x00}, /* XRX200_MAC_FLEN_LEN            Maximum Frame Length */
++//    {0x2318,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_0        MAC VLAN EthertypeRegister 0 */
++//    {0x2318,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_0_OUTER  Ethertype */
++//    {0x231C,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_1        MAC VLAN EthertypeRegister 1 */
++//    {0x231C,         0,     16,     0x00}, /* XRX200_MAC_VLAN_ETYPE_1_INNER  Ethertype */
++//    {0x2320,         0,     16,     0x00}, /* XRX200_MAC_IER                 MAC Interrupt EnableRegister */
++//    {0x2320,         0,      8,     0x00}, /* XRX200_MAC_IER_MACIEN          MAC Interrupt Enable */
++//    {0x2324,         0,     16,     0x00}, /* XRX200_MAC_ISR                 MAC Interrupt StatusRegister */
++//    {0x2324,         0,      8,     0x00}, /* XRX200_MAC_ISR_MACINT          MAC Interrupt */
++//    {0x2400,         0,     16,     0x30}, /* XRX200_MAC_PSTAT               MAC Port Status Register */
++//    {0x2400,        11,      1,     0x30}, /* XRX200_MAC_PSTAT_PACT          PHY Active Status */
++      {0x2400,        10,      1,     0x30}, /* XRX200_MAC_PSTAT_GBIT          Gigabit Speed Status */
++      {0x2400,         9,      1,     0x30}, /* XRX200_MAC_PSTAT_MBIT          Megabit Speed Status */
++      {0x2400,         8,      1,     0x30}, /* XRX200_MAC_PSTAT_FDUP          Full Duplex Status */
++//    {0x2400,         7,      1,     0x30}, /* XRX200_MAC_PSTAT_RXPAU         Receive Pause Status */
++//    {0x2400,         6,      1,     0x30}, /* XRX200_MAC_PSTAT_TXPAU         Transmit Pause Status */
++//    {0x2400,         5,      1,     0x30}, /* XRX200_MAC_PSTAT_RXPAUEN       Receive Pause Enable Status */
++//    {0x2400,         4,      1,     0x30}, /* XRX200_MAC_PSTAT_TXPAUEN       Transmit Pause Enable Status */
++      {0x2400,         3,      1,     0x30}, /* XRX200_MAC_PSTAT_LSTAT         Link Status */
++//    {0x2400,         2,      1,     0x30}, /* XRX200_MAC_PSTAT_CRS           Carrier Sense Status */
++//    {0x2400,         1,      1,     0x30}, /* XRX200_MAC_PSTAT_TXLPI         Transmit Low-power Idle Status */
++//    {0x2400,         0,      1,     0x30}, /* XRX200_MAC_PSTAT_RXLPI         Receive Low-power Idle Status */
++//    {0x2404,         0,     16,     0x30}, /* XRX200_MAC_PISR                MAC Interrupt Status Register */
++//    {0x2404,        13,      1,     0x30}, /* XRX200_MAC_PISR_PACT           PHY Active Status */
++//    {0x2404,        12,      1,     0x30}, /* XRX200_MAC_PISR_SPEED          Megabit Speed Status */
++//    {0x2404,        11,      1,     0x30}, /* XRX200_MAC_PISR_FDUP           Full Duplex Status */
++//    {0x2404,        10,      1,     0x30}, /* XRX200_MAC_PISR_RXPAUEN        Receive Pause Enable Status */
++//    {0x2404,         9,      1,     0x30}, /* XRX200_MAC_PISR_TXPAUEN        Transmit Pause Enable Status */
++//    {0x2404,         8,      1,     0x30}, /* XRX200_MAC_PISR_LPIOFF         Receive Low-power Idle Mode is left */
++//    {0x2404,         7,      1,     0x30}, /* XRX200_MAC_PISR_LPION          Receive Low-power Idle Mode is entered */
++//    {0x2404,         6,      1,     0x30}, /* XRX200_MAC_PISR_JAM            Jam Status Detected */
++//    {0x2404,         5,      1,     0x30}, /* XRX200_MAC_PISR_TOOSHORT       Too Short Frame Error Detected */
++//    {0x2404,         4,      1,     0x30}, /* XRX200_MAC_PISR_TOOLONG        Too Long Frame Error Detected */
++//    {0x2404,         3,      1,     0x30}, /* XRX200_MAC_PISR_LENERR         Length Mismatch Error Detected */
++//    {0x2404,         2,      1,     0x30}, /* XRX200_MAC_PISR_FCSERR         Frame Checksum Error Detected */
++//    {0x2404,         1,      1,     0x30}, /* XRX200_MAC_PISR_TXPAUSE        Pause Frame Transmitted */
++//    {0x2404,         0,      1,     0x30}, /* XRX200_MAC_PISR_RXPAUSE        Pause Frame Received */
++//    {0x2408,         0,     16,     0x30}, /* XRX200_MAC_PIER                MAC Interrupt Enable Register */
++//    {0x2408,        13,      1,     0x30}, /* XRX200_MAC_PIER_PACT           PHY Active Status */
++//    {0x2408,        12,      1,     0x30}, /* XRX200_MAC_PIER_SPEED          Megabit Speed Status */
++//    {0x2408,        11,      1,     0x30}, /* XRX200_MAC_PIER_FDUP           Full Duplex Status */
++//    {0x2408,        10,      1,     0x30}, /* XRX200_MAC_PIER_RXPAUEN        Receive Pause Enable Status */
++//    {0x2408,         9,      1,     0x30}, /* XRX200_MAC_PIER_TXPAUEN        Transmit Pause Enable Status */
++//    {0x2408,         8,      1,     0x30}, /* XRX200_MAC_PIER_LPIOFF         Low-power Idle Off Interrupt Mask */
++//    {0x2408,         7,      1,     0x30}, /* XRX200_MAC_PIER_LPION          Low-power Idle On Interrupt Mask */
++//    {0x2408,         6,      1,     0x30}, /* XRX200_MAC_PIER_JAM            Jam Status Interrupt Mask */
++//    {0x2408,         5,      1,     0x30}, /* XRX200_MAC_PIER_TOOSHORT       Too Short Frame Error Interrupt Mask */
++//    {0x2408,         4,      1,     0x30}, /* XRX200_MAC_PIER_TOOLONG        Too Long Frame Error Interrupt Mask */
++//    {0x2408,         3,      1,     0x30}, /* XRX200_MAC_PIER_LENERR         Length Mismatch Error Interrupt Mask */
++//    {0x2408,         2,      1,     0x30}, /* XRX200_MAC_PIER_FCSERR         Frame Checksum Error Interrupt Mask */
++//    {0x2408,         1,      1,     0x30}, /* XRX200_MAC_PIER_TXPAUSE        Transmit Pause Frame Interrupt Mask */
++//    {0x2408,         0,      1,     0x30}, /* XRX200_MAC_PIER_RXPAUSE        Receive Pause Frame Interrupt Mask */
++//    {0x240C,         0,     16,     0x30}, /* XRX200_MAC_CTRL_0              MAC Control Register0 */
++//    {0x240C,        13,      2,     0x30}, /* XRX200_MAC_CTRL_0_LCOL         Late Collision Control */
++//    {0x240C,        12,      1,     0x30}, /* XRX200_MAC_CTRL_0_BM           Burst Mode Control */
++//    {0x240C,        11,      1,     0x30}, /* XRX200_MAC_CTRL_0_APADEN       Automatic VLAN Padding Enable */
++//    {0x240C,        10,      1,     0x30}, /* XRX200_MAC_CTRL_0_VPAD2EN      Stacked VLAN Padding Enable */
++//    {0x240C,         9,      1,     0x30}, /* XRX200_MAC_CTRL_0_VPADEN       VLAN Padding Enable */
++//    {0x240C,         8,      1,     0x30}, /* XRX200_MAC_CTRL_0_PADEN        Padding Enable */
++//    {0x240C,         7,      1,     0x30}, /* XRX200_MAC_CTRL_0_FCS          Transmit FCS Control */
++      {0x240C,         4,      3,     0x30}, /* XRX200_MAC_CTRL_0_FCON         Flow Control Mode */
++//    {0x240C,         2,      2,     0x30}, /* XRX200_MAC_CTRL_0_FDUP         Full Duplex Control */
++//    {0x240C,         0,      2,     0x30}, /* XRX200_MAC_CTRL_0_GMII         GMII/MII interface mode selection */
++//    {0x2410,         0,     16,     0x30}, /* XRX200_MAC_CTRL_1              MAC Control Register1 */
++//    {0x2410,         8,      1,     0x30}, /* XRX200_MAC_CTRL_1_SHORTPRE     Short Preamble Control */
++//    {0x2410,         0,      4,     0x30}, /* XRX200_MAC_CTRL_1_IPG          Minimum Inter Packet Gap Size */
++//    {0x2414,         0,     16,     0x30}, /* XRX200_MAC_CTRL_2              MAC Control Register2 */
++//    {0x2414,         3,      1,     0x30}, /* XRX200_MAC_CTRL_2_MLEN         Maximum Untagged Frame Length */
++//    {0x2414,         2,      1,     0x30}, /* XRX200_MAC_CTRL_2_LCHKL        Frame Length Check Long Enable */
++//    {0x2414,         0,      2,     0x30}, /* XRX200_MAC_CTRL_2_LCHKS        Frame Length Check Short Enable */
++//    {0x2418,         0,     16,     0x30}, /* XRX200_MAC_CTRL_3              MAC Control Register3 */
++//    {0x2418,         0,      4,     0x30}, /* XRX200_MAC_CTRL_3_RCNT         Retry Count */
++//    {0x241C,         0,     16,     0x30}, /* XRX200_MAC_CTRL_4              MAC Control Register4 */
++//    {0x241C,         7,      1,     0x30}, /* XRX200_MAC_CTRL_4_LPIEN        LPI Mode Enable */
++//    {0x241C,         0,      7,     0x30}, /* XRX200_MAC_CTRL_4_WAIT         LPI Wait Time */
++//    {0x2420,         0,     16,     0x30}, /* XRX200_MAC_CTRL_5_PJPS         MAC Control Register5 */
++//    {0x2420,         1,      1,     0x30}, /* XRX200_MAC_CTRL_5_PJPS_NOBP    Prolonged Jam pattern size during no-backpressure state */
++//    {0x2420,         0,      1,     0x30}, /* XRX200_MAC_CTRL_5_PJPS_BP      Prolonged Jam pattern size during backpressure state */
++//    {0x2424,         0,     16,     0x30}, /* XRX200_MAC_CTRL_6_XBUF         Transmit and ReceiveBuffer Control Register */
++//    {0x2424,         9,      3,     0x30}, /* XRX200_MAC_CTRL_6_RBUF_DLY_WP  Delay */
++//    {0x2424,         8,      1,     0x30}, /* XRX200_MAC_CTRL_6_RBUF_INIT    Receive Buffer Initialization */
++//    {0x2424,         6,      1,     0x30}, /* XRX200_MAC_CTRL_6_RBUF_BYPASS  Bypass the Receive Buffer */
++//    {0x2424,         3,      3,     0x30}, /* XRX200_MAC_CTRL_6_XBUF_DLY_WP  Delay */
++//    {0x2424,         2,      1,     0x30}, /* XRX200_MAC_CTRL_6_XBUF_INIT    Initialize the Transmit Buffer */
++//    {0x2424,         0,      1,     0x30}, /* XRX200_MAC_CTRL_6_XBUF_BYPASS  Bypass the Transmit Buffer */
++//    {0x2428,         0,     16,     0x30}, /* XRX200_MAC_BUFST_XBUF          MAC Receive and TransmitBuffer Status Register */
++//    {0x2428,         3,      1,     0x30}, /* XRX200_MAC_BUFST_RBUF_UFL      Receive Buffer Underflow Indicator */
++//    {0x2428,         2,      1,     0x30}, /* XRX200_MAC_BUFST_RBUF_OFL      Receive Buffer Overflow Indicator */
++//    {0x2428,         1,      1,     0x30}, /* XRX200_MAC_BUFST_XBUF_UFL      Transmit Buffer Underflow Indicator */
++//    {0x2428,         0,      1,     0x30}, /* XRX200_MAC_BUFST_XBUF_OFL      Transmit Buffer Overflow Indicator */
++//    {0x242C,         0,     16,     0x30}, /* XRX200_MAC_TESTEN              MAC Test Enable Register */
++//    {0x242C,         2,      1,     0x30}, /* XRX200_MAC_TESTEN_JTEN         Jitter Test Enable */
++//    {0x242C,         1,      1,     0x30}, /* XRX200_MAC_TESTEN_TXER         Transmit Error Insertion */
++//    {0x242C,         0,      1,     0x30}, /* XRX200_MAC_TESTEN_LOOP         MAC Loopback Enable */
++//    {0x2900,         0,     16,     0x00}, /* XRX200_FDMA_CTRL               Ethernet Switch FetchDMA Control Register */
++//    {0x2900,         7,      5,     0x00}, /* XRX200_FDMA_CTRL_LPI_THRESHOLD Low Power Idle Threshold */
++//    {0x2900,         4,      3,     0x00}, /* XRX200_FDMA_CTRL_LPI_MODE      Low Power Idle Mode */
++//    {0x2900,         2,      2,     0x00}, /* XRX200_FDMA_CTRL_EGSTAG        Egress Special Tag Size */
++//    {0x2900,         1,      1,     0x00}, /* XRX200_FDMA_CTRL_IGSTAG        Ingress Special Tag Size */
++//    {0x2900,         0,      1,     0x00}, /* XRX200_FDMA_CTRL_EXCOL         Excessive Collision Handling */
++//    {0x2904,         0,     16,     0x00}, /* XRX200_FDMA_STETYPE            Special Tag EthertypeControl Register */
++//    {0x2904,         0,     16,     0x00}, /* XRX200_FDMA_STETYPE_ETYPE      Special Tag Ethertype */
++//    {0x2908,         0,     16,     0x00}, /* XRX200_FDMA_VTETYPE            VLAN Tag EthertypeControl Register */
++//    {0x2908,         0,     16,     0x00}, /* XRX200_FDMA_VTETYPE_ETYPE      VLAN Tag Ethertype */
++//    {0x290C,         0,     16,     0x00}, /* XRX200_FDMA_STAT_0             FDMA Status Register0 */
++//    {0x290C,         0,     16,     0x00}, /* XRX200_FDMA_STAT_0_FSMS        FSM states status */
++//    {0x2910,         0,     16,     0x00}, /* XRX200_FDMA_IER                Fetch DMA Global InterruptEnable Register */
++//    {0x2910,        14,      1,     0x00}, /* XRX200_FDMA_IER_PCKD           Packet Drop Interrupt Enable */
++//    {0x2910,        13,      1,     0x00}, /* XRX200_FDMA_IER_PCKR           Packet Ready Interrupt Enable */
++//    {0x2910,         0,      8,     0x00}, /* XRX200_FDMA_IER_PCKT           Packet Sent Interrupt Enable */
++//    {0x2914,         0,     16,     0x00}, /* XRX200_FDMA_ISR                Fetch DMA Global InterruptStatus Register */
++//    {0x2914,        14,      1,     0x00}, /* XRX200_FDMA_ISR_PCKTD          Packet Drop */
++//    {0x2914,        13,      1,     0x00}, /* XRX200_FDMA_ISR_PCKR           Packet is Ready for Transmission */
++//    {0x2914,         0,      8,     0x00}, /* XRX200_FDMA_ISR_PCKT           Packet Sent Event */
++//    {0x2A00,         0,     16,     0x18}, /* XRX200_FDMA_PCTRL              Ethernet SwitchFetch DMA Port Control Register */
++//    {0x2A00,         3,      2,     0x18}, /* XRX200_FDMA_PCTRL_VLANMOD      VLAN Modification Enable */
++//    {0x2A00,         2,      1,     0x18}, /* XRX200_FDMA_PCTRL_DSCPRM       DSCP Re-marking Enable */
++//    {0x2A00,         1,      1,     0x18}, /* XRX200_FDMA_PCTRL_STEN         Special Tag Insertion Enable */
++//    {0x2A00,         0,      1,     0x18}, /* XRX200_FDMA_PCTRL_EN           FDMA Port Enable */
++//    {0x2A04,         0,     16,     0x18}, /* XRX200_FDMA_PRIO               Ethernet SwitchFetch DMA Port Priority Register */
++//    {0x2A04,         0,      2,     0x18}, /* XRX200_FDMA_PRIO_PRIO          FDMA PRIO */
++//    {0x2A08,         0,     16,     0x18}, /* XRX200_FDMA_PSTAT0             Ethernet SwitchFetch DMA Port Status Register 0 */
++//    {0x2A08,        15,      1,     0x18}, /* XRX200_FDMA_PSTAT0_PKT_AVAIL   Port Egress Packet Available */
++//    {0x2A08,        14,      1,     0x18}, /* XRX200_FDMA_PSTAT0_POK         Port Status OK */
++//    {0x2A08,         0,      6,     0x18}, /* XRX200_FDMA_PSTAT0_PSEG        Port Egress Segment Count */
++//    {0x2A0C,         0,     16,     0x18}, /* XRX200_FDMA_PSTAT1_HDR         Ethernet SwitchFetch DMA Port Status Register 1 */
++//    {0x2A0C,         0,     10,     0x18}, /* XRX200_FDMA_PSTAT1_HDR_PTR     Header Pointer */
++//    {0x2A10,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP0            Egress TimeStamp Register 0 */
++//    {0x2A10,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP0_TSTL       Time Stamp [15:0] */
++//    {0x2A14,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP1            Egress TimeStamp Register 1 */
++//    {0x2A14,         0,     16,     0x18}, /* XRX200_FDMA_TSTAMP1_TSTH       Time Stamp [31:16] */
++//    {0x2D00,         0,     16,     0x00}, /* XRX200_SDMA_CTRL               Ethernet Switch StoreDMA Control Register */
++//    {0x2D00,         0,      1,     0x00}, /* XRX200_SDMA_CTRL_TSTEN         Time Stamp Enable */
++//    {0x2D04,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR1             SDMA Flow Control Threshold1 Register */
++//    {0x2D04,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR1_THR1        Threshold 1 */
++//    {0x2D08,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR2             SDMA Flow Control Threshold2 Register */
++//    {0x2D08,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR2_THR2        Threshold 2 */
++//    {0x2D0C,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR3             SDMA Flow Control Threshold3 Register */
++//    {0x2D0C,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR3_THR3        Threshold 3 */
++//    {0x2D10,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR4             SDMA Flow Control Threshold4 Register */
++//    {0x2D10,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR4_THR4        Threshold 4 */
++//    {0x2D14,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR5             SDMA Flow Control Threshold5 Register */
++//    {0x2D14,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR5_THR5        Threshold 5 */
++//    {0x2D18,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR6             SDMA Flow Control Threshold6 Register */
++//    {0x2D18,         0,     10,     0x00}, /* XRX200_SDMA_FCTHR6_THR6        Threshold 6 */
++//    {0x2D1C,         0,     16,     0x00}, /* XRX200_SDMA_FCTHR7             SDMA Flow Control Threshold7 Register */
++//    {0x2D1C,         0,     11,     0x00}, /* XRX200_SDMA_FCTHR7_THR7        Threshold 7 */
++//    {0x2D20,         0,     16,     0x00}, /* XRX200_SDMA_STAT_0             SDMA Status Register0 */
++//    {0x2D20,         4,      3,     0x00}, /* XRX200_SDMA_STAT_0_BPS_FILL    Back Pressure Status */
++//    {0x2D20,         2,      2,     0x00}, /* XRX200_SDMA_STAT_0_BPS_PNT     Back Pressure Status */
++//    {0x2D20,         0,      2,     0x00}, /* XRX200_SDMA_STAT_0_DROP        Back Pressure Status */
++//    {0x2D24,         0,     16,     0x00}, /* XRX200_SDMA_STAT_1             SDMA Status Register1 */
++//    {0x2D24,         0,     10,     0x00}, /* XRX200_SDMA_STAT_1_FILL        Buffer Filling Level */
++//    {0x2D28,         0,     16,     0x00}, /* XRX200_SDMA_STAT_2             SDMA Status Register2 */
++//    {0x2D28,         0,     16,     0x00}, /* XRX200_SDMA_STAT_2_FSMS        FSM states status */
++//    {0x2D2C,         0,     16,     0x00}, /* XRX200_SDMA_IER                SDMA Interrupt Enable Register */
++//    {0x2D2C,        15,      1,     0x00}, /* XRX200_SDMA_IER_BPEX           Buffer Pointers Exceeded */
++//    {0x2D2C,        14,      1,     0x00}, /* XRX200_SDMA_IER_BFULL          Buffer Full */
++//    {0x2D2C,        13,      1,     0x00}, /* XRX200_SDMA_IER_FERR           Frame Error */
++//    {0x2D2C,         0,      8,     0x00}, /* XRX200_SDMA_IER_FRX            Frame Received Successfully */
++//    {0x2D30,         0,     16,     0x00}, /* XRX200_SDMA_ISR                SDMA Interrupt Status Register */
++//    {0x2D30,        15,      1,     0x00}, /* XRX200_SDMA_ISR_BPEX           Packet Descriptors Exceeded */
++//    {0x2D30,        14,      1,     0x00}, /* XRX200_SDMA_ISR_BFULL          Buffer Full */
++//    {0x2D30,        13,      1,     0x00}, /* XRX200_SDMA_ISR_FERR           Frame Error */
++//    {0x2D30,         0,      8,     0x00}, /* XRX200_SDMA_ISR_FRX            Frame Received Successfully */
++//    {0x2F00,         0,     16,     0x18}, /* XRX200_SDMA_PCTRL              Ethernet SwitchStore DMA Port Control Register */
++//    {0x2F00,        13,      2,     0x18}, /* XRX200_SDMA_PCTRL_DTHR         Drop Threshold Selection */
++//    {0x2F00,        11,      2,     0x18}, /* XRX200_SDMA_PCTRL_PTHR         Pause Threshold Selection */
++//    {0x2F00,        10,      1,     0x18}, /* XRX200_SDMA_PCTRL_PHYEFWD      Forward PHY Error Frames */
++//    {0x2F00,         9,      1,     0x18}, /* XRX200_SDMA_PCTRL_ALGFWD       Forward Alignment Error Frames */
++//    {0x2F00,         8,      1,     0x18}, /* XRX200_SDMA_PCTRL_LENFWD       Forward Length Errored Frames */
++//    {0x2F00,         7,      1,     0x18}, /* XRX200_SDMA_PCTRL_OSFWD        Forward Oversized Frames */
++//    {0x2F00,         6,      1,     0x18}, /* XRX200_SDMA_PCTRL_USFWD        Forward Undersized Frames */
++//    {0x2F00,         5,      1,     0x18}, /* XRX200_SDMA_PCTRL_FCSIGN       Ignore FCS Errors */
++//    {0x2F00,         4,      1,     0x18}, /* XRX200_SDMA_PCTRL_FCSFWD       Forward FCS Errored Frames */
++//    {0x2F00,         3,      1,     0x18}, /* XRX200_SDMA_PCTRL_PAUFWD       Pause Frame Forwarding */
++//    {0x2F00,         2,      1,     0x18}, /* XRX200_SDMA_PCTRL_MFCEN        Metering Flow Control Enable */
++//    {0x2F00,         1,      1,     0x18}, /* XRX200_SDMA_PCTRL_FCEN         Flow Control Enable */
++//    {0x2F00,         0,      1,     0x18}, /* XRX200_SDMA_PCTRL_PEN          Port Enable */
++//    {0x2F04,         0,     16,     0x18}, /* XRX200_SDMA_PRIO               Ethernet SwitchStore DMA Port Priority Register */
++//    {0x2F04,         0,      2,     0x18}, /* XRX200_SDMA_PRIO_PRIO          SDMA PRIO */
++//    {0x2F08,         0,     16,     0x18}, /* XRX200_SDMA_PSTAT0_HDR         Ethernet SwitchStore DMA Port Status Register 0 */
++//    {0x2F08,         0,     10,     0x18}, /* XRX200_SDMA_PSTAT0_HDR_PTR     Port Ingress Queue Header Pointer */
++//    {0x2F0C,         0,     16,     0x18}, /* XRX200_SDMA_PSTAT1             Ethernet SwitchStore DMA Port Status Register 1 */
++//    {0x2F0C,         0,     10,     0x18}, /* XRX200_SDMA_PSTAT1_PPKT        Port Ingress Packet Count */
++//    {0x2F10,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP0            Ingress TimeStamp Register 0 */
++//    {0x2F10,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP0_TSTL       Time Stamp [15:0] */
++//    {0x2F14,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP1            Ingress TimeStamp Register 1 */
++//    {0x2F14,         0,     16,     0x18}, /* XRX200_SDMA_TSTAMP1_TSTH       Time Stamp [31:16] */
++};
++
++
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0026-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch b/target/linux/lantiq/patches-3.14/0026-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch
deleted file mode 100644 (file)
index 9a2e961..0000000
+++ /dev/null
@@ -1,1047 +0,0 @@
-From 5b376c19a3608cf37908c58b47483909b8ec173a Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 7 Aug 2014 18:26:42 +0200
-Subject: [PATCH 26/31] I2C: MIPS: lantiq: add FALC-ON i2c bus master
-
-This patch adds the driver needed to make the I2C bus work on FALC-ON SoCs.
-
-Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/i2c/busses/Kconfig      |   10 +
- drivers/i2c/busses/Makefile     |    1 +
- drivers/i2c/busses/i2c-lantiq.c |  747 +++++++++++++++++++++++++++++++++++++++
- drivers/i2c/busses/i2c-lantiq.h |  234 ++++++++++++
- 4 files changed, 992 insertions(+)
- create mode 100644 drivers/i2c/busses/i2c-lantiq.c
- create mode 100644 drivers/i2c/busses/i2c-lantiq.h
-
-diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
-index de17c55..3e003c4 100644
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -514,6 +514,16 @@ config I2C_KEMPLD
-         This driver can also be built as a module. If so, the module
-         will be called i2c-kempld.
-+config I2C_LANTIQ
-+      tristate "Lantiq I2C interface"
-+      depends on LANTIQ && SOC_FALCON
-+      help
-+        If you say yes to this option, support will be included for the
-+        Lantiq I2C core.
-+
-+        This driver can also be built as a module. If so, the module
-+        will be called i2c-lantiq.
-+
- config I2C_MPC
-       tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
-       depends on PPC
-diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
-index a08931f..4417097 100644
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -49,6 +49,7 @@ obj-$(CONFIG_I2C_IBM_IIC)    += i2c-ibm_iic.o
- obj-$(CONFIG_I2C_IMX)         += i2c-imx.o
- obj-$(CONFIG_I2C_IOP3XX)      += i2c-iop3xx.o
- obj-$(CONFIG_I2C_KEMPLD)      += i2c-kempld.o
-+obj-$(CONFIG_I2C_LANTIQ)      += i2c-lantiq.o
- obj-$(CONFIG_I2C_MPC)         += i2c-mpc.o
- obj-$(CONFIG_I2C_MV64XXX)     += i2c-mv64xxx.o
- obj-$(CONFIG_I2C_MXS)         += i2c-mxs.o
-diff --git a/drivers/i2c/busses/i2c-lantiq.c b/drivers/i2c/busses/i2c-lantiq.c
-new file mode 100644
-index 0000000..9a5f58b
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-lantiq.c
-@@ -0,0 +1,747 @@
-+
-+/*
-+ * Lantiq I2C bus adapter
-+ *
-+ * Parts based on i2c-designware.c and other i2c drivers from Linux 2.6.33
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h> /* for kzalloc, kfree */
-+#include <linux/i2c.h>
-+#include <linux/errno.h>
-+#include <linux/completion.h>
-+#include <linux/interrupt.h>
-+#include <linux/platform_device.h>
-+#include <linux/io.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_i2c.h>
-+
-+#include <lantiq_soc.h>
-+#include "i2c-lantiq.h"
-+
-+/*
-+ * CURRENT ISSUES:
-+ * - no high speed support
-+ * - ten bit mode is not tested (no slave devices)
-+ */
-+
-+/* access macros */
-+#define i2c_r32(reg)  \
-+      __raw_readl(&(priv->membase)->reg)
-+#define i2c_w32(val, reg)     \
-+      __raw_writel(val, &(priv->membase)->reg)
-+#define i2c_w32_mask(clear, set, reg) \
-+      i2c_w32((i2c_r32(reg) & ~(clear)) | (set), reg)
-+
-+#define DRV_NAME "i2c-lantiq"
-+#define DRV_VERSION "1.00"
-+
-+#define LTQ_I2C_BUSY_TIMEOUT          20 /* ms */
-+
-+#ifdef DEBUG
-+#define LTQ_I2C_XFER_TIMEOUT          (25*HZ)
-+#else
-+#define LTQ_I2C_XFER_TIMEOUT          HZ
-+#endif
-+
-+#define LTQ_I2C_IMSC_DEFAULT_MASK     (I2C_IMSC_I2C_P_INT_EN | \
-+                                       I2C_IMSC_I2C_ERR_INT_EN)
-+
-+#define LTQ_I2C_ARB_LOST              (1 << 0)
-+#define LTQ_I2C_NACK                  (1 << 1)
-+#define LTQ_I2C_RX_UFL                        (1 << 2)
-+#define LTQ_I2C_RX_OFL                        (1 << 3)
-+#define LTQ_I2C_TX_UFL                        (1 << 4)
-+#define LTQ_I2C_TX_OFL                        (1 << 5)
-+
-+struct ltq_i2c {
-+      struct mutex mutex;
-+
-+
-+      /* active clock settings */
-+      unsigned int input_clock;       /* clock input for i2c hardware block */
-+      unsigned int i2c_clock;         /* approximated bus clock in kHz */
-+
-+      struct clk *clk_gate;
-+      struct clk *clk_input;
-+
-+
-+      /* resources (memory and interrupts) */
-+      int irq_lb;                             /* last burst irq */
-+
-+      struct lantiq_reg_i2c __iomem *membase; /* base of mapped registers */
-+
-+      struct i2c_adapter adap;
-+      struct device *dev;
-+
-+      struct completion cmd_complete;
-+
-+
-+      /* message transfer data */
-+      struct i2c_msg *current_msg;    /* current message */
-+      int msgs_num;           /* number of messages to handle */
-+      u8 *msg_buf;            /* current buffer */
-+      u32 msg_buf_len;        /* remaining length of current buffer */
-+      int msg_err;            /* error status of the current transfer */
-+
-+
-+      /* master status codes */
-+      enum {
-+              STATUS_IDLE,
-+              STATUS_ADDR,    /* address phase */
-+              STATUS_WRITE,
-+              STATUS_READ,
-+              STATUS_READ_END,
-+              STATUS_STOP
-+      } status;
-+};
-+
-+static irqreturn_t ltq_i2c_isr(int irq, void *dev_id);
-+
-+static inline void enable_burst_irq(struct ltq_i2c *priv)
-+{
-+      i2c_w32_mask(0, I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, imsc);
-+}
-+static inline void disable_burst_irq(struct ltq_i2c *priv)
-+{
-+      i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, 0, imsc);
-+}
-+
-+static void prepare_msg_send_addr(struct ltq_i2c *priv)
-+{
-+      struct i2c_msg *msg = priv->current_msg;
-+      int rd = !!(msg->flags & I2C_M_RD);     /* extends to 0 or 1 */
-+      u16 addr = msg->addr;
-+
-+      /* new i2c_msg */
-+      priv->msg_buf = msg->buf;
-+      priv->msg_buf_len = msg->len;
-+      if (rd)
-+              priv->status = STATUS_READ;
-+      else
-+              priv->status = STATUS_WRITE;
-+
-+      /* send slave address */
-+      if (msg->flags & I2C_M_TEN) {
-+              i2c_w32(0xf0 | ((addr & 0x300) >> 7) | rd, txd);
-+              i2c_w32(addr & 0xff, txd);
-+      } else {
-+              i2c_w32((addr & 0x7f) << 1 | rd, txd);
-+      }
-+}
-+
-+static void ltq_i2c_set_tx_len(struct ltq_i2c *priv)
-+{
-+      struct i2c_msg *msg = priv->current_msg;
-+      int len = (msg->flags & I2C_M_TEN) ? 2 : 1;
-+
-+      pr_debug("set_tx_len %cX\n", (msg->flags & I2C_M_RD) ? 'R' : 'T');
-+
-+      priv->status = STATUS_ADDR;
-+
-+      if (!(msg->flags & I2C_M_RD))
-+              len += msg->len;
-+      else
-+              /* set maximum received packet size (before rx int!) */
-+              i2c_w32(msg->len, mrps_ctrl);
-+      i2c_w32(len, tps_ctrl);
-+      enable_burst_irq(priv);
-+}
-+
-+static int ltq_i2c_hw_set_clock(struct i2c_adapter *adap)
-+{
-+      struct ltq_i2c *priv = i2c_get_adapdata(adap);
-+      unsigned int input_clock = clk_get_rate(priv->clk_input);
-+      u32 dec, inc = 1;
-+
-+      /* clock changed? */
-+      if (priv->input_clock == input_clock)
-+              return 0;
-+
-+      /*
-+       * this formula is only an approximation, found by the recommended
-+       * values in the "I2C Architecture Specification 1.7.1"
-+       */
-+      dec = input_clock / (priv->i2c_clock * 2);
-+      if (dec <= 6)
-+              return -ENXIO;
-+
-+      i2c_w32(0, fdiv_high_cfg);
-+      i2c_w32((inc << I2C_FDIV_CFG_INC_OFFSET) |
-+              (dec << I2C_FDIV_CFG_DEC_OFFSET),
-+              fdiv_cfg);
-+
-+      dev_info(priv->dev, "setup clocks (in %d kHz, bus %d kHz, dec=%d)\n",
-+              input_clock, priv->i2c_clock, dec);
-+
-+      priv->input_clock = input_clock;
-+      return 0;
-+}
-+
-+static int ltq_i2c_hw_init(struct i2c_adapter *adap)
-+{
-+      int ret = 0;
-+      struct ltq_i2c *priv = i2c_get_adapdata(adap);
-+
-+      /* disable bus */
-+      i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
-+
-+#ifndef DEBUG
-+      /* set normal operation clock divider */
-+      i2c_w32(1 << I2C_CLC_RMC_OFFSET, clc);
-+#else
-+      /* for debugging a higher divider value! */
-+      i2c_w32(0xF0 << I2C_CLC_RMC_OFFSET, clc);
-+#endif
-+
-+      /* setup clock */
-+      ret = ltq_i2c_hw_set_clock(adap);
-+      if (ret != 0) {
-+              dev_warn(priv->dev, "invalid clock settings\n");
-+              return ret;
-+      }
-+
-+      /* configure fifo */
-+      i2c_w32(I2C_FIFO_CFG_TXFC | /* tx fifo as flow controller */
-+              I2C_FIFO_CFG_RXFC | /* rx fifo as flow controller */
-+              I2C_FIFO_CFG_TXFA_TXFA2 | /* tx fifo 4-byte aligned */
-+              I2C_FIFO_CFG_RXFA_RXFA2 | /* rx fifo 4-byte aligned */
-+              I2C_FIFO_CFG_TXBS_TXBS0 | /* tx fifo burst size is 1 word */
-+              I2C_FIFO_CFG_RXBS_RXBS0,  /* rx fifo burst size is 1 word */
-+              fifo_cfg);
-+
-+      /* configure address */
-+      i2c_w32(I2C_ADDR_CFG_SOPE_EN |  /* generate stop when no more data in
-+                                         the fifo */
-+              I2C_ADDR_CFG_SONA_EN |  /* generate stop when NA received */
-+              I2C_ADDR_CFG_MnS_EN |   /* we are master device */
-+              0,                      /* our slave address (not used!) */
-+              addr_cfg);
-+
-+      /* enable bus */
-+      i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl);
-+
-+      return 0;
-+}
-+
-+static int ltq_i2c_wait_bus_not_busy(struct ltq_i2c *priv)
-+{
-+      unsigned long timeout;
-+
-+      timeout = jiffies + msecs_to_jiffies(LTQ_I2C_BUSY_TIMEOUT);
-+
-+      do {
-+              u32 stat = i2c_r32(bus_stat);
-+
-+              if ((stat & I2C_BUS_STAT_BS_MASK) == I2C_BUS_STAT_BS_FREE)
-+                      return 0;
-+
-+              cond_resched();
-+      } while (!time_after_eq(jiffies, timeout));
-+
-+      dev_err(priv->dev, "timeout waiting for bus ready\n");
-+      return -ETIMEDOUT;
-+}
-+
-+static void ltq_i2c_tx(struct ltq_i2c *priv, int last)
-+{
-+      if (priv->msg_buf_len && priv->msg_buf) {
-+              i2c_w32(*priv->msg_buf, txd);
-+
-+              if (--priv->msg_buf_len)
-+                      priv->msg_buf++;
-+              else
-+                      priv->msg_buf = NULL;
-+      } else {
-+              last = 1;
-+      }
-+
-+      if (last)
-+              disable_burst_irq(priv);
-+}
-+
-+static void ltq_i2c_rx(struct ltq_i2c *priv, int last)
-+{
-+      u32 fifo_stat, timeout;
-+      if (priv->msg_buf_len && priv->msg_buf) {
-+              timeout = 5000000;
-+              do {
-+                      fifo_stat = i2c_r32(ffs_stat);
-+              } while (!fifo_stat && --timeout);
-+              if (!timeout) {
-+                      last = 1;
-+                      pr_debug("\nrx timeout\n");
-+                      goto err;
-+              }
-+              while (fifo_stat) {
-+                      *priv->msg_buf = i2c_r32(rxd);
-+                      if (--priv->msg_buf_len) {
-+                              priv->msg_buf++;
-+                      } else {
-+                              priv->msg_buf = NULL;
-+                              last = 1;
-+                              break;
-+                      }
-+                      /*
-+                       * do not read more than burst size, otherwise no "last
-+                       * burst" is generated and the transaction is blocked!
-+                       */
-+                      fifo_stat = 0;
-+              }
-+      } else {
-+              last = 1;
-+      }
-+err:
-+      if (last) {
-+              disable_burst_irq(priv);
-+
-+              if (priv->status == STATUS_READ_END) {
-+                      /* 
-+                       * do the STATUS_STOP and complete() here, as sometimes
-+                       * the tx_end is already seen before this is finished
-+                       */
-+                      priv->status = STATUS_STOP;
-+                      complete(&priv->cmd_complete);
-+              } else {
-+                      i2c_w32(I2C_ENDD_CTRL_SETEND, endd_ctrl);
-+                      priv->status = STATUS_READ_END;
-+              }
-+      }
-+}
-+
-+static void ltq_i2c_xfer_init(struct ltq_i2c *priv)
-+{
-+      /* enable interrupts */
-+      i2c_w32(LTQ_I2C_IMSC_DEFAULT_MASK, imsc);
-+
-+      /* trigger transfer of first msg */
-+      ltq_i2c_set_tx_len(priv);
-+}
-+
-+static void dump_msgs(struct i2c_msg msgs[], int num, int rx)
-+{
-+#if defined(DEBUG)
-+      int i, j;
-+      pr_debug("Messages %d %s\n", num, rx ? "out" : "in");
-+      for (i = 0; i < num; i++) {
-+              pr_debug("%2d %cX Msg(%d) addr=0x%X: ", i,
-+                      (msgs[i].flags & I2C_M_RD) ? 'R' : 'T',
-+                      msgs[i].len, msgs[i].addr);
-+              if (!(msgs[i].flags & I2C_M_RD) || rx) {
-+                      for (j = 0; j < msgs[i].len; j++)
-+                              pr_debug("%02X ", msgs[i].buf[j]);
-+              }
-+              pr_debug("\n");
-+      }
-+#endif
-+}
-+
-+static void ltq_i2c_release_bus(struct ltq_i2c *priv)
-+{
-+      if ((i2c_r32(bus_stat) & I2C_BUS_STAT_BS_MASK) == I2C_BUS_STAT_BS_BM)
-+              i2c_w32(I2C_ENDD_CTRL_SETEND, endd_ctrl);
-+}
-+
-+static int ltq_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-+                         int num)
-+{
-+      struct ltq_i2c *priv = i2c_get_adapdata(adap);
-+      int ret;
-+
-+      dev_dbg(priv->dev, "xfer %u messages\n", num);
-+      dump_msgs(msgs, num, 0);
-+
-+      mutex_lock(&priv->mutex);
-+
-+      INIT_COMPLETION(priv->cmd_complete);
-+      priv->current_msg = msgs;
-+      priv->msgs_num = num;
-+      priv->msg_err = 0;
-+      priv->status = STATUS_IDLE;
-+
-+      /* wait for the bus to become ready */
-+      ret = ltq_i2c_wait_bus_not_busy(priv);
-+      if (ret)
-+              goto done;
-+
-+      while (priv->msgs_num) {
-+              /* start the transfers */
-+              ltq_i2c_xfer_init(priv);
-+
-+              /* wait for transfers to complete */
-+              ret = wait_for_completion_interruptible_timeout(
-+                      &priv->cmd_complete, LTQ_I2C_XFER_TIMEOUT);
-+              if (ret == 0) {
-+                      dev_err(priv->dev, "controller timed out\n");
-+                      ltq_i2c_hw_init(adap);
-+                      ret = -ETIMEDOUT;
-+                      goto done;
-+              } else if (ret < 0)
-+                      goto done;
-+
-+              if (priv->msg_err) {
-+                      if (priv->msg_err & LTQ_I2C_NACK)
-+                              ret = -ENXIO;
-+                      else
-+                              ret = -EREMOTEIO;
-+                      goto done;
-+              }
-+              if (--priv->msgs_num)
-+                      priv->current_msg++;
-+      }
-+      /* no error? */
-+      ret = num;
-+
-+done:
-+      ltq_i2c_release_bus(priv);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      if (ret >= 0)
-+              dump_msgs(msgs, num, 1);
-+
-+      pr_debug("XFER ret %d\n", ret);
-+      return ret;
-+}
-+
-+static irqreturn_t ltq_i2c_isr_burst(int irq, void *dev_id)
-+{
-+      struct ltq_i2c *priv = dev_id;
-+      struct i2c_msg *msg = priv->current_msg;
-+      int last = (irq == priv->irq_lb);
-+
-+      if (last)
-+              pr_debug("LB ");
-+      else
-+              pr_debug("B ");
-+
-+      if (msg->flags & I2C_M_RD) {
-+              switch (priv->status) {
-+              case STATUS_ADDR:
-+                      pr_debug("X");
-+                      prepare_msg_send_addr(priv);
-+                      disable_burst_irq(priv);
-+                      break;
-+              case STATUS_READ:
-+              case STATUS_READ_END:
-+                      pr_debug("R");
-+                      ltq_i2c_rx(priv, last);
-+                      break;
-+              default:
-+                      disable_burst_irq(priv);
-+                      pr_warn("Status R %d\n", priv->status);
-+                      break;
-+              }
-+      } else {
-+              switch (priv->status) {
-+              case STATUS_ADDR:
-+                      pr_debug("x");
-+                      prepare_msg_send_addr(priv);
-+                      break;
-+              case STATUS_WRITE:
-+                      pr_debug("w");
-+                      ltq_i2c_tx(priv, last);
-+                      break;
-+              default:
-+                      disable_burst_irq(priv);
-+                      pr_warn("Status W %d\n", priv->status);
-+                      break;
-+              }
-+      }
-+
-+      i2c_w32(I2C_ICR_BREQ_INT_CLR | I2C_ICR_LBREQ_INT_CLR, icr);
-+      return IRQ_HANDLED;
-+}
-+
-+static void ltq_i2c_isr_prot(struct ltq_i2c *priv)
-+{
-+      u32 i_pro = i2c_r32(p_irqss);
-+
-+      pr_debug("i2c-p");
-+
-+      /* not acknowledge */
-+      if (i_pro & I2C_P_IRQSS_NACK) {
-+              priv->msg_err |= LTQ_I2C_NACK;
-+              pr_debug(" nack");
-+      }
-+
-+      /* arbitration lost */
-+      if (i_pro & I2C_P_IRQSS_AL) {
-+              priv->msg_err |= LTQ_I2C_ARB_LOST;
-+              pr_debug(" arb-lost");
-+      }
-+      /* tx -> rx switch */
-+      if (i_pro & I2C_P_IRQSS_RX)
-+              pr_debug(" rx");
-+
-+      /* tx end */
-+      if (i_pro & I2C_P_IRQSS_TX_END)
-+              pr_debug(" txend");
-+      pr_debug("\n");
-+
-+      if (!priv->msg_err) {
-+              /* tx -> rx switch */
-+              if (i_pro & I2C_P_IRQSS_RX) {
-+                      priv->status = STATUS_READ;
-+                      enable_burst_irq(priv);
-+              }
-+              if (i_pro & I2C_P_IRQSS_TX_END) {
-+                      if (priv->status == STATUS_READ)
-+                              priv->status = STATUS_READ_END;
-+                      else {
-+                              disable_burst_irq(priv);
-+                              priv->status = STATUS_STOP;
-+                      }
-+              }
-+      }
-+
-+      i2c_w32(i_pro, p_irqsc);
-+}
-+
-+static irqreturn_t ltq_i2c_isr(int irq, void *dev_id)
-+{
-+      u32 i_raw, i_err = 0;
-+      struct ltq_i2c *priv = dev_id;
-+
-+      i_raw = i2c_r32(mis);
-+      pr_debug("i_raw 0x%08X\n", i_raw);
-+
-+      /* error interrupt */
-+      if (i_raw & I2C_RIS_I2C_ERR_INT_INTOCC) {
-+              i_err = i2c_r32(err_irqss);
-+              pr_debug("i_err 0x%08X bus_stat 0x%04X\n",
-+                      i_err, i2c_r32(bus_stat));
-+
-+              /* tx fifo overflow (8) */
-+              if (i_err & I2C_ERR_IRQSS_TXF_OFL)
-+                      priv->msg_err |= LTQ_I2C_TX_OFL;
-+
-+              /* tx fifo underflow (4) */
-+              if (i_err & I2C_ERR_IRQSS_TXF_UFL)
-+                      priv->msg_err |= LTQ_I2C_TX_UFL;
-+
-+              /* rx fifo overflow (2) */
-+              if (i_err & I2C_ERR_IRQSS_RXF_OFL)
-+                      priv->msg_err |= LTQ_I2C_RX_OFL;
-+
-+              /* rx fifo underflow (1) */
-+              if (i_err & I2C_ERR_IRQSS_RXF_UFL)
-+                      priv->msg_err |= LTQ_I2C_RX_UFL;
-+
-+              i2c_w32(i_err, err_irqsc);
-+      }
-+
-+      /* protocol interrupt */
-+      if (i_raw & I2C_RIS_I2C_P_INT_INTOCC)
-+              ltq_i2c_isr_prot(priv);
-+
-+      if ((priv->msg_err) || (priv->status == STATUS_STOP))
-+              complete(&priv->cmd_complete);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static u32 ltq_i2c_functionality(struct i2c_adapter *adap)
-+{
-+      return  I2C_FUNC_I2C |
-+              I2C_FUNC_10BIT_ADDR |
-+              I2C_FUNC_SMBUS_EMUL;
-+}
-+
-+static struct i2c_algorithm ltq_i2c_algorithm = {
-+      .master_xfer    = ltq_i2c_xfer,
-+      .functionality  = ltq_i2c_functionality,
-+};
-+
-+static int __devinit ltq_i2c_probe(struct platform_device *pdev)
-+{
-+      struct device_node *node = pdev->dev.of_node;
-+      struct ltq_i2c *priv;
-+      struct i2c_adapter *adap;
-+      struct resource *mmres, irqres[4];
-+      int ret = 0;
-+
-+      dev_dbg(&pdev->dev, "probing\n");
-+
-+      mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      ret = of_irq_to_resource_table(node, irqres, 4);
-+      if (!mmres || (ret != 4)) {
-+              dev_err(&pdev->dev, "no resources\n");
-+              return -ENODEV;
-+      }
-+
-+      /* allocate private data */
-+      priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv) {
-+              dev_err(&pdev->dev, "can't allocate private data\n");
-+              return -ENOMEM;
-+      }
-+
-+      adap = &priv->adap;
-+      i2c_set_adapdata(adap, priv);
-+      adap->owner = THIS_MODULE;
-+      adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
-+      strlcpy(adap->name, DRV_NAME "-adapter", sizeof(adap->name));
-+      adap->algo = &ltq_i2c_algorithm;
-+
-+      if (of_property_read_u32(node, "clock-frequency", &priv->i2c_clock)) {
-+              dev_warn(&pdev->dev, "No I2C speed selected, using 100kHz\n");
-+              priv->i2c_clock = 100000;
-+      }
-+
-+      init_completion(&priv->cmd_complete);
-+      mutex_init(&priv->mutex);
-+
-+      priv->membase = devm_request_and_ioremap(&pdev->dev, mmres);
-+      if (priv->membase == NULL)
-+              return -ENOMEM;
-+
-+      priv->dev = &pdev->dev;
-+      priv->irq_lb = irqres[0].start;
-+
-+      ret = devm_request_irq(&pdev->dev, irqres[0].start, ltq_i2c_isr_burst,
-+              IRQF_DISABLED, "i2c lb", priv);
-+      if (ret) {
-+              dev_err(&pdev->dev, "can't get last burst IRQ %d\n",
-+                      irqres[0].start);
-+              return -ENODEV;
-+      }
-+
-+      ret = devm_request_irq(&pdev->dev, irqres[1].start, ltq_i2c_isr_burst,
-+              IRQF_DISABLED, "i2c b", priv);
-+      if (ret) {
-+              dev_err(&pdev->dev, "can't get burst IRQ %d\n",
-+                      irqres[1].start);
-+              return -ENODEV;
-+      }
-+
-+      ret = devm_request_irq(&pdev->dev, irqres[2].start, ltq_i2c_isr,
-+              IRQF_DISABLED, "i2c err", priv);
-+      if (ret) {
-+              dev_err(&pdev->dev, "can't get error IRQ %d\n",
-+                      irqres[2].start);
-+              return -ENODEV;
-+      }
-+
-+      ret = devm_request_irq(&pdev->dev, irqres[3].start, ltq_i2c_isr,
-+              IRQF_DISABLED, "i2c p", priv);
-+      if (ret) {
-+              dev_err(&pdev->dev, "can't get protocol IRQ %d\n",
-+                      irqres[3].start);
-+              return -ENODEV;
-+      }
-+
-+      dev_dbg(&pdev->dev, "mapped io-space to %p\n", priv->membase);
-+      dev_dbg(&pdev->dev, "use IRQs %d, %d, %d, %d\n", irqres[0].start,
-+              irqres[1].start, irqres[2].start, irqres[3].start);
-+
-+      priv->clk_gate = devm_clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(priv->clk_gate)) {
-+              dev_err(&pdev->dev, "failed to get i2c clk\n");
-+              return -ENOENT;
-+      }
-+
-+      /* this is a static clock, which has no refcounting */
-+      priv->clk_input = clk_get_fpi();
-+      if (IS_ERR(priv->clk_input)) {
-+              dev_err(&pdev->dev, "failed to get fpi clk\n");
-+              return -ENOENT;
-+      }
-+
-+      clk_activate(priv->clk_gate);
-+
-+      /* add our adapter to the i2c stack */
-+      ret = i2c_add_numbered_adapter(adap);
-+      if (ret) {
-+              dev_err(&pdev->dev, "can't register I2C adapter\n");
-+              goto out;
-+      }
-+
-+      platform_set_drvdata(pdev, priv);
-+      i2c_set_adapdata(adap, priv);
-+
-+      /* print module version information */
-+      dev_dbg(&pdev->dev, "module id=%u revision=%u\n",
-+              (i2c_r32(id) & I2C_ID_ID_MASK) >> I2C_ID_ID_OFFSET,
-+              (i2c_r32(id) & I2C_ID_REV_MASK) >> I2C_ID_REV_OFFSET);
-+
-+      /* initialize HW */
-+      ret = ltq_i2c_hw_init(adap);
-+      if (ret) {
-+              dev_err(&pdev->dev, "can't configure adapter\n");
-+              i2c_del_adapter(adap);
-+              platform_set_drvdata(pdev, NULL);
-+      } else {
-+              dev_info(&pdev->dev, "version %s\n", DRV_VERSION);
-+      }
-+
-+      of_i2c_register_devices(adap);
-+
-+out:
-+      /* if init failed, we need to deactivate the clock gate */
-+      if (ret)
-+              clk_deactivate(priv->clk_gate);
-+
-+      return ret;
-+}
-+
-+static int __devexit ltq_i2c_remove(struct platform_device *pdev)
-+{
-+      struct ltq_i2c *priv = platform_get_drvdata(pdev);
-+
-+      /* disable bus */
-+      i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
-+
-+      /* power down the core */
-+      clk_deactivate(priv->clk_gate);
-+
-+      /* remove driver */
-+      i2c_del_adapter(&priv->adap);
-+      kfree(priv);
-+
-+      dev_dbg(&pdev->dev, "removed\n");
-+      platform_set_drvdata(pdev, NULL);
-+
-+      return 0;
-+}
-+static const struct of_device_id ltq_i2c_match[] = {
-+      { .compatible = "lantiq,lantiq-i2c" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, ltq_i2c_match);
-+
-+static struct platform_driver ltq_i2c_driver = {
-+      .probe  = ltq_i2c_probe,
-+      .remove = __devexit_p(ltq_i2c_remove),
-+      .driver = {
-+              .name   = DRV_NAME,
-+              .owner  = THIS_MODULE,
-+              .of_match_table = ltq_i2c_match,
-+      },
-+};
-+
-+module_platform_driver(ltq_i2c_driver);
-+
-+MODULE_DESCRIPTION("Lantiq I2C bus adapter");
-+MODULE_AUTHOR("Thomas Langer <thomas.langer@lantiq.com>");
-+MODULE_ALIAS("platform:" DRV_NAME);
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
-diff --git a/drivers/i2c/busses/i2c-lantiq.h b/drivers/i2c/busses/i2c-lantiq.h
-new file mode 100644
-index 0000000..7a86b89
---- /dev/null
-+++ b/drivers/i2c/busses/i2c-lantiq.h
-@@ -0,0 +1,234 @@
-+#ifndef I2C_LANTIQ_H
-+#define I2C_LANTIQ_H
-+
-+/* I2C register structure */
-+struct lantiq_reg_i2c {
-+      /* I2C Kernel Clock Control Register */
-+      unsigned int clc; /* 0x00000000 */
-+      /* Reserved */
-+      unsigned int res_0; /* 0x00000004 */
-+      /* I2C Identification Register */
-+      unsigned int id; /* 0x00000008 */
-+      /* Reserved */
-+      unsigned int res_1; /* 0x0000000C */
-+      /*
-+       * I2C RUN Control Register
-+       * This register enables and disables the I2C peripheral. Before
-+       * enabling, the I2C has to be configured properly. After enabling
-+       * no configuration is possible
-+       */
-+      unsigned int run_ctrl; /* 0x00000010 */
-+      /*
-+       * I2C End Data Control Register
-+       * This register is used to either turn around the data transmission
-+       * direction or to address another slave without sending a stop
-+       * condition. Also the software can stop the slave-transmitter by
-+       * sending a not-accolade when working as master-receiver or even
-+       * stop data transmission immediately when operating as
-+       * master-transmitter. The writing to the bits of this control
-+       * register is only effective when in MASTER RECEIVES BYTES, MASTER
-+       * TRANSMITS BYTES, MASTER RESTART or SLAVE RECEIVE BYTES state
-+       */
-+      unsigned int endd_ctrl; /* 0x00000014 */
-+      /*
-+       * I2C Fractional Divider Configuration Register
-+       * These register is used to program the fractional divider of the I2C
-+       * bus. Before the peripheral is switched on by setting the RUN-bit the
-+       * two (fixed) values for the two operating frequencies are programmed
-+       * into these (configuration) registers. The Register FDIV_HIGH_CFG has
-+       * the same layout as I2C_FDIV_CFG.
-+       */
-+      unsigned int fdiv_cfg; /* 0x00000018 */
-+      /*
-+       * I2C Fractional Divider (highspeed mode) Configuration Register
-+       * These register is used to program the fractional divider of the I2C
-+       * bus. Before the peripheral is switched on by setting the RUN-bit the
-+       * two (fixed) values for the two operating frequencies are programmed
-+       * into these (configuration) registers. The Register FDIV_CFG has the
-+       * same layout as I2C_FDIV_CFG.
-+       */
-+      unsigned int fdiv_high_cfg; /* 0x0000001C */
-+      /* I2C Address Configuration Register */
-+      unsigned int addr_cfg; /* 0x00000020 */
-+      /* I2C Bus Status Register
-+       * This register gives a status information of the I2C. This additional
-+       * information can be used by the software to start proper actions.
-+       */
-+      unsigned int bus_stat; /* 0x00000024 */
-+      /* I2C FIFO Configuration Register */
-+      unsigned int fifo_cfg; /* 0x00000028 */
-+      /* I2C Maximum Received Packet Size Register */
-+      unsigned int mrps_ctrl; /* 0x0000002C */
-+      /* I2C Received Packet Size Status Register */
-+      unsigned int rps_stat; /* 0x00000030 */
-+      /* I2C Transmit Packet Size Register */
-+      unsigned int tps_ctrl; /* 0x00000034 */
-+      /* I2C Filled FIFO Stages Status Register */
-+      unsigned int ffs_stat; /* 0x00000038 */
-+      /* Reserved */
-+      unsigned int res_2; /* 0x0000003C */
-+      /* I2C Timing Configuration Register */
-+      unsigned int tim_cfg; /* 0x00000040 */
-+      /* Reserved */
-+      unsigned int res_3[7]; /* 0x00000044 */
-+      /* I2C Error Interrupt Request Source Mask Register */
-+      unsigned int err_irqsm; /* 0x00000060 */
-+      /* I2C Error Interrupt Request Source Status Register */
-+      unsigned int err_irqss; /* 0x00000064 */
-+      /* I2C Error Interrupt Request Source Clear Register */
-+      unsigned int err_irqsc; /* 0x00000068 */
-+      /* Reserved */
-+      unsigned int res_4; /* 0x0000006C */
-+      /* I2C Protocol Interrupt Request Source Mask Register */
-+      unsigned int p_irqsm; /* 0x00000070 */
-+      /* I2C Protocol Interrupt Request Source Status Register */
-+      unsigned int p_irqss; /* 0x00000074 */
-+      /* I2C Protocol Interrupt Request Source Clear Register */
-+      unsigned int p_irqsc; /* 0x00000078 */
-+      /* Reserved */
-+      unsigned int res_5; /* 0x0000007C */
-+      /* I2C Raw Interrupt Status Register */
-+      unsigned int ris; /* 0x00000080 */
-+      /* I2C Interrupt Mask Control Register */
-+      unsigned int imsc; /* 0x00000084 */
-+      /* I2C Masked Interrupt Status Register */
-+      unsigned int mis; /* 0x00000088 */
-+      /* I2C Interrupt Clear Register */
-+      unsigned int icr; /* 0x0000008C */
-+      /* I2C Interrupt Set Register */
-+      unsigned int isr; /* 0x00000090 */
-+      /* I2C DMA Enable Register */
-+      unsigned int dmae; /* 0x00000094 */
-+      /* Reserved */
-+      unsigned int res_6[8154]; /* 0x00000098 */
-+      /* I2C Transmit Data Register */
-+      unsigned int txd; /* 0x00008000 */
-+      /* Reserved */
-+      unsigned int res_7[4095]; /* 0x00008004 */
-+      /* I2C Receive Data Register */
-+      unsigned int rxd; /* 0x0000C000 */
-+      /* Reserved */
-+      unsigned int res_8[4095]; /* 0x0000C004 */
-+};
-+
-+/*
-+ * Clock Divider for Normal Run Mode
-+ * Max 8-bit divider value. IF RMC is 0 the module is disabled. Note: As long
-+ * as the new divider value RMC is not valid, the register returns 0x0000 00xx
-+ * on reading.
-+ */
-+#define I2C_CLC_RMC_MASK 0x0000FF00
-+/* field offset */
-+#define I2C_CLC_RMC_OFFSET 8
-+
-+/* Fields of "I2C Identification Register" */
-+/* Module ID */
-+#define I2C_ID_ID_MASK 0x0000FF00
-+/* field offset */
-+#define I2C_ID_ID_OFFSET 8
-+/* Revision */
-+#define I2C_ID_REV_MASK 0x000000FF
-+/* field offset */
-+#define I2C_ID_REV_OFFSET 0
-+
-+/* Fields of "I2C Interrupt Mask Control Register" */
-+/* Enable */
-+#define I2C_IMSC_BREQ_INT_EN 0x00000008
-+/* Enable */
-+#define I2C_IMSC_LBREQ_INT_EN 0x00000004
-+
-+/* Fields of "I2C Fractional Divider Configuration Register" */
-+/* field offset */
-+#define I2C_FDIV_CFG_INC_OFFSET 16
-+
-+/* Fields of "I2C Interrupt Mask Control Register" */
-+/* Enable */
-+#define I2C_IMSC_I2C_P_INT_EN 0x00000020
-+/* Enable */
-+#define I2C_IMSC_I2C_ERR_INT_EN 0x00000010
-+
-+/* Fields of "I2C Error Interrupt Request Source Status Register" */
-+/* TXF_OFL */
-+#define I2C_ERR_IRQSS_TXF_OFL 0x00000008
-+/* TXF_UFL */
-+#define I2C_ERR_IRQSS_TXF_UFL 0x00000004
-+/* RXF_OFL */
-+#define I2C_ERR_IRQSS_RXF_OFL 0x00000002
-+/* RXF_UFL */
-+#define I2C_ERR_IRQSS_RXF_UFL 0x00000001
-+
-+/* Fields of "I2C Raw Interrupt Status Register" */
-+/* Read: Interrupt occurred. */
-+#define I2C_RIS_I2C_ERR_INT_INTOCC 0x00000010
-+/* Read: Interrupt occurred. */
-+#define I2C_RIS_I2C_P_INT_INTOCC 0x00000020
-+
-+/* Fields of "I2C FIFO Configuration Register" */
-+/* TX FIFO Flow Control */
-+#define I2C_FIFO_CFG_TXFC 0x00020000
-+/* RX FIFO Flow Control */
-+#define I2C_FIFO_CFG_RXFC 0x00010000
-+/* Word aligned (character alignment of four characters) */
-+#define I2C_FIFO_CFG_TXFA_TXFA2 0x00002000
-+/* Word aligned (character alignment of four characters) */
-+#define I2C_FIFO_CFG_RXFA_RXFA2 0x00000200
-+/* 1 word */
-+#define I2C_FIFO_CFG_TXBS_TXBS0 0x00000000
-+
-+/* Fields of "I2C FIFO Configuration Register" */
-+/* 1 word */
-+#define I2C_FIFO_CFG_RXBS_RXBS0 0x00000000
-+/* Stop on Packet End Enable */
-+#define I2C_ADDR_CFG_SOPE_EN 0x00200000
-+/* Stop on Not Acknowledge Enable */
-+#define I2C_ADDR_CFG_SONA_EN 0x00100000
-+/* Enable */
-+#define I2C_ADDR_CFG_MnS_EN 0x00080000
-+
-+/* Fields of "I2C Interrupt Clear Register" */
-+/* Clear */
-+#define I2C_ICR_BREQ_INT_CLR 0x00000008
-+/* Clear */
-+#define I2C_ICR_LBREQ_INT_CLR 0x00000004
-+
-+/* Fields of "I2C Fractional Divider Configuration Register" */
-+/* field offset */
-+#define I2C_FDIV_CFG_DEC_OFFSET 0
-+
-+/* Fields of "I2C Bus Status Register" */
-+/* Bus Status */
-+#define I2C_BUS_STAT_BS_MASK 0x00000003
-+/* Read from I2C Bus. */
-+#define I2C_BUS_STAT_RNW_READ 0x00000004
-+/* I2C Bus is free. */
-+#define I2C_BUS_STAT_BS_FREE 0x00000000
-+/*
-+ * The device is working as master and has claimed the control on the
-+ * I2C-bus (busy master).
-+ */
-+#define I2C_BUS_STAT_BS_BM 0x00000002
-+
-+/* Fields of "I2C RUN Control Register" */
-+/* Enable */
-+#define I2C_RUN_CTRL_RUN_EN 0x00000001
-+
-+/* Fields of "I2C End Data Control Register" */
-+/*
-+ * Set End of Transmission
-+ * Note:Do not write '1' to this bit when bus is free. This will cause an
-+ * abort after the first byte when a new transfer is started.
-+ */
-+#define I2C_ENDD_CTRL_SETEND 0x00000002
-+
-+/* Fields of "I2C Protocol Interrupt Request Source Status Register" */
-+/* NACK */
-+#define I2C_P_IRQSS_NACK 0x00000010
-+/* AL */
-+#define I2C_P_IRQSS_AL 0x00000008
-+/* RX */
-+#define I2C_P_IRQSS_RX 0x00000040
-+/* TX_END */
-+#define I2C_P_IRQSS_TX_END 0x00000020
-+
-+
-+#endif /* I2C_LANTIQ_H */
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0026-NET-multi-phy-support.patch b/target/linux/lantiq/patches-3.14/0026-NET-multi-phy-support.patch
new file mode 100644 (file)
index 0000000..9ffc680
--- /dev/null
@@ -0,0 +1,60 @@
+From c6feeeb407a3b8a6597ae377ba4dd138e185e3dd Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 27 Jul 2014 09:38:50 +0100
+Subject: [PATCH 26/36] NET: multi phy support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/phy/phy.c |    9 ++++++---
+ include/linux/phy.h   |    1 +
+ 2 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 76d96b9..371f0b6 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -715,7 +715,8 @@ void phy_state_machine(struct work_struct *work)
+               /* If the link is down, give up on 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;
+               }
+@@ -781,7 +782,8 @@ void phy_state_machine(struct work_struct *work)
+                       netif_carrier_on(phydev->attached_dev);
+               } else {
+                       phydev->state = PHY_NOLINK;
+-                      netif_carrier_off(phydev->attached_dev);
++                      if (!phydev->no_auto_carrier_off)
++                              netif_carrier_off(phydev->attached_dev);
+               }
+               phydev->adjust_link(phydev->attached_dev);
+@@ -793,7 +795,8 @@ void phy_state_machine(struct work_struct *work)
+       case PHY_HALTED:
+               if (phydev->link) {
+                       phydev->link = 0;
+-                      netif_carrier_off(phydev->attached_dev);
++                      if (!phydev->no_auto_carrier_off)
++                              netif_carrier_off(phydev->attached_dev);
+                       phydev->adjust_link(phydev->attached_dev);
+                       do_suspend = 1;
+               }
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 565188c..91b93f7 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -308,6 +308,7 @@ struct phy_device {
+       struct phy_c45_device_ids c45_ids;
+       bool is_c45;
+       bool is_internal;
++      bool no_auto_carrier_off;
+       enum phy_state state;
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0027-NET-add-of_get_mac_address_mtd.patch b/target/linux/lantiq/patches-3.14/0027-NET-add-of_get_mac_address_mtd.patch
new file mode 100644 (file)
index 0000000..53489ed
--- /dev/null
@@ -0,0 +1,83 @@
+From f393898476aef3e4f49c27725c3d2dd70fca38fe Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 27 Jul 2014 09:40:01 +0100
+Subject: [PATCH 27/36] 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(+)
+
+diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c
+index a208a45..de93111 100644
+--- 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
+@@ -94,3 +95,39 @@ const void *of_get_mac_address(struct device_node *np)
+       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);
+diff --git a/include/linux/of_net.h b/include/linux/of_net.h
+index 34597c8..cdfbc60 100644
+--- a/include/linux/of_net.h
++++ b/include/linux/of_net.h
+@@ -11,6 +11,7 @@
+ #include <linux/of.h>
+ extern 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 int of_get_phy_mode(struct device_node *np)
+ {
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0027-USB-fix-roothub-for-IFXHCD.patch b/target/linux/lantiq/patches-3.14/0027-USB-fix-roothub-for-IFXHCD.patch
deleted file mode 100644 (file)
index 68af3bf..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 53c4acc1d3c7eae439b8bf3422de876e8a3e3bdb Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 6 Dec 2012 19:59:53 +0100
-Subject: [PATCH 27/31] USB: fix roothub for IFXHCD
-
----
- arch/mips/lantiq/Kconfig |    1 +
- drivers/usb/core/hub.c   |    2 +-
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
-index 1621b1d..4c9a241 100644
---- a/arch/mips/lantiq/Kconfig
-+++ b/arch/mips/lantiq/Kconfig
-@@ -3,6 +3,7 @@ if LANTIQ
- config SOC_TYPE_XWAY
-       bool
-       select PINCTRL_XWAY
-+      select USB_ARCH_HAS_HCD
-       default n
- choice
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 64ea219..30f4bdf 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -4077,7 +4077,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
-               udev->ttport = hdev->ttport;
-       } else if (udev->speed != USB_SPEED_HIGH
-                       && hdev->speed == USB_SPEED_HIGH) {
--              if (!hub->tt.hub) {
-+              if (hdev->parent && !hub->tt.hub) {
-                       dev_err(&udev->dev, "parent hub has no TT\n");
-                       retval = -EINVAL;
-                       goto fail;
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0028-NET-lantiq-various-etop-fixes.patch b/target/linux/lantiq/patches-3.14/0028-NET-lantiq-various-etop-fixes.patch
new file mode 100644 (file)
index 0000000..1c8821c
--- /dev/null
@@ -0,0 +1,937 @@
+From 870ed9cae083ff8a60a739ef7e74c5a1800533be Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 9 Sep 2014 22:45:34 +0200
+Subject: [PATCH 28/36] NET: lantiq: various etop fixes
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/ethernet/lantiq_etop.c |  555 +++++++++++++++++++++++++-----------
+ 1 file changed, 389 insertions(+), 166 deletions(-)
+
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index fd4b6ae..1712382 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -11,7 +11,7 @@
+  *   You should have received a copy of the GNU General Public License
+  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
+  *
+- *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
++ *   Copyright (C) 2011-12 John Crispin <blogic@openwrt.org>
+  */
+ #include <linux/kernel.h>
+@@ -30,11 +30,16 @@
+ #include <linux/mm.h>
+ #include <linux/platform_device.h>
+ #include <linux/ethtool.h>
++#include <linux/if_vlan.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/of_net.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
+ #include <asm/checksum.h>
+@@ -42,7 +47,7 @@
+ #include <xway_dma.h>
+ #include <lantiq_platform.h>
+-#define LTQ_ETOP_MDIO         0x11804
++#define LTQ_ETOP_MDIO_ACC     0x11804
+ #define MDIO_REQUEST          0x80000000
+ #define MDIO_READ             0x40000000
+ #define MDIO_ADDR_MASK                0x1f
+@@ -51,44 +56,91 @@
+ #define MDIO_REG_OFFSET               0x10
+ #define MDIO_VAL_MASK         0xffff
+-#define PPE32_CGEN            0x800
+-#define LQ_PPE32_ENET_MAC_CFG 0x1840
++#define LTQ_ETOP_MDIO_CFG       0x11800
++#define MDIO_CFG_MASK           0x6
++
++#define LTQ_ETOP_CFG            0x11808
++#define LTQ_ETOP_IGPLEN         0x11820
++#define LTQ_ETOP_MAC_CFG      0x11840
+ #define LTQ_ETOP_ENETS0               0x11850
+ #define LTQ_ETOP_MAC_DA0      0x1186C
+ #define LTQ_ETOP_MAC_DA1      0x11870
+-#define LTQ_ETOP_CFG          0x16020
+-#define LTQ_ETOP_IGPLEN               0x16080
++
++#define MAC_CFG_MASK          0xfff
++#define MAC_CFG_CGEN          (1 << 11)
++#define MAC_CFG_DUPLEX                (1 << 2)
++#define MAC_CFG_SPEED         (1 << 1)
++#define MAC_CFG_LINK          (1 << 0)
+ #define MAX_DMA_CHAN          0x8
+ #define MAX_DMA_CRC_LEN               0x4
+ #define MAX_DMA_DATA_LEN      0x600
+ #define ETOP_FTCU             BIT(28)
+-#define ETOP_MII_MASK         0xf
+-#define ETOP_MII_NORMAL               0xd
+-#define ETOP_MII_REVERSE      0xe
+ #define ETOP_PLEN_UNDER               0x40
+-#define ETOP_CGEN             0x800
+-
+-/* use 2 static channels for TX/RX */
+-#define LTQ_ETOP_TX_CHANNEL   1
+-#define LTQ_ETOP_RX_CHANNEL   6
+-#define IS_TX(x)              (x == LTQ_ETOP_TX_CHANNEL)
+-#define IS_RX(x)              (x == LTQ_ETOP_RX_CHANNEL)
+-
++#define ETOP_CFG_MII0         0x01
++
++#define ETOP_CFG_MASK           0xfff
++#define ETOP_CFG_FEN0         (1 << 8)
++#define ETOP_CFG_SEN0         (1 << 6)
++#define ETOP_CFG_OFF1         (1 << 3)
++#define ETOP_CFG_REMII0               (1 << 1)
++#define ETOP_CFG_OFF0         (1 << 0)
++
++#define LTQ_GBIT_MDIO_CTL     0xCC
++#define LTQ_GBIT_MDIO_DATA    0xd0
++#define LTQ_GBIT_GCTL0                0x68
++#define LTQ_GBIT_PMAC_HD_CTL  0x8c
++#define LTQ_GBIT_P0_CTL               0x4
++#define LTQ_GBIT_PMAC_RX_IPG  0xa8
++#define LTQ_GBIT_RGMII_CTL    0x78
++
++#define PMAC_HD_CTL_AS                (1 << 19)
++#define PMAC_HD_CTL_RXSH      (1 << 22)
++
++/* Switch Enable (0=disable, 1=enable) */
++#define GCTL0_SE              0x80000000
++/* Disable MDIO auto polling (0=disable, 1=enable) */
++#define PX_CTL_DMDIO          0x00400000
++
++/* MDC clock divider, clock = 25MHz/((MDC_CLOCK + 1) * 2) */
++#define MDC_CLOCK_MASK                0xff000000
++#define MDC_CLOCK_OFFSET      24
++
++/* register information for the gbit's MDIO bus */
++#define MDIO_XR9_REQUEST      0x00008000
++#define MDIO_XR9_READ         0x00000800
++#define MDIO_XR9_WRITE                0x00000400
++#define MDIO_XR9_REG_MASK     0x1f
++#define MDIO_XR9_ADDR_MASK    0x1f
++#define MDIO_XR9_RD_MASK      0xffff
++#define MDIO_XR9_REG_OFFSET   0
++#define MDIO_XR9_ADDR_OFFSET  5
++#define MDIO_XR9_WR_OFFSET    16
++
++#define LTQ_DMA_ETOP  ((of_machine_is_compatible("lantiq,ase")) ? \
++                      (INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0))
++
++/* the newer xway socks have a embedded 3/7 port gbit multiplexer */
+ #define ltq_etop_r32(x)               ltq_r32(ltq_etop_membase + (x))
+ #define ltq_etop_w32(x, y)    ltq_w32(x, ltq_etop_membase + (y))
+ #define ltq_etop_w32_mask(x, y, z)    \
+               ltq_w32_mask(x, y, ltq_etop_membase + (z))
+-#define DRV_VERSION   "1.0"
++#define ltq_gbit_r32(x)               ltq_r32(ltq_gbit_membase + (x))
++#define ltq_gbit_w32(x, y)    ltq_w32(x, ltq_gbit_membase + (y))
++#define ltq_gbit_w32_mask(x, y, z)    \
++              ltq_w32_mask(x, y, ltq_gbit_membase + (z))
++
++#define DRV_VERSION   "1.2"
+ static void __iomem *ltq_etop_membase;
++static void __iomem *ltq_gbit_membase;
+ struct ltq_etop_chan {
+-      int idx;
+       int tx_free;
++      int irq;
+       struct net_device *netdev;
+       struct napi_struct napi;
+       struct ltq_dma_channel dma;
+@@ -98,22 +150,35 @@ struct ltq_etop_chan {
+ struct ltq_etop_priv {
+       struct net_device *netdev;
+       struct platform_device *pdev;
+-      struct ltq_eth_data *pldata;
+       struct resource *res;
+       struct mii_bus *mii_bus;
+       struct phy_device *phydev;
+-      struct ltq_etop_chan ch[MAX_DMA_CHAN];
+-      int tx_free[MAX_DMA_CHAN >> 1];
++      struct ltq_etop_chan txch;
++      struct ltq_etop_chan rxch;
++
++      int tx_irq;
++      int rx_irq;
++
++      const void *mac;
++      int mii_mode;
+       spinlock_t lock;
++
++      struct clk *clk_ppe;
++      struct clk *clk_switch;
++      struct clk *clk_ephy;
++      struct clk *clk_ephycgu;
+ };
++static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr,
++                              int phy_reg, u16 phy_data);
++
+ static int
+ ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
+ {
+-      ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN);
++      ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
+       if (!ch->skb[ch->dma.desc])
+               return -ENOMEM;
+       ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
+@@ -148,8 +213,11 @@ ltq_etop_hw_receive(struct ltq_etop_chan *ch)
+       spin_unlock_irqrestore(&priv->lock, flags);
+       skb_put(skb, len);
++      skb->dev = ch->netdev;
+       skb->protocol = eth_type_trans(skb, ch->netdev);
+       netif_receive_skb(skb);
++      ch->netdev->stats.rx_packets++;
++      ch->netdev->stats.rx_bytes += len;
+ }
+ static int
+@@ -157,8 +225,10 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+ {
+       struct ltq_etop_chan *ch = container_of(napi,
+                               struct ltq_etop_chan, napi);
++      struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+       int rx = 0;
+       int complete = 0;
++      unsigned long flags;
+       while ((rx < budget) && !complete) {
+               struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+@@ -172,7 +242,9 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+       }
+       if (complete || !rx) {
+               napi_complete(&ch->napi);
++              spin_lock_irqsave(&priv->lock, flags);
+               ltq_dma_ack_irq(&ch->dma);
++              spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       return rx;
+ }
+@@ -184,12 +256,14 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+               container_of(napi, struct ltq_etop_chan, napi);
+       struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+       struct netdev_queue *txq =
+-              netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
++              netdev_get_tx_queue(ch->netdev, ch->dma.nr >> 1);
+       unsigned long flags;
+       spin_lock_irqsave(&priv->lock, flags);
+       while ((ch->dma.desc_base[ch->tx_free].ctl &
+                       (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
++              ch->netdev->stats.tx_packets++;
++              ch->netdev->stats.tx_bytes += ch->skb[ch->tx_free]->len;
+               dev_kfree_skb_any(ch->skb[ch->tx_free]);
+               ch->skb[ch->tx_free] = NULL;
+               memset(&ch->dma.desc_base[ch->tx_free], 0,
+@@ -202,7 +276,9 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+       if (netif_tx_queue_stopped(txq))
+               netif_tx_start_queue(txq);
+       napi_complete(&ch->napi);
++      spin_lock_irqsave(&priv->lock, flags);
+       ltq_dma_ack_irq(&ch->dma);
++      spin_unlock_irqrestore(&priv->lock, flags);
+       return 1;
+ }
+@@ -210,9 +286,10 @@ static irqreturn_t
+ ltq_etop_dma_irq(int irq, void *_priv)
+ {
+       struct ltq_etop_priv *priv = _priv;
+-      int ch = irq - LTQ_DMA_CH0_INT;
+-
+-      napi_schedule(&priv->ch[ch].napi);
++      if (irq == priv->txch.dma.irq)
++              napi_schedule(&priv->txch.napi);
++      else
++              napi_schedule(&priv->rxch.napi);
+       return IRQ_HANDLED;
+ }
+@@ -224,7 +301,7 @@ ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
+       ltq_dma_free(&ch->dma);
+       if (ch->dma.irq)
+               free_irq(ch->dma.irq, priv);
+-      if (IS_RX(ch->idx)) {
++      if (ch == &priv->txch) {
+               int desc;
+               for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+                       dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+@@ -235,65 +312,133 @@ static void
+ ltq_etop_hw_exit(struct net_device *dev)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      int i;
+-      ltq_pmu_disable(PMU_PPE);
+-      for (i = 0; i < MAX_DMA_CHAN; i++)
+-              if (IS_TX(i) || IS_RX(i))
+-                      ltq_etop_free_channel(dev, &priv->ch[i]);
++      clk_disable(priv->clk_ppe);
++
++      if (of_machine_is_compatible("lantiq,ar9"))
++              clk_disable(priv->clk_switch);
++
++      if (of_machine_is_compatible("lantiq,ase")) {
++              clk_disable(priv->clk_ephy);
++              clk_disable(priv->clk_ephycgu);
++      }
++
++      ltq_etop_free_channel(dev, &priv->txch);
++      ltq_etop_free_channel(dev, &priv->rxch);
++}
++
++static void
++ltq_etop_gbit_init(struct net_device *dev)
++{
++      struct ltq_etop_priv *priv = netdev_priv(dev);
++
++      clk_enable(priv->clk_switch);
++
++      /* enable gbit port0 on the SoC */
++      ltq_gbit_w32_mask((1 << 17), (1 << 18), LTQ_GBIT_P0_CTL);
++
++      ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
++      /* disable MDIO auto polling mode */
++      ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL);
++      /* set 1522 packet size */
++      ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0);
++      /* disable pmac & dmac headers */
++      ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0,
++              LTQ_GBIT_PMAC_HD_CTL);
++      /* Due to traffic halt when burst length 8,
++              replace default IPG value with 0x3B */
++      ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG);
++      /* set mdc clock to 2.5 MHz */
++      ltq_gbit_w32_mask(MDC_CLOCK_MASK, 4 << MDC_CLOCK_OFFSET,
++              LTQ_GBIT_RGMII_CTL);
+ }
+ static int
+ ltq_etop_hw_init(struct net_device *dev)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      int i;
++      int mii_mode = priv->mii_mode;
++
++      clk_enable(priv->clk_ppe);
+-      ltq_pmu_enable(PMU_PPE);
++      if (of_machine_is_compatible("lantiq,ar9")) {
++              ltq_etop_gbit_init(dev);
++              /* force the etops link to the gbit to MII */
++              mii_mode = PHY_INTERFACE_MODE_MII;
++      }
++      ltq_etop_w32_mask(MDIO_CFG_MASK, 0, LTQ_ETOP_MDIO_CFG);
++      ltq_etop_w32_mask(MAC_CFG_MASK, MAC_CFG_CGEN | MAC_CFG_DUPLEX |
++                      MAC_CFG_SPEED | MAC_CFG_LINK, LTQ_ETOP_MAC_CFG);
+-      switch (priv->pldata->mii_mode) {
++      switch (mii_mode) {
+       case PHY_INTERFACE_MODE_RMII:
+-              ltq_etop_w32_mask(ETOP_MII_MASK,
+-                      ETOP_MII_REVERSE, LTQ_ETOP_CFG);
++              ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_REMII0 | ETOP_CFG_OFF1 |
++                      ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG);
+               break;
+       case PHY_INTERFACE_MODE_MII:
+-              ltq_etop_w32_mask(ETOP_MII_MASK,
+-                      ETOP_MII_NORMAL, LTQ_ETOP_CFG);
++              ltq_etop_w32_mask(ETOP_CFG_MASK, ETOP_CFG_OFF1 |
++                      ETOP_CFG_SEN0 | ETOP_CFG_FEN0, LTQ_ETOP_CFG);
+               break;
+       default:
++              if (of_machine_is_compatible("lantiq,ase")) {
++                      clk_enable(priv->clk_ephy);
++                      /* disable external MII */
++                      ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG);
++                      /* enable clock for internal PHY */
++                      clk_enable(priv->clk_ephycgu);
++                      /* we need to write this magic to the internal phy to
++                         make it work */
++                      ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
++                      pr_info("Selected EPHY mode\n");
++                      break;
++              }
+               netdev_err(dev, "unknown mii mode %d\n",
+-                      priv->pldata->mii_mode);
++                      mii_mode);
+               return -ENOTSUPP;
+       }
+-      /* enable crc generation */
+-      ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG);
++      return 0;
++}
++
++static int
++ltq_etop_dma_init(struct net_device *dev)
++{
++      struct ltq_etop_priv *priv = netdev_priv(dev);
++      int tx = priv->tx_irq - LTQ_DMA_ETOP;
++      int rx = priv->rx_irq - LTQ_DMA_ETOP;
++      int err;
+       ltq_dma_init_port(DMA_PORT_ETOP);
+-      for (i = 0; i < MAX_DMA_CHAN; i++) {
+-              int irq = LTQ_DMA_CH0_INT + i;
+-              struct ltq_etop_chan *ch = &priv->ch[i];
+-
+-              ch->idx = ch->dma.nr = i;
+-
+-              if (IS_TX(i)) {
+-                      ltq_dma_alloc_tx(&ch->dma);
+-                      request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv);
+-              } else if (IS_RX(i)) {
+-                      ltq_dma_alloc_rx(&ch->dma);
+-                      for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
+-                                      ch->dma.desc++)
+-                              if (ltq_etop_alloc_skb(ch))
+-                                      return -ENOMEM;
+-                      ch->dma.desc = 0;
+-                      request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv);
++      priv->txch.dma.nr = tx;
++      ltq_dma_alloc_tx(&priv->txch.dma);
++      err = request_irq(priv->tx_irq, ltq_etop_dma_irq, 0, "eth_tx", priv);
++      if (err) {
++              netdev_err(dev, "failed to allocate tx irq\n");
++              goto err_out;
++      }
++      priv->txch.dma.irq = priv->tx_irq;
++
++      priv->rxch.dma.nr = rx;
++      ltq_dma_alloc_rx(&priv->rxch.dma);
++      for (priv->rxch.dma.desc = 0; priv->rxch.dma.desc < LTQ_DESC_NUM;
++                      priv->rxch.dma.desc++) {
++              if (ltq_etop_alloc_skb(&priv->rxch)) {
++                      netdev_err(dev, "failed to allocate skbs\n");
++                      err = -ENOMEM;
++                      goto err_out;
+               }
+-              ch->dma.irq = irq;
+       }
+-      return 0;
++      priv->rxch.dma.desc = 0;
++      err = request_irq(priv->rx_irq, ltq_etop_dma_irq, 0, "eth_rx", priv);
++      if (err)
++              netdev_err(dev, "failed to allocate rx irq\n");
++      else
++              priv->rxch.dma.irq = priv->rx_irq;
++err_out:
++      return err;
+ }
+ static void
+@@ -309,7 +454,10 @@ ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      return phy_ethtool_gset(priv->phydev, cmd);
++      if (priv->phydev)
++              return phy_ethtool_gset(priv->phydev, cmd);
++      else
++              return 0;
+ }
+ static int
+@@ -317,7 +465,10 @@ ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      return phy_ethtool_sset(priv->phydev, cmd);
++      if (priv->phydev)
++              return phy_ethtool_sset(priv->phydev, cmd);
++      else
++              return 0;
+ }
+ static int
+@@ -325,7 +476,10 @@ ltq_etop_nway_reset(struct net_device *dev)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      return phy_start_aneg(priv->phydev);
++      if (priv->phydev)
++              return phy_start_aneg(priv->phydev);
++      else
++              return 0;
+ }
+ static const struct ethtool_ops ltq_etop_ethtool_ops = {
+@@ -336,6 +490,39 @@ static const struct ethtool_ops ltq_etop_ethtool_ops = {
+ };
+ static int
++ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr,
++              int phy_reg, u16 phy_data)
++{
++      u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE |
++              (phy_data << MDIO_XR9_WR_OFFSET) |
++              ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
++              ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
++
++      while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
++              ;
++      ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
++      while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
++              ;
++      return 0;
++}
++
++static int
++ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg)
++{
++      u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ |
++              ((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
++              ((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
++
++      while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
++              ;
++      ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
++      while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
++              ;
++      val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK;
++      return val;
++}
++
++static int
+ ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
+ {
+       u32 val = MDIO_REQUEST |
+@@ -343,9 +530,9 @@ ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
+               ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) |
+               phy_data;
+-      while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
++      while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST)
+               ;
+-      ltq_etop_w32(val, LTQ_ETOP_MDIO);
++      ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC);
+       return 0;
+ }
+@@ -356,12 +543,12 @@ ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg)
+               ((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+               ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET);
+-      while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
++      while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST)
+               ;
+-      ltq_etop_w32(val, LTQ_ETOP_MDIO);
+-      while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
++      ltq_etop_w32(val, LTQ_ETOP_MDIO_ACC);
++      while (ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_REQUEST)
+               ;
+-      val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK;
++      val = ltq_etop_r32(LTQ_ETOP_MDIO_ACC) & MDIO_VAL_MASK;
+       return val;
+ }
+@@ -376,14 +563,18 @@ ltq_etop_mdio_probe(struct net_device *dev)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       struct phy_device *phydev = NULL;
+-      int phy_addr;
+-
+-      for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+-              if (priv->mii_bus->phy_map[phy_addr]) {
+-                      phydev = priv->mii_bus->phy_map[phy_addr];
+-                      break;
+-              }
+-      }
++      u32 phy_supported =  (SUPPORTED_10baseT_Half
++                      | SUPPORTED_10baseT_Full
++                      | SUPPORTED_100baseT_Half
++                      | SUPPORTED_100baseT_Full
++                      | SUPPORTED_Autoneg
++                      | SUPPORTED_MII
++                      | SUPPORTED_TP);
++
++      if (of_machine_is_compatible("lantiq,ase"))
++              phydev = priv->mii_bus->phy_map[8];
++      else
++              phydev = priv->mii_bus->phy_map[0];
+       if (!phydev) {
+               netdev_err(dev, "no PHY found\n");
+@@ -391,21 +582,18 @@ ltq_etop_mdio_probe(struct net_device *dev)
+       }
+       phydev = phy_connect(dev, dev_name(&phydev->dev),
+-                           &ltq_etop_mdio_link, priv->pldata->mii_mode);
++                      &ltq_etop_mdio_link, priv->mii_mode);
+       if (IS_ERR(phydev)) {
+               netdev_err(dev, "Could not attach to PHY\n");
+               return PTR_ERR(phydev);
+       }
+-      phydev->supported &= (SUPPORTED_10baseT_Half
+-                            | SUPPORTED_10baseT_Full
+-                            | SUPPORTED_100baseT_Half
+-                            | SUPPORTED_100baseT_Full
+-                            | SUPPORTED_Autoneg
+-                            | SUPPORTED_MII
+-                            | SUPPORTED_TP);
++      if (of_machine_is_compatible("lantiq,ar9"))
++              phy_supported |= SUPPORTED_1000baseT_Half
++                      | SUPPORTED_1000baseT_Full;
++      phydev->supported &= phy_supported;
+       phydev->advertising = phydev->supported;
+       priv->phydev = phydev;
+       pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
+@@ -430,8 +618,13 @@ ltq_etop_mdio_init(struct net_device *dev)
+       }
+       priv->mii_bus->priv = dev;
+-      priv->mii_bus->read = ltq_etop_mdio_rd;
+-      priv->mii_bus->write = ltq_etop_mdio_wr;
++      if (of_machine_is_compatible("lantiq,ar9")) {
++              priv->mii_bus->read = ltq_etop_mdio_rd_xr9;
++              priv->mii_bus->write = ltq_etop_mdio_wr_xr9;
++      } else {
++              priv->mii_bus->read = ltq_etop_mdio_rd;
++              priv->mii_bus->write = ltq_etop_mdio_wr;
++      }
+       priv->mii_bus->name = "ltq_mii";
+       snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+               priv->pdev->name, priv->pdev->id);
+@@ -480,17 +673,19 @@ static int
+ ltq_etop_open(struct net_device *dev)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      int i;
++      unsigned long flags;
+-      for (i = 0; i < MAX_DMA_CHAN; i++) {
+-              struct ltq_etop_chan *ch = &priv->ch[i];
++      napi_enable(&priv->txch.napi);
++      napi_enable(&priv->rxch.napi);
++
++      spin_lock_irqsave(&priv->lock, flags);
++      ltq_dma_open(&priv->txch.dma);
++      ltq_dma_open(&priv->rxch.dma);
++      spin_unlock_irqrestore(&priv->lock, flags);
++
++      if (priv->phydev)
++              phy_start(priv->phydev);
+-              if (!IS_TX(i) && (!IS_RX(i)))
+-                      continue;
+-              ltq_dma_open(&ch->dma);
+-              napi_enable(&ch->napi);
+-      }
+-      phy_start(priv->phydev);
+       netif_tx_start_all_queues(dev);
+       return 0;
+ }
+@@ -499,18 +694,19 @@ static int
+ ltq_etop_stop(struct net_device *dev)
+ {
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      int i;
++      unsigned long flags;
+       netif_tx_stop_all_queues(dev);
+-      phy_stop(priv->phydev);
+-      for (i = 0; i < MAX_DMA_CHAN; i++) {
+-              struct ltq_etop_chan *ch = &priv->ch[i];
++      if (priv->phydev)
++              phy_stop(priv->phydev);
++      napi_disable(&priv->txch.napi);
++      napi_disable(&priv->rxch.napi);
++
++      spin_lock_irqsave(&priv->lock, flags);
++      ltq_dma_close(&priv->txch.dma);
++      ltq_dma_close(&priv->rxch.dma);
++      spin_unlock_irqrestore(&priv->lock, flags);
+-              if (!IS_RX(i) && !IS_TX(i))
+-                      continue;
+-              napi_disable(&ch->napi);
+-              ltq_dma_close(&ch->dma);
+-      }
+       return 0;
+ }
+@@ -520,16 +716,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+       int queue = skb_get_queue_mapping(skb);
+       struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+-      struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
+-      struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+-      int len;
++      struct ltq_dma_desc *desc =
++              &priv->txch.dma.desc_base[priv->txch.dma.desc];
+       unsigned long flags;
+       u32 byte_offset;
++      int len;
+       len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+-      if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
+-              dev_kfree_skb_any(skb);
++      if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) ||
++                      priv->txch.skb[priv->txch.dma.desc]) {
+               netdev_err(dev, "tx ring full\n");
+               netif_tx_stop_queue(txq);
+               return NETDEV_TX_BUSY;
+@@ -537,7 +733,7 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+       /* dma needs to start on a 16 byte aligned address */
+       byte_offset = CPHYSADDR(skb->data) % 16;
+-      ch->skb[ch->dma.desc] = skb;
++      priv->txch.skb[priv->txch.dma.desc] = skb;
+       dev->trans_start = jiffies;
+@@ -547,11 +743,11 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+       wmb();
+       desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
+               LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
+-      ch->dma.desc++;
+-      ch->dma.desc %= LTQ_DESC_NUM;
++      priv->txch.dma.desc++;
++      priv->txch.dma.desc %= LTQ_DESC_NUM;
+       spin_unlock_irqrestore(&priv->lock, flags);
+-      if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
++      if (priv->txch.dma.desc_base[priv->txch.dma.desc].ctl & LTQ_DMA_OWN)
+               netif_tx_stop_queue(txq);
+       return NETDEV_TX_OK;
+@@ -566,8 +762,10 @@ ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
+               struct ltq_etop_priv *priv = netdev_priv(dev);
+               unsigned long flags;
++              int max = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN;
++
+               spin_lock_irqsave(&priv->lock, flags);
+-              ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
++              ltq_etop_w32((ETOP_PLEN_UNDER << 16) | max,
+                       LTQ_ETOP_IGPLEN);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+@@ -631,34 +829,33 @@ ltq_etop_init(struct net_device *dev)
+       struct ltq_etop_priv *priv = netdev_priv(dev);
+       struct sockaddr mac;
+       int err;
+-      bool random_mac = false;
+       ether_setup(dev);
+       dev->watchdog_timeo = 10 * HZ;
+       err = ltq_etop_hw_init(dev);
+       if (err)
+               goto err_hw;
++      err = ltq_etop_dma_init(dev);
++      if (err)
++              goto err_hw;
++
+       ltq_etop_change_mtu(dev, 1500);
+-      memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
++      if (priv->mac)
++              memcpy(&mac.sa_data, priv->mac, ETH_ALEN);
+       if (!is_valid_ether_addr(mac.sa_data)) {
+               pr_warn("etop: invalid MAC, using random\n");
+-              eth_random_addr(mac.sa_data);
+-              random_mac = true;
++              random_ether_addr(mac.sa_data);
+       }
+       err = ltq_etop_set_mac_address(dev, &mac);
+       if (err)
+               goto err_netdev;
+-
+-      /* Set addr_assign_type here, ltq_etop_set_mac_address would reset it. */
+-      if (random_mac)
+-              dev->addr_assign_type = NET_ADDR_RANDOM;
+-
+       ltq_etop_set_multicast_list(dev);
+-      err = ltq_etop_mdio_init(dev);
+-      if (err)
+-              goto err_netdev;
++      if (!ltq_etop_mdio_init(dev))
++              dev->ethtool_ops = &ltq_etop_ethtool_ops;
++      else
++              pr_warn("etop: mdio probe failed\n");;
+       return 0;
+ err_netdev:
+@@ -678,6 +875,9 @@ ltq_etop_tx_timeout(struct net_device *dev)
+       err = ltq_etop_hw_init(dev);
+       if (err)
+               goto err_hw;
++      err = ltq_etop_dma_init(dev);
++      if (err)
++              goto err_hw;
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+       return;
+@@ -701,14 +901,18 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
+       .ndo_tx_timeout = ltq_etop_tx_timeout,
+ };
+-static int __init
+-ltq_etop_probe(struct platform_device *pdev)
++static int ltq_etop_probe(struct platform_device *pdev)
+ {
+       struct net_device *dev;
+       struct ltq_etop_priv *priv;
+-      struct resource *res;
++      struct resource *res, *gbit_res, irqres[2];
+       int err;
+-      int i;
++
++      err = of_irq_to_resource_table(pdev->dev.of_node, irqres, 2);
++      if (err != 2) {
++              dev_err(&pdev->dev, "failed to get etop irqs\n");
++              return -EINVAL;
++      }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+@@ -734,30 +938,58 @@ ltq_etop_probe(struct platform_device *pdev)
+               goto err_out;
+       }
+-      dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+-      if (!dev) {
+-              err = -ENOMEM;
+-              goto err_out;
++      if (of_machine_is_compatible("lantiq,ar9")) {
++              gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++              if (!gbit_res) {
++                      dev_err(&pdev->dev, "failed to get gbit resource\n");
++                      err = -ENOENT;
++                      goto err_out;
++              }
++              ltq_gbit_membase = devm_ioremap_nocache(&pdev->dev,
++                      gbit_res->start, resource_size(gbit_res));
++              if (!ltq_gbit_membase) {
++                      dev_err(&pdev->dev, "failed to remap gigabit switch %d\n",
++                              pdev->id);
++                      err = -ENOMEM;
++                      goto err_out;
++              }
+       }
++
++      dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+       strcpy(dev->name, "eth%d");
+       dev->netdev_ops = &ltq_eth_netdev_ops;
+-      dev->ethtool_ops = &ltq_etop_ethtool_ops;
+       priv = netdev_priv(dev);
+       priv->res = res;
+       priv->pdev = pdev;
+-      priv->pldata = dev_get_platdata(&pdev->dev);
+       priv->netdev = dev;
++      priv->tx_irq = irqres[0].start;
++      priv->rx_irq = irqres[1].start;
++      priv->mii_mode = of_get_phy_mode(pdev->dev.of_node);
++      of_get_mac_address_mtd(pdev->dev.of_node, priv->mac);
++
++      priv->clk_ppe = clk_get(&pdev->dev, NULL);
++      if (IS_ERR(priv->clk_ppe))
++              return PTR_ERR(priv->clk_ppe);
++      if (of_machine_is_compatible("lantiq,ar9")) {
++              priv->clk_switch = clk_get(&pdev->dev, "switch");
++              if (IS_ERR(priv->clk_switch))
++                      return PTR_ERR(priv->clk_switch);
++      }
++      if (of_machine_is_compatible("lantiq,ase")) {
++              priv->clk_ephy = clk_get(&pdev->dev, "ephy");
++              if (IS_ERR(priv->clk_ephy))
++                      return PTR_ERR(priv->clk_ephy);
++              priv->clk_ephycgu = clk_get(&pdev->dev, "ephycgu");
++              if (IS_ERR(priv->clk_ephycgu))
++                      return PTR_ERR(priv->clk_ephycgu);
++      }
++
+       spin_lock_init(&priv->lock);
+-      for (i = 0; i < MAX_DMA_CHAN; i++) {
+-              if (IS_TX(i))
+-                      netif_napi_add(dev, &priv->ch[i].napi,
+-                              ltq_etop_poll_tx, 8);
+-              else if (IS_RX(i))
+-                      netif_napi_add(dev, &priv->ch[i].napi,
+-                              ltq_etop_poll_rx, 32);
+-              priv->ch[i].netdev = dev;
+-      }
++      netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8);
++      netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32);
++      priv->txch.netdev = dev;
++      priv->rxch.netdev = dev;
+       err = register_netdev(dev);
+       if (err)
+@@ -786,32 +1018,23 @@ ltq_etop_remove(struct platform_device *pdev)
+       return 0;
+ }
++static const struct of_device_id ltq_etop_match[] = {
++      { .compatible = "lantiq,etop-xway" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, ltq_etop_match);
++
+ static struct platform_driver ltq_mii_driver = {
++      .probe = ltq_etop_probe,
+       .remove = ltq_etop_remove,
+       .driver = {
+               .name = "ltq_etop",
+               .owner = THIS_MODULE,
++              .of_match_table = ltq_etop_match,
+       },
+ };
+-int __init
+-init_ltq_etop(void)
+-{
+-      int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
+-
+-      if (ret)
+-              pr_err("ltq_etop: Error registering platform driver!");
+-      return ret;
+-}
+-
+-static void __exit
+-exit_ltq_etop(void)
+-{
+-      platform_driver_unregister(&ltq_mii_driver);
+-}
+-
+-module_init(init_ltq_etop);
+-module_exit(exit_ltq_etop);
++module_platform_driver(ltq_mii_driver);
+ MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+ MODULE_DESCRIPTION("Lantiq SoC ETOP");
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0028-SPI-MIPS-lantiq-adds-spi-xway.patch b/target/linux/lantiq/patches-3.14/0028-SPI-MIPS-lantiq-adds-spi-xway.patch
deleted file mode 100644 (file)
index 3c3703e..0000000
+++ /dev/null
@@ -1,1032 +0,0 @@
-From 855c99aff4c1fb440a679cc8481947daf95643b8 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Wed, 13 Mar 2013 09:29:37 +0100
-Subject: [PATCH 28/31] SPI: MIPS: lantiq: adds spi-xway
-
-This patch adds support for the SPI core found on several Lantiq SoCs.
-The Driver has been runtime tested in combination with m25p80 Flash Devices
-on Amazon_SE and VR9.
-
-Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/spi/Kconfig    |    8 +
- drivers/spi/Makefile   |    1 +
- drivers/spi/spi-xway.c |  977 ++++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 986 insertions(+)
- create mode 100644 drivers/spi/spi-xway.c
-
-diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
-index 581ee2a..b2cd93c 100644
---- a/drivers/spi/Kconfig
-+++ b/drivers/spi/Kconfig
-@@ -527,6 +527,14 @@ config SPI_NUC900
-       help
-         SPI driver for Nuvoton NUC900 series ARM SoCs
-+config SPI_XWAY
-+      tristate "Lantiq XWAY SPI controller"
-+      depends on LANTIQ && SOC_TYPE_XWAY
-+      select SPI_BITBANG
-+      help
-+        This driver supports the Lantiq SoC SPI controller in master
-+        mode.
-+
- #
- # Add new SPI master controllers in alphabetical order above this line
- #
-diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
-index 95af48d..82d3799 100644
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -79,3 +79,4 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH)               += spi-topcliff-pch.o
- obj-$(CONFIG_SPI_TXX9)                        += spi-txx9.o
- obj-$(CONFIG_SPI_XCOMM)               += spi-xcomm.o
- obj-$(CONFIG_SPI_XILINX)              += spi-xilinx.o
-+obj-$(CONFIG_SPI_XWAY)                        += spi-xway.o
-diff --git a/drivers/spi/spi-xway.c b/drivers/spi/spi-xway.c
-new file mode 100644
-index 0000000..61532e3
---- /dev/null
-+++ b/drivers/spi/spi-xway.c
-@@ -0,0 +1,977 @@
-+/*
-+ * Lantiq SoC SPI controller
-+ *
-+ * Copyright (C) 2011 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
-+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
-+ *
-+ * This program is free software; you can distribute it and/or modify it
-+ * under the terms of the GNU General Public License (Version 2) as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/workqueue.h>
-+#include <linux/platform_device.h>
-+#include <linux/io.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/completion.h>
-+#include <linux/spinlock.h>
-+#include <linux/err.h>
-+#include <linux/clk.h>
-+#include <linux/spi/spi.h>
-+#include <linux/spi/spi_bitbang.h>
-+#include <linux/of_irq.h>
-+
-+#include <lantiq_soc.h>
-+
-+#define LTQ_SPI_CLC           0x00    /* Clock control */
-+#define LTQ_SPI_PISEL         0x04    /* Port input select */
-+#define LTQ_SPI_ID            0x08    /* Identification */
-+#define LTQ_SPI_CON           0x10    /* Control */
-+#define LTQ_SPI_STAT          0x14    /* Status */
-+#define LTQ_SPI_WHBSTATE      0x18    /* Write HW modified state */
-+#define LTQ_SPI_TB            0x20    /* Transmit buffer */
-+#define LTQ_SPI_RB            0x24    /* Receive buffer */
-+#define LTQ_SPI_RXFCON                0x30    /* Receive FIFO control */
-+#define LTQ_SPI_TXFCON                0x34    /* Transmit FIFO control */
-+#define LTQ_SPI_FSTAT         0x38    /* FIFO status */
-+#define LTQ_SPI_BRT           0x40    /* Baudrate timer */
-+#define LTQ_SPI_BRSTAT                0x44    /* Baudrate timer status */
-+#define LTQ_SPI_SFCON         0x60    /* Serial frame control */
-+#define LTQ_SPI_SFSTAT                0x64    /* Serial frame status */
-+#define LTQ_SPI_GPOCON                0x70    /* General purpose output control */
-+#define LTQ_SPI_GPOSTAT               0x74    /* General purpose output status */
-+#define LTQ_SPI_FGPO          0x78    /* Forced general purpose output */
-+#define LTQ_SPI_RXREQ         0x80    /* Receive request */
-+#define LTQ_SPI_RXCNT         0x84    /* Receive count */
-+#define LTQ_SPI_DMACON                0xEC    /* DMA control */
-+#define LTQ_SPI_IRNEN         0xF4    /* Interrupt node enable */
-+#define LTQ_SPI_IRNICR                0xF8    /* Interrupt node interrupt capture */
-+#define LTQ_SPI_IRNCR         0xFC    /* Interrupt node control */
-+
-+#define LTQ_SPI_CLC_SMC_SHIFT 16      /* Clock divider for sleep mode */
-+#define LTQ_SPI_CLC_SMC_MASK  0xFF
-+#define LTQ_SPI_CLC_RMC_SHIFT 8       /* Clock divider for normal run mode */
-+#define LTQ_SPI_CLC_RMC_MASK  0xFF
-+#define LTQ_SPI_CLC_DISS      BIT(1)  /* Disable status bit */
-+#define LTQ_SPI_CLC_DISR      BIT(0)  /* Disable request bit */
-+
-+#define LTQ_SPI_ID_TXFS_SHIFT 24      /* Implemented TX FIFO size */
-+#define LTQ_SPI_ID_TXFS_MASK  0x3F
-+#define LTQ_SPI_ID_RXFS_SHIFT 16      /* Implemented RX FIFO size */
-+#define LTQ_SPI_ID_RXFS_MASK  0x3F
-+#define LTQ_SPI_ID_REV_MASK   0x1F    /* Hardware revision number */
-+#define LTQ_SPI_ID_CFG                BIT(5)  /* DMA interface support */
-+
-+#define LTQ_SPI_CON_BM_SHIFT  16      /* Data width selection */
-+#define LTQ_SPI_CON_BM_MASK   0x1F
-+#define LTQ_SPI_CON_EM                BIT(24) /* Echo mode */
-+#define LTQ_SPI_CON_IDLE      BIT(23) /* Idle bit value */
-+#define LTQ_SPI_CON_ENBV      BIT(22) /* Enable byte valid control */
-+#define LTQ_SPI_CON_RUEN      BIT(12) /* Receive underflow error enable */
-+#define LTQ_SPI_CON_TUEN      BIT(11) /* Transmit underflow error enable */
-+#define LTQ_SPI_CON_AEN               BIT(10) /* Abort error enable */
-+#define LTQ_SPI_CON_REN               BIT(9)  /* Receive overflow error enable */
-+#define LTQ_SPI_CON_TEN               BIT(8)  /* Transmit overflow error enable */
-+#define LTQ_SPI_CON_LB                BIT(7)  /* Loopback control */
-+#define LTQ_SPI_CON_PO                BIT(6)  /* Clock polarity control */
-+#define LTQ_SPI_CON_PH                BIT(5)  /* Clock phase control */
-+#define LTQ_SPI_CON_HB                BIT(4)  /* Heading control */
-+#define LTQ_SPI_CON_RXOFF     BIT(1)  /* Switch receiver off */
-+#define LTQ_SPI_CON_TXOFF     BIT(0)  /* Switch transmitter off */
-+
-+#define LTQ_SPI_STAT_RXBV_MASK        0x7
-+#define LTQ_SPI_STAT_RXBV_SHIFT       28
-+#define LTQ_SPI_STAT_BSY      BIT(13) /* Busy flag */
-+#define LTQ_SPI_STAT_RUE      BIT(12) /* Receive underflow error flag */
-+#define LTQ_SPI_STAT_TUE      BIT(11) /* Transmit underflow error flag */
-+#define LTQ_SPI_STAT_AE               BIT(10) /* Abort error flag */
-+#define LTQ_SPI_STAT_RE               BIT(9)  /* Receive error flag */
-+#define LTQ_SPI_STAT_TE               BIT(8)  /* Transmit error flag */
-+#define LTQ_SPI_STAT_MS               BIT(1)  /* Master/slave select bit */
-+#define LTQ_SPI_STAT_EN               BIT(0)  /* Enable bit */
-+
-+#define LTQ_SPI_WHBSTATE_SETTUE       BIT(15) /* Set transmit underflow error flag */
-+#define LTQ_SPI_WHBSTATE_SETAE        BIT(14) /* Set abort error flag */
-+#define LTQ_SPI_WHBSTATE_SETRE        BIT(13) /* Set receive error flag */
-+#define LTQ_SPI_WHBSTATE_SETTE        BIT(12) /* Set transmit error flag */
-+#define LTQ_SPI_WHBSTATE_CLRTUE       BIT(11) /* Clear transmit underflow error
-+                                              flag */
-+#define LTQ_SPI_WHBSTATE_CLRAE        BIT(10) /* Clear abort error flag */
-+#define LTQ_SPI_WHBSTATE_CLRRE        BIT(9)  /* Clear receive error flag */
-+#define LTQ_SPI_WHBSTATE_CLRTE        BIT(8)  /* Clear transmit error flag */
-+#define LTQ_SPI_WHBSTATE_SETME        BIT(7)  /* Set mode error flag */
-+#define LTQ_SPI_WHBSTATE_CLRME        BIT(6)  /* Clear mode error flag */
-+#define LTQ_SPI_WHBSTATE_SETRUE       BIT(5)  /* Set receive underflow error flag */
-+#define LTQ_SPI_WHBSTATE_CLRRUE       BIT(4)  /* Clear receive underflow error flag */
-+#define LTQ_SPI_WHBSTATE_SETMS        BIT(3)  /* Set master select bit */
-+#define LTQ_SPI_WHBSTATE_CLRMS        BIT(2)  /* Clear master select bit */
-+#define LTQ_SPI_WHBSTATE_SETEN        BIT(1)  /* Set enable bit (operational mode) */
-+#define LTQ_SPI_WHBSTATE_CLREN        BIT(0)  /* Clear enable bit (config mode */
-+#define LTQ_SPI_WHBSTATE_CLR_ERRORS   0x0F50
-+
-+#define LTQ_SPI_RXFCON_RXFITL_SHIFT   8 /* FIFO interrupt trigger level */
-+#define LTQ_SPI_RXFCON_RXFITL_MASK    0x3F
-+#define LTQ_SPI_RXFCON_RXFLU          BIT(1)  /* FIFO flush */
-+#define LTQ_SPI_RXFCON_RXFEN          BIT(0)  /* FIFO enable */
-+
-+#define LTQ_SPI_TXFCON_TXFITL_SHIFT   8 /* FIFO interrupt trigger level */
-+#define LTQ_SPI_TXFCON_TXFITL_MASK    0x3F
-+#define LTQ_SPI_TXFCON_TXFLU          BIT(1)  /* FIFO flush */
-+#define LTQ_SPI_TXFCON_TXFEN          BIT(0)  /* FIFO enable */
-+
-+#define LTQ_SPI_FSTAT_RXFFL_MASK      0x3f
-+#define LTQ_SPI_FSTAT_RXFFL_SHIFT     0
-+#define LTQ_SPI_FSTAT_TXFFL_MASK      0x3f
-+#define LTQ_SPI_FSTAT_TXFFL_SHIFT     8
-+
-+#define LTQ_SPI_GPOCON_ISCSBN_SHIFT   8
-+#define LTQ_SPI_GPOCON_INVOUTN_SHIFT  0
-+
-+#define LTQ_SPI_FGPO_SETOUTN_SHIFT    8
-+#define LTQ_SPI_FGPO_CLROUTN_SHIFT    0
-+
-+#define LTQ_SPI_RXREQ_RXCNT_MASK      0xFFFF  /* Receive count value */
-+#define LTQ_SPI_RXCNT_TODO_MASK               0xFFFF  /* Recevie to-do value */
-+
-+#define LTQ_SPI_IRNEN_F               BIT(3)  /* Frame end interrupt request */
-+#define LTQ_SPI_IRNEN_E               BIT(2)  /* Error end interrupt request */
-+#define LTQ_SPI_IRNEN_T               BIT(1)  /* Transmit end interrupt request */
-+#define LTQ_SPI_IRNEN_R               BIT(0)  /* Receive end interrupt request */
-+#define LTQ_SPI_IRNEN_ALL     0xF
-+
-+struct ltq_spi {
-+      struct spi_bitbang      bitbang;
-+      struct completion       done;
-+      spinlock_t              lock;
-+
-+      struct device           *dev;
-+      void __iomem            *base;
-+      struct clk              *fpiclk;
-+      struct clk              *spiclk;
-+
-+      int                     status;
-+      int                     irq[3];
-+
-+      const u8                *tx;
-+      u8                      *rx;
-+      u32                     tx_cnt;
-+      u32                     rx_cnt;
-+      u32                     len;
-+      struct spi_transfer     *curr_transfer;
-+
-+      u32 (*get_tx) (struct ltq_spi *);
-+
-+      u16                     txfs;
-+      u16                     rxfs;
-+      unsigned                dma_support:1;
-+      unsigned                cfg_mode:1;
-+};
-+
-+static inline struct ltq_spi *ltq_spi_to_hw(struct spi_device *spi)
-+{
-+      return spi_master_get_devdata(spi->master);
-+}
-+
-+static inline u32 ltq_spi_reg_read(struct ltq_spi *hw, u32 reg)
-+{
-+      return ioread32be(hw->base + reg);
-+}
-+
-+static inline void ltq_spi_reg_write(struct ltq_spi *hw, u32 val, u32 reg)
-+{
-+      iowrite32be(val, hw->base + reg);
-+}
-+
-+static inline void ltq_spi_reg_setbit(struct ltq_spi *hw, u32 bits, u32 reg)
-+{
-+      u32 val;
-+
-+      val = ltq_spi_reg_read(hw, reg);
-+      val |= bits;
-+      ltq_spi_reg_write(hw, val, reg);
-+}
-+
-+static inline void ltq_spi_reg_clearbit(struct ltq_spi *hw, u32 bits, u32 reg)
-+{
-+      u32 val;
-+
-+      val = ltq_spi_reg_read(hw, reg);
-+      val &= ~bits;
-+      ltq_spi_reg_write(hw, val, reg);
-+}
-+
-+static void ltq_spi_hw_enable(struct ltq_spi *hw)
-+{
-+      u32 clc;
-+
-+      /* Power-up module */
-+      clk_enable(hw->spiclk);
-+
-+      /*
-+       * Set clock divider for run mode to 1 to
-+       * run at same frequency as FPI bus
-+       */
-+      clc = (1 << LTQ_SPI_CLC_RMC_SHIFT);
-+      ltq_spi_reg_write(hw, clc, LTQ_SPI_CLC);
-+}
-+
-+static void ltq_spi_hw_disable(struct ltq_spi *hw)
-+{
-+      /* Set clock divider to 0 and set module disable bit */
-+      ltq_spi_reg_write(hw, LTQ_SPI_CLC_DISS, LTQ_SPI_CLC);
-+
-+      /* Power-down module */
-+      clk_disable(hw->spiclk);
-+}
-+
-+static void ltq_spi_reset_fifos(struct ltq_spi *hw)
-+{
-+      u32 val;
-+
-+      /*
-+       * Enable and flush FIFOs. Set interrupt trigger level to
-+       * half of FIFO count implemented in hardware.
-+       */
-+      if (hw->txfs > 1) {
-+              val = hw->txfs << (LTQ_SPI_TXFCON_TXFITL_SHIFT - 1);
-+              val |= LTQ_SPI_TXFCON_TXFEN | LTQ_SPI_TXFCON_TXFLU;
-+              ltq_spi_reg_write(hw, val, LTQ_SPI_TXFCON);
-+      }
-+
-+      if (hw->rxfs > 1) {
-+              val = hw->rxfs << (LTQ_SPI_RXFCON_RXFITL_SHIFT - 1);
-+              val |= LTQ_SPI_RXFCON_RXFEN | LTQ_SPI_RXFCON_RXFLU;
-+              ltq_spi_reg_write(hw, val, LTQ_SPI_RXFCON);
-+      }
-+}
-+
-+static inline int ltq_spi_wait_ready(struct ltq_spi *hw)
-+{
-+      u32 stat;
-+      unsigned long timeout;
-+
-+      timeout = jiffies + msecs_to_jiffies(200);
-+
-+      do {
-+              stat = ltq_spi_reg_read(hw, LTQ_SPI_STAT);
-+              if (!(stat & LTQ_SPI_STAT_BSY))
-+                      return 0;
-+
-+              cond_resched();
-+      } while (!time_after_eq(jiffies, timeout));
-+
-+      dev_err(hw->dev, "SPI wait ready timed out stat: %x\n", stat);
-+
-+      return -ETIMEDOUT;
-+}
-+
-+static void ltq_spi_config_mode_set(struct ltq_spi *hw)
-+{
-+      if (hw->cfg_mode)
-+              return;
-+
-+      /*
-+       * Putting the SPI module in config mode is only safe if no
-+       * transfer is in progress as indicated by busy flag STATE.BSY.
-+       */
-+      if (ltq_spi_wait_ready(hw)) {
-+              ltq_spi_reset_fifos(hw);
-+              hw->status = -ETIMEDOUT;
-+      }
-+      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_CLREN, LTQ_SPI_WHBSTATE);
-+
-+      hw->cfg_mode = 1;
-+}
-+
-+static void ltq_spi_run_mode_set(struct ltq_spi *hw)
-+{
-+      if (!hw->cfg_mode)
-+              return;
-+
-+      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_SETEN, LTQ_SPI_WHBSTATE);
-+
-+      hw->cfg_mode = 0;
-+}
-+
-+static u32 ltq_spi_tx_word_u8(struct ltq_spi *hw)
-+{
-+      const u8 *tx = hw->tx;
-+      u32 data = *tx++;
-+
-+      hw->tx_cnt++;
-+      hw->tx++;
-+
-+      return data;
-+}
-+
-+static u32 ltq_spi_tx_word_u16(struct ltq_spi *hw)
-+{
-+      const u16 *tx = (u16 *) hw->tx;
-+      u32 data = *tx++;
-+
-+      hw->tx_cnt += 2;
-+      hw->tx += 2;
-+
-+      return data;
-+}
-+
-+static u32 ltq_spi_tx_word_u32(struct ltq_spi *hw)
-+{
-+      const u32 *tx = (u32 *) hw->tx;
-+      u32 data = *tx++;
-+
-+      hw->tx_cnt += 4;
-+      hw->tx += 4;
-+
-+      return data;
-+}
-+
-+static void ltq_spi_bits_per_word_set(struct spi_device *spi)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 bm;
-+      u8 bits_per_word = spi->bits_per_word;
-+
-+      /*
-+       * Use either default value of SPI device or value
-+       * from current transfer.
-+       */
-+      if (hw->curr_transfer && hw->curr_transfer->bits_per_word)
-+              bits_per_word = hw->curr_transfer->bits_per_word;
-+
-+      if (bits_per_word <= 8)
-+              hw->get_tx = ltq_spi_tx_word_u8;
-+      else if (bits_per_word <= 16)
-+              hw->get_tx = ltq_spi_tx_word_u16;
-+      else if (bits_per_word <= 32)
-+              hw->get_tx = ltq_spi_tx_word_u32;
-+
-+      /* CON.BM value = bits_per_word - 1 */
-+      bm = (bits_per_word - 1) << LTQ_SPI_CON_BM_SHIFT;
-+
-+      ltq_spi_reg_clearbit(hw, LTQ_SPI_CON_BM_MASK <<
-+                           LTQ_SPI_CON_BM_SHIFT, LTQ_SPI_CON);
-+      ltq_spi_reg_setbit(hw, bm, LTQ_SPI_CON);
-+}
-+
-+static void ltq_spi_speed_set(struct spi_device *spi)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 br, max_speed_hz, spi_clk;
-+      u32 speed_hz = spi->max_speed_hz;
-+
-+      /*
-+       * Use either default value of SPI device or value
-+       * from current transfer.
-+       */
-+      if (hw->curr_transfer && hw->curr_transfer->speed_hz)
-+              speed_hz = hw->curr_transfer->speed_hz;
-+
-+      /*
-+       * SPI module clock is derived from FPI bus clock dependent on
-+       * divider value in CLC.RMS which is always set to 1.
-+       */
-+      spi_clk = clk_get_rate(hw->fpiclk);
-+
-+      /*
-+       * Maximum SPI clock frequency in master mode is half of
-+       * SPI module clock frequency. Maximum reload value of
-+       * baudrate generator BR is 2^16.
-+       */
-+      max_speed_hz = spi_clk / 2;
-+      if (speed_hz >= max_speed_hz)
-+              br = 0;
-+      else
-+              br = (max_speed_hz / speed_hz) - 1;
-+
-+      if (br > 0xFFFF)
-+              br = 0xFFFF;
-+
-+      ltq_spi_reg_write(hw, br, LTQ_SPI_BRT);
-+}
-+
-+static void ltq_spi_clockmode_set(struct spi_device *spi)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 con;
-+
-+      con = ltq_spi_reg_read(hw, LTQ_SPI_CON);
-+
-+      /*
-+       * SPI mode mapping in CON register:
-+       * Mode CPOL CPHA CON.PO CON.PH
-+       *  0    0    0      0      1
-+       *  1    0    1      0      0
-+       *  2    1    0      1      1
-+       *  3    1    1      1      0
-+       */
-+      if (spi->mode & SPI_CPHA)
-+              con &= ~LTQ_SPI_CON_PH;
-+      else
-+              con |= LTQ_SPI_CON_PH;
-+
-+      if (spi->mode & SPI_CPOL)
-+              con |= LTQ_SPI_CON_PO;
-+      else
-+              con &= ~LTQ_SPI_CON_PO;
-+
-+      /* Set heading control */
-+      if (spi->mode & SPI_LSB_FIRST)
-+              con &= ~LTQ_SPI_CON_HB;
-+      else
-+              con |= LTQ_SPI_CON_HB;
-+
-+      ltq_spi_reg_write(hw, con, LTQ_SPI_CON);
-+}
-+
-+static void ltq_spi_xmit_set(struct ltq_spi *hw, struct spi_transfer *t)
-+{
-+      u32 con;
-+
-+      con = ltq_spi_reg_read(hw, LTQ_SPI_CON);
-+
-+      if (t) {
-+              if (t->tx_buf && t->rx_buf) {
-+                      con &= ~(LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF);
-+              } else if (t->rx_buf) {
-+                      con &= ~LTQ_SPI_CON_RXOFF;
-+                      con |= LTQ_SPI_CON_TXOFF;
-+              } else if (t->tx_buf) {
-+                      con &= ~LTQ_SPI_CON_TXOFF;
-+                      con |= LTQ_SPI_CON_RXOFF;
-+              }
-+      } else
-+              con |= (LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF);
-+
-+      ltq_spi_reg_write(hw, con, LTQ_SPI_CON);
-+}
-+
-+static void ltq_spi_internal_cs_activate(struct spi_device *spi)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 fgpo;
-+
-+      fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_CLROUTN_SHIFT));
-+      ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
-+}
-+
-+static void ltq_spi_internal_cs_deactivate(struct spi_device *spi)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 fgpo;
-+
-+      fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_SETOUTN_SHIFT));
-+      ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
-+}
-+
-+static void ltq_spi_chipselect(struct spi_device *spi, int cs)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+
-+      switch (cs) {
-+      case BITBANG_CS_ACTIVE:
-+              ltq_spi_bits_per_word_set(spi);
-+              ltq_spi_speed_set(spi);
-+              ltq_spi_clockmode_set(spi);
-+              ltq_spi_run_mode_set(hw);
-+              ltq_spi_internal_cs_activate(spi);
-+              break;
-+
-+      case BITBANG_CS_INACTIVE:
-+              ltq_spi_internal_cs_deactivate(spi);
-+              ltq_spi_config_mode_set(hw);
-+              break;
-+      }
-+}
-+
-+static int ltq_spi_setup_transfer(struct spi_device *spi,
-+                                struct spi_transfer *t)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u8 bits_per_word = spi->bits_per_word;
-+
-+      hw->curr_transfer = t;
-+
-+      if (t && t->bits_per_word)
-+              bits_per_word = t->bits_per_word;
-+
-+      if (bits_per_word > 32)
-+              return -EINVAL;
-+
-+      ltq_spi_config_mode_set(hw);
-+
-+      return 0;
-+}
-+
-+static int ltq_spi_setup(struct spi_device *spi)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 gpocon, fgpo;
-+
-+      /* Set default word length to 8 if not set */
-+      if (!spi->bits_per_word)
-+              spi->bits_per_word = 8;
-+
-+      if (spi->bits_per_word > 32)
-+              return -EINVAL;
-+
-+      /*
-+       * Up to six GPIOs can be connected to the SPI module
-+       * via GPIO alternate function to control the chip select lines.
-+       */
-+      gpocon = (1 << (spi->chip_select +
-+                      LTQ_SPI_GPOCON_ISCSBN_SHIFT));
-+
-+      if (spi->mode & SPI_CS_HIGH)
-+              gpocon |= (1 << spi->chip_select);
-+
-+      fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_SETOUTN_SHIFT));
-+
-+      ltq_spi_reg_setbit(hw, gpocon, LTQ_SPI_GPOCON);
-+      ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
-+
-+      return 0;
-+}
-+
-+static void ltq_spi_cleanup(struct spi_device *spi)
-+{
-+
-+}
-+
-+static void ltq_spi_txfifo_write(struct ltq_spi *hw)
-+{
-+      u32 fstat, data;
-+      u16 fifo_space;
-+
-+      /* Determine how much FIFOs are free for TX data */
-+      fstat = ltq_spi_reg_read(hw, LTQ_SPI_FSTAT);
-+      fifo_space = hw->txfs - ((fstat >> LTQ_SPI_FSTAT_TXFFL_SHIFT) &
-+                                      LTQ_SPI_FSTAT_TXFFL_MASK);
-+
-+      if (!fifo_space)
-+              return;
-+
-+      while (hw->tx_cnt < hw->len && fifo_space) {
-+              data = hw->get_tx(hw);
-+              ltq_spi_reg_write(hw, data, LTQ_SPI_TB);
-+              fifo_space--;
-+      }
-+}
-+
-+static void ltq_spi_rxfifo_read(struct ltq_spi *hw)
-+{
-+      u32 fstat, data, *rx32;
-+      u16 fifo_fill;
-+      u8 rxbv, shift, *rx8;
-+
-+      /* Determine how much FIFOs are filled with RX data */
-+      fstat = ltq_spi_reg_read(hw, LTQ_SPI_FSTAT);
-+      fifo_fill = ((fstat >> LTQ_SPI_FSTAT_RXFFL_SHIFT)
-+                      & LTQ_SPI_FSTAT_RXFFL_MASK);
-+
-+      if (!fifo_fill)
-+              return;
-+
-+      /*
-+       * The 32 bit FIFO is always used completely independent from the
-+       * bits_per_word value. Thus four bytes have to be read at once
-+       * per FIFO.
-+       */
-+      rx32 = (u32 *) hw->rx;
-+      while (hw->len - hw->rx_cnt >= 4 && fifo_fill) {
-+              *rx32++ = ltq_spi_reg_read(hw, LTQ_SPI_RB);
-+              hw->rx_cnt += 4;
-+              hw->rx += 4;
-+              fifo_fill--;
-+      }
-+
-+      /*
-+       * If there are remaining bytes, read byte count from STAT.RXBV
-+       * register and read the data byte-wise.
-+       */
-+      while (fifo_fill && hw->rx_cnt < hw->len) {
-+              rxbv = (ltq_spi_reg_read(hw, LTQ_SPI_STAT) >>
-+                      LTQ_SPI_STAT_RXBV_SHIFT) & LTQ_SPI_STAT_RXBV_MASK;
-+              data = ltq_spi_reg_read(hw, LTQ_SPI_RB);
-+
-+              shift = (rxbv - 1) * 8;
-+              rx8 = hw->rx;
-+
-+              while (rxbv) {
-+                      *rx8++ = (data >> shift) & 0xFF;
-+                      rxbv--;
-+                      shift -= 8;
-+                      hw->rx_cnt++;
-+                      hw->rx++;
-+              }
-+
-+              fifo_fill--;
-+      }
-+}
-+
-+static void ltq_spi_rxreq_set(struct ltq_spi *hw)
-+{
-+      u32 rxreq, rxreq_max, rxtodo;
-+
-+      rxtodo = ltq_spi_reg_read(hw, LTQ_SPI_RXCNT) & LTQ_SPI_RXCNT_TODO_MASK;
-+
-+      /*
-+       * In RX-only mode the serial clock is activated only after writing
-+       * the expected amount of RX bytes into RXREQ register.
-+       * To avoid receive overflows at high clocks it is better to request
-+       * only the amount of bytes that fits into all FIFOs. This value
-+       * depends on the FIFO size implemented in hardware.
-+       */
-+      rxreq = hw->len - hw->rx_cnt;
-+      rxreq_max = hw->rxfs << 2;
-+      rxreq = min(rxreq_max, rxreq);
-+
-+      if (!rxtodo && rxreq)
-+              ltq_spi_reg_write(hw, rxreq, LTQ_SPI_RXREQ);
-+}
-+
-+static inline void ltq_spi_complete(struct ltq_spi *hw)
-+{
-+      complete(&hw->done);
-+}
-+
-+irqreturn_t ltq_spi_tx_irq(int irq, void *data)
-+{
-+      struct ltq_spi *hw = data;
-+      unsigned long flags;
-+      int completed = 0;
-+
-+      spin_lock_irqsave(&hw->lock, flags);
-+
-+      if (hw->tx_cnt < hw->len)
-+              ltq_spi_txfifo_write(hw);
-+
-+      if (hw->tx_cnt == hw->len)
-+              completed = 1;
-+
-+      spin_unlock_irqrestore(&hw->lock, flags);
-+
-+      if (completed)
-+              ltq_spi_complete(hw);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+irqreturn_t ltq_spi_rx_irq(int irq, void *data)
-+{
-+      struct ltq_spi *hw = data;
-+      unsigned long flags;
-+      int completed = 0;
-+
-+      spin_lock_irqsave(&hw->lock, flags);
-+
-+      if (hw->rx_cnt < hw->len) {
-+              ltq_spi_rxfifo_read(hw);
-+
-+              if (hw->tx && hw->tx_cnt < hw->len)
-+                      ltq_spi_txfifo_write(hw);
-+      }
-+
-+      if (hw->rx_cnt == hw->len)
-+              completed = 1;
-+      else if (!hw->tx)
-+              ltq_spi_rxreq_set(hw);
-+
-+      spin_unlock_irqrestore(&hw->lock, flags);
-+
-+      if (completed)
-+              ltq_spi_complete(hw);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+irqreturn_t ltq_spi_err_irq(int irq, void *data)
-+{
-+      struct ltq_spi *hw = data;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&hw->lock, flags);
-+
-+      /* Disable all interrupts */
-+      ltq_spi_reg_clearbit(hw, LTQ_SPI_IRNEN_ALL, LTQ_SPI_IRNEN);
-+
-+      /* Clear all error flags */
-+      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
-+
-+      /* Flush FIFOs */
-+      ltq_spi_reg_setbit(hw, LTQ_SPI_RXFCON_RXFLU, LTQ_SPI_RXFCON);
-+      ltq_spi_reg_setbit(hw, LTQ_SPI_TXFCON_TXFLU, LTQ_SPI_TXFCON);
-+
-+      hw->status = -EIO;
-+      spin_unlock_irqrestore(&hw->lock, flags);
-+
-+      ltq_spi_complete(hw);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int ltq_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
-+{
-+      struct ltq_spi *hw = ltq_spi_to_hw(spi);
-+      u32 irq_flags = 0;
-+
-+      hw->tx = t->tx_buf;
-+      hw->rx = t->rx_buf;
-+      hw->len = t->len;
-+      hw->tx_cnt = 0;
-+      hw->rx_cnt = 0;
-+      hw->status = 0;
-+      INIT_COMPLETION(hw->done);
-+
-+      ltq_spi_xmit_set(hw, t);
-+
-+      /* Enable error interrupts */
-+      ltq_spi_reg_setbit(hw, LTQ_SPI_IRNEN_E, LTQ_SPI_IRNEN);
-+
-+      if (hw->tx) {
-+              /* Initially fill TX FIFO with as much data as possible */
-+              ltq_spi_txfifo_write(hw);
-+              irq_flags |= LTQ_SPI_IRNEN_T;
-+
-+              /* Always enable RX interrupt in Full Duplex mode */
-+              if (hw->rx)
-+                      irq_flags |= LTQ_SPI_IRNEN_R;
-+      } else if (hw->rx) {
-+              /* Start RX clock */
-+              ltq_spi_rxreq_set(hw);
-+
-+              /* Enable RX interrupt to receive data from RX FIFOs */
-+              irq_flags |= LTQ_SPI_IRNEN_R;
-+      }
-+
-+      /* Enable TX or RX interrupts */
-+      ltq_spi_reg_setbit(hw, irq_flags, LTQ_SPI_IRNEN);
-+      wait_for_completion_interruptible(&hw->done);
-+
-+      /* Disable all interrupts */
-+      ltq_spi_reg_clearbit(hw, LTQ_SPI_IRNEN_ALL, LTQ_SPI_IRNEN);
-+
-+      /*
-+       * Return length of current transfer for bitbang utility code if
-+       * no errors occured during transmission.
-+       */
-+      if (!hw->status)
-+              hw->status = hw->len;
-+
-+      return hw->status;
-+}
-+
-+static const struct ltq_spi_irq_map {
-+      char *name;
-+      irq_handler_t handler;
-+} ltq_spi_irqs[] = {
-+      { "spi_rx", ltq_spi_rx_irq },
-+      { "spi_tx", ltq_spi_tx_irq },
-+      { "spi_err", ltq_spi_err_irq },
-+};
-+
-+static int ltq_spi_probe(struct platform_device *pdev)
-+{
-+      struct resource irqres[3];
-+      struct spi_master *master;
-+      struct resource *r;
-+      struct ltq_spi *hw;
-+      int ret, i;
-+      u32 data, id;
-+
-+      if (of_irq_to_resource_table(pdev->dev.of_node, irqres, 3) != 3) {
-+              dev_err(&pdev->dev, "IRQ settings missing in device tree\n");
-+              return -EINVAL;
-+      }
-+
-+      master = spi_alloc_master(&pdev->dev, sizeof(struct ltq_spi));
-+      if (!master) {
-+              dev_err(&pdev->dev, "spi_alloc_master\n");
-+              ret = -ENOMEM;
-+              goto err;
-+      }
-+
-+      hw = spi_master_get_devdata(master);
-+
-+      r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (r == NULL) {
-+              dev_err(&pdev->dev, "platform_get_resource\n");
-+              ret = -ENOENT;
-+              goto err_master;
-+      }
-+
-+      r = devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
-+                      pdev->name);
-+      if (!r) {
-+              dev_err(&pdev->dev, "failed to request memory region\n");
-+              ret = -ENXIO;
-+              goto err_master;
-+      }
-+
-+      hw->base = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r));
-+      if (!hw->base) {
-+              dev_err(&pdev->dev, "failed to remap memory region\n");
-+              ret = -ENXIO;
-+              goto err_master;
-+      }
-+
-+      memset(hw->irq, 0, sizeof(hw->irq));
-+      for (i = 0; i < ARRAY_SIZE(ltq_spi_irqs); i++) {
-+              hw->irq[i] = irqres[i].start;
-+              ret = request_irq(hw->irq[i], ltq_spi_irqs[i].handler,
-+                                0, ltq_spi_irqs[i].name, hw);
-+              if (ret) {
-+                      dev_err(&pdev->dev, "failed to request %s irq (%d)\n",
-+                                      ltq_spi_irqs[i].name, hw->irq[i]);
-+                      goto err_irq;
-+              }
-+      }
-+
-+      hw->fpiclk = clk_get_fpi();
-+      if (IS_ERR(hw->fpiclk)) {
-+              dev_err(&pdev->dev, "failed to get fpi clock\n");
-+              ret = PTR_ERR(hw->fpiclk);
-+              goto err_clk;
-+      }
-+
-+      hw->spiclk = clk_get(&pdev->dev, NULL);
-+      if (IS_ERR(hw->spiclk)) {
-+              dev_err(&pdev->dev, "failed to get spi clock gate\n");
-+              ret = PTR_ERR(hw->spiclk);
-+              goto err_clk;
-+      }
-+
-+      hw->bitbang.master = spi_master_get(master);
-+      hw->bitbang.chipselect = ltq_spi_chipselect;
-+      hw->bitbang.setup_transfer = ltq_spi_setup_transfer;
-+      hw->bitbang.txrx_bufs = ltq_spi_txrx_bufs;
-+
-+      if (of_machine_is_compatible("lantiq,ase"))
-+              master->num_chipselect = 3;
-+      else
-+              master->num_chipselect = 6;
-+      master->bus_num = pdev->id;
-+      master->setup = ltq_spi_setup;
-+      master->cleanup = ltq_spi_cleanup;
-+      master->dev.of_node = pdev->dev.of_node;
-+
-+      hw->dev = &pdev->dev;
-+      init_completion(&hw->done);
-+      spin_lock_init(&hw->lock);
-+
-+      ltq_spi_hw_enable(hw);
-+
-+      /* Read module capabilities */
-+      id = ltq_spi_reg_read(hw, LTQ_SPI_ID);
-+      hw->txfs = (id >> LTQ_SPI_ID_TXFS_SHIFT) & LTQ_SPI_ID_TXFS_MASK;
-+      hw->rxfs = (id >> LTQ_SPI_ID_TXFS_SHIFT) & LTQ_SPI_ID_TXFS_MASK;
-+      hw->dma_support = (id & LTQ_SPI_ID_CFG) ? 1 : 0;
-+
-+      ltq_spi_config_mode_set(hw);
-+
-+      /* Enable error checking, disable TX/RX, set idle value high */
-+      data = LTQ_SPI_CON_RUEN | LTQ_SPI_CON_AEN |
-+          LTQ_SPI_CON_TEN | LTQ_SPI_CON_REN |
-+          LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF | LTQ_SPI_CON_IDLE;
-+      ltq_spi_reg_write(hw, data, LTQ_SPI_CON);
-+
-+      /* Enable master mode and clear error flags */
-+      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_SETMS |
-+                        LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
-+
-+      /* Reset GPIO/CS registers */
-+      ltq_spi_reg_write(hw, 0x0, LTQ_SPI_GPOCON);
-+      ltq_spi_reg_write(hw, 0xFF00, LTQ_SPI_FGPO);
-+
-+      /* Enable and flush FIFOs */
-+      ltq_spi_reset_fifos(hw);
-+
-+      ret = spi_bitbang_start(&hw->bitbang);
-+      if (ret) {
-+              dev_err(&pdev->dev, "spi_bitbang_start failed\n");
-+              goto err_bitbang;
-+      }
-+
-+      platform_set_drvdata(pdev, hw);
-+
-+      pr_info("Lantiq SoC SPI controller rev %u (TXFS %u, RXFS %u, DMA %u)\n",
-+              id & LTQ_SPI_ID_REV_MASK, hw->txfs, hw->rxfs, hw->dma_support);
-+
-+      return 0;
-+
-+err_bitbang:
-+      ltq_spi_hw_disable(hw);
-+
-+err_clk:
-+      if (hw->fpiclk)
-+              clk_put(hw->fpiclk);
-+      if (hw->spiclk)
-+              clk_put(hw->spiclk);
-+
-+err_irq:
-+      clk_put(hw->fpiclk);
-+
-+      for (; i > 0; i--)
-+              free_irq(hw->irq[i], hw);
-+
-+err_master:
-+      spi_master_put(master);
-+
-+err:
-+      return ret;
-+}
-+
-+static int ltq_spi_remove(struct platform_device *pdev)
-+{
-+      struct ltq_spi *hw = platform_get_drvdata(pdev);
-+      int ret, i;
-+
-+      ret = spi_bitbang_stop(&hw->bitbang);
-+      if (ret)
-+              return ret;
-+
-+      platform_set_drvdata(pdev, NULL);
-+
-+      ltq_spi_config_mode_set(hw);
-+      ltq_spi_hw_disable(hw);
-+
-+      for (i = 0; i < ARRAY_SIZE(hw->irq); i++)
-+              if (0 < hw->irq[i])
-+                      free_irq(hw->irq[i], hw);
-+
-+      if (hw->fpiclk)
-+              clk_put(hw->fpiclk);
-+      if (hw->spiclk)
-+              clk_put(hw->spiclk);
-+
-+      spi_master_put(hw->bitbang.master);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id ltq_spi_match[] = {
-+      { .compatible = "lantiq,spi-xway" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, ltq_spi_match);
-+
-+static struct platform_driver ltq_spi_driver = {
-+      .probe = ltq_spi_probe,
-+      .remove = ltq_spi_remove,
-+      .driver = {
-+              .name = "spi-xway",
-+              .owner = THIS_MODULE,
-+              .of_match_table = ltq_spi_match,
-+      },
-+};
-+
-+module_platform_driver(ltq_spi_driver);
-+
-+MODULE_DESCRIPTION("Lantiq SoC SPI controller driver");
-+MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:spi-xway");
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0029-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch b/target/linux/lantiq/patches-3.14/0029-GPIO-MIPS-lantiq-add-gpio-driver-for-falcon-SoC.patch
new file mode 100644 (file)
index 0000000..a9be6fc
--- /dev/null
@@ -0,0 +1,404 @@
+From 7e178ce2e5f3aef38d4bdd2c0e02eae6100d5af4 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 7 Aug 2014 18:22:19 +0200
+Subject: [PATCH 29/36] GPIO: MIPS: lantiq: add gpio driver for falcon SoC
+
+Add driver for GPIO blocks found on Lantiq FALCON SoC. The SoC has 5 banks of
+up to 32 pads. The GPIO blocks have a per pin IRQs.
+
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Acked-by: John Crispin <blogic@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: linux-gpio@vger.kernel.org
+---
+ drivers/gpio/Kconfig       |    5 +
+ drivers/gpio/Makefile      |    1 +
+ drivers/gpio/gpio-falcon.c |  348 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 354 insertions(+)
+ create mode 100644 drivers/gpio/gpio-falcon.c
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 903f24d..670c064 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -145,6 +145,11 @@ config GPIO_EP93XX
+       depends on ARCH_EP93XX
+       select GPIO_GENERIC
++config GPIO_FALCON
++      def_bool y
++      depends on MIPS && SOC_FALCON
++      select GPIO_GENERIC
++
+ config GPIO_MM_LANTIQ
+       bool "Lantiq Memory mapped GPIOs"
+       depends on LANTIQ && SOC_XWAY
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index 5d50179..c92db39 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_DAVINCI)   += gpio-davinci.o
+ obj-$(CONFIG_GPIO_EM)         += gpio-em.o
+ obj-$(CONFIG_GPIO_EP93XX)     += gpio-ep93xx.o
+ obj-$(CONFIG_GPIO_F7188X)     += gpio-f7188x.o
++obj-$(CONFIG_GPIO_FALCON)     += gpio-falcon.o
+ obj-$(CONFIG_GPIO_GE_FPGA)    += gpio-ge.o
+ obj-$(CONFIG_GPIO_GRGPIO)     += gpio-grgpio.o
+ obj-$(CONFIG_GPIO_ICH)                += gpio-ich.o
+diff --git a/drivers/gpio/gpio-falcon.c b/drivers/gpio/gpio-falcon.c
+new file mode 100644
+index 0000000..ae3bdfb
+--- /dev/null
++++ b/drivers/gpio/gpio-falcon.c
+@@ -0,0 +1,348 @@
++/*
++ *  This program is free software; you can redistribute it and/or modify it
++ *  under the terms of the GNU General Public License version 2 as published
++ *  by the Free Software Foundation.
++ *
++ *  Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
++ *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/gpio.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/export.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++
++#include <lantiq_soc.h>
++
++/* Data Output Register */
++#define GPIO_OUT            0x00000000
++/* Data Input Register */
++#define GPIO_IN             0x00000004
++/* Direction Register */
++#define GPIO_DIR            0x00000008
++/* External Interrupt Control Register 0 */
++#define GPIO_EXINTCR0       0x00000018
++/* External Interrupt Control Register 1 */
++#define GPIO_EXINTCR1       0x0000001C
++/* IRN Capture Register */
++#define GPIO_IRNCR          0x00000020
++/* IRN Interrupt Configuration Register */
++#define GPIO_IRNCFG           0x0000002C
++/* IRN Interrupt Enable Set Register */
++#define GPIO_IRNRNSET       0x00000030
++/* IRN Interrupt Enable Clear Register */
++#define GPIO_IRNENCLR       0x00000034
++/* Output Set Register */
++#define GPIO_OUTSET         0x00000040
++/* Output Cler Register */
++#define GPIO_OUTCLR         0x00000044
++/* Direction Clear Register */
++#define GPIO_DIRSET         0x00000048
++/* Direction Set Register */
++#define GPIO_DIRCLR         0x0000004C
++
++/* turn a gpio_chip into a falcon_gpio_port */
++#define ctop(c)               container_of(c, struct falcon_gpio_port, gpio_chip)
++/* turn a irq_data into a falcon_gpio_port */
++#define itop(i)               ((struct falcon_gpio_port *) irq_get_chip_data(i->irq))
++
++#define port_r32(p, reg)      ltq_r32(p->port + reg)
++#define port_w32(p, val, reg) ltq_w32(val, p->port + reg)
++#define port_w32_mask(p, clear, set, reg) \
++              port_w32(p, (port_r32(p, reg) & ~(clear)) | (set), reg)
++
++#define MAX_BANKS             5
++#define PINS_PER_PORT         32
++
++struct falcon_gpio_port {
++      struct gpio_chip gpio_chip;
++      void __iomem *port;
++      unsigned int irq_base;
++      unsigned int chained_irq;
++      struct clk *clk;
++      char name[6];
++};
++
++static struct irq_chip falcon_gpio_irq_chip;
++
++static int falcon_gpio_direction_input(struct gpio_chip *chip,
++                                      unsigned int offset)
++{
++      port_w32(ctop(chip), 1 << offset, GPIO_DIRCLR);
++
++      return 0;
++}
++
++static void falcon_gpio_set(struct gpio_chip *chip, unsigned int offset,
++                                      int value)
++{
++      if (value)
++              port_w32(ctop(chip), 1 << offset, GPIO_OUTSET);
++      else
++              port_w32(ctop(chip), 1 << offset, GPIO_OUTCLR);
++}
++
++static int falcon_gpio_direction_output(struct gpio_chip *chip,
++                                      unsigned int offset, int value)
++{
++      falcon_gpio_set(chip, offset, value);
++      port_w32(ctop(chip), 1 << offset, GPIO_DIRSET);
++
++      return 0;
++}
++
++static int falcon_gpio_get(struct gpio_chip *chip, unsigned int offset)
++{
++      if ((port_r32(ctop(chip), GPIO_DIR) >> offset) & 1)
++              return (port_r32(ctop(chip), GPIO_OUT) >> offset) & 1;
++      else
++              return (port_r32(ctop(chip), GPIO_IN) >> offset) & 1;
++}
++
++static int falcon_gpio_request(struct gpio_chip *chip, unsigned offset)
++{
++      int gpio = chip->base + offset;
++
++      return pinctrl_request_gpio(gpio);
++}
++
++static void falcon_gpio_free(struct gpio_chip *chip, unsigned offset)
++{
++      int gpio = chip->base + offset;
++
++      pinctrl_free_gpio(gpio);
++}
++
++static int falcon_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
++{
++      return ctop(chip)->irq_base + offset;
++}
++
++static void falcon_gpio_disable_irq(struct irq_data *d)
++{
++      unsigned int offset = d->irq - itop(d)->irq_base;
++
++      port_w32(itop(d), 1 << offset, GPIO_IRNENCLR);
++}
++
++static void falcon_gpio_enable_irq(struct irq_data *d)
++{
++      unsigned int offset = d->irq - itop(d)->irq_base;
++
++      port_w32(itop(d), 1 << offset, GPIO_IRNRNSET);
++}
++
++static void falcon_gpio_ack_irq(struct irq_data *d)
++{
++      unsigned int offset = d->irq - itop(d)->irq_base;
++
++      port_w32(itop(d), 1 << offset, GPIO_IRNCR);
++}
++
++static void falcon_gpio_mask_and_ack_irq(struct irq_data *d)
++{
++      unsigned int offset = d->irq - itop(d)->irq_base;
++
++      port_w32(itop(d), 1 << offset, GPIO_IRNENCLR);
++      port_w32(itop(d), 1 << offset, GPIO_IRNCR);
++}
++
++static int falcon_gpio_irq_type(struct irq_data *d, unsigned int type)
++{
++      unsigned int offset = d->irq - itop(d)->irq_base;
++      unsigned int mask = 1 << offset;
++
++      if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE)
++              return 0;
++
++      if ((type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) != 0) {
++              /* level triggered */
++              port_w32_mask(itop(d), 0, mask, GPIO_IRNCFG);
++              irq_set_chip_and_handler_name(d->irq,
++                      &falcon_gpio_irq_chip, handle_level_irq, "mux");
++      } else {
++              /* edge triggered */
++              port_w32_mask(itop(d), mask, 0, GPIO_IRNCFG);
++              irq_set_chip_and_handler_name(d->irq,
++                      &falcon_gpio_irq_chip, handle_simple_irq, "mux");
++      }
++
++      if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
++              port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR0);
++              port_w32_mask(itop(d), 0, mask, GPIO_EXINTCR1);
++      } else {
++              if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) != 0)
++                      /* positive logic: rising edge, high level */
++                      port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR0);
++              else
++                      /* negative logic: falling edge, low level */
++                      port_w32_mask(itop(d), 0, mask, GPIO_EXINTCR0);
++              port_w32_mask(itop(d), mask, 0, GPIO_EXINTCR1);
++      }
++
++      return gpio_direction_input(itop(d)->gpio_chip.base + offset);
++}
++
++static void falcon_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
++{
++      struct falcon_gpio_port *gpio_port = irq_desc_get_handler_data(desc);
++      unsigned long irncr;
++      int offset;
++
++      /* acknowledge interrupt */
++      irncr = port_r32(gpio_port, GPIO_IRNCR);
++      port_w32(gpio_port, irncr, GPIO_IRNCR);
++
++      desc->irq_data.chip->irq_ack(&desc->irq_data);
++
++      for_each_set_bit(offset, &irncr, gpio_port->gpio_chip.ngpio)
++              generic_handle_irq(gpio_port->irq_base + offset);
++}
++
++static int falcon_gpio_irq_map(struct irq_domain *d, unsigned int irq,
++                              irq_hw_number_t hw)
++{
++      struct falcon_gpio_port *port = d->host_data;
++
++      irq_set_chip_and_handler_name(irq, &falcon_gpio_irq_chip,
++                      handle_simple_irq, "mux");
++      irq_set_chip_data(irq, port);
++
++      /* set to negative logic (falling edge, low level) */
++      port_w32_mask(port, 0, 1 << hw, GPIO_EXINTCR0);
++      return 0;
++}
++
++static struct irq_chip falcon_gpio_irq_chip = {
++      .name = "gpio_irq_mux",
++      .irq_mask = falcon_gpio_disable_irq,
++      .irq_unmask = falcon_gpio_enable_irq,
++      .irq_ack = falcon_gpio_ack_irq,
++      .irq_mask_ack = falcon_gpio_mask_and_ack_irq,
++      .irq_set_type = falcon_gpio_irq_type,
++};
++
++static const struct irq_domain_ops irq_domain_ops = {
++      .xlate = irq_domain_xlate_onetwocell,
++      .map = falcon_gpio_irq_map,
++};
++
++static struct irqaction gpio_cascade = {
++      .handler = no_action,
++      .flags = IRQF_DISABLED,
++      .name = "gpio_cascade",
++};
++
++static int falcon_gpio_probe(struct platform_device *pdev)
++{
++      struct pinctrl_gpio_range *gpio_range;
++      struct device_node *node = pdev->dev.of_node;
++      const __be32 *bank = of_get_property(node, "lantiq,bank", NULL);
++      struct falcon_gpio_port *gpio_port;
++      struct resource *gpiores, irqres;
++      int ret, size;
++
++      if (!bank || *bank >= MAX_BANKS)
++              return -ENODEV;
++
++      size = pinctrl_falcon_get_range_size(*bank);
++      if (size < 1) {
++              dev_err(&pdev->dev, "pad not loaded for bank %d\n", *bank);
++              return size;
++      }
++
++      gpio_range = devm_kzalloc(&pdev->dev, sizeof(struct pinctrl_gpio_range),
++                              GFP_KERNEL);
++      if (!gpio_range)
++              return -ENOMEM;
++
++      gpio_port = devm_kzalloc(&pdev->dev, sizeof(struct falcon_gpio_port),
++                              GFP_KERNEL);
++      if (!gpio_port)
++              return -ENOMEM;
++
++      snprintf(gpio_port->name, 6, "gpio%d", *bank);
++      gpio_port->gpio_chip.label = gpio_port->name;
++      gpio_port->gpio_chip.direction_input = falcon_gpio_direction_input;
++      gpio_port->gpio_chip.direction_output = falcon_gpio_direction_output;
++      gpio_port->gpio_chip.get = falcon_gpio_get;
++      gpio_port->gpio_chip.set = falcon_gpio_set;
++      gpio_port->gpio_chip.request = falcon_gpio_request;
++      gpio_port->gpio_chip.free = falcon_gpio_free;
++      gpio_port->gpio_chip.base = *bank * PINS_PER_PORT;
++      gpio_port->gpio_chip.ngpio = size;
++      gpio_port->gpio_chip.dev = &pdev->dev;
++
++      gpiores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      gpio_port->port = devm_request_and_ioremap(&pdev->dev, gpiores);
++      if (IS_ERR(gpio_port->port))
++              return PTR_ERR(gpio_port->port);
++
++      gpio_port->clk = devm_clk_get(&pdev->dev, NULL);
++      if (IS_ERR(gpio_port->clk))
++              return PTR_ERR(gpio_port->clk);
++      clk_activate(gpio_port->clk);
++
++      if (of_irq_to_resource_table(node, &irqres, 1) == 1) {
++              gpio_port->irq_base = INT_NUM_EXTRA_START + (32 * *bank);
++              gpio_port->gpio_chip.to_irq = falcon_gpio_to_irq;
++              gpio_port->chained_irq = irqres.start;
++              irq_domain_add_legacy(node, size, gpio_port->irq_base, 0,
++                                      &irq_domain_ops, gpio_port);
++              setup_irq(irqres.start, &gpio_cascade);
++              irq_set_handler_data(irqres.start, gpio_port);
++              irq_set_chained_handler(irqres.start, falcon_gpio_irq_handler);
++      }
++
++      ret = gpiochip_add(&gpio_port->gpio_chip);
++      if (ret)
++              return ret;
++
++      platform_set_drvdata(pdev, gpio_port);
++
++      gpio_range->name = "FALCON GPIO";
++      gpio_range->id = *bank;
++      gpio_range->base = gpio_port->gpio_chip.base;
++      gpio_range->pin_base = gpio_port->gpio_chip.base;
++      gpio_range->npins = gpio_port->gpio_chip.ngpio;
++      gpio_range->gc = &gpio_port->gpio_chip;
++
++      pinctrl_falcon_add_gpio_range(gpio_range);
++
++      return 0;
++}
++
++static const struct of_device_id falcon_gpio_match[] = {
++      { .compatible = "lantiq,falcon-gpio" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, falcon_gpio_match);
++
++static struct platform_driver falcon_gpio_driver = {
++      .probe = falcon_gpio_probe,
++      .driver = {
++              .name = "gpio-falcon",
++              .owner = THIS_MODULE,
++              .of_match_table = falcon_gpio_match,
++      },
++};
++
++int __init falcon_gpio_init(void)
++{
++      int ret;
++
++      pr_info("FALC(tm) ON GPIO Driver, (C) 2012 Lantiq Deutschland Gmbh\n");
++      ret = platform_driver_register(&falcon_gpio_driver);
++      if (ret)
++              pr_err("falcon_gpio: Error registering platform driver!");
++      return ret;
++}
++
++subsys_initcall(falcon_gpio_init);
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0029-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch b/target/linux/lantiq/patches-3.14/0029-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch
deleted file mode 100644 (file)
index ca9dd5a..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-From 748c654a6ba890e9a1b5bd29d0f198ce6b2c091f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 9 Aug 2013 18:47:27 +0200
-Subject: [PATCH 29/31] 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(+)
-
-diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
-index 41a4695..f38f530 100644
---- a/include/linux/reset-controller.h
-+++ b/include/linux/reset-controller.h
-@@ -46,7 +46,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
-diff --git a/include/linux/reset.h b/include/linux/reset.h
-index 6082247..1b36c9e 100644
---- 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_get(struct device *dev, const char *id)
- 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
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0030-GPIO-add-named-gpio-exports.patch b/target/linux/lantiq/patches-3.14/0030-GPIO-add-named-gpio-exports.patch
new file mode 100644 (file)
index 0000000..0a10642
--- /dev/null
@@ -0,0 +1,177 @@
+From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 12 Aug 2014 20:49:27 +0200
+Subject: [PATCH 30/36] GPIO: add named gpio exports
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++
+ drivers/gpio/gpiolib.c        |   11 +++++--
+ include/asm-generic/gpio.h    |    5 +++
+ include/linux/gpio/consumer.h |    8 +++++
+ 4 files changed, 90 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
+index e0a98f5..f16f271 100644
+--- a/drivers/gpio/gpiolib-of.c
++++ b/drivers/gpio/gpiolib-of.c
+@@ -21,6 +21,8 @@
+ #include <linux/of_gpio.h>
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
+ struct gpio_desc;
+@@ -296,3 +298,69 @@ void of_gpiochip_remove(struct gpio_chip *chip)
+       if (chip->of_node)
+               of_node_put(chip->of_node);
+ }
++
++static struct of_device_id gpio_export_ids[] = {
++      { .compatible = "gpio-export" },
++      { /* sentinel */ }
++};
++
++static int __init of_gpio_export_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      struct device_node *cnp;
++      u32 val;
++      int nb = 0;
++
++      for_each_child_of_node(np, cnp) {
++              const char *name = NULL;
++              int gpio;
++              bool dmc;
++              int max_gpio = 1;
++              int i;
++
++              of_property_read_string(cnp, "gpio-export,name", &name);
++
++              if (!name)
++                      max_gpio = of_gpio_count(cnp);
++
++              for (i = 0; i < max_gpio; i++) {
++                      unsigned flags = 0;
++                      enum of_gpio_flags of_flags;
++
++                      gpio = of_get_gpio_flags(cnp, i, &of_flags);
++
++                      if (of_flags == OF_GPIO_ACTIVE_LOW)
++                              flags |= GPIOF_ACTIVE_LOW;
++
++                      if (!of_property_read_u32(cnp, "gpio-export,output", &val))
++                              flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
++                      else
++                              flags |= GPIOF_IN;
++
++                      if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
++                              continue;
++
++                      dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
++                      gpio_export_with_name(gpio, dmc, name);
++                      nb++;
++              }
++      }
++
++      dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
++
++      return 0;
++}
++
++static struct platform_driver gpio_export_driver = {
++      .driver         = {
++              .name           = "gpio-export",
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(gpio_export_ids),
++      },
++};
++
++static int __init of_gpio_export_init(void)
++{
++      return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe);
++}
++device_initcall(of_gpio_export_init);
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 50c4922..aece9f1 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -803,7 +803,7 @@ static struct class gpio_class = {
+  *
+  * Returns zero on success, else an error.
+  */
+-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
+ {
+       unsigned long           flags;
+       int                     status;
+@@ -843,7 +843,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+       offset = gpio_chip_hwgpio(desc);
+       if (desc->chip->names && desc->chip->names[offset])
+               ioname = desc->chip->names[offset];
+-
++      if (name)
++              ioname = name;
+       dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+                           desc, ioname ? ioname : "gpio%u",
+                           desc_to_gpio(desc));
+@@ -880,6 +881,12 @@ fail_unlock:
+       gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+       return status;
+ }
++EXPORT_SYMBOL_GPL(_gpiod_export);
++
++int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
++{
++      return _gpiod_export(desc, direction_may_change, NULL);
++}
+ EXPORT_SYMBOL_GPL(gpiod_export);
+ static int match_export(struct device *dev, const void *data)
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index a5f56a0..70a32ee 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -126,6 +126,11 @@ static inline int gpio_export(unsigned gpio, bool direction_may_change)
+       return gpiod_export(gpio_to_desc(gpio), direction_may_change);
+ }
++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
++{
++      return _gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
++}
++
+ static inline int gpio_export_link(struct device *dev, const char *name,
+                                  unsigned gpio)
+ {
+diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
+index 7a8144f..085c31c 100644
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -219,6 +219,7 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
+ #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
+ int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
+ int gpiod_export_link(struct device *dev, const char *name,
+                     struct gpio_desc *desc);
+@@ -227,6 +228,13 @@ void gpiod_unexport(struct gpio_desc *desc);
+ #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
++static inline int _gpiod_export(struct gpio_desc *desc,
++                             bool direction_may_change,
++                             const char *name)
++{
++      return -ENOSYS;
++}
++
+ static inline int gpiod_export(struct gpio_desc *desc,
+                              bool direction_may_change)
+ {
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0030-MIPS-lantiq-command-line-work-around.patch b/target/linux/lantiq/patches-3.14/0030-MIPS-lantiq-command-line-work-around.patch
deleted file mode 100644 (file)
index 77aee7e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 015e22a637fe6ab9f9d2d94d3be1b0b312d21b39 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 12 Aug 2014 21:40:41 +0200
-Subject: [PATCH 30/31] MIPS: lantiq: command line work around
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- arch/mips/lantiq/prom.c |    2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
-index 202e118..227feed 100644
---- a/arch/mips/lantiq/prom.c
-+++ b/arch/mips/lantiq/prom.c
-@@ -74,6 +74,8 @@ void __init plat_mem_setup(void)
-        * parsed resulting in our memory appearing
-        */
-       __dt_setup_arch(&__image_dtb);
-+
-+      strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
- }
- void __init device_tree_init(void)
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0031-GPIO-add-named-gpio-exports.patch b/target/linux/lantiq/patches-3.14/0031-GPIO-add-named-gpio-exports.patch
deleted file mode 100644 (file)
index 412a32a..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-From 6774a8fcd63da9511faa7501ee20c4dde289bb07 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Tue, 12 Aug 2014 20:49:27 +0200
-Subject: [PATCH 31/31] GPIO: add named gpio exports
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++
- drivers/gpio/gpiolib.c        |   11 +++++--
- include/asm-generic/gpio.h    |    5 +++
- include/linux/gpio/consumer.h |    8 +++++
- 4 files changed, 90 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
-index e0a98f5..f16f271 100644
---- a/drivers/gpio/gpiolib-of.c
-+++ b/drivers/gpio/gpiolib-of.c
-@@ -21,6 +21,8 @@
- #include <linux/of_gpio.h>
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/platform_device.h>
- struct gpio_desc;
-@@ -296,3 +298,69 @@ void of_gpiochip_remove(struct gpio_chip *chip)
-       if (chip->of_node)
-               of_node_put(chip->of_node);
- }
-+
-+static struct of_device_id gpio_export_ids[] = {
-+      { .compatible = "gpio-export" },
-+      { /* sentinel */ }
-+};
-+
-+static int __init of_gpio_export_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node;
-+      struct device_node *cnp;
-+      u32 val;
-+      int nb = 0;
-+
-+      for_each_child_of_node(np, cnp) {
-+              const char *name = NULL;
-+              int gpio;
-+              bool dmc;
-+              int max_gpio = 1;
-+              int i;
-+
-+              of_property_read_string(cnp, "gpio-export,name", &name);
-+
-+              if (!name)
-+                      max_gpio = of_gpio_count(cnp);
-+
-+              for (i = 0; i < max_gpio; i++) {
-+                      unsigned flags = 0;
-+                      enum of_gpio_flags of_flags;
-+
-+                      gpio = of_get_gpio_flags(cnp, i, &of_flags);
-+
-+                      if (of_flags == OF_GPIO_ACTIVE_LOW)
-+                              flags |= GPIOF_ACTIVE_LOW;
-+
-+                      if (!of_property_read_u32(cnp, "gpio-export,output", &val))
-+                              flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-+                      else
-+                              flags |= GPIOF_IN;
-+
-+                      if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
-+                              continue;
-+
-+                      dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
-+                      gpio_export_with_name(gpio, dmc, name);
-+                      nb++;
-+              }
-+      }
-+
-+      dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
-+
-+      return 0;
-+}
-+
-+static struct platform_driver gpio_export_driver = {
-+      .driver         = {
-+              .name           = "gpio-export",
-+              .owner  = THIS_MODULE,
-+              .of_match_table = of_match_ptr(gpio_export_ids),
-+      },
-+};
-+
-+static int __init of_gpio_export_init(void)
-+{
-+      return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe);
-+}
-+device_initcall(of_gpio_export_init);
-diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index 50c4922..aece9f1 100644
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -803,7 +803,7 @@ static struct class gpio_class = {
-  *
-  * Returns zero on success, else an error.
-  */
--int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
-+int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
- {
-       unsigned long           flags;
-       int                     status;
-@@ -843,7 +843,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
-       offset = gpio_chip_hwgpio(desc);
-       if (desc->chip->names && desc->chip->names[offset])
-               ioname = desc->chip->names[offset];
--
-+      if (name)
-+              ioname = name;
-       dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
-                           desc, ioname ? ioname : "gpio%u",
-                           desc_to_gpio(desc));
-@@ -880,6 +881,12 @@ fail_unlock:
-       gpiod_dbg(desc, "%s: status %d\n", __func__, status);
-       return status;
- }
-+EXPORT_SYMBOL_GPL(_gpiod_export);
-+
-+int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
-+{
-+      return _gpiod_export(desc, direction_may_change, NULL);
-+}
- EXPORT_SYMBOL_GPL(gpiod_export);
- static int match_export(struct device *dev, const void *data)
-diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
-index a5f56a0..70a32ee 100644
---- a/include/asm-generic/gpio.h
-+++ b/include/asm-generic/gpio.h
-@@ -126,6 +126,11 @@ static inline int gpio_export(unsigned gpio, bool direction_may_change)
-       return gpiod_export(gpio_to_desc(gpio), direction_may_change);
- }
-+static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
-+{
-+      return _gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
-+}
-+
- static inline int gpio_export_link(struct device *dev, const char *name,
-                                  unsigned gpio)
- {
-diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
-index 7a8144f..085c31c 100644
---- a/include/linux/gpio/consumer.h
-+++ b/include/linux/gpio/consumer.h
-@@ -219,6 +219,7 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
- #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
-+int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
- int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
- int gpiod_export_link(struct device *dev, const char *name,
-                     struct gpio_desc *desc);
-@@ -227,6 +228,13 @@ void gpiod_unexport(struct gpio_desc *desc);
- #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
-+static inline int _gpiod_export(struct gpio_desc *desc,
-+                             bool direction_may_change,
-+                             const char *name)
-+{
-+      return -ENOSYS;
-+}
-+
- static inline int gpiod_export(struct gpio_desc *desc,
-                              bool direction_may_change)
- {
--- 
-1.7.10.4
-
diff --git a/target/linux/lantiq/patches-3.14/0031-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch b/target/linux/lantiq/patches-3.14/0031-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch
new file mode 100644 (file)
index 0000000..713c2aa
--- /dev/null
@@ -0,0 +1,1047 @@
+From f17e50f67fa3c77624edf2ca03fae0d50f0ce39b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 7 Aug 2014 18:26:42 +0200
+Subject: [PATCH 31/36] I2C: MIPS: lantiq: add FALC-ON i2c bus master
+
+This patch adds the driver needed to make the I2C bus work on FALC-ON SoCs.
+
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/i2c/busses/Kconfig      |   10 +
+ drivers/i2c/busses/Makefile     |    1 +
+ drivers/i2c/busses/i2c-lantiq.c |  747 +++++++++++++++++++++++++++++++++++++++
+ drivers/i2c/busses/i2c-lantiq.h |  234 ++++++++++++
+ 4 files changed, 992 insertions(+)
+ create mode 100644 drivers/i2c/busses/i2c-lantiq.c
+ create mode 100644 drivers/i2c/busses/i2c-lantiq.h
+
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index de17c55..3e003c4 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -514,6 +514,16 @@ config I2C_KEMPLD
+         This driver can also be built as a module. If so, the module
+         will be called i2c-kempld.
++config I2C_LANTIQ
++      tristate "Lantiq I2C interface"
++      depends on LANTIQ && SOC_FALCON
++      help
++        If you say yes to this option, support will be included for the
++        Lantiq I2C core.
++
++        This driver can also be built as a module. If so, the module
++        will be called i2c-lantiq.
++
+ config I2C_MPC
+       tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
+       depends on PPC
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index a08931f..4417097 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -49,6 +49,7 @@ obj-$(CONFIG_I2C_IBM_IIC)    += i2c-ibm_iic.o
+ obj-$(CONFIG_I2C_IMX)         += i2c-imx.o
+ obj-$(CONFIG_I2C_IOP3XX)      += i2c-iop3xx.o
+ obj-$(CONFIG_I2C_KEMPLD)      += i2c-kempld.o
++obj-$(CONFIG_I2C_LANTIQ)      += i2c-lantiq.o
+ obj-$(CONFIG_I2C_MPC)         += i2c-mpc.o
+ obj-$(CONFIG_I2C_MV64XXX)     += i2c-mv64xxx.o
+ obj-$(CONFIG_I2C_MXS)         += i2c-mxs.o
+diff --git a/drivers/i2c/busses/i2c-lantiq.c b/drivers/i2c/busses/i2c-lantiq.c
+new file mode 100644
+index 0000000..9a5f58b
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-lantiq.c
+@@ -0,0 +1,747 @@
++
++/*
++ * Lantiq I2C bus adapter
++ *
++ * Parts based on i2c-designware.c and other i2c drivers from Linux 2.6.33
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/slab.h> /* for kzalloc, kfree */
++#include <linux/i2c.h>
++#include <linux/errno.h>
++#include <linux/completion.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/of_irq.h>
++#include <linux/of_i2c.h>
++
++#include <lantiq_soc.h>
++#include "i2c-lantiq.h"
++
++/*
++ * CURRENT ISSUES:
++ * - no high speed support
++ * - ten bit mode is not tested (no slave devices)
++ */
++
++/* access macros */
++#define i2c_r32(reg)  \
++      __raw_readl(&(priv->membase)->reg)
++#define i2c_w32(val, reg)     \
++      __raw_writel(val, &(priv->membase)->reg)
++#define i2c_w32_mask(clear, set, reg) \
++      i2c_w32((i2c_r32(reg) & ~(clear)) | (set), reg)
++
++#define DRV_NAME "i2c-lantiq"
++#define DRV_VERSION "1.00"
++
++#define LTQ_I2C_BUSY_TIMEOUT          20 /* ms */
++
++#ifdef DEBUG
++#define LTQ_I2C_XFER_TIMEOUT          (25*HZ)
++#else
++#define LTQ_I2C_XFER_TIMEOUT          HZ
++#endif
++
++#define LTQ_I2C_IMSC_DEFAULT_MASK     (I2C_IMSC_I2C_P_INT_EN | \
++                                       I2C_IMSC_I2C_ERR_INT_EN)
++
++#define LTQ_I2C_ARB_LOST              (1 << 0)
++#define LTQ_I2C_NACK                  (1 << 1)
++#define LTQ_I2C_RX_UFL                        (1 << 2)
++#define LTQ_I2C_RX_OFL                        (1 << 3)
++#define LTQ_I2C_TX_UFL                        (1 << 4)
++#define LTQ_I2C_TX_OFL                        (1 << 5)
++
++struct ltq_i2c {
++      struct mutex mutex;
++
++
++      /* active clock settings */
++      unsigned int input_clock;       /* clock input for i2c hardware block */
++      unsigned int i2c_clock;         /* approximated bus clock in kHz */
++
++      struct clk *clk_gate;
++      struct clk *clk_input;
++
++
++      /* resources (memory and interrupts) */
++      int irq_lb;                             /* last burst irq */
++
++      struct lantiq_reg_i2c __iomem *membase; /* base of mapped registers */
++
++      struct i2c_adapter adap;
++      struct device *dev;
++
++      struct completion cmd_complete;
++
++
++      /* message transfer data */
++      struct i2c_msg *current_msg;    /* current message */
++      int msgs_num;           /* number of messages to handle */
++      u8 *msg_buf;            /* current buffer */
++      u32 msg_buf_len;        /* remaining length of current buffer */
++      int msg_err;            /* error status of the current transfer */
++
++
++      /* master status codes */
++      enum {
++              STATUS_IDLE,
++              STATUS_ADDR,    /* address phase */
++              STATUS_WRITE,
++              STATUS_READ,
++              STATUS_READ_END,
++              STATUS_STOP
++      } status;
++};
++
++static irqreturn_t ltq_i2c_isr(int irq, void *dev_id);
++
++static inline void enable_burst_irq(struct ltq_i2c *priv)
++{
++      i2c_w32_mask(0, I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, imsc);
++}
++static inline void disable_burst_irq(struct ltq_i2c *priv)
++{
++      i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, 0, imsc);
++}
++
++static void prepare_msg_send_addr(struct ltq_i2c *priv)
++{
++      struct i2c_msg *msg = priv->current_msg;
++      int rd = !!(msg->flags & I2C_M_RD);     /* extends to 0 or 1 */
++      u16 addr = msg->addr;
++
++      /* new i2c_msg */
++      priv->msg_buf = msg->buf;
++      priv->msg_buf_len = msg->len;
++      if (rd)
++              priv->status = STATUS_READ;
++      else
++              priv->status = STATUS_WRITE;
++
++      /* send slave address */
++      if (msg->flags & I2C_M_TEN) {
++              i2c_w32(0xf0 | ((addr & 0x300) >> 7) | rd, txd);
++              i2c_w32(addr & 0xff, txd);
++      } else {
++              i2c_w32((addr & 0x7f) << 1 | rd, txd);
++      }
++}
++
++static void ltq_i2c_set_tx_len(struct ltq_i2c *priv)
++{
++      struct i2c_msg *msg = priv->current_msg;
++      int len = (msg->flags & I2C_M_TEN) ? 2 : 1;
++
++      pr_debug("set_tx_len %cX\n", (msg->flags & I2C_M_RD) ? 'R' : 'T');
++
++      priv->status = STATUS_ADDR;
++
++      if (!(msg->flags & I2C_M_RD))
++              len += msg->len;
++      else
++              /* set maximum received packet size (before rx int!) */
++              i2c_w32(msg->len, mrps_ctrl);
++      i2c_w32(len, tps_ctrl);
++      enable_burst_irq(priv);
++}
++
++static int ltq_i2c_hw_set_clock(struct i2c_adapter *adap)
++{
++      struct ltq_i2c *priv = i2c_get_adapdata(adap);
++      unsigned int input_clock = clk_get_rate(priv->clk_input);
++      u32 dec, inc = 1;
++
++      /* clock changed? */
++      if (priv->input_clock == input_clock)
++              return 0;
++
++      /*
++       * this formula is only an approximation, found by the recommended
++       * values in the "I2C Architecture Specification 1.7.1"
++       */
++      dec = input_clock / (priv->i2c_clock * 2);
++      if (dec <= 6)
++              return -ENXIO;
++
++      i2c_w32(0, fdiv_high_cfg);
++      i2c_w32((inc << I2C_FDIV_CFG_INC_OFFSET) |
++              (dec << I2C_FDIV_CFG_DEC_OFFSET),
++              fdiv_cfg);
++
++      dev_info(priv->dev, "setup clocks (in %d kHz, bus %d kHz, dec=%d)\n",
++              input_clock, priv->i2c_clock, dec);
++
++      priv->input_clock = input_clock;
++      return 0;
++}
++
++static int ltq_i2c_hw_init(struct i2c_adapter *adap)
++{
++      int ret = 0;
++      struct ltq_i2c *priv = i2c_get_adapdata(adap);
++
++      /* disable bus */
++      i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
++
++#ifndef DEBUG
++      /* set normal operation clock divider */
++      i2c_w32(1 << I2C_CLC_RMC_OFFSET, clc);
++#else
++      /* for debugging a higher divider value! */
++      i2c_w32(0xF0 << I2C_CLC_RMC_OFFSET, clc);
++#endif
++
++      /* setup clock */
++      ret = ltq_i2c_hw_set_clock(adap);
++      if (ret != 0) {
++              dev_warn(priv->dev, "invalid clock settings\n");
++              return ret;
++      }
++
++      /* configure fifo */
++      i2c_w32(I2C_FIFO_CFG_TXFC | /* tx fifo as flow controller */
++              I2C_FIFO_CFG_RXFC | /* rx fifo as flow controller */
++              I2C_FIFO_CFG_TXFA_TXFA2 | /* tx fifo 4-byte aligned */
++              I2C_FIFO_CFG_RXFA_RXFA2 | /* rx fifo 4-byte aligned */
++              I2C_FIFO_CFG_TXBS_TXBS0 | /* tx fifo burst size is 1 word */
++              I2C_FIFO_CFG_RXBS_RXBS0,  /* rx fifo burst size is 1 word */
++              fifo_cfg);
++
++      /* configure address */
++      i2c_w32(I2C_ADDR_CFG_SOPE_EN |  /* generate stop when no more data in
++                                         the fifo */
++              I2C_ADDR_CFG_SONA_EN |  /* generate stop when NA received */
++              I2C_ADDR_CFG_MnS_EN |   /* we are master device */
++              0,                      /* our slave address (not used!) */
++              addr_cfg);
++
++      /* enable bus */
++      i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl);
++
++      return 0;
++}
++
++static int ltq_i2c_wait_bus_not_busy(struct ltq_i2c *priv)
++{
++      unsigned long timeout;
++
++      timeout = jiffies + msecs_to_jiffies(LTQ_I2C_BUSY_TIMEOUT);
++
++      do {
++              u32 stat = i2c_r32(bus_stat);
++
++              if ((stat & I2C_BUS_STAT_BS_MASK) == I2C_BUS_STAT_BS_FREE)
++                      return 0;
++
++              cond_resched();
++      } while (!time_after_eq(jiffies, timeout));
++
++      dev_err(priv->dev, "timeout waiting for bus ready\n");
++      return -ETIMEDOUT;
++}
++
++static void ltq_i2c_tx(struct ltq_i2c *priv, int last)
++{
++      if (priv->msg_buf_len && priv->msg_buf) {
++              i2c_w32(*priv->msg_buf, txd);
++
++              if (--priv->msg_buf_len)
++                      priv->msg_buf++;
++              else
++                      priv->msg_buf = NULL;
++      } else {
++              last = 1;
++      }
++
++      if (last)
++              disable_burst_irq(priv);
++}
++
++static void ltq_i2c_rx(struct ltq_i2c *priv, int last)
++{
++      u32 fifo_stat, timeout;
++      if (priv->msg_buf_len && priv->msg_buf) {
++              timeout = 5000000;
++              do {
++                      fifo_stat = i2c_r32(ffs_stat);
++              } while (!fifo_stat && --timeout);
++              if (!timeout) {
++                      last = 1;
++                      pr_debug("\nrx timeout\n");
++                      goto err;
++              }
++              while (fifo_stat) {
++                      *priv->msg_buf = i2c_r32(rxd);
++                      if (--priv->msg_buf_len) {
++                              priv->msg_buf++;
++                      } else {
++                              priv->msg_buf = NULL;
++                              last = 1;
++                              break;
++                      }
++                      /*
++                       * do not read more than burst size, otherwise no "last
++                       * burst" is generated and the transaction is blocked!
++                       */
++                      fifo_stat = 0;
++              }
++      } else {
++              last = 1;
++      }
++err:
++      if (last) {
++              disable_burst_irq(priv);
++
++              if (priv->status == STATUS_READ_END) {
++                      /* 
++                       * do the STATUS_STOP and complete() here, as sometimes
++                       * the tx_end is already seen before this is finished
++                       */
++                      priv->status = STATUS_STOP;
++                      complete(&priv->cmd_complete);
++              } else {
++                      i2c_w32(I2C_ENDD_CTRL_SETEND, endd_ctrl);
++                      priv->status = STATUS_READ_END;
++              }
++      }
++}
++
++static void ltq_i2c_xfer_init(struct ltq_i2c *priv)
++{
++      /* enable interrupts */
++      i2c_w32(LTQ_I2C_IMSC_DEFAULT_MASK, imsc);
++
++      /* trigger transfer of first msg */
++      ltq_i2c_set_tx_len(priv);
++}
++
++static void dump_msgs(struct i2c_msg msgs[], int num, int rx)
++{
++#if defined(DEBUG)
++      int i, j;
++      pr_debug("Messages %d %s\n", num, rx ? "out" : "in");
++      for (i = 0; i < num; i++) {
++              pr_debug("%2d %cX Msg(%d) addr=0x%X: ", i,
++                      (msgs[i].flags & I2C_M_RD) ? 'R' : 'T',
++                      msgs[i].len, msgs[i].addr);
++              if (!(msgs[i].flags & I2C_M_RD) || rx) {
++                      for (j = 0; j < msgs[i].len; j++)
++                              pr_debug("%02X ", msgs[i].buf[j]);
++              }
++              pr_debug("\n");
++      }
++#endif
++}
++
++static void ltq_i2c_release_bus(struct ltq_i2c *priv)
++{
++      if ((i2c_r32(bus_stat) & I2C_BUS_STAT_BS_MASK) == I2C_BUS_STAT_BS_BM)
++              i2c_w32(I2C_ENDD_CTRL_SETEND, endd_ctrl);
++}
++
++static int ltq_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
++                         int num)
++{
++      struct ltq_i2c *priv = i2c_get_adapdata(adap);
++      int ret;
++
++      dev_dbg(priv->dev, "xfer %u messages\n", num);
++      dump_msgs(msgs, num, 0);
++
++      mutex_lock(&priv->mutex);
++
++      INIT_COMPLETION(priv->cmd_complete);
++      priv->current_msg = msgs;
++      priv->msgs_num = num;
++      priv->msg_err = 0;
++      priv->status = STATUS_IDLE;
++
++      /* wait for the bus to become ready */
++      ret = ltq_i2c_wait_bus_not_busy(priv);
++      if (ret)
++              goto done;
++
++      while (priv->msgs_num) {
++              /* start the transfers */
++              ltq_i2c_xfer_init(priv);
++
++              /* wait for transfers to complete */
++              ret = wait_for_completion_interruptible_timeout(
++                      &priv->cmd_complete, LTQ_I2C_XFER_TIMEOUT);
++              if (ret == 0) {
++                      dev_err(priv->dev, "controller timed out\n");
++                      ltq_i2c_hw_init(adap);
++                      ret = -ETIMEDOUT;
++                      goto done;
++              } else if (ret < 0)
++                      goto done;
++
++              if (priv->msg_err) {
++                      if (priv->msg_err & LTQ_I2C_NACK)
++                              ret = -ENXIO;
++                      else
++                              ret = -EREMOTEIO;
++                      goto done;
++              }
++              if (--priv->msgs_num)
++                      priv->current_msg++;
++      }
++      /* no error? */
++      ret = num;
++
++done:
++      ltq_i2c_release_bus(priv);
++
++      mutex_unlock(&priv->mutex);
++
++      if (ret >= 0)
++              dump_msgs(msgs, num, 1);
++
++      pr_debug("XFER ret %d\n", ret);
++      return ret;
++}
++
++static irqreturn_t ltq_i2c_isr_burst(int irq, void *dev_id)
++{
++      struct ltq_i2c *priv = dev_id;
++      struct i2c_msg *msg = priv->current_msg;
++      int last = (irq == priv->irq_lb);
++
++      if (last)
++              pr_debug("LB ");
++      else
++              pr_debug("B ");
++
++      if (msg->flags & I2C_M_RD) {
++              switch (priv->status) {
++              case STATUS_ADDR:
++                      pr_debug("X");
++                      prepare_msg_send_addr(priv);
++                      disable_burst_irq(priv);
++                      break;
++              case STATUS_READ:
++              case STATUS_READ_END:
++                      pr_debug("R");
++                      ltq_i2c_rx(priv, last);
++                      break;
++              default:
++                      disable_burst_irq(priv);
++                      pr_warn("Status R %d\n", priv->status);
++                      break;
++              }
++      } else {
++              switch (priv->status) {
++              case STATUS_ADDR:
++                      pr_debug("x");
++                      prepare_msg_send_addr(priv);
++                      break;
++              case STATUS_WRITE:
++                      pr_debug("w");
++                      ltq_i2c_tx(priv, last);
++                      break;
++              default:
++                      disable_burst_irq(priv);
++                      pr_warn("Status W %d\n", priv->status);
++                      break;
++              }
++      }
++
++      i2c_w32(I2C_ICR_BREQ_INT_CLR | I2C_ICR_LBREQ_INT_CLR, icr);
++      return IRQ_HANDLED;
++}
++
++static void ltq_i2c_isr_prot(struct ltq_i2c *priv)
++{
++      u32 i_pro = i2c_r32(p_irqss);
++
++      pr_debug("i2c-p");
++
++      /* not acknowledge */
++      if (i_pro & I2C_P_IRQSS_NACK) {
++              priv->msg_err |= LTQ_I2C_NACK;
++              pr_debug(" nack");
++      }
++
++      /* arbitration lost */
++      if (i_pro & I2C_P_IRQSS_AL) {
++              priv->msg_err |= LTQ_I2C_ARB_LOST;
++              pr_debug(" arb-lost");
++      }
++      /* tx -> rx switch */
++      if (i_pro & I2C_P_IRQSS_RX)
++              pr_debug(" rx");
++
++      /* tx end */
++      if (i_pro & I2C_P_IRQSS_TX_END)
++              pr_debug(" txend");
++      pr_debug("\n");
++
++      if (!priv->msg_err) {
++              /* tx -> rx switch */
++              if (i_pro & I2C_P_IRQSS_RX) {
++                      priv->status = STATUS_READ;
++                      enable_burst_irq(priv);
++              }
++              if (i_pro & I2C_P_IRQSS_TX_END) {
++                      if (priv->status == STATUS_READ)
++                              priv->status = STATUS_READ_END;
++                      else {
++                              disable_burst_irq(priv);
++                              priv->status = STATUS_STOP;
++                      }
++              }
++      }
++
++      i2c_w32(i_pro, p_irqsc);
++}
++
++static irqreturn_t ltq_i2c_isr(int irq, void *dev_id)
++{
++      u32 i_raw, i_err = 0;
++      struct ltq_i2c *priv = dev_id;
++
++      i_raw = i2c_r32(mis);
++      pr_debug("i_raw 0x%08X\n", i_raw);
++
++      /* error interrupt */
++      if (i_raw & I2C_RIS_I2C_ERR_INT_INTOCC) {
++              i_err = i2c_r32(err_irqss);
++              pr_debug("i_err 0x%08X bus_stat 0x%04X\n",
++                      i_err, i2c_r32(bus_stat));
++
++              /* tx fifo overflow (8) */
++              if (i_err & I2C_ERR_IRQSS_TXF_OFL)
++                      priv->msg_err |= LTQ_I2C_TX_OFL;
++
++              /* tx fifo underflow (4) */
++              if (i_err & I2C_ERR_IRQSS_TXF_UFL)
++                      priv->msg_err |= LTQ_I2C_TX_UFL;
++
++              /* rx fifo overflow (2) */
++              if (i_err & I2C_ERR_IRQSS_RXF_OFL)
++                      priv->msg_err |= LTQ_I2C_RX_OFL;
++
++              /* rx fifo underflow (1) */
++              if (i_err & I2C_ERR_IRQSS_RXF_UFL)
++                      priv->msg_err |= LTQ_I2C_RX_UFL;
++
++              i2c_w32(i_err, err_irqsc);
++      }
++
++      /* protocol interrupt */
++      if (i_raw & I2C_RIS_I2C_P_INT_INTOCC)
++              ltq_i2c_isr_prot(priv);
++
++      if ((priv->msg_err) || (priv->status == STATUS_STOP))
++              complete(&priv->cmd_complete);
++
++      return IRQ_HANDLED;
++}
++
++static u32 ltq_i2c_functionality(struct i2c_adapter *adap)
++{
++      return  I2C_FUNC_I2C |
++              I2C_FUNC_10BIT_ADDR |
++              I2C_FUNC_SMBUS_EMUL;
++}
++
++static struct i2c_algorithm ltq_i2c_algorithm = {
++      .master_xfer    = ltq_i2c_xfer,
++      .functionality  = ltq_i2c_functionality,
++};
++
++static int __devinit ltq_i2c_probe(struct platform_device *pdev)
++{
++      struct device_node *node = pdev->dev.of_node;
++      struct ltq_i2c *priv;
++      struct i2c_adapter *adap;
++      struct resource *mmres, irqres[4];
++      int ret = 0;
++
++      dev_dbg(&pdev->dev, "probing\n");
++
++      mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      ret = of_irq_to_resource_table(node, irqres, 4);
++      if (!mmres || (ret != 4)) {
++              dev_err(&pdev->dev, "no resources\n");
++              return -ENODEV;
++      }
++
++      /* allocate private data */
++      priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv) {
++              dev_err(&pdev->dev, "can't allocate private data\n");
++              return -ENOMEM;
++      }
++
++      adap = &priv->adap;
++      i2c_set_adapdata(adap, priv);
++      adap->owner = THIS_MODULE;
++      adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
++      strlcpy(adap->name, DRV_NAME "-adapter", sizeof(adap->name));
++      adap->algo = &ltq_i2c_algorithm;
++
++      if (of_property_read_u32(node, "clock-frequency", &priv->i2c_clock)) {
++              dev_warn(&pdev->dev, "No I2C speed selected, using 100kHz\n");
++              priv->i2c_clock = 100000;
++      }
++
++      init_completion(&priv->cmd_complete);
++      mutex_init(&priv->mutex);
++
++      priv->membase = devm_request_and_ioremap(&pdev->dev, mmres);
++      if (priv->membase == NULL)
++              return -ENOMEM;
++
++      priv->dev = &pdev->dev;
++      priv->irq_lb = irqres[0].start;
++
++      ret = devm_request_irq(&pdev->dev, irqres[0].start, ltq_i2c_isr_burst,
++              IRQF_DISABLED, "i2c lb", priv);
++      if (ret) {
++              dev_err(&pdev->dev, "can't get last burst IRQ %d\n",
++                      irqres[0].start);
++              return -ENODEV;
++      }
++
++      ret = devm_request_irq(&pdev->dev, irqres[1].start, ltq_i2c_isr_burst,
++              IRQF_DISABLED, "i2c b", priv);
++      if (ret) {
++              dev_err(&pdev->dev, "can't get burst IRQ %d\n",
++                      irqres[1].start);
++              return -ENODEV;
++      }
++
++      ret = devm_request_irq(&pdev->dev, irqres[2].start, ltq_i2c_isr,
++              IRQF_DISABLED, "i2c err", priv);
++      if (ret) {
++              dev_err(&pdev->dev, "can't get error IRQ %d\n",
++                      irqres[2].start);
++              return -ENODEV;
++      }
++
++      ret = devm_request_irq(&pdev->dev, irqres[3].start, ltq_i2c_isr,
++              IRQF_DISABLED, "i2c p", priv);
++      if (ret) {
++              dev_err(&pdev->dev, "can't get protocol IRQ %d\n",
++                      irqres[3].start);
++              return -ENODEV;
++      }
++
++      dev_dbg(&pdev->dev, "mapped io-space to %p\n", priv->membase);
++      dev_dbg(&pdev->dev, "use IRQs %d, %d, %d, %d\n", irqres[0].start,
++              irqres[1].start, irqres[2].start, irqres[3].start);
++
++      priv->clk_gate = devm_clk_get(&pdev->dev, NULL);
++      if (IS_ERR(priv->clk_gate)) {
++              dev_err(&pdev->dev, "failed to get i2c clk\n");
++              return -ENOENT;
++      }
++
++      /* this is a static clock, which has no refcounting */
++      priv->clk_input = clk_get_fpi();
++      if (IS_ERR(priv->clk_input)) {
++              dev_err(&pdev->dev, "failed to get fpi clk\n");
++              return -ENOENT;
++      }
++
++      clk_activate(priv->clk_gate);
++
++      /* add our adapter to the i2c stack */
++      ret = i2c_add_numbered_adapter(adap);
++      if (ret) {
++              dev_err(&pdev->dev, "can't register I2C adapter\n");
++              goto out;
++      }
++
++      platform_set_drvdata(pdev, priv);
++      i2c_set_adapdata(adap, priv);
++
++      /* print module version information */
++      dev_dbg(&pdev->dev, "module id=%u revision=%u\n",
++              (i2c_r32(id) & I2C_ID_ID_MASK) >> I2C_ID_ID_OFFSET,
++              (i2c_r32(id) & I2C_ID_REV_MASK) >> I2C_ID_REV_OFFSET);
++
++      /* initialize HW */
++      ret = ltq_i2c_hw_init(adap);
++      if (ret) {
++              dev_err(&pdev->dev, "can't configure adapter\n");
++              i2c_del_adapter(adap);
++              platform_set_drvdata(pdev, NULL);
++      } else {
++              dev_info(&pdev->dev, "version %s\n", DRV_VERSION);
++      }
++
++      of_i2c_register_devices(adap);
++
++out:
++      /* if init failed, we need to deactivate the clock gate */
++      if (ret)
++              clk_deactivate(priv->clk_gate);
++
++      return ret;
++}
++
++static int __devexit ltq_i2c_remove(struct platform_device *pdev)
++{
++      struct ltq_i2c *priv = platform_get_drvdata(pdev);
++
++      /* disable bus */
++      i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
++
++      /* power down the core */
++      clk_deactivate(priv->clk_gate);
++
++      /* remove driver */
++      i2c_del_adapter(&priv->adap);
++      kfree(priv);
++
++      dev_dbg(&pdev->dev, "removed\n");
++      platform_set_drvdata(pdev, NULL);
++
++      return 0;
++}
++static const struct of_device_id ltq_i2c_match[] = {
++      { .compatible = "lantiq,lantiq-i2c" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, ltq_i2c_match);
++
++static struct platform_driver ltq_i2c_driver = {
++      .probe  = ltq_i2c_probe,
++      .remove = __devexit_p(ltq_i2c_remove),
++      .driver = {
++              .name   = DRV_NAME,
++              .owner  = THIS_MODULE,
++              .of_match_table = ltq_i2c_match,
++      },
++};
++
++module_platform_driver(ltq_i2c_driver);
++
++MODULE_DESCRIPTION("Lantiq I2C bus adapter");
++MODULE_AUTHOR("Thomas Langer <thomas.langer@lantiq.com>");
++MODULE_ALIAS("platform:" DRV_NAME);
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
+diff --git a/drivers/i2c/busses/i2c-lantiq.h b/drivers/i2c/busses/i2c-lantiq.h
+new file mode 100644
+index 0000000..7a86b89
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-lantiq.h
+@@ -0,0 +1,234 @@
++#ifndef I2C_LANTIQ_H
++#define I2C_LANTIQ_H
++
++/* I2C register structure */
++struct lantiq_reg_i2c {
++      /* I2C Kernel Clock Control Register */
++      unsigned int clc; /* 0x00000000 */
++      /* Reserved */
++      unsigned int res_0; /* 0x00000004 */
++      /* I2C Identification Register */
++      unsigned int id; /* 0x00000008 */
++      /* Reserved */
++      unsigned int res_1; /* 0x0000000C */
++      /*
++       * I2C RUN Control Register
++       * This register enables and disables the I2C peripheral. Before
++       * enabling, the I2C has to be configured properly. After enabling
++       * no configuration is possible
++       */
++      unsigned int run_ctrl; /* 0x00000010 */
++      /*
++       * I2C End Data Control Register
++       * This register is used to either turn around the data transmission
++       * direction or to address another slave without sending a stop
++       * condition. Also the software can stop the slave-transmitter by
++       * sending a not-accolade when working as master-receiver or even
++       * stop data transmission immediately when operating as
++       * master-transmitter. The writing to the bits of this control
++       * register is only effective when in MASTER RECEIVES BYTES, MASTER
++       * TRANSMITS BYTES, MASTER RESTART or SLAVE RECEIVE BYTES state
++       */
++      unsigned int endd_ctrl; /* 0x00000014 */
++      /*
++       * I2C Fractional Divider Configuration Register
++       * These register is used to program the fractional divider of the I2C
++       * bus. Before the peripheral is switched on by setting the RUN-bit the
++       * two (fixed) values for the two operating frequencies are programmed
++       * into these (configuration) registers. The Register FDIV_HIGH_CFG has
++       * the same layout as I2C_FDIV_CFG.
++       */
++      unsigned int fdiv_cfg; /* 0x00000018 */
++      /*
++       * I2C Fractional Divider (highspeed mode) Configuration Register
++       * These register is used to program the fractional divider of the I2C
++       * bus. Before the peripheral is switched on by setting the RUN-bit the
++       * two (fixed) values for the two operating frequencies are programmed
++       * into these (configuration) registers. The Register FDIV_CFG has the
++       * same layout as I2C_FDIV_CFG.
++       */
++      unsigned int fdiv_high_cfg; /* 0x0000001C */
++      /* I2C Address Configuration Register */
++      unsigned int addr_cfg; /* 0x00000020 */
++      /* I2C Bus Status Register
++       * This register gives a status information of the I2C. This additional
++       * information can be used by the software to start proper actions.
++       */
++      unsigned int bus_stat; /* 0x00000024 */
++      /* I2C FIFO Configuration Register */
++      unsigned int fifo_cfg; /* 0x00000028 */
++      /* I2C Maximum Received Packet Size Register */
++      unsigned int mrps_ctrl; /* 0x0000002C */
++      /* I2C Received Packet Size Status Register */
++      unsigned int rps_stat; /* 0x00000030 */
++      /* I2C Transmit Packet Size Register */
++      unsigned int tps_ctrl; /* 0x00000034 */
++      /* I2C Filled FIFO Stages Status Register */
++      unsigned int ffs_stat; /* 0x00000038 */
++      /* Reserved */
++      unsigned int res_2; /* 0x0000003C */
++      /* I2C Timing Configuration Register */
++      unsigned int tim_cfg; /* 0x00000040 */
++      /* Reserved */
++      unsigned int res_3[7]; /* 0x00000044 */
++      /* I2C Error Interrupt Request Source Mask Register */
++      unsigned int err_irqsm; /* 0x00000060 */
++      /* I2C Error Interrupt Request Source Status Register */
++      unsigned int err_irqss; /* 0x00000064 */
++      /* I2C Error Interrupt Request Source Clear Register */
++      unsigned int err_irqsc; /* 0x00000068 */
++      /* Reserved */
++      unsigned int res_4; /* 0x0000006C */
++      /* I2C Protocol Interrupt Request Source Mask Register */
++      unsigned int p_irqsm; /* 0x00000070 */
++      /* I2C Protocol Interrupt Request Source Status Register */
++      unsigned int p_irqss; /* 0x00000074 */
++      /* I2C Protocol Interrupt Request Source Clear Register */
++      unsigned int p_irqsc; /* 0x00000078 */
++      /* Reserved */
++      unsigned int res_5; /* 0x0000007C */
++      /* I2C Raw Interrupt Status Register */
++      unsigned int ris; /* 0x00000080 */
++      /* I2C Interrupt Mask Control Register */
++      unsigned int imsc; /* 0x00000084 */
++      /* I2C Masked Interrupt Status Register */
++      unsigned int mis; /* 0x00000088 */
++      /* I2C Interrupt Clear Register */
++      unsigned int icr; /* 0x0000008C */
++      /* I2C Interrupt Set Register */
++      unsigned int isr; /* 0x00000090 */
++      /* I2C DMA Enable Register */
++      unsigned int dmae; /* 0x00000094 */
++      /* Reserved */
++      unsigned int res_6[8154]; /* 0x00000098 */
++      /* I2C Transmit Data Register */
++      unsigned int txd; /* 0x00008000 */
++      /* Reserved */
++      unsigned int res_7[4095]; /* 0x00008004 */
++      /* I2C Receive Data Register */
++      unsigned int rxd; /* 0x0000C000 */
++      /* Reserved */
++      unsigned int res_8[4095]; /* 0x0000C004 */
++};
++
++/*
++ * Clock Divider for Normal Run Mode
++ * Max 8-bit divider value. IF RMC is 0 the module is disabled. Note: As long
++ * as the new divider value RMC is not valid, the register returns 0x0000 00xx
++ * on reading.
++ */
++#define I2C_CLC_RMC_MASK 0x0000FF00
++/* field offset */
++#define I2C_CLC_RMC_OFFSET 8
++
++/* Fields of "I2C Identification Register" */
++/* Module ID */
++#define I2C_ID_ID_MASK 0x0000FF00
++/* field offset */
++#define I2C_ID_ID_OFFSET 8
++/* Revision */
++#define I2C_ID_REV_MASK 0x000000FF
++/* field offset */
++#define I2C_ID_REV_OFFSET 0
++
++/* Fields of "I2C Interrupt Mask Control Register" */
++/* Enable */
++#define I2C_IMSC_BREQ_INT_EN 0x00000008
++/* Enable */
++#define I2C_IMSC_LBREQ_INT_EN 0x00000004
++
++/* Fields of "I2C Fractional Divider Configuration Register" */
++/* field offset */
++#define I2C_FDIV_CFG_INC_OFFSET 16
++
++/* Fields of "I2C Interrupt Mask Control Register" */
++/* Enable */
++#define I2C_IMSC_I2C_P_INT_EN 0x00000020
++/* Enable */
++#define I2C_IMSC_I2C_ERR_INT_EN 0x00000010
++
++/* Fields of "I2C Error Interrupt Request Source Status Register" */
++/* TXF_OFL */
++#define I2C_ERR_IRQSS_TXF_OFL 0x00000008
++/* TXF_UFL */
++#define I2C_ERR_IRQSS_TXF_UFL 0x00000004
++/* RXF_OFL */
++#define I2C_ERR_IRQSS_RXF_OFL 0x00000002
++/* RXF_UFL */
++#define I2C_ERR_IRQSS_RXF_UFL 0x00000001
++
++/* Fields of "I2C Raw Interrupt Status Register" */
++/* Read: Interrupt occurred. */
++#define I2C_RIS_I2C_ERR_INT_INTOCC 0x00000010
++/* Read: Interrupt occurred. */
++#define I2C_RIS_I2C_P_INT_INTOCC 0x00000020
++
++/* Fields of "I2C FIFO Configuration Register" */
++/* TX FIFO Flow Control */
++#define I2C_FIFO_CFG_TXFC 0x00020000
++/* RX FIFO Flow Control */
++#define I2C_FIFO_CFG_RXFC 0x00010000
++/* Word aligned (character alignment of four characters) */
++#define I2C_FIFO_CFG_TXFA_TXFA2 0x00002000
++/* Word aligned (character alignment of four characters) */
++#define I2C_FIFO_CFG_RXFA_RXFA2 0x00000200
++/* 1 word */
++#define I2C_FIFO_CFG_TXBS_TXBS0 0x00000000
++
++/* Fields of "I2C FIFO Configuration Register" */
++/* 1 word */
++#define I2C_FIFO_CFG_RXBS_RXBS0 0x00000000
++/* Stop on Packet End Enable */
++#define I2C_ADDR_CFG_SOPE_EN 0x00200000
++/* Stop on Not Acknowledge Enable */
++#define I2C_ADDR_CFG_SONA_EN 0x00100000
++/* Enable */
++#define I2C_ADDR_CFG_MnS_EN 0x00080000
++
++/* Fields of "I2C Interrupt Clear Register" */
++/* Clear */
++#define I2C_ICR_BREQ_INT_CLR 0x00000008
++/* Clear */
++#define I2C_ICR_LBREQ_INT_CLR 0x00000004
++
++/* Fields of "I2C Fractional Divider Configuration Register" */
++/* field offset */
++#define I2C_FDIV_CFG_DEC_OFFSET 0
++
++/* Fields of "I2C Bus Status Register" */
++/* Bus Status */
++#define I2C_BUS_STAT_BS_MASK 0x00000003
++/* Read from I2C Bus. */
++#define I2C_BUS_STAT_RNW_READ 0x00000004
++/* I2C Bus is free. */
++#define I2C_BUS_STAT_BS_FREE 0x00000000
++/*
++ * The device is working as master and has claimed the control on the
++ * I2C-bus (busy master).
++ */
++#define I2C_BUS_STAT_BS_BM 0x00000002
++
++/* Fields of "I2C RUN Control Register" */
++/* Enable */
++#define I2C_RUN_CTRL_RUN_EN 0x00000001
++
++/* Fields of "I2C End Data Control Register" */
++/*
++ * Set End of Transmission
++ * Note:Do not write '1' to this bit when bus is free. This will cause an
++ * abort after the first byte when a new transfer is started.
++ */
++#define I2C_ENDD_CTRL_SETEND 0x00000002
++
++/* Fields of "I2C Protocol Interrupt Request Source Status Register" */
++/* NACK */
++#define I2C_P_IRQSS_NACK 0x00000010
++/* AL */
++#define I2C_P_IRQSS_AL 0x00000008
++/* RX */
++#define I2C_P_IRQSS_RX 0x00000040
++/* TX_END */
++#define I2C_P_IRQSS_TX_END 0x00000020
++
++
++#endif /* I2C_LANTIQ_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0032-USB-fix-roothub-for-IFXHCD.patch b/target/linux/lantiq/patches-3.14/0032-USB-fix-roothub-for-IFXHCD.patch
new file mode 100644 (file)
index 0000000..6209426
--- /dev/null
@@ -0,0 +1,38 @@
+From 326714a47233e4a524afa0c8398276fddf0dbd4d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 6 Dec 2012 19:59:53 +0100
+Subject: [PATCH 32/36] USB: fix roothub for IFXHCD
+
+---
+ arch/mips/lantiq/Kconfig |    1 +
+ drivers/usb/core/hub.c   |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
+index 1621b1d..4c9a241 100644
+--- a/arch/mips/lantiq/Kconfig
++++ b/arch/mips/lantiq/Kconfig
+@@ -3,6 +3,7 @@ if LANTIQ
+ config SOC_TYPE_XWAY
+       bool
+       select PINCTRL_XWAY
++      select USB_ARCH_HAS_HCD
+       default n
+ choice
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 64ea219..30f4bdf 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -4077,7 +4077,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+               udev->ttport = hdev->ttport;
+       } else if (udev->speed != USB_SPEED_HIGH
+                       && hdev->speed == USB_SPEED_HIGH) {
+-              if (!hub->tt.hub) {
++              if (hdev->parent && !hub->tt.hub) {
+                       dev_err(&udev->dev, "parent hub has no TT\n");
+                       retval = -EINVAL;
+                       goto fail;
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0033-SPI-MIPS-lantiq-adds-spi-xway.patch b/target/linux/lantiq/patches-3.14/0033-SPI-MIPS-lantiq-adds-spi-xway.patch
new file mode 100644 (file)
index 0000000..3a57416
--- /dev/null
@@ -0,0 +1,1032 @@
+From e75df4f96373e5d16f8ca13aa031e54cdcfeda62 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 13 Mar 2013 09:29:37 +0100
+Subject: [PATCH 33/36] SPI: MIPS: lantiq: adds spi-xway
+
+This patch adds support for the SPI core found on several Lantiq SoCs.
+The Driver has been runtime tested in combination with m25p80 Flash Devices
+on Amazon_SE and VR9.
+
+Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/spi/Kconfig    |    8 +
+ drivers/spi/Makefile   |    1 +
+ drivers/spi/spi-xway.c |  977 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 986 insertions(+)
+ create mode 100644 drivers/spi/spi-xway.c
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 581ee2a..b2cd93c 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -527,6 +527,14 @@ config SPI_NUC900
+       help
+         SPI driver for Nuvoton NUC900 series ARM SoCs
++config SPI_XWAY
++      tristate "Lantiq XWAY SPI controller"
++      depends on LANTIQ && SOC_TYPE_XWAY
++      select SPI_BITBANG
++      help
++        This driver supports the Lantiq SoC SPI controller in master
++        mode.
++
+ #
+ # Add new SPI master controllers in alphabetical order above this line
+ #
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 95af48d..82d3799 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -79,3 +79,4 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH)               += spi-topcliff-pch.o
+ obj-$(CONFIG_SPI_TXX9)                        += spi-txx9.o
+ obj-$(CONFIG_SPI_XCOMM)               += spi-xcomm.o
+ obj-$(CONFIG_SPI_XILINX)              += spi-xilinx.o
++obj-$(CONFIG_SPI_XWAY)                        += spi-xway.o
+diff --git a/drivers/spi/spi-xway.c b/drivers/spi/spi-xway.c
+new file mode 100644
+index 0000000..61532e3
+--- /dev/null
++++ b/drivers/spi/spi-xway.c
+@@ -0,0 +1,977 @@
++/*
++ * Lantiq SoC SPI controller
++ *
++ * Copyright (C) 2011 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
++ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ *
++ * This program is free software; you can distribute it and/or modify it
++ * under the terms of the GNU General Public License (Version 2) as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/workqueue.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/completion.h>
++#include <linux/spinlock.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/spi_bitbang.h>
++#include <linux/of_irq.h>
++
++#include <lantiq_soc.h>
++
++#define LTQ_SPI_CLC           0x00    /* Clock control */
++#define LTQ_SPI_PISEL         0x04    /* Port input select */
++#define LTQ_SPI_ID            0x08    /* Identification */
++#define LTQ_SPI_CON           0x10    /* Control */
++#define LTQ_SPI_STAT          0x14    /* Status */
++#define LTQ_SPI_WHBSTATE      0x18    /* Write HW modified state */
++#define LTQ_SPI_TB            0x20    /* Transmit buffer */
++#define LTQ_SPI_RB            0x24    /* Receive buffer */
++#define LTQ_SPI_RXFCON                0x30    /* Receive FIFO control */
++#define LTQ_SPI_TXFCON                0x34    /* Transmit FIFO control */
++#define LTQ_SPI_FSTAT         0x38    /* FIFO status */
++#define LTQ_SPI_BRT           0x40    /* Baudrate timer */
++#define LTQ_SPI_BRSTAT                0x44    /* Baudrate timer status */
++#define LTQ_SPI_SFCON         0x60    /* Serial frame control */
++#define LTQ_SPI_SFSTAT                0x64    /* Serial frame status */
++#define LTQ_SPI_GPOCON                0x70    /* General purpose output control */
++#define LTQ_SPI_GPOSTAT               0x74    /* General purpose output status */
++#define LTQ_SPI_FGPO          0x78    /* Forced general purpose output */
++#define LTQ_SPI_RXREQ         0x80    /* Receive request */
++#define LTQ_SPI_RXCNT         0x84    /* Receive count */
++#define LTQ_SPI_DMACON                0xEC    /* DMA control */
++#define LTQ_SPI_IRNEN         0xF4    /* Interrupt node enable */
++#define LTQ_SPI_IRNICR                0xF8    /* Interrupt node interrupt capture */
++#define LTQ_SPI_IRNCR         0xFC    /* Interrupt node control */
++
++#define LTQ_SPI_CLC_SMC_SHIFT 16      /* Clock divider for sleep mode */
++#define LTQ_SPI_CLC_SMC_MASK  0xFF
++#define LTQ_SPI_CLC_RMC_SHIFT 8       /* Clock divider for normal run mode */
++#define LTQ_SPI_CLC_RMC_MASK  0xFF
++#define LTQ_SPI_CLC_DISS      BIT(1)  /* Disable status bit */
++#define LTQ_SPI_CLC_DISR      BIT(0)  /* Disable request bit */
++
++#define LTQ_SPI_ID_TXFS_SHIFT 24      /* Implemented TX FIFO size */
++#define LTQ_SPI_ID_TXFS_MASK  0x3F
++#define LTQ_SPI_ID_RXFS_SHIFT 16      /* Implemented RX FIFO size */
++#define LTQ_SPI_ID_RXFS_MASK  0x3F
++#define LTQ_SPI_ID_REV_MASK   0x1F    /* Hardware revision number */
++#define LTQ_SPI_ID_CFG                BIT(5)  /* DMA interface support */
++
++#define LTQ_SPI_CON_BM_SHIFT  16      /* Data width selection */
++#define LTQ_SPI_CON_BM_MASK   0x1F
++#define LTQ_SPI_CON_EM                BIT(24) /* Echo mode */
++#define LTQ_SPI_CON_IDLE      BIT(23) /* Idle bit value */
++#define LTQ_SPI_CON_ENBV      BIT(22) /* Enable byte valid control */
++#define LTQ_SPI_CON_RUEN      BIT(12) /* Receive underflow error enable */
++#define LTQ_SPI_CON_TUEN      BIT(11) /* Transmit underflow error enable */
++#define LTQ_SPI_CON_AEN               BIT(10) /* Abort error enable */
++#define LTQ_SPI_CON_REN               BIT(9)  /* Receive overflow error enable */
++#define LTQ_SPI_CON_TEN               BIT(8)  /* Transmit overflow error enable */
++#define LTQ_SPI_CON_LB                BIT(7)  /* Loopback control */
++#define LTQ_SPI_CON_PO                BIT(6)  /* Clock polarity control */
++#define LTQ_SPI_CON_PH                BIT(5)  /* Clock phase control */
++#define LTQ_SPI_CON_HB                BIT(4)  /* Heading control */
++#define LTQ_SPI_CON_RXOFF     BIT(1)  /* Switch receiver off */
++#define LTQ_SPI_CON_TXOFF     BIT(0)  /* Switch transmitter off */
++
++#define LTQ_SPI_STAT_RXBV_MASK        0x7
++#define LTQ_SPI_STAT_RXBV_SHIFT       28
++#define LTQ_SPI_STAT_BSY      BIT(13) /* Busy flag */
++#define LTQ_SPI_STAT_RUE      BIT(12) /* Receive underflow error flag */
++#define LTQ_SPI_STAT_TUE      BIT(11) /* Transmit underflow error flag */
++#define LTQ_SPI_STAT_AE               BIT(10) /* Abort error flag */
++#define LTQ_SPI_STAT_RE               BIT(9)  /* Receive error flag */
++#define LTQ_SPI_STAT_TE               BIT(8)  /* Transmit error flag */
++#define LTQ_SPI_STAT_MS               BIT(1)  /* Master/slave select bit */
++#define LTQ_SPI_STAT_EN               BIT(0)  /* Enable bit */
++
++#define LTQ_SPI_WHBSTATE_SETTUE       BIT(15) /* Set transmit underflow error flag */
++#define LTQ_SPI_WHBSTATE_SETAE        BIT(14) /* Set abort error flag */
++#define LTQ_SPI_WHBSTATE_SETRE        BIT(13) /* Set receive error flag */
++#define LTQ_SPI_WHBSTATE_SETTE        BIT(12) /* Set transmit error flag */
++#define LTQ_SPI_WHBSTATE_CLRTUE       BIT(11) /* Clear transmit underflow error
++                                              flag */
++#define LTQ_SPI_WHBSTATE_CLRAE        BIT(10) /* Clear abort error flag */
++#define LTQ_SPI_WHBSTATE_CLRRE        BIT(9)  /* Clear receive error flag */
++#define LTQ_SPI_WHBSTATE_CLRTE        BIT(8)  /* Clear transmit error flag */
++#define LTQ_SPI_WHBSTATE_SETME        BIT(7)  /* Set mode error flag */
++#define LTQ_SPI_WHBSTATE_CLRME        BIT(6)  /* Clear mode error flag */
++#define LTQ_SPI_WHBSTATE_SETRUE       BIT(5)  /* Set receive underflow error flag */
++#define LTQ_SPI_WHBSTATE_CLRRUE       BIT(4)  /* Clear receive underflow error flag */
++#define LTQ_SPI_WHBSTATE_SETMS        BIT(3)  /* Set master select bit */
++#define LTQ_SPI_WHBSTATE_CLRMS        BIT(2)  /* Clear master select bit */
++#define LTQ_SPI_WHBSTATE_SETEN        BIT(1)  /* Set enable bit (operational mode) */
++#define LTQ_SPI_WHBSTATE_CLREN        BIT(0)  /* Clear enable bit (config mode */
++#define LTQ_SPI_WHBSTATE_CLR_ERRORS   0x0F50
++
++#define LTQ_SPI_RXFCON_RXFITL_SHIFT   8 /* FIFO interrupt trigger level */
++#define LTQ_SPI_RXFCON_RXFITL_MASK    0x3F
++#define LTQ_SPI_RXFCON_RXFLU          BIT(1)  /* FIFO flush */
++#define LTQ_SPI_RXFCON_RXFEN          BIT(0)  /* FIFO enable */
++
++#define LTQ_SPI_TXFCON_TXFITL_SHIFT   8 /* FIFO interrupt trigger level */
++#define LTQ_SPI_TXFCON_TXFITL_MASK    0x3F
++#define LTQ_SPI_TXFCON_TXFLU          BIT(1)  /* FIFO flush */
++#define LTQ_SPI_TXFCON_TXFEN          BIT(0)  /* FIFO enable */
++
++#define LTQ_SPI_FSTAT_RXFFL_MASK      0x3f
++#define LTQ_SPI_FSTAT_RXFFL_SHIFT     0
++#define LTQ_SPI_FSTAT_TXFFL_MASK      0x3f
++#define LTQ_SPI_FSTAT_TXFFL_SHIFT     8
++
++#define LTQ_SPI_GPOCON_ISCSBN_SHIFT   8
++#define LTQ_SPI_GPOCON_INVOUTN_SHIFT  0
++
++#define LTQ_SPI_FGPO_SETOUTN_SHIFT    8
++#define LTQ_SPI_FGPO_CLROUTN_SHIFT    0
++
++#define LTQ_SPI_RXREQ_RXCNT_MASK      0xFFFF  /* Receive count value */
++#define LTQ_SPI_RXCNT_TODO_MASK               0xFFFF  /* Recevie to-do value */
++
++#define LTQ_SPI_IRNEN_F               BIT(3)  /* Frame end interrupt request */
++#define LTQ_SPI_IRNEN_E               BIT(2)  /* Error end interrupt request */
++#define LTQ_SPI_IRNEN_T               BIT(1)  /* Transmit end interrupt request */
++#define LTQ_SPI_IRNEN_R               BIT(0)  /* Receive end interrupt request */
++#define LTQ_SPI_IRNEN_ALL     0xF
++
++struct ltq_spi {
++      struct spi_bitbang      bitbang;
++      struct completion       done;
++      spinlock_t              lock;
++
++      struct device           *dev;
++      void __iomem            *base;
++      struct clk              *fpiclk;
++      struct clk              *spiclk;
++
++      int                     status;
++      int                     irq[3];
++
++      const u8                *tx;
++      u8                      *rx;
++      u32                     tx_cnt;
++      u32                     rx_cnt;
++      u32                     len;
++      struct spi_transfer     *curr_transfer;
++
++      u32 (*get_tx) (struct ltq_spi *);
++
++      u16                     txfs;
++      u16                     rxfs;
++      unsigned                dma_support:1;
++      unsigned                cfg_mode:1;
++};
++
++static inline struct ltq_spi *ltq_spi_to_hw(struct spi_device *spi)
++{
++      return spi_master_get_devdata(spi->master);
++}
++
++static inline u32 ltq_spi_reg_read(struct ltq_spi *hw, u32 reg)
++{
++      return ioread32be(hw->base + reg);
++}
++
++static inline void ltq_spi_reg_write(struct ltq_spi *hw, u32 val, u32 reg)
++{
++      iowrite32be(val, hw->base + reg);
++}
++
++static inline void ltq_spi_reg_setbit(struct ltq_spi *hw, u32 bits, u32 reg)
++{
++      u32 val;
++
++      val = ltq_spi_reg_read(hw, reg);
++      val |= bits;
++      ltq_spi_reg_write(hw, val, reg);
++}
++
++static inline void ltq_spi_reg_clearbit(struct ltq_spi *hw, u32 bits, u32 reg)
++{
++      u32 val;
++
++      val = ltq_spi_reg_read(hw, reg);
++      val &= ~bits;
++      ltq_spi_reg_write(hw, val, reg);
++}
++
++static void ltq_spi_hw_enable(struct ltq_spi *hw)
++{
++      u32 clc;
++
++      /* Power-up module */
++      clk_enable(hw->spiclk);
++
++      /*
++       * Set clock divider for run mode to 1 to
++       * run at same frequency as FPI bus
++       */
++      clc = (1 << LTQ_SPI_CLC_RMC_SHIFT);
++      ltq_spi_reg_write(hw, clc, LTQ_SPI_CLC);
++}
++
++static void ltq_spi_hw_disable(struct ltq_spi *hw)
++{
++      /* Set clock divider to 0 and set module disable bit */
++      ltq_spi_reg_write(hw, LTQ_SPI_CLC_DISS, LTQ_SPI_CLC);
++
++      /* Power-down module */
++      clk_disable(hw->spiclk);
++}
++
++static void ltq_spi_reset_fifos(struct ltq_spi *hw)
++{
++      u32 val;
++
++      /*
++       * Enable and flush FIFOs. Set interrupt trigger level to
++       * half of FIFO count implemented in hardware.
++       */
++      if (hw->txfs > 1) {
++              val = hw->txfs << (LTQ_SPI_TXFCON_TXFITL_SHIFT - 1);
++              val |= LTQ_SPI_TXFCON_TXFEN | LTQ_SPI_TXFCON_TXFLU;
++              ltq_spi_reg_write(hw, val, LTQ_SPI_TXFCON);
++      }
++
++      if (hw->rxfs > 1) {
++              val = hw->rxfs << (LTQ_SPI_RXFCON_RXFITL_SHIFT - 1);
++              val |= LTQ_SPI_RXFCON_RXFEN | LTQ_SPI_RXFCON_RXFLU;
++              ltq_spi_reg_write(hw, val, LTQ_SPI_RXFCON);
++      }
++}
++
++static inline int ltq_spi_wait_ready(struct ltq_spi *hw)
++{
++      u32 stat;
++      unsigned long timeout;
++
++      timeout = jiffies + msecs_to_jiffies(200);
++
++      do {
++              stat = ltq_spi_reg_read(hw, LTQ_SPI_STAT);
++              if (!(stat & LTQ_SPI_STAT_BSY))
++                      return 0;
++
++              cond_resched();
++      } while (!time_after_eq(jiffies, timeout));
++
++      dev_err(hw->dev, "SPI wait ready timed out stat: %x\n", stat);
++
++      return -ETIMEDOUT;
++}
++
++static void ltq_spi_config_mode_set(struct ltq_spi *hw)
++{
++      if (hw->cfg_mode)
++              return;
++
++      /*
++       * Putting the SPI module in config mode is only safe if no
++       * transfer is in progress as indicated by busy flag STATE.BSY.
++       */
++      if (ltq_spi_wait_ready(hw)) {
++              ltq_spi_reset_fifos(hw);
++              hw->status = -ETIMEDOUT;
++      }
++      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_CLREN, LTQ_SPI_WHBSTATE);
++
++      hw->cfg_mode = 1;
++}
++
++static void ltq_spi_run_mode_set(struct ltq_spi *hw)
++{
++      if (!hw->cfg_mode)
++              return;
++
++      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_SETEN, LTQ_SPI_WHBSTATE);
++
++      hw->cfg_mode = 0;
++}
++
++static u32 ltq_spi_tx_word_u8(struct ltq_spi *hw)
++{
++      const u8 *tx = hw->tx;
++      u32 data = *tx++;
++
++      hw->tx_cnt++;
++      hw->tx++;
++
++      return data;
++}
++
++static u32 ltq_spi_tx_word_u16(struct ltq_spi *hw)
++{
++      const u16 *tx = (u16 *) hw->tx;
++      u32 data = *tx++;
++
++      hw->tx_cnt += 2;
++      hw->tx += 2;
++
++      return data;
++}
++
++static u32 ltq_spi_tx_word_u32(struct ltq_spi *hw)
++{
++      const u32 *tx = (u32 *) hw->tx;
++      u32 data = *tx++;
++
++      hw->tx_cnt += 4;
++      hw->tx += 4;
++
++      return data;
++}
++
++static void ltq_spi_bits_per_word_set(struct spi_device *spi)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 bm;
++      u8 bits_per_word = spi->bits_per_word;
++
++      /*
++       * Use either default value of SPI device or value
++       * from current transfer.
++       */
++      if (hw->curr_transfer && hw->curr_transfer->bits_per_word)
++              bits_per_word = hw->curr_transfer->bits_per_word;
++
++      if (bits_per_word <= 8)
++              hw->get_tx = ltq_spi_tx_word_u8;
++      else if (bits_per_word <= 16)
++              hw->get_tx = ltq_spi_tx_word_u16;
++      else if (bits_per_word <= 32)
++              hw->get_tx = ltq_spi_tx_word_u32;
++
++      /* CON.BM value = bits_per_word - 1 */
++      bm = (bits_per_word - 1) << LTQ_SPI_CON_BM_SHIFT;
++
++      ltq_spi_reg_clearbit(hw, LTQ_SPI_CON_BM_MASK <<
++                           LTQ_SPI_CON_BM_SHIFT, LTQ_SPI_CON);
++      ltq_spi_reg_setbit(hw, bm, LTQ_SPI_CON);
++}
++
++static void ltq_spi_speed_set(struct spi_device *spi)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 br, max_speed_hz, spi_clk;
++      u32 speed_hz = spi->max_speed_hz;
++
++      /*
++       * Use either default value of SPI device or value
++       * from current transfer.
++       */
++      if (hw->curr_transfer && hw->curr_transfer->speed_hz)
++              speed_hz = hw->curr_transfer->speed_hz;
++
++      /*
++       * SPI module clock is derived from FPI bus clock dependent on
++       * divider value in CLC.RMS which is always set to 1.
++       */
++      spi_clk = clk_get_rate(hw->fpiclk);
++
++      /*
++       * Maximum SPI clock frequency in master mode is half of
++       * SPI module clock frequency. Maximum reload value of
++       * baudrate generator BR is 2^16.
++       */
++      max_speed_hz = spi_clk / 2;
++      if (speed_hz >= max_speed_hz)
++              br = 0;
++      else
++              br = (max_speed_hz / speed_hz) - 1;
++
++      if (br > 0xFFFF)
++              br = 0xFFFF;
++
++      ltq_spi_reg_write(hw, br, LTQ_SPI_BRT);
++}
++
++static void ltq_spi_clockmode_set(struct spi_device *spi)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 con;
++
++      con = ltq_spi_reg_read(hw, LTQ_SPI_CON);
++
++      /*
++       * SPI mode mapping in CON register:
++       * Mode CPOL CPHA CON.PO CON.PH
++       *  0    0    0      0      1
++       *  1    0    1      0      0
++       *  2    1    0      1      1
++       *  3    1    1      1      0
++       */
++      if (spi->mode & SPI_CPHA)
++              con &= ~LTQ_SPI_CON_PH;
++      else
++              con |= LTQ_SPI_CON_PH;
++
++      if (spi->mode & SPI_CPOL)
++              con |= LTQ_SPI_CON_PO;
++      else
++              con &= ~LTQ_SPI_CON_PO;
++
++      /* Set heading control */
++      if (spi->mode & SPI_LSB_FIRST)
++              con &= ~LTQ_SPI_CON_HB;
++      else
++              con |= LTQ_SPI_CON_HB;
++
++      ltq_spi_reg_write(hw, con, LTQ_SPI_CON);
++}
++
++static void ltq_spi_xmit_set(struct ltq_spi *hw, struct spi_transfer *t)
++{
++      u32 con;
++
++      con = ltq_spi_reg_read(hw, LTQ_SPI_CON);
++
++      if (t) {
++              if (t->tx_buf && t->rx_buf) {
++                      con &= ~(LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF);
++              } else if (t->rx_buf) {
++                      con &= ~LTQ_SPI_CON_RXOFF;
++                      con |= LTQ_SPI_CON_TXOFF;
++              } else if (t->tx_buf) {
++                      con &= ~LTQ_SPI_CON_TXOFF;
++                      con |= LTQ_SPI_CON_RXOFF;
++              }
++      } else
++              con |= (LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF);
++
++      ltq_spi_reg_write(hw, con, LTQ_SPI_CON);
++}
++
++static void ltq_spi_internal_cs_activate(struct spi_device *spi)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 fgpo;
++
++      fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_CLROUTN_SHIFT));
++      ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
++}
++
++static void ltq_spi_internal_cs_deactivate(struct spi_device *spi)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 fgpo;
++
++      fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_SETOUTN_SHIFT));
++      ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
++}
++
++static void ltq_spi_chipselect(struct spi_device *spi, int cs)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++
++      switch (cs) {
++      case BITBANG_CS_ACTIVE:
++              ltq_spi_bits_per_word_set(spi);
++              ltq_spi_speed_set(spi);
++              ltq_spi_clockmode_set(spi);
++              ltq_spi_run_mode_set(hw);
++              ltq_spi_internal_cs_activate(spi);
++              break;
++
++      case BITBANG_CS_INACTIVE:
++              ltq_spi_internal_cs_deactivate(spi);
++              ltq_spi_config_mode_set(hw);
++              break;
++      }
++}
++
++static int ltq_spi_setup_transfer(struct spi_device *spi,
++                                struct spi_transfer *t)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u8 bits_per_word = spi->bits_per_word;
++
++      hw->curr_transfer = t;
++
++      if (t && t->bits_per_word)
++              bits_per_word = t->bits_per_word;
++
++      if (bits_per_word > 32)
++              return -EINVAL;
++
++      ltq_spi_config_mode_set(hw);
++
++      return 0;
++}
++
++static int ltq_spi_setup(struct spi_device *spi)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 gpocon, fgpo;
++
++      /* Set default word length to 8 if not set */
++      if (!spi->bits_per_word)
++              spi->bits_per_word = 8;
++
++      if (spi->bits_per_word > 32)
++              return -EINVAL;
++
++      /*
++       * Up to six GPIOs can be connected to the SPI module
++       * via GPIO alternate function to control the chip select lines.
++       */
++      gpocon = (1 << (spi->chip_select +
++                      LTQ_SPI_GPOCON_ISCSBN_SHIFT));
++
++      if (spi->mode & SPI_CS_HIGH)
++              gpocon |= (1 << spi->chip_select);
++
++      fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_SETOUTN_SHIFT));
++
++      ltq_spi_reg_setbit(hw, gpocon, LTQ_SPI_GPOCON);
++      ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
++
++      return 0;
++}
++
++static void ltq_spi_cleanup(struct spi_device *spi)
++{
++
++}
++
++static void ltq_spi_txfifo_write(struct ltq_spi *hw)
++{
++      u32 fstat, data;
++      u16 fifo_space;
++
++      /* Determine how much FIFOs are free for TX data */
++      fstat = ltq_spi_reg_read(hw, LTQ_SPI_FSTAT);
++      fifo_space = hw->txfs - ((fstat >> LTQ_SPI_FSTAT_TXFFL_SHIFT) &
++                                      LTQ_SPI_FSTAT_TXFFL_MASK);
++
++      if (!fifo_space)
++              return;
++
++      while (hw->tx_cnt < hw->len && fifo_space) {
++              data = hw->get_tx(hw);
++              ltq_spi_reg_write(hw, data, LTQ_SPI_TB);
++              fifo_space--;
++      }
++}
++
++static void ltq_spi_rxfifo_read(struct ltq_spi *hw)
++{
++      u32 fstat, data, *rx32;
++      u16 fifo_fill;
++      u8 rxbv, shift, *rx8;
++
++      /* Determine how much FIFOs are filled with RX data */
++      fstat = ltq_spi_reg_read(hw, LTQ_SPI_FSTAT);
++      fifo_fill = ((fstat >> LTQ_SPI_FSTAT_RXFFL_SHIFT)
++                      & LTQ_SPI_FSTAT_RXFFL_MASK);
++
++      if (!fifo_fill)
++              return;
++
++      /*
++       * The 32 bit FIFO is always used completely independent from the
++       * bits_per_word value. Thus four bytes have to be read at once
++       * per FIFO.
++       */
++      rx32 = (u32 *) hw->rx;
++      while (hw->len - hw->rx_cnt >= 4 && fifo_fill) {
++              *rx32++ = ltq_spi_reg_read(hw, LTQ_SPI_RB);
++              hw->rx_cnt += 4;
++              hw->rx += 4;
++              fifo_fill--;
++      }
++
++      /*
++       * If there are remaining bytes, read byte count from STAT.RXBV
++       * register and read the data byte-wise.
++       */
++      while (fifo_fill && hw->rx_cnt < hw->len) {
++              rxbv = (ltq_spi_reg_read(hw, LTQ_SPI_STAT) >>
++                      LTQ_SPI_STAT_RXBV_SHIFT) & LTQ_SPI_STAT_RXBV_MASK;
++              data = ltq_spi_reg_read(hw, LTQ_SPI_RB);
++
++              shift = (rxbv - 1) * 8;
++              rx8 = hw->rx;
++
++              while (rxbv) {
++                      *rx8++ = (data >> shift) & 0xFF;
++                      rxbv--;
++                      shift -= 8;
++                      hw->rx_cnt++;
++                      hw->rx++;
++              }
++
++              fifo_fill--;
++      }
++}
++
++static void ltq_spi_rxreq_set(struct ltq_spi *hw)
++{
++      u32 rxreq, rxreq_max, rxtodo;
++
++      rxtodo = ltq_spi_reg_read(hw, LTQ_SPI_RXCNT) & LTQ_SPI_RXCNT_TODO_MASK;
++
++      /*
++       * In RX-only mode the serial clock is activated only after writing
++       * the expected amount of RX bytes into RXREQ register.
++       * To avoid receive overflows at high clocks it is better to request
++       * only the amount of bytes that fits into all FIFOs. This value
++       * depends on the FIFO size implemented in hardware.
++       */
++      rxreq = hw->len - hw->rx_cnt;
++      rxreq_max = hw->rxfs << 2;
++      rxreq = min(rxreq_max, rxreq);
++
++      if (!rxtodo && rxreq)
++              ltq_spi_reg_write(hw, rxreq, LTQ_SPI_RXREQ);
++}
++
++static inline void ltq_spi_complete(struct ltq_spi *hw)
++{
++      complete(&hw->done);
++}
++
++irqreturn_t ltq_spi_tx_irq(int irq, void *data)
++{
++      struct ltq_spi *hw = data;
++      unsigned long flags;
++      int completed = 0;
++
++      spin_lock_irqsave(&hw->lock, flags);
++
++      if (hw->tx_cnt < hw->len)
++              ltq_spi_txfifo_write(hw);
++
++      if (hw->tx_cnt == hw->len)
++              completed = 1;
++
++      spin_unlock_irqrestore(&hw->lock, flags);
++
++      if (completed)
++              ltq_spi_complete(hw);
++
++      return IRQ_HANDLED;
++}
++
++irqreturn_t ltq_spi_rx_irq(int irq, void *data)
++{
++      struct ltq_spi *hw = data;
++      unsigned long flags;
++      int completed = 0;
++
++      spin_lock_irqsave(&hw->lock, flags);
++
++      if (hw->rx_cnt < hw->len) {
++              ltq_spi_rxfifo_read(hw);
++
++              if (hw->tx && hw->tx_cnt < hw->len)
++                      ltq_spi_txfifo_write(hw);
++      }
++
++      if (hw->rx_cnt == hw->len)
++              completed = 1;
++      else if (!hw->tx)
++              ltq_spi_rxreq_set(hw);
++
++      spin_unlock_irqrestore(&hw->lock, flags);
++
++      if (completed)
++              ltq_spi_complete(hw);
++
++      return IRQ_HANDLED;
++}
++
++irqreturn_t ltq_spi_err_irq(int irq, void *data)
++{
++      struct ltq_spi *hw = data;
++      unsigned long flags;
++
++      spin_lock_irqsave(&hw->lock, flags);
++
++      /* Disable all interrupts */
++      ltq_spi_reg_clearbit(hw, LTQ_SPI_IRNEN_ALL, LTQ_SPI_IRNEN);
++
++      /* Clear all error flags */
++      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
++
++      /* Flush FIFOs */
++      ltq_spi_reg_setbit(hw, LTQ_SPI_RXFCON_RXFLU, LTQ_SPI_RXFCON);
++      ltq_spi_reg_setbit(hw, LTQ_SPI_TXFCON_TXFLU, LTQ_SPI_TXFCON);
++
++      hw->status = -EIO;
++      spin_unlock_irqrestore(&hw->lock, flags);
++
++      ltq_spi_complete(hw);
++
++      return IRQ_HANDLED;
++}
++
++static int ltq_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
++{
++      struct ltq_spi *hw = ltq_spi_to_hw(spi);
++      u32 irq_flags = 0;
++
++      hw->tx = t->tx_buf;
++      hw->rx = t->rx_buf;
++      hw->len = t->len;
++      hw->tx_cnt = 0;
++      hw->rx_cnt = 0;
++      hw->status = 0;
++      INIT_COMPLETION(hw->done);
++
++      ltq_spi_xmit_set(hw, t);
++
++      /* Enable error interrupts */
++      ltq_spi_reg_setbit(hw, LTQ_SPI_IRNEN_E, LTQ_SPI_IRNEN);
++
++      if (hw->tx) {
++              /* Initially fill TX FIFO with as much data as possible */
++              ltq_spi_txfifo_write(hw);
++              irq_flags |= LTQ_SPI_IRNEN_T;
++
++              /* Always enable RX interrupt in Full Duplex mode */
++              if (hw->rx)
++                      irq_flags |= LTQ_SPI_IRNEN_R;
++      } else if (hw->rx) {
++              /* Start RX clock */
++              ltq_spi_rxreq_set(hw);
++
++              /* Enable RX interrupt to receive data from RX FIFOs */
++              irq_flags |= LTQ_SPI_IRNEN_R;
++      }
++
++      /* Enable TX or RX interrupts */
++      ltq_spi_reg_setbit(hw, irq_flags, LTQ_SPI_IRNEN);
++      wait_for_completion_interruptible(&hw->done);
++
++      /* Disable all interrupts */
++      ltq_spi_reg_clearbit(hw, LTQ_SPI_IRNEN_ALL, LTQ_SPI_IRNEN);
++
++      /*
++       * Return length of current transfer for bitbang utility code if
++       * no errors occured during transmission.
++       */
++      if (!hw->status)
++              hw->status = hw->len;
++
++      return hw->status;
++}
++
++static const struct ltq_spi_irq_map {
++      char *name;
++      irq_handler_t handler;
++} ltq_spi_irqs[] = {
++      { "spi_rx", ltq_spi_rx_irq },
++      { "spi_tx", ltq_spi_tx_irq },
++      { "spi_err", ltq_spi_err_irq },
++};
++
++static int ltq_spi_probe(struct platform_device *pdev)
++{
++      struct resource irqres[3];
++      struct spi_master *master;
++      struct resource *r;
++      struct ltq_spi *hw;
++      int ret, i;
++      u32 data, id;
++
++      if (of_irq_to_resource_table(pdev->dev.of_node, irqres, 3) != 3) {
++              dev_err(&pdev->dev, "IRQ settings missing in device tree\n");
++              return -EINVAL;
++      }
++
++      master = spi_alloc_master(&pdev->dev, sizeof(struct ltq_spi));
++      if (!master) {
++              dev_err(&pdev->dev, "spi_alloc_master\n");
++              ret = -ENOMEM;
++              goto err;
++      }
++
++      hw = spi_master_get_devdata(master);
++
++      r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (r == NULL) {
++              dev_err(&pdev->dev, "platform_get_resource\n");
++              ret = -ENOENT;
++              goto err_master;
++      }
++
++      r = devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
++                      pdev->name);
++      if (!r) {
++              dev_err(&pdev->dev, "failed to request memory region\n");
++              ret = -ENXIO;
++              goto err_master;
++      }
++
++      hw->base = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r));
++      if (!hw->base) {
++              dev_err(&pdev->dev, "failed to remap memory region\n");
++              ret = -ENXIO;
++              goto err_master;
++      }
++
++      memset(hw->irq, 0, sizeof(hw->irq));
++      for (i = 0; i < ARRAY_SIZE(ltq_spi_irqs); i++) {
++              hw->irq[i] = irqres[i].start;
++              ret = request_irq(hw->irq[i], ltq_spi_irqs[i].handler,
++                                0, ltq_spi_irqs[i].name, hw);
++              if (ret) {
++                      dev_err(&pdev->dev, "failed to request %s irq (%d)\n",
++                                      ltq_spi_irqs[i].name, hw->irq[i]);
++                      goto err_irq;
++              }
++      }
++
++      hw->fpiclk = clk_get_fpi();
++      if (IS_ERR(hw->fpiclk)) {
++              dev_err(&pdev->dev, "failed to get fpi clock\n");
++              ret = PTR_ERR(hw->fpiclk);
++              goto err_clk;
++      }
++
++      hw->spiclk = clk_get(&pdev->dev, NULL);
++      if (IS_ERR(hw->spiclk)) {
++              dev_err(&pdev->dev, "failed to get spi clock gate\n");
++              ret = PTR_ERR(hw->spiclk);
++              goto err_clk;
++      }
++
++      hw->bitbang.master = spi_master_get(master);
++      hw->bitbang.chipselect = ltq_spi_chipselect;
++      hw->bitbang.setup_transfer = ltq_spi_setup_transfer;
++      hw->bitbang.txrx_bufs = ltq_spi_txrx_bufs;
++
++      if (of_machine_is_compatible("lantiq,ase"))
++              master->num_chipselect = 3;
++      else
++              master->num_chipselect = 6;
++      master->bus_num = pdev->id;
++      master->setup = ltq_spi_setup;
++      master->cleanup = ltq_spi_cleanup;
++      master->dev.of_node = pdev->dev.of_node;
++
++      hw->dev = &pdev->dev;
++      init_completion(&hw->done);
++      spin_lock_init(&hw->lock);
++
++      ltq_spi_hw_enable(hw);
++
++      /* Read module capabilities */
++      id = ltq_spi_reg_read(hw, LTQ_SPI_ID);
++      hw->txfs = (id >> LTQ_SPI_ID_TXFS_SHIFT) & LTQ_SPI_ID_TXFS_MASK;
++      hw->rxfs = (id >> LTQ_SPI_ID_TXFS_SHIFT) & LTQ_SPI_ID_TXFS_MASK;
++      hw->dma_support = (id & LTQ_SPI_ID_CFG) ? 1 : 0;
++
++      ltq_spi_config_mode_set(hw);
++
++      /* Enable error checking, disable TX/RX, set idle value high */
++      data = LTQ_SPI_CON_RUEN | LTQ_SPI_CON_AEN |
++          LTQ_SPI_CON_TEN | LTQ_SPI_CON_REN |
++          LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF | LTQ_SPI_CON_IDLE;
++      ltq_spi_reg_write(hw, data, LTQ_SPI_CON);
++
++      /* Enable master mode and clear error flags */
++      ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_SETMS |
++                        LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
++
++      /* Reset GPIO/CS registers */
++      ltq_spi_reg_write(hw, 0x0, LTQ_SPI_GPOCON);
++      ltq_spi_reg_write(hw, 0xFF00, LTQ_SPI_FGPO);
++
++      /* Enable and flush FIFOs */
++      ltq_spi_reset_fifos(hw);
++
++      ret = spi_bitbang_start(&hw->bitbang);
++      if (ret) {
++              dev_err(&pdev->dev, "spi_bitbang_start failed\n");
++              goto err_bitbang;
++      }
++
++      platform_set_drvdata(pdev, hw);
++
++      pr_info("Lantiq SoC SPI controller rev %u (TXFS %u, RXFS %u, DMA %u)\n",
++              id & LTQ_SPI_ID_REV_MASK, hw->txfs, hw->rxfs, hw->dma_support);
++
++      return 0;
++
++err_bitbang:
++      ltq_spi_hw_disable(hw);
++
++err_clk:
++      if (hw->fpiclk)
++              clk_put(hw->fpiclk);
++      if (hw->spiclk)
++              clk_put(hw->spiclk);
++
++err_irq:
++      clk_put(hw->fpiclk);
++
++      for (; i > 0; i--)
++              free_irq(hw->irq[i], hw);
++
++err_master:
++      spi_master_put(master);
++
++err:
++      return ret;
++}
++
++static int ltq_spi_remove(struct platform_device *pdev)
++{
++      struct ltq_spi *hw = platform_get_drvdata(pdev);
++      int ret, i;
++
++      ret = spi_bitbang_stop(&hw->bitbang);
++      if (ret)
++              return ret;
++
++      platform_set_drvdata(pdev, NULL);
++
++      ltq_spi_config_mode_set(hw);
++      ltq_spi_hw_disable(hw);
++
++      for (i = 0; i < ARRAY_SIZE(hw->irq); i++)
++              if (0 < hw->irq[i])
++                      free_irq(hw->irq[i], hw);
++
++      if (hw->fpiclk)
++              clk_put(hw->fpiclk);
++      if (hw->spiclk)
++              clk_put(hw->spiclk);
++
++      spi_master_put(hw->bitbang.master);
++
++      return 0;
++}
++
++static const struct of_device_id ltq_spi_match[] = {
++      { .compatible = "lantiq,spi-xway" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, ltq_spi_match);
++
++static struct platform_driver ltq_spi_driver = {
++      .probe = ltq_spi_probe,
++      .remove = ltq_spi_remove,
++      .driver = {
++              .name = "spi-xway",
++              .owner = THIS_MODULE,
++              .of_match_table = ltq_spi_match,
++      },
++};
++
++module_platform_driver(ltq_spi_driver);
++
++MODULE_DESCRIPTION("Lantiq SoC SPI controller driver");
++MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:spi-xway");
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0034-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch b/target/linux/lantiq/patches-3.14/0034-reset-Fix-compile-when-reset-RESET_CONTROLLER-is-not.patch
new file mode 100644 (file)
index 0000000..9589baa
--- /dev/null
@@ -0,0 +1,112 @@
+From b1b9fca8c317afc3f2b78bb54f877e8a830a819d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 9 Aug 2013 18:47:27 +0200
+Subject: [PATCH 34/36] 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(+)
+
+diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
+index 41a4695..f38f530 100644
+--- a/include/linux/reset-controller.h
++++ b/include/linux/reset-controller.h
+@@ -46,7 +46,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
+diff --git a/include/linux/reset.h b/include/linux/reset.h
+index 6082247..1b36c9e 100644
+--- 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_get(struct device *dev, const char *id)
+ 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
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch b/target/linux/lantiq/patches-3.14/0035-owrt-lantiq-wifi-and-ethernet-eeprom-handling.patch
new file mode 100644 (file)
index 0000000..3b92b95
--- /dev/null
@@ -0,0 +1,612 @@
+From f8c5db89e793a4bc6c1e87bd7b3a5cec16b75bc3 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 10 Sep 2014 22:42:14 +0200
+Subject: [PATCH 35/36] owrt: lantiq: wifi and ethernet eeprom handling
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h  |    6 +
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    3 +
+ arch/mips/lantiq/xway/Makefile                     |    3 +
+ arch/mips/lantiq/xway/ath_eep.c                    |  282 ++++++++++++++++++++
+ arch/mips/lantiq/xway/eth_mac.c                    |   76 ++++++
+ arch/mips/lantiq/xway/pci-ath-fixup.c              |  109 ++++++++
+ arch/mips/lantiq/xway/rt_eep.c                     |   60 +++++
+ 7 files changed, 539 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
+ create mode 100644 arch/mips/lantiq/xway/ath_eep.c
+ create mode 100644 arch/mips/lantiq/xway/eth_mac.c
+ create mode 100644 arch/mips/lantiq/xway/pci-ath-fixup.c
+ create mode 100644 arch/mips/lantiq/xway/rt_eep.c
+
+diff --git a/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h b/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
+new file mode 100644
+index 0000000..095d261
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/pci-ath-fixup.h
+@@ -0,0 +1,6 @@
++#ifndef _PCI_ATH_FIXUP
++#define _PCI_ATH_FIXUP
++
++void ltq_pci_ath_fixup(unsigned slot, u16 *cal_data) __init;
++
++#endif /* _PCI_ATH_FIXUP */
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 133336b..779715c 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -90,5 +90,8 @@ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr);
+ extern void ltq_pmu_enable(unsigned int module);
+ extern void ltq_pmu_disable(unsigned int module);
++/* allow the ethernet driver to load a flash mapped mac addr */
++const u8* ltq_get_eth_mac(void);
++
+ #endif /* CONFIG_SOC_TYPE_XWAY */
+ #endif /* _LTQ_XWAY_H__ */
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 2dd442c..de876e1 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -2,4 +2,7 @@ obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
+ obj-y += vmmc.o tffs.o
++obj-y += eth_mac.o
++obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
++
+ obj-$(CONFIG_XRX200_PHY_FW) += xrx200_phy_fw.o
+diff --git a/arch/mips/lantiq/xway/ath_eep.c b/arch/mips/lantiq/xway/ath_eep.c
+new file mode 100644
+index 0000000..aff42ac
+--- /dev/null
++++ b/arch/mips/lantiq/xway/ath_eep.c
+@@ -0,0 +1,282 @@
++/*
++ *  Copyright (C) 2011 Luca Olivetti <luca@ventoso.org>
++ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
++ *  Copyright (C) 2011 Andrej Vlašić <andrej.vlasic0@gmail.com>
++ *  Copyright (C) 2013 Álvaro Fernández Rojas <noltari@gmail.com>
++ *  Copyright (C) 2013 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
++ *
++ *  This program is free software; you can redistribute it and/or modify it
++ *  under the terms of the GNU General Public License version 2 as published
++ *  by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/etherdevice.h>
++#include <linux/ath5k_platform.h>
++#include <linux/ath9k_platform.h>
++#include <linux/pci.h>
++#include <linux/err.h>
++#include <linux/mtd/mtd.h>
++#include <pci-ath-fixup.h>
++#include <lantiq_soc.h>
++
++extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
++struct ath5k_platform_data ath5k_pdata;
++struct ath9k_platform_data ath9k_pdata = {
++      .led_pin = -1,
++};
++static u8 athxk_eeprom_mac[6];
++
++static int ath9k_pci_plat_dev_init(struct pci_dev *dev)
++{
++      dev->dev.platform_data = &ath9k_pdata;
++      return 0;
++}
++
++static int ath9k_eep_load;
++int __init of_ath9k_eeprom_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node, *mtd_np;
++      struct resource *eep_res, *mac_res = NULL;
++      void __iomem *eep, *mac;
++      int mac_offset, led_pin;
++      u32 mac_inc = 0, pci_slot = 0;
++      int i;
++      struct mtd_info *the_mtd;
++      size_t flash_readlen;
++      const __be32 *list;
++      const char *part;
++      phandle phandle;
++
++      if ((list = of_get_property(np, "ath,eep-flash", &i)) && i == 2 *
++                      sizeof(*list) && (phandle = be32_to_cpup(list++)) &&
++                      (mtd_np = of_find_node_by_phandle(phandle)) && ((part =
++                      of_get_property(mtd_np, "label", NULL)) || (part =
++                      mtd_np->name)) && (the_mtd = get_mtd_device_nm(part))
++                      != ERR_PTR(-ENODEV)) {
++              i = mtd_read(the_mtd, be32_to_cpup(list),
++                              ATH9K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
++                              (void *) ath9k_pdata.eeprom_data);
++              if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
++                      size_t mac_readlen;
++                      mtd_read(the_mtd, mac_offset, 6, &mac_readlen,
++                              (void *) athxk_eeprom_mac);
++              }
++              put_mtd_device(the_mtd);
++              if ((sizeof(ath9k_pdata.eeprom_data) != flash_readlen) || i) {
++                      dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
++                      return -ENODEV;
++              }
++      } else {
++              eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++              mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++
++              if (!eep_res) {
++                      dev_err(&pdev->dev, "failed to load eeprom address\n");
++                      return -ENODEV;
++              }
++              if (resource_size(eep_res) != ATH9K_PLAT_EEP_MAX_WORDS << 1) {
++                      dev_err(&pdev->dev, "eeprom has an invalid size\n");
++                      return -EINVAL;
++              }
++
++              eep = ioremap(eep_res->start, resource_size(eep_res));
++              memcpy_fromio(ath9k_pdata.eeprom_data, eep,
++                              ATH9K_PLAT_EEP_MAX_WORDS << 1);
++      }
++
++      if (of_find_property(np, "ath,eep-swap", NULL))
++              for (i = 0; i < ATH9K_PLAT_EEP_MAX_WORDS; i++)
++                      ath9k_pdata.eeprom_data[i] = swab16(ath9k_pdata.eeprom_data[i]);
++
++      if (of_find_property(np, "ath,eep-endian", NULL)) {
++              ath9k_pdata.endian_check = true;
++
++              dev_info(&pdev->dev, "endian check enabled.\n");
++      }
++
++      if (!is_valid_ether_addr(athxk_eeprom_mac)) {
++              if (mac_res) {
++                      if (resource_size(mac_res) != 6) {
++                              dev_err(&pdev->dev, "mac has an invalid size\n");
++                              return -EINVAL;
++                      }
++                      mac = ioremap(mac_res->start, resource_size(mac_res));
++                      memcpy_fromio(athxk_eeprom_mac, mac, 6);
++              } else if (ltq_get_eth_mac()) {
++                      memcpy(athxk_eeprom_mac, ltq_get_eth_mac(), 6);
++              }
++      }
++      if (!is_valid_ether_addr(athxk_eeprom_mac)) {
++              dev_warn(&pdev->dev, "using random mac\n");
++              random_ether_addr(athxk_eeprom_mac);
++      }
++
++      if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
++              athxk_eeprom_mac[5] += mac_inc;
++
++      ath9k_pdata.macaddr = athxk_eeprom_mac;
++      ltq_pci_plat_dev_init = ath9k_pci_plat_dev_init;
++
++      if (!of_property_read_u32(np, "ath,pci-slot", &pci_slot)) {
++              ltq_pci_ath_fixup(pci_slot, ath9k_pdata.eeprom_data);
++
++              dev_info(&pdev->dev, "pci slot: %u\n", pci_slot);
++                if (ath9k_eep_load) {
++                        struct pci_dev *d = NULL;
++                        while ((d = pci_get_device(PCI_VENDOR_ID_ATHEROS,
++                                        PCI_ANY_ID, d)) != NULL)
++                                pci_fixup_device(pci_fixup_early, d);
++                }
++
++      }
++
++      if (!of_property_read_u32(np, "ath,led-pin", &led_pin)) {
++              ath9k_pdata.led_pin = led_pin;
++              dev_info(&pdev->dev, "using led pin %d.\n", led_pin);
++      }
++
++      dev_info(&pdev->dev, "loaded ath9k eeprom\n");
++
++      return 0;
++}
++
++static struct of_device_id ath9k_eeprom_ids[] = {
++      { .compatible = "ath9k,eeprom" },
++      { }
++};
++
++static struct platform_driver ath9k_eeprom_driver = {
++      .driver         = {
++              .name           = "ath9k,eeprom",
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(ath9k_eeprom_ids),
++      },
++};
++
++static int __init of_ath9k_eeprom_init(void)
++{
++        int ret = platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
++
++        if (ret)
++                ath9k_eep_load = 1;
++
++        return ret;
++}
++
++static int __init of_ath9k_eeprom_init_late(void)
++{
++        if (!ath9k_eep_load)
++                return 0;
++        return platform_driver_probe(&ath9k_eeprom_driver, of_ath9k_eeprom_probe);
++}
++late_initcall(of_ath9k_eeprom_init_late);
++subsys_initcall(of_ath9k_eeprom_init);
++
++
++static int ath5k_pci_plat_dev_init(struct pci_dev *dev)
++{
++      dev->dev.platform_data = &ath5k_pdata;
++      return 0;
++}
++
++int __init of_ath5k_eeprom_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node, *mtd_np;
++      struct resource *eep_res, *mac_res = NULL;
++      void __iomem *eep, *mac;
++      int mac_offset;
++      u32 mac_inc = 0;
++      int i;
++      struct mtd_info *the_mtd;
++      size_t flash_readlen;
++      const __be32 *list;
++      const char *part;
++      phandle phandle;
++
++      if ((list = of_get_property(np, "ath,eep-flash", &i)) && i == 2 *
++                      sizeof(*list) && (phandle = be32_to_cpup(list++)) &&
++                      (mtd_np = of_find_node_by_phandle(phandle)) && ((part =
++                      of_get_property(mtd_np, "label", NULL)) || (part =
++                      mtd_np->name)) && (the_mtd = get_mtd_device_nm(part))
++                      != ERR_PTR(-ENODEV)) {
++              i = mtd_read(the_mtd, be32_to_cpup(list),
++                              ATH5K_PLAT_EEP_MAX_WORDS << 1, &flash_readlen,
++                              (void *) ath5k_pdata.eeprom_data);
++              put_mtd_device(the_mtd);
++              if ((sizeof(ATH5K_PLAT_EEP_MAX_WORDS << 1) != flash_readlen)
++                              || i) {
++                      dev_err(&pdev->dev, "failed to load eeprom from mtd\n");
++                      return -ENODEV;
++              }
++      } else {
++              eep_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++              mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++
++              if (!eep_res) {
++                      dev_err(&pdev->dev, "failed to load eeprom address\n");
++                      return -ENODEV;
++              }
++              if (resource_size(eep_res) != ATH5K_PLAT_EEP_MAX_WORDS << 1) {
++                      dev_err(&pdev->dev, "eeprom has an invalid size\n");
++                      return -EINVAL;
++              }
++
++              eep = ioremap(eep_res->start, resource_size(eep_res));
++              ath5k_pdata.eeprom_data = kmalloc(ATH5K_PLAT_EEP_MAX_WORDS<<1,
++                              GFP_KERNEL);
++              memcpy_fromio(ath5k_pdata.eeprom_data, eep,
++                              ATH5K_PLAT_EEP_MAX_WORDS << 1);
++      }
++
++      if (of_find_property(np, "ath,eep-swap", NULL))
++              for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS; i++)
++                      ath5k_pdata.eeprom_data[i] = swab16(ath5k_pdata.eeprom_data[i]);
++
++      if (!of_property_read_u32(np, "ath,mac-offset", &mac_offset)) {
++              memcpy_fromio(athxk_eeprom_mac, (void*) ath5k_pdata.eeprom_data + mac_offset, 6);
++      } else if (mac_res) {
++              if (resource_size(mac_res) != 6) {
++                      dev_err(&pdev->dev, "mac has an invalid size\n");
++                      return -EINVAL;
++              }
++              mac = ioremap(mac_res->start, resource_size(mac_res));
++              memcpy_fromio(athxk_eeprom_mac, mac, 6);
++      } else if (ltq_get_eth_mac())
++              memcpy(athxk_eeprom_mac, ltq_get_eth_mac(), 6);
++      else {
++              dev_warn(&pdev->dev, "using random mac\n");
++              random_ether_addr(athxk_eeprom_mac);
++      }
++
++      if (!of_property_read_u32(np, "ath,mac-increment", &mac_inc))
++              athxk_eeprom_mac[5] += mac_inc;
++
++      ath5k_pdata.macaddr = athxk_eeprom_mac;
++      ltq_pci_plat_dev_init = ath5k_pci_plat_dev_init;
++
++      dev_info(&pdev->dev, "loaded ath5k eeprom\n");
++
++      return 0;
++}
++
++static struct of_device_id ath5k_eeprom_ids[] = {
++      { .compatible = "ath5k,eeprom" },
++      { }
++};
++
++static struct platform_driver ath5k_eeprom_driver = {
++      .driver         = {
++              .name           = "ath5k,eeprom",
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(ath5k_eeprom_ids),
++      },
++};
++
++static int __init of_ath5k_eeprom_init(void)
++{
++      return platform_driver_probe(&ath5k_eeprom_driver, of_ath5k_eeprom_probe);
++}
++device_initcall(of_ath5k_eeprom_init);
+diff --git a/arch/mips/lantiq/xway/eth_mac.c b/arch/mips/lantiq/xway/eth_mac.c
+new file mode 100644
+index 0000000..d288a0e
+--- /dev/null
++++ b/arch/mips/lantiq/xway/eth_mac.c
+@@ -0,0 +1,76 @@
++/*
++ *  Copyright (C) 2012 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/init.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/if_ether.h>
++
++static u8 eth_mac[6];
++static int eth_mac_set;
++
++const u8* ltq_get_eth_mac(void)
++{
++      return eth_mac;
++}
++
++static int __init setup_ethaddr(char *str)
++{
++      eth_mac_set = mac_pton(str, eth_mac);
++      return !eth_mac_set;
++}
++__setup("ethaddr=", setup_ethaddr);
++
++int __init of_eth_mac_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      struct resource *mac_res;
++      void __iomem *mac;
++      u32 mac_inc = 0;
++
++      if (eth_mac_set) {
++              dev_err(&pdev->dev, "mac was already set by bootloader\n");
++              return -EINVAL;
++      }
++      mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++      if (!mac_res) {
++              dev_err(&pdev->dev, "failed to load mac\n");
++              return -EINVAL;
++      }
++      if (resource_size(mac_res) != 6) {
++              dev_err(&pdev->dev, "mac has an invalid size\n");
++              return -EINVAL;
++      }
++      mac = ioremap(mac_res->start, resource_size(mac_res));
++      memcpy_fromio(eth_mac, mac, 6);
++
++      if (!of_property_read_u32(np, "mac-increment", &mac_inc))
++              eth_mac[5] += mac_inc;
++
++      return 0;
++}
++
++static struct of_device_id eth_mac_ids[] = {
++      { .compatible = "lantiq,eth-mac" },
++      { /* sentinel */ }
++};
++
++static struct platform_driver eth_mac_driver = {
++      .driver         = {
++              .name           = "lantiq,eth-mac",
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(eth_mac_ids),
++      },
++};
++
++static int __init of_eth_mac_init(void)
++{
++      return platform_driver_probe(&eth_mac_driver, of_eth_mac_probe);
++}
++device_initcall(of_eth_mac_init);
+diff --git a/arch/mips/lantiq/xway/pci-ath-fixup.c b/arch/mips/lantiq/xway/pci-ath-fixup.c
+new file mode 100644
+index 0000000..c87ffb2
+--- /dev/null
++++ b/arch/mips/lantiq/xway/pci-ath-fixup.c
+@@ -0,0 +1,109 @@
++/*
++ *  Atheros AP94 reference board PCI initialization
++ *
++ *  Copyright (C) 2009-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.
++ */
++
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <lantiq_soc.h>
++
++#define LTQ_PCI_MEM_BASE              0x18000000
++
++struct ath_fixup {
++      u16             *cal_data;
++      unsigned        slot;
++};
++
++static int ath_num_fixups;
++static struct ath_fixup ath_fixups[2];
++
++static void ath_pci_fixup(struct pci_dev *dev)
++{
++      void __iomem *mem;
++      u16 *cal_data = NULL;
++      u16 cmd;
++      u32 bar0;
++      u32 val;
++      unsigned i;
++
++      for (i = 0; i < ath_num_fixups; i++) {
++              if (ath_fixups[i].cal_data == NULL)
++                      continue;
++
++              if (ath_fixups[i].slot != PCI_SLOT(dev->devfn))
++                      continue;
++
++              cal_data = ath_fixups[i].cal_data;
++              break;
++      }
++
++      if (cal_data == NULL)
++              return;
++
++      if (*cal_data != 0xa55a) {
++              pr_err("pci %s: invalid calibration data\n", pci_name(dev));
++              return;
++      }
++
++      pr_info("pci %s: fixup device configuration\n", pci_name(dev));
++
++      mem = ioremap(LTQ_PCI_MEM_BASE, 0x10000);
++      if (!mem) {
++              pr_err("pci %s: ioremap error\n", pci_name(dev));
++              return;
++      }
++
++      pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
++      pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, LTQ_PCI_MEM_BASE);
++      pci_read_config_word(dev, PCI_COMMAND, &cmd);
++      cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++      pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++      /* set pointer to first reg address */
++      cal_data += 3;
++      while (*cal_data != 0xffff) {
++              u32 reg;
++              reg = *cal_data++;
++              val = *cal_data++;
++              val |= (*cal_data++) << 16;
++
++              ltq_w32(swab32(val), mem + reg);
++              udelay(100);
++      }
++
++      pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
++      dev->vendor = val & 0xffff;
++      dev->device = (val >> 16) & 0xffff;
++
++      pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
++      dev->revision = val & 0xff;
++      dev->class = val >> 8; /* upper 3 bytes */
++
++      pr_info("pci %s: fixup info: [%04x:%04x] revision %02x class %#08x\n", 
++              pci_name(dev), dev->vendor, dev->device, dev->revision, dev->class);
++
++      pci_read_config_word(dev, PCI_COMMAND, &cmd);
++      cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
++      pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++      pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
++
++      iounmap(mem);
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath_pci_fixup);
++
++void __init ltq_pci_ath_fixup(unsigned slot, u16 *cal_data)
++{
++      if (ath_num_fixups >= ARRAY_SIZE(ath_fixups))
++              return;
++
++      ath_fixups[ath_num_fixups].slot = slot;
++      ath_fixups[ath_num_fixups].cal_data = cal_data;
++      ath_num_fixups++;
++}
+diff --git a/arch/mips/lantiq/xway/rt_eep.c b/arch/mips/lantiq/xway/rt_eep.c
+new file mode 100644
+index 0000000..00f2d4c
+--- /dev/null
++++ b/arch/mips/lantiq/xway/rt_eep.c
+@@ -0,0 +1,60 @@
++/*
++ *  Copyright (C) 2011 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/init.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/rt2x00_platform.h>
++
++extern int (*ltq_pci_plat_dev_init)(struct pci_dev *dev);
++static struct rt2x00_platform_data rt2x00_pdata;
++
++static int rt2x00_pci_plat_dev_init(struct pci_dev *dev)
++{
++      dev->dev.platform_data = &rt2x00_pdata;
++      return 0;
++}
++
++int __init of_ralink_eeprom_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      const char *eeprom;
++
++      if (of_property_read_string(np, "ralink,eeprom", &eeprom)) {
++              dev_err(&pdev->dev, "failed to load eeprom filename\n");
++              return 0;
++      }
++
++      rt2x00_pdata.eeprom_file_name = kstrdup(eeprom, GFP_KERNEL);
++//    rt2x00_pdata.mac_address = mac;
++      ltq_pci_plat_dev_init = rt2x00_pci_plat_dev_init;
++
++      dev_info(&pdev->dev, "using %s as eeprom\n", eeprom);
++
++      return 0;
++}
++
++static struct of_device_id ralink_eeprom_ids[] = {
++      { .compatible = "ralink,eeprom" },
++      { }
++};
++
++static struct platform_driver ralink_eeprom_driver = {
++      .driver         = {
++              .name           = "ralink,eeprom",
++              .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(ralink_eeprom_ids),
++      },
++};
++
++static int __init of_ralink_eeprom_init(void)
++{
++      return platform_driver_probe(&ralink_eeprom_driver, of_ralink_eeprom_probe);
++}
++device_initcall(of_ralink_eeprom_init);
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0036-owrt-generic-dtb-image-hack.patch b/target/linux/lantiq/patches-3.14/0036-owrt-generic-dtb-image-hack.patch
new file mode 100644 (file)
index 0000000..fba8bb3
--- /dev/null
@@ -0,0 +1,27 @@
+From dba8578e06aedf1e67312ebfc6162e2fadc9448d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 7 Aug 2014 18:32:12 +0200
+Subject: [PATCH 36/36] owrt: generic dtb image hack
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/kernel/head.S |    3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
+index 7b6a5b3..78518b8 100644
+--- a/arch/mips/kernel/head.S
++++ b/arch/mips/kernel/head.S
+@@ -101,6 +101,9 @@ FEXPORT(__kernel_entry)
+       j       kernel_entry
+ #endif
++      .ascii  "OWRTDTB:"
++      EXPORT(__image_dtb)
++      .fill   0x4000
+       __REF
+ NESTED(kernel_entry, 16, sp)                  # kernel entry point
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0037-MIPS-lantiq-move-eiu-init-after-irq_domain-register.patch b/target/linux/lantiq/patches-3.14/0037-MIPS-lantiq-move-eiu-init-after-irq_domain-register.patch
new file mode 100644 (file)
index 0000000..856733a
--- /dev/null
@@ -0,0 +1,79 @@
+From baea71233ed1796651cab6ead484a18666a765aa Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 11 Sep 2014 19:25:25 +0200
+Subject: [PATCH] MIPS: lantiq: move eiu init after irq_domain register
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/irq.c |   48 ++++++++++++++++++++++++------------------------
+ 1 file changed, 24 insertions(+), 24 deletions(-)
+
+diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
+index 6b94cc7..3bbedf6 100644
+--- a/arch/mips/lantiq/irq.c
++++ b/arch/mips/lantiq/irq.c
+@@ -380,30 +380,6 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
+                       panic("Failed to remap icu memory");
+       }
+-      /* the external interrupts are optional and xway only */
+-      eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
+-      if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
+-              /* find out how many external irq sources we have */
+-              exin_avail = of_irq_count(eiu_node);
+-
+-              if (exin_avail > MAX_EIU)
+-                      exin_avail = MAX_EIU;
+-
+-              ret = of_irq_to_resource_table(eiu_node,
+-                                              ltq_eiu_irq, exin_avail);
+-              if (ret != exin_avail)
+-                      panic("failed to load external irq resources");
+-
+-              if (request_mem_region(res.start, resource_size(&res),
+-                                                      res.name) < 0)
+-                      pr_err("Failed to request eiu memory");
+-
+-              ltq_eiu_membase = ioremap_nocache(res.start,
+-                                                      resource_size(&res));
+-              if (!ltq_eiu_membase)
+-                      panic("Failed to remap eiu memory");
+-      }
+-
+       /* turn off all irqs by default */
+       for (i = 0; i < MAX_IM; i++) {
+               /* make sure all irqs are turned off by default */
+@@ -460,6 +436,30 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
+       if (MIPS_CPU_TIMER_IRQ != 7)
+               irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ);
++      /* the external interrupts are optional and xway only */
++      eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
++      if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
++              /* find out how many external irq sources we have */
++              exin_avail = of_irq_count(eiu_node);
++
++              if (exin_avail > MAX_EIU)
++                      exin_avail = MAX_EIU;
++
++              ret = of_irq_to_resource_table(eiu_node,
++                                              ltq_eiu_irq, exin_avail);
++              if (ret != exin_avail)
++                      panic("failed to load external irq resources");
++
++              if (request_mem_region(res.start, resource_size(&res),
++                                                      res.name) < 0)
++                      pr_err("Failed to request eiu memory");
++
++              ltq_eiu_membase = ioremap_nocache(res.start,
++                                                      resource_size(&res));
++              if (!ltq_eiu_membase)
++                      panic("Failed to remap eiu memory");
++      }
++
+       return 0;
+ }
+-- 
+1.7.10.4
+
diff --git a/target/linux/lantiq/patches-3.14/0101-mtd-split.patch b/target/linux/lantiq/patches-3.14/0101-mtd-split.patch
new file mode 100644 (file)
index 0000000..e766207
--- /dev/null
@@ -0,0 +1,200 @@
+Index: linux-3.14.18/arch/mips/lantiq/xway/Makefile
+===================================================================
+--- linux-3.14.18.orig/arch/mips/lantiq/xway/Makefile  2014-09-11 16:31:10.000000000 +0200
++++ linux-3.14.18/arch/mips/lantiq/xway/Makefile       2014-09-11 16:32:52.188968735 +0200
+@@ -1,6 +1,6 @@
+ obj-y := prom.o sysctrl.o clk.o reset.o dma.o timer.o dcdc.o
+-obj-y += vmmc.o tffs.o
++obj-y += vmmc.o tffs.o mtd_split.o
+ obj-y += eth_mac.o
+ obj-$(CONFIG_PCI) += ath_eep.o rt_eep.o pci-ath-fixup.o
+Index: linux-3.14.18/arch/mips/lantiq/xway/mtd_split.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-3.14.18/arch/mips/lantiq/xway/mtd_split.c    2014-09-11 16:31:51.712967248 +0200
+@@ -0,0 +1,129 @@
++#include <linux/magic.h>
++#include <linux/root_dev.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++
++#define ROOTFS_SPLIT_NAME "rootfs_data"
++
++struct squashfs_super_block {
++      __le32 s_magic;
++      __le32 pad0[9];
++      __le64 bytes_used;
++};
++
++static void split_brnimage_kernel(struct mtd_info *master, const char *name,
++                                       int offset, int size)
++{
++      unsigned long buf[4];
++      // Assume at most 2MB of kernel image
++      unsigned long end = offset + (2 << 20);
++      unsigned long part_size = offset + 0x400 - 12;
++      size_t len;
++      int ret;
++
++      if (strcmp(name, "firmware") != 0)
++              return;
++      while (part_size < end) {
++              long size_min = part_size - 0x400 - 12 - offset;
++              long size_max = part_size + 12 - offset;
++              ret = mtd_read(master, part_size, 16, &len, (void *)buf);
++              if (ret || len != 16)
++                      return;
++
++              if (le32_to_cpu(buf[0]) < size_min ||
++                              le32_to_cpu(buf[0]) > size_max) {
++                      part_size += 0x400;
++                      continue;
++              }
++
++              if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC) {
++                      part_size += 12 - offset;
++                      __mtd_add_partition(master, "rootfs", offset + part_size,
++                                                  size - part_size, false);
++                      return;
++              }
++              part_size += 0x400;
++      }
++}
++
++static void split_eva_kernel(struct mtd_info *master, const char *name,
++                              int offset, int size)
++{
++#define EVA_MAGIC   0xfeed1281
++      unsigned long magic = 0;
++      unsigned long part_size = 0, p;
++      size_t len;
++      int ret;
++
++      if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
++              return;
++
++      ret = mtd_read(master, offset, 4, &len, (void *)&magic);
++      if (ret || len != sizeof(magic))
++              return;
++
++      if (le32_to_cpu(magic) != EVA_MAGIC)
++              return;
++
++      ret = mtd_read(master, offset + 4, 4, &len, (void *)&part_size);
++      if (ret || len != sizeof(part_size))
++              return;
++
++      p = part_size = le32_to_cpu(part_size) + 0x18;
++      p &= ~0xffff;
++      p += 0x10000;
++
++      ret = mtd_read(master, offset + p, 4, &len, (void *)&magic);
++      if (ret || len != sizeof(magic))
++              return;
++
++      if (magic == SQUASHFS_MAGIC)
++              part_size = p + 0x100;
++      else
++              part_size = mtd_pad_erasesize(master, offset, len);
++
++      if (part_size + master->erasesize > size)
++              return;
++
++      __mtd_add_partition(master, "rootfs", offset + part_size,
++                          size - part_size, false);
++}
++
++static void split_tplink_kernel(struct mtd_info *master, const char *name,
++                              int offset, int size)
++{
++#define TPLINK_MAGIC   0x00000002
++      unsigned long magic = 0;
++      unsigned long part_size = 0;
++      size_t len;
++      int ret;
++
++      if (strcmp(name, CONFIG_MTD_SPLIT_FIRMWARE_NAME) != 0)
++              return;
++
++      ret = mtd_read(master, offset, 4, &len, (void *)&magic);
++      if (ret || len != sizeof(magic))
++              return;
++
++      if (le32_to_cpu(magic) != TPLINK_MAGIC)
++              return;
++
++      ret = mtd_read(master, offset + 0x78, 4, &len, (void *)&part_size);
++      if (ret || len != sizeof(part_size))
++              return;
++
++      part_size = be32_to_cpu(part_size) + 0x200;
++      if (part_size + master->erasesize > size)
++              return;
++
++      __mtd_add_partition(master, "rootfs", offset + part_size,
++                          size - part_size, false);
++}
++
++void arch_split_mtd_part(struct mtd_info *master, const char *name,
++                              int offset, int size)
++{
++      split_tplink_kernel(master, name, offset, size);
++      split_eva_kernel(master, name, offset, size);
++      split_brnimage_kernel(master, name, offset, size);
++}
+Index: linux-3.14.18/include/linux/mtd/partitions.h
+===================================================================
+--- linux-3.14.18.orig/include/linux/mtd/partitions.h  2014-09-11 16:31:10.752966240 +0200
++++ linux-3.14.18/include/linux/mtd/partitions.h       2014-09-11 16:44:49.432986380 +0200
+@@ -89,12 +89,17 @@
+ int mtd_is_partition(const struct mtd_info *mtd);
+ int mtd_add_partition(struct mtd_info *master, const char *name,
+                     long long offset, long long length);
++int __mtd_add_partition(struct mtd_info *master, const char *name,
++                  long long offset, long long length, bool dup_check);
++
+ int mtd_del_partition(struct mtd_info *master, int partno);
+ struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
+ uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
+ uint64_t mtd_get_device_size(const struct mtd_info *mtd);
+-extern void __weak arch_split_mtd_part(struct mtd_info *master,
+-                                     const char *name, int offset, int size);
++void __weak arch_split_mtd_part(struct mtd_info *master,
++                                     const char *name, int offset, int size);
++unsigned long
++mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len);
+ int parse_mtd_partitions_by_type(struct mtd_info *master,
+                                enum mtd_parser_type type,
+Index: linux-3.14.18/drivers/mtd/mtdpart.c
+===================================================================
+--- linux-3.14.18.orig/drivers/mtd/mtdpart.c   2014-09-11 16:31:10.752966240 +0200
++++ linux-3.14.18/drivers/mtd/mtdpart.c        2014-09-11 16:33:11.732969216 +0200
+@@ -617,7 +617,7 @@
+ }
+-static int
++int
+ __mtd_add_partition(struct mtd_info *master, const char *name,
+                   long long offset, long long length, bool dup_check)
+ {
+@@ -738,7 +738,7 @@
+       return nr_parts;
+ }
+-static inline unsigned long
++unsigned long
+ mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
+ {
+       unsigned long mask = mtd->erasesize - 1;
+@@ -807,7 +807,6 @@
+               return;
+       len = be32_to_cpu(hdr.size) + 0x40;
+-      len = mtd_pad_erasesize(master, part->offset, len);
+       if (len + master->erasesize > part->mtd.size)
+               return;