+++ /dev/null
-From 9fff5375229a4ba3a200747e079c46fa19b90797 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Date: Fri, 20 Jun 2014 07:26:20 +0200
-Subject: [3.17][PATCH 1/2] MIPS: BCM47XX: Distinguish WRT54G series devices by
- boardtype
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Catalin reported that GPIOs used by bcm47xx don't match layout of his
-WRT54GS V1.0 board. It seems we need to distinguish these 54G* devices.
-
-Reported-by: Catalin Patulea <cat@vv.carleton.ca>
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
- arch/mips/bcm47xx/board.c | 6 +++---
- arch/mips/bcm47xx/buttons.c | 10 ++++++----
- arch/mips/bcm47xx/leds.c | 10 ++++++----
- arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 4 +++-
- 4 files changed, 18 insertions(+), 12 deletions(-)
-
---- a/arch/mips/bcm47xx/board.c
-+++ b/arch/mips/bcm47xx/board.c
-@@ -180,9 +180,9 @@ struct bcm47xx_board_type_list3 bcm47xx_
- {{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
- {{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
- {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
-- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
-- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
-- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
-+ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
-+ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
-+ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
- { {0}, NULL},
- };
-
---- a/arch/mips/bcm47xx/buttons.c
-+++ b/arch/mips/bcm47xx/buttons.c
-@@ -265,7 +265,7 @@ bcm47xx_buttons_linksys_wrt54g3gv2[] __i
- };
-
- static const struct gpio_keys_button
--bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
-+bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
- BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
- BCM47XX_GPIO_KEY(6, KEY_RESTART),
- };
-@@ -501,12 +501,14 @@ int __init bcm47xx_buttons_register(void
- case BCM47XX_BOARD_LINKSYS_WRT310NV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
- break;
-- case BCM47XX_BOARD_LINKSYS_WRT54G:
-- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
-- break;
- case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
- break;
-+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
-+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
-+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
-+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
-+ break;
- case BCM47XX_BOARD_LINKSYS_WRT610NV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
- break;
---- a/arch/mips/bcm47xx/leds.c
-+++ b/arch/mips/bcm47xx/leds.c
-@@ -292,7 +292,7 @@ bcm47xx_leds_linksys_wrt310nv1[] __initc
- };
-
- static const struct gpio_led
--bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
-+bcm47xx_leds_linksys_wrt54g_generic[] __initconst = {
- BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
- BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
- BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-@@ -538,12 +538,14 @@ void __init bcm47xx_leds_register(void)
- case BCM47XX_BOARD_LINKSYS_WRT310NV1:
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
- break;
-- case BCM47XX_BOARD_LINKSYS_WRT54G:
-- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
-- break;
- case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
- break;
-+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
-+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
-+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
-+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
-+ break;
- case BCM47XX_BOARD_LINKSYS_WRT610NV1:
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
- break;
---- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
-+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
-@@ -70,7 +70,9 @@ enum bcm47xx_board {
- BCM47XX_BOARD_LINKSYS_WRT310NV1,
- BCM47XX_BOARD_LINKSYS_WRT310NV2,
- BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
-- BCM47XX_BOARD_LINKSYS_WRT54G,
-+ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101,
-+ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467,
-+ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708,
- BCM47XX_BOARD_LINKSYS_WRT610NV1,
- BCM47XX_BOARD_LINKSYS_WRT610NV2,
- BCM47XX_BOARD_LINKSYS_WRTSL54GS,
--- /dev/null
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -59,12 +59,12 @@ static void bcm47xx_machine_restart(char
+ switch (bcm47xx_bus_type) {
+ #ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+- ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
++ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 3);
+ break;
+ #endif
+ #ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+- bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
++ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 3);
+ break;
+ #endif
+ }
+++ /dev/null
-From d12264ddf6c29ddab9889cd87a1e60d2209f9922 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Date: Fri, 20 Jun 2014 07:53:14 +0200
-Subject: [3.17][PATCH 2/2] MIPS: BCM47XX: Fix LEDs on WRT54GS V1.0
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reported-by: Catalin Patulea <cat@vv.carleton.ca>
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
- arch/mips/bcm47xx/leds.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/mips/bcm47xx/leds.c
-+++ b/arch/mips/bcm47xx/leds.c
-@@ -306,6 +306,14 @@ bcm47xx_leds_linksys_wrt54g3gv2[] __init
- BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
- };
-
-+/* Verified on: WRT54GS V1.0 */
-+static const struct gpio_led
-+bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = {
-+ BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
-+};
-+
- static const struct gpio_led
- bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
- BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
-@@ -542,6 +550,8 @@ void __init bcm47xx_leds_register(void)
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
- break;
- case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
-+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
-+ break;
- case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
- case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
--- /dev/null
+From 103c0bf3ff46486466bc9138d70c25133d516003 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Tue, 29 Jul 2014 00:08:01 +0200
+Subject: [PATCH] MIPS: BCM47XX: fixup broken MAC addresses in nvram
+
+The address prefix 00:90:4C is used by Broadcom in their initial
+configuration. When a mac address with the prefix 00:90:4C is used all
+devices from the same series are sharing the same mac address. To
+prevent mac address collisions we replace them with a mac address based
+on the base address. To generate such addresses we take the main mac
+address from et0macaddr and increase it by two for the first wifi
+device and by 3 for the second one. This matches the printed mac
+address on the device. The main mac address increased by one is used as
+wan address by the vendor code.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Cc: zajec5@gmail.com
+Cc: linux-mips@linux-mips.org
+Patchwork: https://patchwork.linux-mips.org/patch/7489/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm47xx/sprom.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+--- a/arch/mips/bcm47xx/sprom.c
++++ b/arch/mips/bcm47xx/sprom.c
+@@ -28,6 +28,8 @@
+
+ #include <bcm47xx.h>
+ #include <bcm47xx_nvram.h>
++#include <linux/if_ether.h>
++#include <linux/etherdevice.h>
+
+ static void create_key(const char *prefix, const char *postfix,
+ const char *name, char *buf, int len)
+@@ -631,6 +633,33 @@ static void bcm47xx_fill_sprom_path_r45(
+ }
+ }
+
++static bool bcm47xx_is_valid_mac(u8 *mac)
++{
++ return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
++}
++
++static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
++{
++ u8 *oui = mac + ETH_ALEN/2 - 1;
++ u8 *p = mac + ETH_ALEN - 1;
++
++ do {
++ (*p) += num;
++ if (*p > num)
++ break;
++ p--;
++ num = 1;
++ } while (p != oui);
++
++ if (p == oui) {
++ pr_err("unable to fetch mac address\n");
++ return -ENOENT;
++ }
++ return 0;
++}
++
++static int mac_addr_used = 2;
++
+ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
+ const char *prefix, bool fallback)
+ {
+@@ -648,6 +677,25 @@ static void bcm47xx_fill_sprom_ethernet(
+
+ nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
+ nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
++
++ /* The address prefix 00:90:4C is used by Broadcom in their initial
++ configuration. When a mac address with the prefix 00:90:4C is used
++ all devices from the same series are sharing the same mac address.
++ To prevent mac address collisions we replace them with a mac address
++ based on the base address. */
++ if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
++ u8 mac[6];
++
++ nvram_read_macaddr(NULL, "et0macaddr", mac, false);
++ if (bcm47xx_is_valid_mac(mac)) {
++ int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
++
++ if (!err) {
++ ether_addr_copy(sprom->il0mac, mac);
++ mac_addr_used++;
++ }
++ }
++ }
+ }
+
+ static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
+++ /dev/null
---- a/arch/mips/bcm47xx/leds.c
-+++ b/arch/mips/bcm47xx/leds.c
-@@ -35,6 +35,15 @@ bcm47xx_leds_asus_rtn12[] __initconst =
- };
-
- static const struct gpio_led
-+bcm47xx_leds_asus_rtn15u[] __initconst = {
-+ /* TODO: Add "wlan" LED */
-+ BCM47XX_GPIO_LED(3, "blue", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(4, "blue", "lan", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(9, "blue", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
-+};
-+
-+static const struct gpio_led
- bcm47xx_leds_asus_rtn16[] __initconst = {
- BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
- BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-@@ -42,8 +51,8 @@ bcm47xx_leds_asus_rtn16[] __initconst =
-
- static const struct gpio_led
- bcm47xx_leds_asus_rtn66u[] __initconst = {
-- BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-- BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(12, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(15, "blue", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
- };
-
- static const struct gpio_led
-@@ -216,8 +225,8 @@ bcm47xx_leds_linksys_e1000v1[] __initcon
-
- static const struct gpio_led
- bcm47xx_leds_linksys_e1000v21[] __initconst = {
-- BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-- BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(5, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
- BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
- BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
- };
-@@ -314,6 +323,16 @@ bcm47xx_leds_linksys_wrt54g_type_0101[]
- BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
- };
-
-+/* Verified on: WRT54GL V1.1 */
-+static const struct gpio_led
-+bcm47xx_leds_linksys_wrt54g_type_0467[] __initconst = {
-+ BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
-+};
-+
- static const struct gpio_led
- bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
- BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
-@@ -333,11 +352,10 @@ bcm47xx_leds_linksys_wrt610nv2[] __initc
-
- static const struct gpio_led
- bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
-- BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
-- BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-- BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-- BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-- BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(0, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
- };
-
- /* Motorola */
-@@ -385,6 +403,15 @@ bcm47xx_leds_netgear_wndr4500v1[] __init
- };
-
- static const struct gpio_led
-+bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
-+ BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(2, "green", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
-+ BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-+ BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
-+};
-+
-+static const struct gpio_led
- bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
- BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
- BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
-@@ -425,6 +452,9 @@ void __init bcm47xx_leds_register(void)
- case BCM47XX_BOARD_ASUS_RTN12:
- bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
- break;
-+ case BCM47XX_BOARD_ASUS_RTN15U:
-+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn15u);
-+ break;
- case BCM47XX_BOARD_ASUS_RTN16:
- bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
- break;
-@@ -553,6 +583,8 @@ void __init bcm47xx_leds_register(void)
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
- break;
- case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
-+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0467);
-+ break;
- case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
- break;
-@@ -582,6 +614,9 @@ void __init bcm47xx_leds_register(void)
- case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
- bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
- break;
-+ case BCM47XX_BOARD_NETGEAR_WNR3500L:
-+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
-+ break;
- case BCM47XX_BOARD_NETGEAR_WNR834BV2:
- bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
- break;
---- a/arch/mips/bcm47xx/buttons.c
-+++ b/arch/mips/bcm47xx/buttons.c
-@@ -329,6 +329,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __i
- };
-
- static const struct gpio_keys_button
-+bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
-+ BCM47XX_GPIO_KEY(4, KEY_RESTART),
-+ BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
-+};
-+
-+static const struct gpio_keys_button
- bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
- BCM47XX_GPIO_KEY(6, KEY_RESTART),
- };
-@@ -538,6 +544,9 @@ int __init bcm47xx_buttons_register(void
- case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
- break;
-+ case BCM47XX_BOARD_NETGEAR_WNR3500L:
-+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
-+ break;
- case BCM47XX_BOARD_NETGEAR_WNR834BV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
- break;
--- /dev/null
+From 250dc03727b9cce91bd86091f05bf2443e2be9ec Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Tue, 29 Jul 2014 00:12:09 +0200
+Subject: [PATCH] MIPS: BCM47XX: add Microsoft MN-700 and Asus WL500G
+
+This patch adds detection for the Microsoft MN-700 and the Asus WL500G
+router. This is based on some old code from OpenWrt.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Cc: zajec5@gmail.com
+Cc: linux-mips@linux-mips.org
+Patchwork: https://patchwork.linux-mips.org/patch/7490/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm47xx/board.c | 17 +++++++++++++++++
+ arch/mips/bcm47xx/buttons.c | 19 +++++++++++++++++++
+ arch/mips/bcm47xx/leds.c | 19 +++++++++++++++++++
+ arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 3 +++
+ 4 files changed, 58 insertions(+)
+
+--- a/arch/mips/bcm47xx/board.c
++++ b/arch/mips/bcm47xx/board.c
+@@ -80,6 +80,14 @@ struct bcm47xx_board_type_list1 bcm47xx_
+ { {0}, NULL},
+ };
+
++/* hardware_version, boardnum */
++static const
++struct bcm47xx_board_type_list2 bcm47xx_board_list_hw_version_num[] __initconst = {
++ {{BCM47XX_BOARD_MICROSOFT_MN700, "Microsoft MN-700"}, "WL500-", "mn700"},
++ {{BCM47XX_BOARD_ASUS_WL500G, "Asus WL500G"}, "WL500-", "asusX"},
++ { {0}, NULL},
++};
++
+ /* productid */
+ static const
+ struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
+@@ -237,6 +245,15 @@ static __init const struct bcm47xx_board
+ }
+ }
+
++ if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
++ bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
++ for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
++ if (!strstarts(buf1, e2->value1) &&
++ !strcmp(buf2, e2->value2))
++ return &e2->board;
++ }
++ }
++
+ if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+--- a/arch/mips/bcm47xx/buttons.c
++++ b/arch/mips/bcm47xx/buttons.c
+@@ -56,6 +56,11 @@ bcm47xx_buttons_asus_wl330ge[] __initcon
+ };
+
+ static const struct gpio_keys_button
++bcm47xx_buttons_asus_wl500g[] __initconst = {
++ BCM47XX_GPIO_KEY(6, KEY_RESTART),
++};
++
++static const struct gpio_keys_button
+ bcm47xx_buttons_asus_wl500gd[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ };
+@@ -288,6 +293,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __in
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ };
+
++/* Microsoft */
++
++static const struct gpio_keys_button
++bcm47xx_buttons_microsoft_nm700[] __initconst = {
++ BCM47XX_GPIO_KEY(7, KEY_RESTART),
++};
++
+ /* Motorola */
+
+ static const struct gpio_keys_button
+@@ -395,6 +407,9 @@ int __init bcm47xx_buttons_register(void
+ case BCM47XX_BOARD_ASUS_WL330GE:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
+ break;
++ case BCM47XX_BOARD_ASUS_WL500G:
++ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
++ break;
+ case BCM47XX_BOARD_ASUS_WL500GD:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
+ break;
+@@ -517,6 +532,10 @@ int __init bcm47xx_buttons_register(void
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
+ break;
+
++ case BCM47XX_BOARD_MICROSOFT_MN700:
++ err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
++ break;
++
+ case BCM47XX_BOARD_MOTOROLA_WE800G:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
+ break;
+--- a/arch/mips/bcm47xx/leds.c
++++ b/arch/mips/bcm47xx/leds.c
+@@ -64,6 +64,11 @@ bcm47xx_leds_asus_wl330ge[] __initconst
+ };
+
+ static const struct gpio_led
++bcm47xx_leds_asus_wl500g[] __initconst = {
++ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
++};
++
++static const struct gpio_led
+ bcm47xx_leds_asus_wl500gd[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ };
+@@ -332,6 +337,13 @@ bcm47xx_leds_linksys_wrtsl54gs[] __initc
+ BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ };
+
++/* Microsoft */
++
++static const struct gpio_led
++bcm47xx_leds_microsoft_nm700[] __initconst = {
++ BCM47XX_GPIO_LED(6, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
++};
++
+ /* Motorola */
+
+ static const struct gpio_led
+@@ -432,6 +444,9 @@ void __init bcm47xx_leds_register(void)
+ case BCM47XX_BOARD_ASUS_WL330GE:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
+ break;
++ case BCM47XX_BOARD_ASUS_WL500G:
++ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500g);
++ break;
+ case BCM47XX_BOARD_ASUS_WL500GD:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
+ break;
+@@ -554,6 +569,10 @@ void __init bcm47xx_leds_register(void)
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
+ break;
+
++ case BCM47XX_BOARD_MICROSOFT_MN700:
++ bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
++ break;
++
+ case BCM47XX_BOARD_MOTOROLA_WE800G:
+ bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
+ break;
+--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+@@ -18,6 +18,7 @@ enum bcm47xx_board {
+ BCM47XX_BOARD_ASUS_WL300G,
+ BCM47XX_BOARD_ASUS_WL320GE,
+ BCM47XX_BOARD_ASUS_WL330GE,
++ BCM47XX_BOARD_ASUS_WL500G,
+ BCM47XX_BOARD_ASUS_WL500GD,
+ BCM47XX_BOARD_ASUS_WL500GPV1,
+ BCM47XX_BOARD_ASUS_WL500GPV2,
+@@ -75,6 +76,8 @@ enum bcm47xx_board {
+ BCM47XX_BOARD_LINKSYS_WRT610NV2,
+ BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+
++ BCM47XX_BOARD_MICROSOFT_MN700,
++
+ BCM47XX_BOARD_MOTOROLA_WE800G,
+ BCM47XX_BOARD_MOTOROLA_WR850GP,
+ BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
+++ /dev/null
-From 3d0704e7d371ea3ea5c8fe5bd796f5f15d44da59 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 12 Jul 2014 18:01:32 +0200
-Subject: [PATCH 3/5] MIPS: BCM47XX: fix detection of Asus RT-N10D
-
-Sometimes we do not have a productid, but only a hardware_version.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- arch/mips/bcm47xx/board.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/mips/bcm47xx/board.c
-+++ b/arch/mips/bcm47xx/board.c
-@@ -58,6 +58,7 @@ struct bcm47xx_board_type_list1 bcm47xx_
- static const
- struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
- {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
-+ {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RTN10D"},
- {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
- {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
- {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
--- /dev/null
+From 41a867cb07443c77c24747dcbad1a40002516469 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Fri, 20 Jun 2014 07:56:39 +0200
+Subject: [PATCH] MIPS: BCM47xx: Distinguish WRT54G series devices by boardtype
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Catalin reported that GPIOs used by bcm47xx don't match layout of his
+WRT54GS V1.0 board. It seems we need to distinguish these 54G* devices.
+
+Reported-by: Catalin Patulea <cat@vv.carleton.ca>
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Hauke Mehrtens <hauke@hauke-m.de>
+Patchwork: https://patchwork.linux-mips.org/patch/7112/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm47xx/board.c | 6 +++---
+ arch/mips/bcm47xx/buttons.c | 10 ++++++----
+ arch/mips/bcm47xx/leds.c | 10 ++++++----
+ arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 4 +++-
+ 4 files changed, 18 insertions(+), 12 deletions(-)
+
+--- a/arch/mips/bcm47xx/board.c
++++ b/arch/mips/bcm47xx/board.c
+@@ -188,9 +188,9 @@ struct bcm47xx_board_type_list3 bcm47xx_
+ {{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
+ {{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
+- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
+- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
+- {{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
++ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
++ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
++ {{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
+ { {0}, NULL},
+ };
+
+--- a/arch/mips/bcm47xx/buttons.c
++++ b/arch/mips/bcm47xx/buttons.c
+@@ -270,7 +270,7 @@ bcm47xx_buttons_linksys_wrt54g3gv2[] __i
+ };
+
+ static const struct gpio_keys_button
+-bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
++bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ };
+@@ -516,12 +516,14 @@ int __init bcm47xx_buttons_register(void
+ case BCM47XX_BOARD_LINKSYS_WRT310NV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
+ break;
+- case BCM47XX_BOARD_LINKSYS_WRT54G:
+- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
+- break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
+ break;
++ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
++ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
++ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
++ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
++ break;
+ case BCM47XX_BOARD_LINKSYS_WRT610NV1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
+ break;
+--- a/arch/mips/bcm47xx/leds.c
++++ b/arch/mips/bcm47xx/leds.c
+@@ -297,7 +297,7 @@ bcm47xx_leds_linksys_wrt310nv1[] __initc
+ };
+
+ static const struct gpio_led
+-bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
++bcm47xx_leds_linksys_wrt54g_generic[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+@@ -553,12 +553,14 @@ void __init bcm47xx_leds_register(void)
+ case BCM47XX_BOARD_LINKSYS_WRT310NV1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
+ break;
+- case BCM47XX_BOARD_LINKSYS_WRT54G:
+- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
+- break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
+ break;
++ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
++ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
++ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
++ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
++ break;
+ case BCM47XX_BOARD_LINKSYS_WRT610NV1:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
+ break;
+--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+@@ -71,7 +71,9 @@ enum bcm47xx_board {
+ BCM47XX_BOARD_LINKSYS_WRT310NV1,
+ BCM47XX_BOARD_LINKSYS_WRT310NV2,
+ BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
+- BCM47XX_BOARD_LINKSYS_WRT54G,
++ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101,
++ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467,
++ BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708,
+ BCM47XX_BOARD_LINKSYS_WRT610NV1,
+ BCM47XX_BOARD_LINKSYS_WRT610NV2,
+ BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+++ /dev/null
-From 9ccf31da4cac8fdb58d3d47f21b9fc7d2857026d Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Mon, 14 Jul 2014 23:15:32 +0200
-Subject: [PATCH 4/5] MIPS: BCM47XX: fix name of Dell TrueMobile 2300
-
-This looks like a copy and paste error in the initial version.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- arch/mips/bcm47xx/board.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/mips/bcm47xx/board.c
-+++ b/arch/mips/bcm47xx/board.c
-@@ -99,7 +99,7 @@ struct bcm47xx_board_type_list1 bcm47xx_
- /* ModelId */
- static const
- struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
-- {{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
-+ {{BCM47XX_BOARD_DELL_TM2300, "Dell TrueMobile 2300"}, "WX-5565"},
- {{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
- {{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
- {{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
--- /dev/null
+From 7bb26b1691166d0d830c42c1a25caf82208bf90d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Fri, 20 Jun 2014 07:56:40 +0200
+Subject: [PATCH] MIPS: BCM47xx: Fix LEDs on WRT54GS V1.0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reported-by: Catalin Patulea <cat@vv.carleton.ca>
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
+Cc: linux-mips@linux-mips.org
+Cc: Hauke Mehrtens <hauke@hauke-m.de>
+Patchwork: https://patchwork.linux-mips.org/patch/7113/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm47xx/leds.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/mips/bcm47xx/leds.c
++++ b/arch/mips/bcm47xx/leds.c
+@@ -311,6 +311,14 @@ bcm47xx_leds_linksys_wrt54g3gv2[] __init
+ BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
+ };
+
++/* Verified on: WRT54GS V1.0 */
++static const struct gpio_led
++bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = {
++ BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
++};
++
+ static const struct gpio_led
+ bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+@@ -557,6 +565,8 @@ void __init bcm47xx_leds_register(void)
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
++ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
++ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
+++ /dev/null
-From 35661c37bde151764e8526e77d4e02ca77e19160 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Mon, 14 Jul 2014 23:32:10 +0200
-Subject: [PATCH 5/5] MIPS: BCM47XX: add some more devices
-
-This adds Microsoft MN-700 and Asus WL500G.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- arch/mips/bcm47xx/board.c | 17 +++++++++++++++++
- arch/mips/bcm47xx/buttons.c | 19 +++++++++++++++++++
- arch/mips/bcm47xx/leds.c | 19 +++++++++++++++++++
- arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 3 +++
- 4 files changed, 58 insertions(+)
-
---- a/arch/mips/bcm47xx/board.c
-+++ b/arch/mips/bcm47xx/board.c
-@@ -81,6 +81,14 @@ struct bcm47xx_board_type_list1 bcm47xx_
- { {0}, NULL},
- };
-
-+/* hardware_version, boardnum */
-+static const
-+struct bcm47xx_board_type_list2 bcm47xx_board_list_hw_version_num[] __initconst = {
-+ {{BCM47XX_BOARD_MICROSOFT_MN700, "Microsoft MN-700"}, "WL500-", "mn700"},
-+ {{BCM47XX_BOARD_ASUS_WL500G, "Asus WL500G"}, "WL500-", "asusX"},
-+ { {0}, NULL},
-+};
-+
- /* productid */
- static const
- struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
-@@ -238,6 +246,15 @@ static __init const struct bcm47xx_board
- }
- }
-
-+ if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
-+ bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
-+ for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
-+ if (!strstarts(buf1, e2->value1) &&
-+ !strcmp(buf2, e2->value2))
-+ return &e2->board;
-+ }
-+ }
-+
- if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
- for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
- if (!strcmp(buf1, e1->value1))
---- a/arch/mips/bcm47xx/buttons.c
-+++ b/arch/mips/bcm47xx/buttons.c
-@@ -56,6 +56,11 @@ bcm47xx_buttons_asus_wl330ge[] __initcon
- };
-
- static const struct gpio_keys_button
-+bcm47xx_buttons_asus_wl500g[] __initconst = {
-+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
-+};
-+
-+static const struct gpio_keys_button
- bcm47xx_buttons_asus_wl500gd[] __initconst = {
- BCM47XX_GPIO_KEY(6, KEY_RESTART),
- };
-@@ -288,6 +293,13 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __in
- BCM47XX_GPIO_KEY(6, KEY_RESTART),
- };
-
-+/* Microsoft */
-+
-+static const struct gpio_keys_button
-+bcm47xx_buttons_microsoft_nm700[] __initconst = {
-+ BCM47XX_GPIO_KEY(7, KEY_RESTART),
-+};
-+
- /* Motorola */
-
- static const struct gpio_keys_button
-@@ -401,6 +413,9 @@ int __init bcm47xx_buttons_register(void
- case BCM47XX_BOARD_ASUS_WL330GE:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
- break;
-+ case BCM47XX_BOARD_ASUS_WL500G:
-+ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
-+ break;
- case BCM47XX_BOARD_ASUS_WL500GD:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
- break;
-@@ -525,6 +540,10 @@ int __init bcm47xx_buttons_register(void
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
- break;
-
-+ case BCM47XX_BOARD_MICROSOFT_MN700:
-+ err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
-+ break;
-+
- case BCM47XX_BOARD_MOTOROLA_WE800G:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
- break;
---- a/arch/mips/bcm47xx/leds.c
-+++ b/arch/mips/bcm47xx/leds.c
-@@ -73,6 +73,11 @@ bcm47xx_leds_asus_wl330ge[] __initconst
- };
-
- static const struct gpio_led
-+bcm47xx_leds_asus_wl500g[] __initconst = {
-+ BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-+};
-+
-+static const struct gpio_led
- bcm47xx_leds_asus_wl500gd[] __initconst = {
- BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
- };
-@@ -358,6 +363,13 @@ bcm47xx_leds_linksys_wrtsl54gs[] __initc
- BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
- };
-
-+/* Microsoft */
-+
-+static const struct gpio_led
-+bcm47xx_leds_microsoft_nm700[] __initconst = {
-+ BCM47XX_GPIO_LED(6, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-+};
-+
- /* Motorola */
-
- static const struct gpio_led
-@@ -470,6 +482,9 @@ void __init bcm47xx_leds_register(void)
- case BCM47XX_BOARD_ASUS_WL330GE:
- bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
- break;
-+ case BCM47XX_BOARD_ASUS_WL500G:
-+ bcm47xx_set_pdata(bcm47xx_leds_asus_wl500g);
-+ break;
- case BCM47XX_BOARD_ASUS_WL500GD:
- bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
- break;
-@@ -598,6 +613,10 @@ void __init bcm47xx_leds_register(void)
- bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
- break;
-
-+ case BCM47XX_BOARD_MICROSOFT_MN700:
-+ bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
-+ break;
-+
- case BCM47XX_BOARD_MOTOROLA_WE800G:
- bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
- break;
---- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
-+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
-@@ -18,6 +18,7 @@ enum bcm47xx_board {
- BCM47XX_BOARD_ASUS_WL300G,
- BCM47XX_BOARD_ASUS_WL320GE,
- BCM47XX_BOARD_ASUS_WL330GE,
-+ BCM47XX_BOARD_ASUS_WL500G,
- BCM47XX_BOARD_ASUS_WL500GD,
- BCM47XX_BOARD_ASUS_WL500GPV1,
- BCM47XX_BOARD_ASUS_WL500GPV2,
-@@ -77,6 +78,8 @@ enum bcm47xx_board {
- BCM47XX_BOARD_LINKSYS_WRT610NV2,
- BCM47XX_BOARD_LINKSYS_WRTSL54GS,
-
-+ BCM47XX_BOARD_MICROSOFT_MN700,
-+
- BCM47XX_BOARD_MOTOROLA_WE800G,
- BCM47XX_BOARD_MOTOROLA_WR850GP,
- BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
+++ /dev/null
---- a/arch/mips/include/asm/r4kcache.h
-+++ b/arch/mips/include/asm/r4kcache.h
-@@ -18,6 +18,20 @@
- #include <asm/cpu-type.h>
- #include <asm/mipsmtregs.h>
-
-+#ifdef CONFIG_BCM47XX
-+#include <asm/paccess.h>
-+#include <linux/ssb/ssb.h>
-+#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE)))
-+
-+#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
-+#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
-+#else
-+#define BCM4710_DUMMY_RREG()
-+
-+#define BCM4710_FILL_TLB(addr)
-+#define BCM4710_PROTECTED_FILL_TLB(addr)
-+#endif
-+
- /*
- * This macro return a properly sign-extended address suitable as base address
- * for indexed cache operations. Two issues here:
-@@ -151,6 +165,7 @@ static inline void flush_icache_line_ind
- static inline void flush_dcache_line_indexed(unsigned long addr)
- {
- __dflush_prologue
-+ BCM4710_DUMMY_RREG();
- cache_op(Index_Writeback_Inv_D, addr);
- __dflush_epilogue
- }
-@@ -178,6 +193,7 @@ static inline void flush_icache_line(uns
- static inline void flush_dcache_line(unsigned long addr)
- {
- __dflush_prologue
-+ BCM4710_DUMMY_RREG();
- cache_op(Hit_Writeback_Inv_D, addr);
- __dflush_epilogue
- }
-@@ -185,6 +201,7 @@ static inline void flush_dcache_line(uns
- static inline void invalidate_dcache_line(unsigned long addr)
- {
- __dflush_prologue
-+ BCM4710_DUMMY_RREG();
- cache_op(Hit_Invalidate_D, addr);
- __dflush_epilogue
- }
-@@ -223,6 +240,7 @@ static inline void protected_flush_icach
- break;
-
- default:
-+ BCM4710_DUMMY_RREG();
- protected_cache_op(Hit_Invalidate_I, addr);
- break;
- }
-@@ -236,6 +254,7 @@ static inline void protected_flush_icach
- */
- static inline void protected_writeback_dcache_line(unsigned long addr)
- {
-+ BCM4710_DUMMY_RREG();
- protected_cache_op(Hit_Writeback_Inv_D, addr);
- }
-
-@@ -356,8 +375,51 @@ static inline void invalidate_tcache_pag
- : "r" (base), \
- "i" (op));
-
-+static inline void blast_dcache(void)
-+{
-+ unsigned long start = KSEG0;
-+ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
-+ unsigned long end = (start + dcache_size);
-+
-+ do {
-+ BCM4710_DUMMY_RREG();
-+ cache_op(Index_Writeback_Inv_D, start);
-+ start += current_cpu_data.dcache.linesz;
-+ } while(start < end);
-+}
-+
-+static inline void blast_dcache_page(unsigned long page)
-+{
-+ unsigned long start = page;
-+ unsigned long end = start + PAGE_SIZE;
-+
-+ BCM4710_FILL_TLB(start);
-+ do {
-+ BCM4710_DUMMY_RREG();
-+ cache_op(Hit_Writeback_Inv_D, start);
-+ start += current_cpu_data.dcache.linesz;
-+ } while(start < end);
-+}
-+
-+static inline void blast_dcache_page_indexed(unsigned long page)
-+{
-+ unsigned long start = page;
-+ unsigned long end = start + PAGE_SIZE;
-+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
-+ unsigned long ws_end = current_cpu_data.dcache.ways <<
-+ current_cpu_data.dcache.waybit;
-+ unsigned long ws, addr;
-+ for (ws = 0; ws < ws_end; ws += ws_inc) {
-+ start = page + ws;
-+ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
-+ BCM4710_DUMMY_RREG();
-+ cache_op(Index_Writeback_Inv_D, addr);
-+ }
-+ }
-+}
-+
- /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
--#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \
-+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra, war) \
- static inline void extra##blast_##pfx##cache##lsize(void) \
- { \
- unsigned long start = INDEX_BASE; \
-@@ -369,6 +431,7 @@ static inline void extra##blast_##pfx##c
- \
- __##pfx##flush_prologue \
- \
-+ war \
- for (ws = 0; ws < ws_end; ws += ws_inc) \
- for (addr = start; addr < end; addr += lsize * 32) \
- cache##lsize##_unroll32(addr|ws, indexop); \
-@@ -383,6 +446,7 @@ static inline void extra##blast_##pfx##c
- \
- __##pfx##flush_prologue \
- \
-+ war \
- do { \
- cache##lsize##_unroll32(start, hitop); \
- start += lsize * 32; \
-@@ -401,6 +465,8 @@ static inline void extra##blast_##pfx##c
- current_cpu_data.desc.waybit; \
- unsigned long ws, addr; \
- \
-+ war \
-+ \
- __##pfx##flush_prologue \
- \
- for (ws = 0; ws < ws_end; ws += ws_inc) \
-@@ -410,37 +476,40 @@ static inline void extra##blast_##pfx##c
- __##pfx##flush_epilogue \
- }
-
--__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
--__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
--__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
--__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
--__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
--__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
--__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
--__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
--__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
--__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
--__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
--
--__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
--__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
--__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
--__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
--__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
--__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
-+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, , )
-+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, , BCM4710_FILL_TLB(start);)
-+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, , )
-+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, , )
-+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, , BCM4710_FILL_TLB(start);)
-+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_, BCM4710_FILL_TLB(start);)
-+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, , )
-+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, , )
-+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, , BCM4710_FILL_TLB(start);)
-+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, , )
-+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, , )
-+
-+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, , )
-+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, , )
-+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, , )
-+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, , )
-+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, , )
-+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, , )
-+
-
- /* build blast_xxx_range, protected_blast_xxx_range */
--#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \
-+#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra, war, war2) \
- static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \
- unsigned long end) \
- { \
- unsigned long lsize = cpu_##desc##_line_size(); \
- unsigned long addr = start & ~(lsize - 1); \
- unsigned long aend = (end - 1) & ~(lsize - 1); \
-+ war \
- \
- __##pfx##flush_prologue \
- \
- while (1) { \
-+ war2 \
- prot##cache_op(hitop, addr); \
- if (addr == aend) \
- break; \
-@@ -450,15 +519,15 @@ static inline void prot##extra##blast_##
- __##pfx##flush_epilogue \
- }
-
--__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
--__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
--__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
-+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, , BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
-+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, , , )
-+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, , , )
- __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
-- protected_, loongson2_)
--__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
--__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
-+ protected_, loongson2_, , )
-+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
-+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , , , )
- /* blast_inv_dcache_range */
--__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
--__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
-+__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , , , BCM4710_DUMMY_RREG();)
-+__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , , , )
-
- #endif /* _ASM_R4KCACHE_H */
---- a/arch/mips/include/asm/stackframe.h
-+++ b/arch/mips/include/asm/stackframe.h
-@@ -436,6 +436,10 @@
- .macro RESTORE_SP_AND_RET
- LONG_L sp, PT_R29(sp)
- .set mips3
-+#ifdef CONFIG_BCM47XX
-+ nop
-+ nop
-+#endif
- eret
- .set mips0
- .endm
---- a/arch/mips/kernel/genex.S
-+++ b/arch/mips/kernel/genex.S
-@@ -46,6 +46,10 @@
- NESTED(except_vec3_generic, 0, sp)
- .set push
- .set noat
-+#ifdef CONFIG_BCM47XX
-+ nop
-+ nop
-+#endif
- #if R5432_CP0_INTERRUPT_WAR
- mfc0 k0, CP0_INDEX
- #endif
---- a/arch/mips/mm/c-r4k.c
-+++ b/arch/mips/mm/c-r4k.c
-@@ -37,6 +37,9 @@
- #include <asm/traps.h>
- #include <asm/dma-coherence.h>
-
-+/* For enabling BCM4710 cache workarounds */
-+int bcm4710 = 0;
-+
- /*
- * Special Variant of smp_call_function for use by cache functions:
- *
-@@ -113,6 +116,9 @@ static void r4k_blast_dcache_page_setup(
- {
- unsigned long dc_lsize = cpu_dcache_line_size();
-
-+ if (bcm4710)
-+ r4k_blast_dcache_page = blast_dcache_page;
-+ else
- if (dc_lsize == 0)
- r4k_blast_dcache_page = (void *)cache_noop;
- else if (dc_lsize == 16)
-@@ -129,6 +135,9 @@ static void r4k_blast_dcache_page_indexe
- {
- unsigned long dc_lsize = cpu_dcache_line_size();
-
-+ if (bcm4710)
-+ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
-+ else
- if (dc_lsize == 0)
- r4k_blast_dcache_page_indexed = (void *)cache_noop;
- else if (dc_lsize == 16)
-@@ -146,6 +155,9 @@ static void r4k_blast_dcache_setup(void)
- {
- unsigned long dc_lsize = cpu_dcache_line_size();
-
-+ if (bcm4710)
-+ r4k_blast_dcache = blast_dcache;
-+ else
- if (dc_lsize == 0)
- r4k_blast_dcache = (void *)cache_noop;
- else if (dc_lsize == 16)
-@@ -703,6 +715,8 @@ static void local_r4k_flush_cache_sigtra
- unsigned long addr = (unsigned long) arg;
-
- R4600_HIT_CACHEOP_WAR_IMPL;
-+ BCM4710_PROTECTED_FILL_TLB(addr);
-+ BCM4710_PROTECTED_FILL_TLB(addr + 4);
- if (dc_lsize)
- protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
- if (!cpu_icache_snoops_remote_store && scache_size)
-@@ -1403,6 +1417,17 @@ static void coherency_setup(void)
- * silly idea of putting something else there ...
- */
- switch (current_cpu_type()) {
-+ case CPU_BMIPS3300:
-+ {
-+ u32 cm;
-+ cm = read_c0_diag();
-+ /* Enable icache */
-+ cm |= (1 << 31);
-+ /* Enable dcache */
-+ cm |= (1 << 30);
-+ write_c0_diag(cm);
-+ }
-+ break;
- case CPU_R4000PC:
- case CPU_R4000SC:
- case CPU_R4000MC:
-@@ -1449,6 +1474,15 @@ void r4k_cache_init(void)
- extern void build_copy_page(void);
- struct cpuinfo_mips *c = ¤t_cpu_data;
-
-+ /* Check if special workarounds are required */
-+#ifdef CONFIG_BCM47XX
-+ if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) {
-+ printk("Enabling BCM4710A0 cache workarounds.\n");
-+ bcm4710 = 1;
-+ } else
-+#endif
-+ bcm4710 = 0;
-+
- probe_pcache();
- setup_scache();
-
-@@ -1514,6 +1548,14 @@ void r4k_cache_init(void)
- */
- local_r4k___flush_cache_all(NULL);
-
-+#ifdef CONFIG_BCM47XX
-+ {
-+ static void (*_coherency_setup)(void);
-+ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
-+ _coherency_setup();
-+ }
-+#else
- coherency_setup();
-+#endif
- board_cache_error_setup = r4k_cache_error_setup;
- }
---- a/arch/mips/mm/tlbex.c
-+++ b/arch/mips/mm/tlbex.c
-@@ -1277,6 +1277,9 @@ static void build_r4000_tlb_refill_handl
- /* No need for uasm_i_nop */
- }
-
-+#ifdef CONFIG_BCM47XX
-+ uasm_i_nop(&p);
-+#endif
- #ifdef CONFIG_64BIT
- build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
- #else
-@@ -1835,6 +1838,9 @@ build_r4000_tlbchange_handler_head(u32 *
- {
- struct work_registers wr = build_get_work_registers(p);
-
-+#ifdef CONFIG_BCM47XX
-+ uasm_i_nop(p);
-+#endif
- #ifdef CONFIG_64BIT
- build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
- #else
--- /dev/null
+From 9194b3431616567ffbf69ef970506d695912be0b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Thu, 17 Jul 2014 23:24:30 +0200
+Subject: [PATCH] MIPS: BCM47XX: Devices database update for 3.17
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Detect more devices and register leds & buttons for them.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Cc: linux-mips@linux-mips.org
+Patchwork: https://patchwork.linux-mips.org/patch/7394/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm47xx/board.c | 3 ++-
+ arch/mips/bcm47xx/buttons.c | 9 ++++++++
+ arch/mips/bcm47xx/leds.c | 53 +++++++++++++++++++++++++++++++++++++--------
+ 3 files changed, 55 insertions(+), 10 deletions(-)
+
+--- a/arch/mips/bcm47xx/board.c
++++ b/arch/mips/bcm47xx/board.c
+@@ -58,6 +58,7 @@ struct bcm47xx_board_type_list1 bcm47xx_
+ static const
+ struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
++ {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RTN10D"},
+ {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
+ {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
+ {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
+@@ -106,7 +107,7 @@ struct bcm47xx_board_type_list1 bcm47xx_
+ /* ModelId */
+ static const
+ struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
+- {{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
++ {{BCM47XX_BOARD_DELL_TM2300, "Dell TrueMobile 2300"}, "WX-5565"},
+ {{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
+ {{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
+ {{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
+--- a/arch/mips/bcm47xx/buttons.c
++++ b/arch/mips/bcm47xx/buttons.c
+@@ -341,6 +341,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __i
+ };
+
+ static const struct gpio_keys_button
++bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
++ BCM47XX_GPIO_KEY(4, KEY_RESTART),
++ BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
++};
++
++static const struct gpio_keys_button
+ bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+ };
+@@ -557,6 +563,9 @@ int __init bcm47xx_buttons_register(void
+ case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
+ break;
++ case BCM47XX_BOARD_NETGEAR_WNR3500L:
++ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
++ break;
+ case BCM47XX_BOARD_NETGEAR_WNR834BV2:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
+ break;
+--- a/arch/mips/bcm47xx/leds.c
++++ b/arch/mips/bcm47xx/leds.c
+@@ -35,6 +35,15 @@ bcm47xx_leds_asus_rtn12[] __initconst =
+ };
+
+ static const struct gpio_led
++bcm47xx_leds_asus_rtn15u[] __initconst = {
++ /* TODO: Add "wlan" LED */
++ BCM47XX_GPIO_LED(3, "blue", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(4, "blue", "lan", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(9, "blue", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
++};
++
++static const struct gpio_led
+ bcm47xx_leds_asus_rtn16[] __initconst = {
+ BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+@@ -42,8 +51,8 @@ bcm47xx_leds_asus_rtn16[] __initconst =
+
+ static const struct gpio_led
+ bcm47xx_leds_asus_rtn66u[] __initconst = {
+- BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+- BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(12, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(15, "blue", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+ };
+
+ static const struct gpio_led
+@@ -221,8 +230,8 @@ bcm47xx_leds_linksys_e1000v1[] __initcon
+
+ static const struct gpio_led
+ bcm47xx_leds_linksys_e1000v21[] __initconst = {
+- BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+- BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(5, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
+ };
+@@ -319,6 +328,16 @@ bcm47xx_leds_linksys_wrt54g_type_0101[]
+ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ };
+
++/* Verified on: WRT54GL V1.1 */
++static const struct gpio_led
++bcm47xx_leds_linksys_wrt54g_type_0467[] __initconst = {
++ BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
++};
++
+ static const struct gpio_led
+ bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+@@ -338,11 +357,10 @@ bcm47xx_leds_linksys_wrt610nv2[] __initc
+
+ static const struct gpio_led
+ bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
+- BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+- BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+- BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+- BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+- BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(0, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+ };
+
+ /* Microsoft */
+@@ -397,6 +415,15 @@ bcm47xx_leds_netgear_wndr4500v1[] __init
+ };
+
+ static const struct gpio_led
++bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
++ BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(2, "green", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
++ BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
++ BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
++};
++
++static const struct gpio_led
+ bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
+ BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+@@ -437,6 +464,9 @@ void __init bcm47xx_leds_register(void)
+ case BCM47XX_BOARD_ASUS_RTN12:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
+ break;
++ case BCM47XX_BOARD_ASUS_RTN15U:
++ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn15u);
++ break;
+ case BCM47XX_BOARD_ASUS_RTN16:
+ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
+ break;
+@@ -568,6 +598,8 @@ void __init bcm47xx_leds_register(void)
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
+ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
++ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0467);
++ break;
+ case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
+ break;
+@@ -601,6 +633,9 @@ void __init bcm47xx_leds_register(void)
+ case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
+ break;
++ case BCM47XX_BOARD_NETGEAR_WNR3500L:
++ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
++ break;
+ case BCM47XX_BOARD_NETGEAR_WNR834BV2:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
+ break;
--- /dev/null
+--- a/arch/mips/include/asm/r4kcache.h
++++ b/arch/mips/include/asm/r4kcache.h
+@@ -18,6 +18,20 @@
+ #include <asm/cpu-type.h>
+ #include <asm/mipsmtregs.h>
+
++#ifdef CONFIG_BCM47XX
++#include <asm/paccess.h>
++#include <linux/ssb/ssb.h>
++#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE)))
++
++#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
++#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
++#else
++#define BCM4710_DUMMY_RREG()
++
++#define BCM4710_FILL_TLB(addr)
++#define BCM4710_PROTECTED_FILL_TLB(addr)
++#endif
++
+ /*
+ * This macro return a properly sign-extended address suitable as base address
+ * for indexed cache operations. Two issues here:
+@@ -151,6 +165,7 @@ static inline void flush_icache_line_ind
+ static inline void flush_dcache_line_indexed(unsigned long addr)
+ {
+ __dflush_prologue
++ BCM4710_DUMMY_RREG();
+ cache_op(Index_Writeback_Inv_D, addr);
+ __dflush_epilogue
+ }
+@@ -178,6 +193,7 @@ static inline void flush_icache_line(uns
+ static inline void flush_dcache_line(unsigned long addr)
+ {
+ __dflush_prologue
++ BCM4710_DUMMY_RREG();
+ cache_op(Hit_Writeback_Inv_D, addr);
+ __dflush_epilogue
+ }
+@@ -185,6 +201,7 @@ static inline void flush_dcache_line(uns
+ static inline void invalidate_dcache_line(unsigned long addr)
+ {
+ __dflush_prologue
++ BCM4710_DUMMY_RREG();
+ cache_op(Hit_Invalidate_D, addr);
+ __dflush_epilogue
+ }
+@@ -223,6 +240,7 @@ static inline void protected_flush_icach
+ break;
+
+ default:
++ BCM4710_DUMMY_RREG();
+ protected_cache_op(Hit_Invalidate_I, addr);
+ break;
+ }
+@@ -236,6 +254,7 @@ static inline void protected_flush_icach
+ */
+ static inline void protected_writeback_dcache_line(unsigned long addr)
+ {
++ BCM4710_DUMMY_RREG();
+ protected_cache_op(Hit_Writeback_Inv_D, addr);
+ }
+
+@@ -356,8 +375,51 @@ static inline void invalidate_tcache_pag
+ : "r" (base), \
+ "i" (op));
+
++static inline void blast_dcache(void)
++{
++ unsigned long start = KSEG0;
++ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
++ unsigned long end = (start + dcache_size);
++
++ do {
++ BCM4710_DUMMY_RREG();
++ cache_op(Index_Writeback_Inv_D, start);
++ start += current_cpu_data.dcache.linesz;
++ } while(start < end);
++}
++
++static inline void blast_dcache_page(unsigned long page)
++{
++ unsigned long start = page;
++ unsigned long end = start + PAGE_SIZE;
++
++ BCM4710_FILL_TLB(start);
++ do {
++ BCM4710_DUMMY_RREG();
++ cache_op(Hit_Writeback_Inv_D, start);
++ start += current_cpu_data.dcache.linesz;
++ } while(start < end);
++}
++
++static inline void blast_dcache_page_indexed(unsigned long page)
++{
++ unsigned long start = page;
++ unsigned long end = start + PAGE_SIZE;
++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
++ unsigned long ws_end = current_cpu_data.dcache.ways <<
++ current_cpu_data.dcache.waybit;
++ unsigned long ws, addr;
++ for (ws = 0; ws < ws_end; ws += ws_inc) {
++ start = page + ws;
++ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
++ BCM4710_DUMMY_RREG();
++ cache_op(Index_Writeback_Inv_D, addr);
++ }
++ }
++}
++
+ /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
+-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \
++#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra, war) \
+ static inline void extra##blast_##pfx##cache##lsize(void) \
+ { \
+ unsigned long start = INDEX_BASE; \
+@@ -369,6 +431,7 @@ static inline void extra##blast_##pfx##c
+ \
+ __##pfx##flush_prologue \
+ \
++ war \
+ for (ws = 0; ws < ws_end; ws += ws_inc) \
+ for (addr = start; addr < end; addr += lsize * 32) \
+ cache##lsize##_unroll32(addr|ws, indexop); \
+@@ -383,6 +446,7 @@ static inline void extra##blast_##pfx##c
+ \
+ __##pfx##flush_prologue \
+ \
++ war \
+ do { \
+ cache##lsize##_unroll32(start, hitop); \
+ start += lsize * 32; \
+@@ -401,6 +465,8 @@ static inline void extra##blast_##pfx##c
+ current_cpu_data.desc.waybit; \
+ unsigned long ws, addr; \
+ \
++ war \
++ \
+ __##pfx##flush_prologue \
+ \
+ for (ws = 0; ws < ws_end; ws += ws_inc) \
+@@ -410,37 +476,40 @@ static inline void extra##blast_##pfx##c
+ __##pfx##flush_epilogue \
+ }
+
+-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
+-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
+-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
+-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
+-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
+-
+-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
+-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
+-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
+-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
+-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
+-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, , )
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, , BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, , )
++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, , )
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, , BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_, BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, , )
++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, , )
++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, , BCM4710_FILL_TLB(start);)
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, , )
++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, , )
++
++__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, , )
++__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, , )
++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, , )
++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, , )
++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, , )
++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, , )
++
+
+ /* build blast_xxx_range, protected_blast_xxx_range */
+-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \
++#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra, war, war2) \
+ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \
+ unsigned long end) \
+ { \
+ unsigned long lsize = cpu_##desc##_line_size(); \
+ unsigned long addr = start & ~(lsize - 1); \
+ unsigned long aend = (end - 1) & ~(lsize - 1); \
++ war \
+ \
+ __##pfx##flush_prologue \
+ \
+ while (1) { \
++ war2 \
+ prot##cache_op(hitop, addr); \
+ if (addr == aend) \
+ break; \
+@@ -450,15 +519,15 @@ static inline void prot##extra##blast_##
+ __##pfx##flush_epilogue \
+ }
+
+-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
+-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
+-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, , BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, , , )
++__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, , , )
+ __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
+- protected_, loongson2_)
+-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
+-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
++ protected_, loongson2_, , )
++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , , , )
+ /* blast_inv_dcache_range */
+-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
+-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
++__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , , , BCM4710_DUMMY_RREG();)
++__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , , , )
+
+ #endif /* _ASM_R4KCACHE_H */
+--- a/arch/mips/include/asm/stackframe.h
++++ b/arch/mips/include/asm/stackframe.h
+@@ -436,6 +436,10 @@
+ .macro RESTORE_SP_AND_RET
+ LONG_L sp, PT_R29(sp)
+ .set mips3
++#ifdef CONFIG_BCM47XX
++ nop
++ nop
++#endif
+ eret
+ .set mips0
+ .endm
+--- a/arch/mips/kernel/genex.S
++++ b/arch/mips/kernel/genex.S
+@@ -46,6 +46,10 @@
+ NESTED(except_vec3_generic, 0, sp)
+ .set push
+ .set noat
++#ifdef CONFIG_BCM47XX
++ nop
++ nop
++#endif
+ #if R5432_CP0_INTERRUPT_WAR
+ mfc0 k0, CP0_INDEX
+ #endif
+--- a/arch/mips/mm/c-r4k.c
++++ b/arch/mips/mm/c-r4k.c
+@@ -37,6 +37,9 @@
+ #include <asm/traps.h>
+ #include <asm/dma-coherence.h>
+
++/* For enabling BCM4710 cache workarounds */
++int bcm4710 = 0;
++
+ /*
+ * Special Variant of smp_call_function for use by cache functions:
+ *
+@@ -113,6 +116,9 @@ static void r4k_blast_dcache_page_setup(
+ {
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
++ if (bcm4710)
++ r4k_blast_dcache_page = blast_dcache_page;
++ else
+ if (dc_lsize == 0)
+ r4k_blast_dcache_page = (void *)cache_noop;
+ else if (dc_lsize == 16)
+@@ -129,6 +135,9 @@ static void r4k_blast_dcache_page_indexe
+ {
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
++ if (bcm4710)
++ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
++ else
+ if (dc_lsize == 0)
+ r4k_blast_dcache_page_indexed = (void *)cache_noop;
+ else if (dc_lsize == 16)
+@@ -146,6 +155,9 @@ static void r4k_blast_dcache_setup(void)
+ {
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
++ if (bcm4710)
++ r4k_blast_dcache = blast_dcache;
++ else
+ if (dc_lsize == 0)
+ r4k_blast_dcache = (void *)cache_noop;
+ else if (dc_lsize == 16)
+@@ -703,6 +715,8 @@ static void local_r4k_flush_cache_sigtra
+ unsigned long addr = (unsigned long) arg;
+
+ R4600_HIT_CACHEOP_WAR_IMPL;
++ BCM4710_PROTECTED_FILL_TLB(addr);
++ BCM4710_PROTECTED_FILL_TLB(addr + 4);
+ if (dc_lsize)
+ protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
+ if (!cpu_icache_snoops_remote_store && scache_size)
+@@ -1403,6 +1417,17 @@ static void coherency_setup(void)
+ * silly idea of putting something else there ...
+ */
+ switch (current_cpu_type()) {
++ case CPU_BMIPS3300:
++ {
++ u32 cm;
++ cm = read_c0_diag();
++ /* Enable icache */
++ cm |= (1 << 31);
++ /* Enable dcache */
++ cm |= (1 << 30);
++ write_c0_diag(cm);
++ }
++ break;
+ case CPU_R4000PC:
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+@@ -1449,6 +1474,15 @@ void r4k_cache_init(void)
+ extern void build_copy_page(void);
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+
++ /* Check if special workarounds are required */
++#ifdef CONFIG_BCM47XX
++ if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) {
++ printk("Enabling BCM4710A0 cache workarounds.\n");
++ bcm4710 = 1;
++ } else
++#endif
++ bcm4710 = 0;
++
+ probe_pcache();
+ setup_scache();
+
+@@ -1514,6 +1548,14 @@ void r4k_cache_init(void)
+ */
+ local_r4k___flush_cache_all(NULL);
+
++#ifdef CONFIG_BCM47XX
++ {
++ static void (*_coherency_setup)(void);
++ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
++ _coherency_setup();
++ }
++#else
+ coherency_setup();
++#endif
+ board_cache_error_setup = r4k_cache_error_setup;
+ }
+--- a/arch/mips/mm/tlbex.c
++++ b/arch/mips/mm/tlbex.c
+@@ -1277,6 +1277,9 @@ static void build_r4000_tlb_refill_handl
+ /* No need for uasm_i_nop */
+ }
+
++#ifdef CONFIG_BCM47XX
++ uasm_i_nop(&p);
++#endif
+ #ifdef CONFIG_64BIT
+ build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
+ #else
+@@ -1835,6 +1838,9 @@ build_r4000_tlbchange_handler_head(u32 *
+ {
+ struct work_registers wr = build_get_work_registers(p);
+
++#ifdef CONFIG_BCM47XX
++ uasm_i_nop(p);
++#endif
+ #ifdef CONFIG_64BIT
+ build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */
+ #else
+++ /dev/null
---- a/arch/mips/bcm47xx/sprom.c
-+++ b/arch/mips/bcm47xx/sprom.c
-@@ -28,6 +28,7 @@
-
- #include <bcm47xx.h>
- #include <bcm47xx_nvram.h>
-+#include <linux/if_ether.h>
-
- static void create_key(const char *prefix, const char *postfix,
- const char *name, char *buf, int len)
-@@ -631,6 +632,33 @@ static void bcm47xx_fill_sprom_path_r45(
- }
- }
-
-+static bool bcm47xx_is_valid_mac(u8 *mac)
-+{
-+ return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
-+}
-+
-+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
-+{
-+ u8 *oui = mac + ETH_ALEN/2 - 1;
-+ u8 *p = mac + ETH_ALEN - 1;
-+
-+ do {
-+ (*p) += num;
-+ if (*p > num)
-+ break;
-+ p--;
-+ num = 1;
-+ } while (p != oui);
-+
-+ if (p == oui) {
-+ pr_err("unable to fetch mac address\n");
-+ return -ENOENT;
-+ }
-+ return 0;
-+}
-+
-+static int mac_addr_used = 2;
-+
- static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
- const char *prefix, bool fallback)
- {
-@@ -648,6 +676,23 @@ static void bcm47xx_fill_sprom_ethernet(
-
- nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
- nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
-+
-+ /* The address prefix 00:90:4C is used by Broadcom in their initial
-+ configuration. When a mac address with the prefix 00:90:4C is used
-+ all devices from the same series are sharing the same mac address.
-+ To prevent mac address collisions we replace them with a mac address
-+ based on the base address. */
-+ if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
-+ u8 mac[6];
-+ nvram_read_macaddr(NULL, "et0macaddr", mac, false);
-+ if (bcm47xx_is_valid_mac(mac)) {
-+ int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
-+ if (!err) {
-+ memcpy(sprom->il0mac, mac, ETH_ALEN);
-+ mac_addr_used++;
-+ }
-+ }
-+ }
- }
-
- static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
+++ /dev/null
---- a/arch/mips/bcm47xx/setup.c
-+++ b/arch/mips/bcm47xx/setup.c
-@@ -59,12 +59,12 @@ static void bcm47xx_machine_restart(char
- switch (bcm47xx_bus_type) {
- #ifdef CONFIG_BCM47XX_SSB
- case BCM47XX_BUS_TYPE_SSB:
-- ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
-+ ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 3);
- break;
- #endif
- #ifdef CONFIG_BCM47XX_BCMA
- case BCM47XX_BUS_TYPE_BCMA:
-- bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
-+ bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 3);
- break;
- #endif
- }