brcm47xx: add initial support for kernel 3.14

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 39905
This commit is contained in:
Hauke Mehrtens 2014-03-12 23:28:41 +00:00
parent 128bb9f1a3
commit 00dc53dd2e
23 changed files with 1959 additions and 1 deletions

View file

@ -15,7 +15,7 @@ include $(INCLUDE_DIR)/package.mk
define KernelPackage/diag define KernelPackage/diag
SUBMENU:=Other modules SUBMENU:=Other modules
DEPENDS:=@TARGET_brcm47xx DEPENDS:=@TARGET_brcm47xx @!LINUX_3_14
TITLE:=Driver for router LEDs and Buttons TITLE:=Driver for router LEDs and Buttons
FILES:=$(PKG_BUILD_DIR)/diag.ko FILES:=$(PKG_BUILD_DIR)/diag.ko
AUTOLOAD:=$(call AutoLoad,05,diag,1) AUTOLOAD:=$(call AutoLoad,05,diag,1)

View file

@ -0,0 +1,172 @@
CONFIG_ADM6996_PHY=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_B53=y
# CONFIG_B53_MMAP_DRIVER is not set
CONFIG_B53_PHY_DRIVER=y
CONFIG_B53_PHY_FIXUP=y
# CONFIG_B53_SRAB_DRIVER is not set
CONFIG_BCM47XX=y
CONFIG_BCM47XX_BCMA=y
CONFIG_BCM47XX_SSB=y
CONFIG_BCM47XX_WDT=y
CONFIG_BCMA=y
CONFIG_BCMA_BLOCKIO=y
CONFIG_BCMA_DEBUG=y
CONFIG_BCMA_DRIVER_GMAC_CMN=y
CONFIG_BCMA_DRIVER_GPIO=y
CONFIG_BCMA_DRIVER_MIPS=y
CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
CONFIG_BCMA_HOST_SOC=y
CONFIG_BCMA_NFLASH=y
CONFIG_BCMA_SFLASH=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_CEVT_R4K=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMDLINE="noinitrd console=ttyS0,115200"
CONFIG_CMDLINE_BOOL=y
# CONFIG_CMDLINE_OVERRIDE is not set
# CONFIG_CPU_BMIPS is not set
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_MIPS32_R1=y
# CONFIG_CPU_MIPS32_R2 is not set
CONFIG_CPU_MIPSR1=y
CONFIG_CPU_MIPSR2_IRQ_VI=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_R4K_FPU=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CSRC_R4K=y
CONFIG_DMA_NONCOHERENT=y
# CONFIG_EARLY_PRINTK is not set
CONFIG_FIXED_PHY=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_DEVRES=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_WDT=y
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_HAVE_CC_STACKPROTECTOR=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_HAVE_NET_DSA=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=y
CONFIG_HZ_PERIODIC=y
CONFIG_IMAGE_CMDLINE_HACK=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQ_CPU=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_LEDS_GPIO_REGISTER=y
CONFIG_MDIO_BOARDINFO=y
CONFIG_MIPS=y
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_MIPS_MACHINE is not set
CONFIG_MIPS_MT_DISABLED=y
CONFIG_MIPS_O32_FP64_SUPPORT=y
# CONFIG_MLX5_CORE is not set
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MTD_BCM47XXSFLASH=y
CONFIG_MTD_BCM47XX_PARTS=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_BCM47XXNFLASH=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_PHYSMAP=y
# CONFIG_MTD_SM_COMMON is not set
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_NO_EXCEPT_FILL=y
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PCI=y
CONFIG_PCI_DISABLE_COMMON_QUIRKS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
# CONFIG_PREEMPT_RCU is not set
# CONFIG_RCU_STALL_COMMON is not set
# CONFIG_SCSI_DMA is not set
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SSB=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_BLOCKIO=y
CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_EXTIF=y
CONFIG_SSB_DRIVER_GIGE=y
CONFIG_SSB_DRIVER_GPIO=y
CONFIG_SSB_DRIVER_MIPS=y
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_EMBEDDED=y
CONFIG_SSB_PCICORE_HOSTMODE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_SERIAL=y
CONFIG_SSB_SFLASH=y
CONFIG_SSB_SPROM=y
CONFIG_SWCONFIG=y
CONFIG_SYS_HAS_CPU_BMIPS=y
CONFIG_SYS_HAS_CPU_BMIPS32_3300=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_USB_SUPPORT=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_ZBUD is not set
CONFIG_ZONE_DMA_FLAG=0

View file

@ -0,0 +1,34 @@
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -68,6 +68,7 @@ static int bcm47xxpart_parse(struct mtd_
int trx_part = -1;
int last_trx_part = -1;
int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
+ bool found_nvram = false;
if (blocksize <= 0x10000)
blocksize = 0x10000;
@@ -229,12 +230,23 @@ static int bcm47xxpart_parse(struct mtd_
if (buf[0] == NVRAM_HEADER) {
bcm47xxpart_add_part(&parts[curr_part++], "nvram",
master->size - blocksize, 0);
+ found_nvram = true;
break;
}
}
kfree(buf);
+ if (!found_nvram) {
+ pr_err("can not find a nvram partition reserve last block\n");
+ bcm47xxpart_add_part(&parts[curr_part++], "nvram_guess",
+ master->size - blocksize * 2, MTD_WRITEABLE);
+ for (i = 0; i < curr_part; i++) {
+ if (parts[i].size + parts[i].offset == master->size)
+ parts[i].offset -= blocksize * 2;
+ }
+ }
+
/*
* Assume that partitions end at the beginning of the one they are
* followed by.

View file

@ -0,0 +1,72 @@
From 1f3e1c682a0b5273e3ee8799b54319971f426e6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Wed, 29 Jan 2014 18:06:52 +0100
Subject: [RFC V2][PATCH] MIPS: BCM47XX: Add new file for device specific workarounds
---
V2: Drop pr_debug for devices we don't need workarounds for. It was too
load and not useful at all.
---
arch/mips/bcm47xx/Makefile | 2 +-
arch/mips/bcm47xx/bcm47xx_private.h | 3 +++
arch/mips/bcm47xx/setup.c | 1 +
arch/mips/bcm47xx/workarounds.c | 25 +++++++++++++++++++++++++
4 files changed, 30 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/bcm47xx/workarounds.c
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -4,4 +4,4 @@
#
obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
-obj-y += board.o buttons.o leds.o
+obj-y += board.o buttons.o leds.o workarounds.o
--- a/arch/mips/bcm47xx/bcm47xx_private.h
+++ b/arch/mips/bcm47xx/bcm47xx_private.h
@@ -9,4 +9,7 @@ int __init bcm47xx_buttons_register(void
/* leds.c */
void __init bcm47xx_leds_register(void);
+/* workarounds.c */
+void __init bcm47xx_workarounds(void);
+
#endif
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -282,6 +282,7 @@ static int __init bcm47xx_register_bus_c
}
bcm47xx_buttons_register();
bcm47xx_leds_register();
+ bcm47xx_workarounds();
fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
return 0;
--- /dev/null
+++ b/arch/mips/bcm47xx/workarounds.c
@@ -0,0 +1,25 @@
+#include "bcm47xx_private.h"
+
+#include <linux/gpio.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx.h>
+
+static void __init bcm47xx_workarounds_netgear_wnr3500l(void)
+{
+ /* Set GPIO 12 to 1 to pass power to the USB port */
+ gpio_set_value(12, 1);
+}
+
+void __init bcm47xx_workarounds(void)
+{
+ enum bcm47xx_board board = bcm47xx_board_get();
+
+ switch (board) {
+ case BCM47XX_BOARD_NETGEAR_WNR3500L:
+ bcm47xx_workarounds_netgear_wnr3500l();
+ break;
+ default:
+ /* No workaround(s) needed */
+ break;
+ }
+}

View file

@ -0,0 +1,39 @@
From b09189336f6d974c554aed03b4651e9f68ce0abd Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 23 Feb 2014 16:38:29 +0100
Subject: [PATCH 3/6] MIPS: BCM47XX: detect some more Linksys devices
The Linksys WRT54G/GS/GL family uses the same boardtype numbers, and
the same gpio configuration. The boardtype numbers are changing with
the hardware versions, but these hardware numbers are different or each
model.
Detect them all as one device, this also worked in OpenWrt.
---
arch/mips/bcm47xx/board.c | 4 +++-
arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -175,7 +175,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_WRT54GSV1, "Linksys WRT54GS V1"}, "0x0101", "42", "0x10"},
+ {{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"},
{ {0}, NULL},
};
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -66,7 +66,7 @@ enum bcm47xx_board {
BCM47XX_BOARD_LINKSYS_WRT310NV1,
BCM47XX_BOARD_LINKSYS_WRT310NV2,
BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
- BCM47XX_BOARD_LINKSYS_WRT54GSV1,
+ BCM47XX_BOARD_LINKSYS_WRT54G,
BCM47XX_BOARD_LINKSYS_WRT610NV1,
BCM47XX_BOARD_LINKSYS_WRT610NV2,
BCM47XX_BOARD_LINKSYS_WRTSL54GS,

View file

@ -0,0 +1,133 @@
From e3d15471f1be2bd2fd4db82907ad4b2d74ec2636 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Fri, 10 Jan 2014 23:55:28 +0100
Subject: [PATCH 4/6] MIPS: BCM47XX: add button and led configuration for some
Linksys devices
This adds led and button GPIO configuration for Linksys wrt54g3gv2,
wrt54gsv1 and wrtsl54gs. This is based on OpenWrt broadcom-diag code.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/buttons.c | 27 +++++++++++++++++++++++++++
arch/mips/bcm47xx/leds.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+)
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -259,6 +259,18 @@ bcm47xx_buttons_linksys_wrt310nv1[] __in
};
static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = {
+ BCM47XX_GPIO_KEY(5, KEY_WIMAX),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
bcm47xx_buttons_linksys_wrt610nv1[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
@@ -270,6 +282,12 @@ bcm47xx_buttons_linksys_wrt610nv2[] __in
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
+static const struct gpio_keys_button
+bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
+ BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
/* Motorola */
static const struct gpio_keys_button
@@ -479,12 +497,21 @@ 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_WRT610NV1:
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
break;
case BCM47XX_BOARD_LINKSYS_WRT610NV2:
err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv2);
break;
+ case BCM47XX_BOARD_LINKSYS_WRTSL54GS:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
+ break;
case BCM47XX_BOARD_MOTOROLA_WE800G:
err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
--- a/arch/mips/bcm47xx/leds.c
+++ b/arch/mips/bcm47xx/leds.c
@@ -292,6 +292,21 @@ bcm47xx_leds_linksys_wrt310nv1[] __initc
};
static const struct gpio_led
+bcm47xx_leds_linksys_wrt54gsv1[] __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),
+ BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g3gv2[] __initconst = {
+ BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+ BCM47XX_GPIO_LED(2, "green", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "blue", "3g", 0, 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),
BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -308,6 +323,15 @@ bcm47xx_leds_linksys_wrt610nv2[] __initc
BCM47XX_GPIO_LED(7, "unk", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
};
+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),
+};
+
/* Motorola */
static const struct gpio_led
@@ -502,12 +526,21 @@ 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_WRT610NV1:
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
break;
case BCM47XX_BOARD_LINKSYS_WRT610NV2:
bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv2);
break;
+ case BCM47XX_BOARD_LINKSYS_WRTSL54GS:
+ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
+ break;
case BCM47XX_BOARD_MOTOROLA_WE800G:
bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);

View file

@ -0,0 +1,89 @@
From c546fa49901252cbc1e4046d7188858b2f9e130f Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Fri, 10 Jan 2014 23:55:43 +0100
Subject: [PATCH 2/2] MIPS: BCM47XX: add detection and GPIO config for Siemens
SE505v2
This adds board detection for the Siemens SE505v2 and the led gpio
configuration. This board does not have any buttons.
This is based on OpenWrt broadcom-diag and Manuel Munz's nvram dump.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/board.c | 17 +++++++++++++++++
arch/mips/bcm47xx/leds.c | 12 ++++++++++++
arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 2 ++
3 files changed, 31 insertions(+)
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -181,6 +181,13 @@ struct bcm47xx_board_type_list3 bcm47xx_
{ {0}, NULL},
};
+/* boardtype, boardrev */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_board_type_rev[] __initconst = {
+ {{BCM47XX_BOARD_SIEMENS_SE505V2, "Siemens SE505 V2"}, "0x0101", "0x10"},
+ { {0}, NULL},
+};
+
static const
struct bcm47xx_board_type bcm47xx_board_unknown[] __initconst = {
{BCM47XX_BOARD_UNKNOWN, "Unknown Board"},
@@ -274,6 +281,16 @@ static __init const struct bcm47xx_board
return &e3->board;
}
}
+
+ if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boardrev", buf2, sizeof(buf2)) >= 0 &&
+ bcm47xx_nvram_getenv("boardnum", buf3, sizeof(buf3)) == -ENOENT) {
+ for (e2 = bcm47xx_board_list_board_type_rev; e2->value1; e2++) {
+ if (!strcmp(buf1, e2->value1) &&
+ !strcmp(buf2, e2->value2))
+ return &e2->board;
+ }
+ }
return bcm47xx_board_unknown;
}
--- a/arch/mips/bcm47xx/leds.c
+++ b/arch/mips/bcm47xx/leds.c
@@ -383,6 +383,14 @@ bcm47xx_leds_netgear_wnr834bv2[] __initc
BCM47XX_GPIO_LED(7, "unk", "connected", 0, LEDS_GPIO_DEFSTATE_OFF),
};
+/* Siemens */
+static const struct gpio_led
+bcm47xx_leds_siemens_se505v2[] __initconst = {
+ BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(3, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(5, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
/* SimpleTech */
static const struct gpio_led
@@ -562,6 +570,10 @@ void __init bcm47xx_leds_register(void)
bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
break;
+ case BCM47XX_BOARD_SIEMENS_SE505V2:
+ bcm47xx_set_pdata(bcm47xx_leds_siemens_se505v2);
+ break;
+
case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE:
bcm47xx_set_pdata(bcm47xx_leds_simpletech_simpleshare);
break;
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -94,6 +94,8 @@ enum bcm47xx_board {
BCM47XX_BOARD_PHICOMM_M1,
+ BCM47XX_BOARD_SIEMENS_SE505V2,
+
BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE,
BCM47XX_BOARD_ZTE_H218N,

View file

@ -0,0 +1,77 @@
From 44927df87162ae9beb6e7b934b0e75818b88e350 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 2 Jan 2014 19:10:05 +0100
Subject: [PATCH] MIPS: BCM47XX: add Belkin F7Dxxxx board detection
From: Cody P Schafer <devel@codyps.com>
Add a few Belkin F7Dxxxx entries, with F7D4401 sourced from online
documentation and the "F7D7302" being observed. F7D3301, F7D3302, and
F7D4302 are reasonable guesses which are unlikely to cause
mis-detection.
Signed-off-by: Cody P Schafer <devel@codyps.com>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/bcm47xx/board.c | 4 ++++
arch/mips/bcm47xx/buttons.c | 4 ++++
arch/mips/bcm47xx/leds.c | 4 ++++
arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 4 ++++
4 files changed, 16 insertions(+)
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -71,7 +71,11 @@ struct bcm47xx_board_type_list1 bcm47xx_
{{BCM47XX_BOARD_ASUS_WL500W, "Asus WL500W"}, "WL500gW-"},
{{BCM47XX_BOARD_ASUS_WL520GC, "Asus WL520GC"}, "WL520GC-"},
{{BCM47XX_BOARD_ASUS_WL520GU, "Asus WL520GU"}, "WL520GU-"},
+ {{BCM47XX_BOARD_BELKIN_F7D3301, "Belkin F7D3301"}, "F7D3301"},
+ {{BCM47XX_BOARD_BELKIN_F7D3302, "Belkin F7D3302"}, "F7D3302"},
{{BCM47XX_BOARD_BELKIN_F7D4301, "Belkin F7D4301"}, "F7D4301"},
+ {{BCM47XX_BOARD_BELKIN_F7D4302, "Belkin F7D4302"}, "F7D4302"},
+ {{BCM47XX_BOARD_BELKIN_F7D4401, "Belkin F7D4401"}, "F7D4401"},
{ {0}, NULL},
};
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -420,7 +420,11 @@ int __init bcm47xx_buttons_register(void
err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wlhdd);
break;
+ case BCM47XX_BOARD_BELKIN_F7D3301:
+ case BCM47XX_BOARD_BELKIN_F7D3302:
case BCM47XX_BOARD_BELKIN_F7D4301:
+ case BCM47XX_BOARD_BELKIN_F7D4302:
+ case BCM47XX_BOARD_BELKIN_F7D4401:
err = bcm47xx_copy_bdata(bcm47xx_buttons_belkin_f7d4301);
break;
--- a/arch/mips/bcm47xx/leds.c
+++ b/arch/mips/bcm47xx/leds.c
@@ -457,7 +457,11 @@ void __init bcm47xx_leds_register(void)
bcm47xx_set_pdata(bcm47xx_leds_asus_wlhdd);
break;
+ case BCM47XX_BOARD_BELKIN_F7D3301:
+ case BCM47XX_BOARD_BELKIN_F7D3302:
case BCM47XX_BOARD_BELKIN_F7D4301:
+ case BCM47XX_BOARD_BELKIN_F7D4302:
+ case BCM47XX_BOARD_BELKIN_F7D4401:
bcm47xx_set_pdata(bcm47xx_leds_belkin_f7d4301);
break;
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -27,7 +27,11 @@ enum bcm47xx_board {
BCM47XX_BOARD_ASUS_WL700GE,
BCM47XX_BOARD_ASUS_WLHDD,
+ BCM47XX_BOARD_BELKIN_F7D3301,
+ BCM47XX_BOARD_BELKIN_F7D3302,
BCM47XX_BOARD_BELKIN_F7D4301,
+ BCM47XX_BOARD_BELKIN_F7D4302,
+ BCM47XX_BOARD_BELKIN_F7D4401,
BCM47XX_BOARD_BUFFALO_WBR2_G54,
BCM47XX_BOARD_BUFFALO_WHR2_A54G54,

View file

@ -0,0 +1,373 @@
--- 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 = &current_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

View file

@ -0,0 +1,70 @@
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -133,6 +133,9 @@
#ifndef cpu_has_local_ebase
#define cpu_has_local_ebase 1
#endif
+#ifndef cpu_use_kmap_coherent
+#define cpu_use_kmap_coherent 1
+#endif
/*
* I-Cache snoops remote store. This only matters on SMP. Some multiprocessors
--- a/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h
@@ -79,4 +79,6 @@
#define cpu_scache_line_size() 0
#define cpu_has_vz 0
+#define cpu_use_kmap_coherent 0
+
#endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -523,7 +523,7 @@ static inline void local_r4k_flush_cache
*/
map_coherent = (cpu_has_dc_aliases &&
page_mapped(page) && !Page_dcache_dirty(page));
- if (map_coherent)
+ if (map_coherent && cpu_use_kmap_coherent)
vaddr = kmap_coherent(page, addr);
else
vaddr = kmap_atomic(page);
@@ -546,7 +546,7 @@ static inline void local_r4k_flush_cache
}
if (vaddr) {
- if (map_coherent)
+ if (map_coherent && cpu_use_kmap_coherent)
kunmap_coherent();
else
kunmap_atomic(vaddr);
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -200,7 +200,7 @@ void copy_user_highpage(struct page *to,
void *vfrom, *vto;
vto = kmap_atomic(to);
- if (cpu_has_dc_aliases &&
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
page_mapped(from) && !Page_dcache_dirty(from)) {
vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom);
@@ -222,7 +222,7 @@ void copy_to_user_page(struct vm_area_st
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
- if (cpu_has_dc_aliases &&
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
page_mapped(page) && !Page_dcache_dirty(page)) {
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len);
@@ -240,7 +240,7 @@ void copy_from_user_page(struct vm_area_
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
- if (cpu_has_dc_aliases &&
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
page_mapped(page) && !Page_dcache_dirty(page)) {
void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len);

View file

@ -0,0 +1,102 @@
From b36f694256f41bc71571f467646d015dda128d14 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sat, 9 Nov 2013 17:03:59 +0100
Subject: [PATCH 210/210] b44: register adm switch
---
drivers/net/ethernet/broadcom/b44.c | 57 +++++++++++++++++++++++++++++++++++
drivers/net/ethernet/broadcom/b44.h | 3 ++
2 files changed, 60 insertions(+)
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -31,6 +31,8 @@
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/adm6996-gpio.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -2239,6 +2241,58 @@ static void b44_adjust_link(struct net_d
}
}
+#ifdef CONFIG_BCM47XX
+static struct adm6996_gpio_platform_data b44_adm_data = {
+ .eecs = 2,
+ .eesk = 3,
+ .eedi = 4,
+ .eerc = 5,
+ .model = ADM6996L,
+};
+
+static struct platform_device b44_adm_dev = {
+ .name = "adm6996_gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &b44_adm_data,
+ },
+};
+
+static int b44_register_adm_switch(struct b44 *bp)
+{
+ int gpio;
+ int err;
+
+ gpio = bcm47xx_nvram_gpio_pin("adm_eecs");
+ if (gpio >= 0)
+ b44_adm_data.eecs = gpio;
+
+ gpio = bcm47xx_nvram_gpio_pin("adm_eesk");
+ if (gpio >= 0)
+ b44_adm_data.eesk = gpio;
+
+ gpio = bcm47xx_nvram_gpio_pin("adm_eedi");
+ if (gpio >= 0)
+ b44_adm_data.eedi = gpio;
+
+ gpio = bcm47xx_nvram_gpio_pin("adm_rc");
+ if (gpio >= 0)
+ b44_adm_data.eerc = gpio;
+
+ if (!bp->adm_switch) {
+ err = platform_device_register(&b44_adm_dev);
+ if (!err)
+ bp->adm_switch = &b44_adm_dev;
+ }
+ return err;
+}
+#else
+static int b44_register_adm_switch(struct b44 *bp)
+{
+ return 0;
+}
+#endif /* CONFIG_BCM47XX */
+
static int b44_register_phy_one(struct b44 *bp)
{
struct mii_bus *mii_bus;
@@ -2282,6 +2336,9 @@ static int b44_register_phy_one(struct b
if (!bp->mii_bus->phy_map[bp->phy_addr] &&
(sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) {
+ if (sprom->boardflags_lo & B44_BOARDFLAG_ADM)
+ b44_register_adm_switch(bp);
+
dev_info(sdev->dev,
"could not find PHY at %i, use fixed one\n",
bp->phy_addr);
--- a/drivers/net/ethernet/broadcom/b44.h
+++ b/drivers/net/ethernet/broadcom/b44.h
@@ -404,6 +404,9 @@ struct b44 {
struct mii_bus *mii_bus;
int old_link;
struct mii_if_info mii_if;
+
+ /* platform device for associated switch */
+ struct platform_device *adm_switch;
};
#endif /* _B44_H */

View file

@ -0,0 +1,54 @@
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -431,10 +431,34 @@ static void b44_wap54g10_workaround(stru
error:
pr_warning("PHY: cannot reset MII transceiver isolate bit\n");
}
+
+static void b44_bcm47xx_workarounds(struct b44 *bp)
+{
+ char buf[20];
+ struct ssb_device *sdev = bp->sdev;
+
+ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */
+ if (sdev->bus->sprom.board_num == 100) {
+ bp->phy_addr = B44_PHY_ADDR_NO_LOCAL_PHY;
+ } else {
+ /* WL-HDD */
+ if (bcm47xx_nvram_getenv("hardware_version", buf, sizeof(buf)) >= 0 &&
+ !strncmp(buf, "WL300-", strlen("WL300-"))) {
+ if (sdev->bus->sprom.et0phyaddr == 0 &&
+ sdev->bus->sprom.et1phyaddr == 1)
+ bp->phy_addr = B44_PHY_ADDR_NO_LOCAL_PHY;
+ }
+ }
+ return;
+}
#else
static inline void b44_wap54g10_workaround(struct b44 *bp)
{
}
+
+static inline void b44_bcm47xx_workarounds(struct b44 *bp)
+{
+}
#endif
static int b44_setup_phy(struct b44 *bp)
@@ -443,6 +467,7 @@ static int b44_setup_phy(struct b44 *bp)
int err;
b44_wap54g10_workaround(bp);
+ b44_bcm47xx_workarounds(bp);
if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0;
@@ -2169,6 +2194,8 @@ static int b44_get_invariants(struct b44
* valid PHY address. */
bp->phy_addr &= 0x1F;
+ b44_bcm47xx_workarounds(bp);
+
memcpy(bp->dev->dev_addr, addr, ETH_ALEN);
if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){

View file

@ -0,0 +1,25 @@
This prevents the options from being delete with make kernel_oldconfig.
---
drivers/ssb/Kconfig | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -38,6 +38,7 @@ config BCMA_DRIVER_PCI_HOSTMODE
config BCMA_HOST_SOC
bool "Support for BCMA in a SoC"
depends on BCMA
+ select USB_HCD_BCMA if USB_EHCI_HCD || USB_OHCI_HCD
help
Host interface for a Broadcom AIX bus directly mapped into
the memory. This only works with the Broadcom SoCs from the
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -146,6 +146,7 @@ config SSB_SFLASH
config SSB_EMBEDDED
bool
depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE
+ select USB_HCD_SSB if USB_EHCI_HCD || USB_OHCI_HCD
default y
config SSB_DRIVER_EXTIF

View file

@ -0,0 +1,11 @@
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -32,7 +32,7 @@
extern void (*flush_cache_all)(void);
extern void (*__flush_cache_all)(void);
extern void (*flush_cache_mm)(struct mm_struct *mm);
-#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
extern void (*flush_cache_range)(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);

View file

@ -0,0 +1,66 @@
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -71,6 +71,7 @@ static inline unsigned int page_size_ftl
#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */
#include <linux/pfn.h>
+#include <asm/cpu-features.h>
extern void build_clear_page(void);
extern void build_copy_page(void);
@@ -105,13 +106,16 @@ static inline void clear_user_page(void
flush_data_cache_page((unsigned long)addr);
}
-extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
- struct page *to);
-struct vm_area_struct;
-extern void copy_user_highpage(struct page *to, struct page *from,
- unsigned long vaddr, struct vm_area_struct *vma);
+static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+ struct page *to)
+{
+ extern void (*flush_data_cache_page)(unsigned long addr);
-#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+ copy_page(vto, vfrom);
+ if (!cpu_has_ic_fills_f_dc ||
+ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
+ flush_data_cache_page((unsigned long)vto);
+}
/*
* These are used to make use of C type-checking..
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -194,30 +194,6 @@ void kunmap_coherent(void)
pagefault_enable();
}
-void copy_user_highpage(struct page *to, struct page *from,
- unsigned long vaddr, struct vm_area_struct *vma)
-{
- void *vfrom, *vto;
-
- vto = kmap_atomic(to);
- if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
- page_mapped(from) && !Page_dcache_dirty(from)) {
- vfrom = kmap_coherent(from, vaddr);
- copy_page(vto, vfrom);
- kunmap_coherent();
- } else {
- vfrom = kmap_atomic(from);
- copy_page(vto, vfrom);
- kunmap_atomic(vfrom);
- }
- if ((!cpu_has_ic_fills_f_dc) ||
- pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
- flush_data_cache_page((unsigned long)vto);
- kunmap_atomic(vto);
- /* Make sure this page is cleared on other CPU's too before using it */
- smp_wmb();
-}
-
void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)

View file

@ -0,0 +1,14 @@
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -191,7 +191,11 @@ static inline void ide_std_init_ports(st
hw->io_ports.ctl_addr = ctl_addr;
}
+#if defined CONFIG_BCM47XX
+# define MAX_HWIFS 2
+#else
#define MAX_HWIFS 10
+#endif
/*
* Now for the data we need to maintain per-drive: ide_drive_t

View file

@ -0,0 +1,296 @@
The Netgear wgt634u uses a different format for storing the
configuration. This patch is needed to read out the correct
configuration. The cfe_env.c file uses a different method way to read
out the configuration than the in kernel cfe config reader.
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -5,3 +5,4 @@
obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
obj-y += board.o buttons.o leds.o workarounds.o
+obj-y += cfe_env.o
--- /dev/null
+++ b/arch/mips/bcm47xx/cfe_env.c
@@ -0,0 +1,229 @@
+/*
+ * CFE environment variable access
+ *
+ * Copyright 2001-2003, Broadcom Corporation
+ * Copyright 2006, Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define NVRAM_SIZE (0x1ff0)
+static char _nvdata[NVRAM_SIZE];
+static char _valuestr[256];
+
+/*
+ * TLV types. These codes are used in the "type-length-value"
+ * encoding of the items stored in the NVRAM device (flash or EEPROM)
+ *
+ * The layout of the flash/nvram is as follows:
+ *
+ * <type> <length> <data ...> <type> <length> <data ...> <type_end>
+ *
+ * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
+ * The "length" field marks the length of the data section, not
+ * including the type and length fields.
+ *
+ * Environment variables are stored as follows:
+ *
+ * <type_env> <length> <flags> <name> = <value>
+ *
+ * If bit 0 (low bit) is set, the length is an 8-bit value.
+ * If bit 0 (low bit) is clear, the length is a 16-bit value
+ *
+ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
+ * indicates the size of the length field.
+ *
+ * Flags are from the constants below:
+ *
+ */
+#define ENV_LENGTH_16BITS 0x00 /* for low bit */
+#define ENV_LENGTH_8BITS 0x01
+
+#define ENV_TYPE_USER 0x80
+
+#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
+#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
+
+/*
+ * The actual TLV types we support
+ */
+
+#define ENV_TLV_TYPE_END 0x00
+#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
+
+/*
+ * Environment variable flags
+ */
+
+#define ENV_FLG_NORMAL 0x00 /* normal read/write */
+#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
+#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
+
+#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
+#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
+
+
+/* *********************************************************************
+ * _nvram_read(buffer,offset,length)
+ *
+ * Read data from the NVRAM device
+ *
+ * Input parameters:
+ * buffer - destination buffer
+ * offset - offset of data to read
+ * length - number of bytes to read
+ *
+ * Return value:
+ * number of bytes read, or <0 if error occured
+ ********************************************************************* */
+static int
+_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
+{
+ int i;
+ if (offset > NVRAM_SIZE)
+ return -1;
+
+ for ( i = 0; i < length; i++) {
+ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
+ }
+ return length;
+}
+
+
+static char*
+_strnchr(const char *dest,int c,size_t cnt)
+{
+ while (*dest && (cnt > 0)) {
+ if (*dest == c) return (char *) dest;
+ dest++;
+ cnt--;
+ }
+ return NULL;
+}
+
+
+
+/*
+ * Core support API: Externally visible.
+ */
+
+/*
+ * Get the value of an NVRAM variable
+ * @param name name of variable to get
+ * @return value of variable or NULL if undefined
+ */
+
+char*
+cfe_env_get(unsigned char *nv_buf, char* name)
+{
+ int size;
+ unsigned char *buffer;
+ unsigned char *ptr;
+ unsigned char *envval;
+ unsigned int reclen;
+ unsigned int rectype;
+ int offset;
+ int flg;
+
+ if (!strcmp(name, "nvram_type"))
+ return "cfe";
+
+ size = NVRAM_SIZE;
+ buffer = &_nvdata[0];
+
+ ptr = buffer;
+ offset = 0;
+
+ /* Read the record type and length */
+ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
+ goto error;
+ }
+
+ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
+
+ /* Adjust pointer for TLV type */
+ rectype = *(ptr);
+ offset++;
+ size--;
+
+ /*
+ * Read the length. It can be either 1 or 2 bytes
+ * depending on the code
+ */
+ if (rectype & ENV_LENGTH_8BITS) {
+ /* Read the record type and length - 8 bits */
+ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
+ goto error;
+ }
+ reclen = *(ptr);
+ size--;
+ offset++;
+ }
+ else {
+ /* Read the record type and length - 16 bits, MSB first */
+ if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
+ goto error;
+ }
+ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
+ size -= 2;
+ offset += 2;
+ }
+
+ if (reclen > size)
+ break; /* should not happen, bad NVRAM */
+
+ switch (rectype) {
+ case ENV_TLV_TYPE_ENV:
+ /* Read the TLV data */
+ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
+ goto error;
+ flg = *ptr++;
+ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
+ if (envval) {
+ *envval++ = '\0';
+ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
+ _valuestr[(reclen-1)-(envval-ptr)] = '\0';
+#if 0
+ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
+#endif
+ if(!strcmp(ptr, name)){
+ return _valuestr;
+ }
+ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
+ return _valuestr;
+ }
+ break;
+
+ default:
+ /* Unknown TLV type, skip it. */
+ break;
+ }
+
+ /*
+ * Advance to next TLV
+ */
+
+ size -= (int)reclen;
+ offset += reclen;
+
+ /* Read the next record type */
+ ptr = buffer;
+ if (_nvram_read(nv_buf, ptr,offset,1) != 1)
+ goto error;
+ }
+
+error:
+ return NULL;
+
+}
+
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -22,6 +22,8 @@
static char nvram_buf[NVRAM_SPACE];
static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
+static int cfe_env;
+extern char *cfe_env_get(char *nv_buf, const char *name);
static u32 find_nvram_size(u32 end)
{
@@ -46,6 +48,26 @@ static int nvram_find_and_copy(u32 base,
u32 *src, *dst;
u32 size;
+ cfe_env = 0;
+
+ /* XXX: hack for supporting the CFE environment stuff on WGT634U */
+ if (lim >= 8 * 1024 * 1024) {
+ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
+ dst = (u32 *) nvram_buf;
+
+ if ((*src & 0xff00ff) == 0x000001) {
+ printk("early_nvram_init: WGT634U NVRAM found.\n");
+
+ for (i = 0; i < 0x1ff0; i++) {
+ if (*src == 0xFFFFFFFF)
+ break;
+ *dst++ = *src++;
+ }
+ cfe_env = 1;
+ return 0;
+ }
+ }
+
/* TODO: when nvram is on nand flash check for bad blocks first. */
off = FLASH_MIN;
while (off <= lim) {
@@ -172,6 +194,13 @@ int bcm47xx_nvram_getenv(char *name, cha
return err;
}
+ if (cfe_env) {
+ value = cfe_env_get(nvram_buf, name);
+ if (!value)
+ return -ENOENT;
+ return snprintf(val, val_len, "%s", value);
+ }
+
/* Look for name=value and return value */
var = &nvram_buf[sizeof(struct nvram_header)];
end = nvram_buf + sizeof(nvram_buf) - 2;

View file

@ -0,0 +1,101 @@
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -36,6 +36,7 @@
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
+#include <linux/old_gpio_wdt.h>
#include <asm/bootinfo.h>
#include <asm/idle.h>
#include <asm/prom.h>
@@ -266,6 +267,33 @@ static struct fixed_phy_status bcm47xx_f
.duplex = DUPLEX_FULL,
};
+static struct gpio_wdt_platform_data gpio_wdt_data;
+
+static struct platform_device gpio_wdt_device = {
+ .name = "gpio-wdt",
+ .id = 0,
+ .dev = {
+ .platform_data = &gpio_wdt_data,
+ },
+};
+
+static int __init bcm47xx_register_gpio_watchdog(void)
+{
+ enum bcm47xx_board board = bcm47xx_board_get();
+
+ switch (board) {
+ case BCM47XX_BOARD_HUAWEI_E970:
+ pr_info("bcm47xx: detected Huawei E970 or similar, starting early gpio_wdt timer\n");
+ gpio_wdt_data.gpio = 7;
+ gpio_wdt_data.interval = HZ;
+ gpio_wdt_data.first_interval = HZ / 5;
+ return platform_device_register(&gpio_wdt_device);
+ default:
+ /* Nothing to do */
+ return 0;
+ }
+}
+
static int __init bcm47xx_register_bus_complete(void)
{
switch (bcm47xx_bus_type) {
@@ -285,6 +313,7 @@ static int __init bcm47xx_register_bus_c
bcm47xx_workarounds();
fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
+ bcm47xx_register_gpio_watchdog();
return 0;
}
device_initcall(bcm47xx_register_bus_complete);
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -67,6 +67,7 @@ CONFIG_HW_RANDOM=y
CONFIG_GPIO_SYSFS=y
CONFIG_WATCHDOG=y
CONFIG_BCM47XX_WDT=y
+CONFIG_GPIO_WDT=y
CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_GIGE=y
CONFIG_BCMA_DRIVER_GMAC_CMN=y
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -34,11 +34,36 @@ int ssb_watchdog_timer_set(struct ssb_bu
}
EXPORT_SYMBOL(ssb_watchdog_timer_set);
+#ifdef CONFIG_BCM47XX
+#include <bcm47xx_board.h>
+
+static bool ssb_watchdog_supported(void)
+{
+ enum bcm47xx_board board = bcm47xx_board_get();
+
+ /* The Huawei E970 has a hardware watchdog using a GPIO */
+ switch (board) {
+ case BCM47XX_BOARD_HUAWEI_E970:
+ return false;
+ default:
+ return true;
+ }
+}
+#else
+static bool ssb_watchdog_supported(void)
+{
+ return true;
+}
+#endif
+
int ssb_watchdog_register(struct ssb_bus *bus)
{
struct bcm47xx_wdt wdt = {};
struct platform_device *pdev;
+ if (!ssb_watchdog_supported())
+ return 0;
+
if (ssb_chipco_available(&bus->chipco)) {
wdt.driver_data = &bus->chipco;
wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;

View file

@ -0,0 +1,138 @@
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -21,10 +21,28 @@
#ifdef CONFIG_BCM47XX
#include <asm/paccess.h>
#include <linux/ssb/ssb.h>
-#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE)))
+#define BCM4710_DUMMY_RREG() bcm4710_dummy_rreg()
+
+static inline unsigned long bcm4710_dummy_rreg(void)
+{
+ return *(volatile unsigned long *)(KSEG1ADDR(SSB_ENUM_BASE));
+}
+
+#define BCM4710_FILL_TLB(addr) bcm4710_fill_tlb((void *)(addr))
+
+static inline unsigned long bcm4710_fill_tlb(void *addr)
+{
+ return *(unsigned long *)addr;
+}
+
+#define BCM4710_PROTECTED_FILL_TLB(addr) bcm4710_protected_fill_tlb((void *)(addr))
+
+static inline void bcm4710_protected_fill_tlb(void *addr)
+{
+ unsigned long x;
+ get_dbe(x, (unsigned long *)addr);;
+}
-#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()
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -935,6 +935,9 @@ build_get_pgde32(u32 **p, unsigned int t
uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
uasm_i_addu(p, ptr, tmp, ptr);
#else
+#ifdef CONFIG_BCM47XX
+ uasm_i_nop(p);
+#endif
UASM_i_LA_mostly(p, ptr, pgdc);
#endif
uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
@@ -1277,12 +1280,12 @@ 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
+# ifdef CONFIG_BCM47XX
+ uasm_i_nop(&p);
+# endif
build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
#endif
@@ -1294,6 +1297,9 @@ static void build_r4000_tlb_refill_handl
build_update_entries(&p, K0, K1);
build_tlb_write_entry(&p, &l, &r, tlb_random);
uasm_l_leave(&l, p);
+#ifdef CONFIG_BCM47XX
+ uasm_i_nop(&p);
+#endif
uasm_i_eret(&p); /* return from trap */
}
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -1838,12 +1844,12 @@ 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
+# ifdef CONFIG_BCM47XX
+ uasm_i_nop(p);
+# endif
build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */
#endif
@@ -1882,6 +1888,9 @@ build_r4000_tlbchange_handler_tail(u32 *
build_tlb_write_entry(p, l, r, tlb_indexed);
uasm_l_leave(l, *p);
build_restore_work_registers(p);
+#ifdef CONFIG_BCM47XX
+ uasm_i_nop(p);
+#endif
uasm_i_eret(p); /* return from trap */
#ifdef CONFIG_64BIT
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -21,6 +21,19 @@
#include <asm/war.h>
#include <asm/thread_info.h>
+#ifdef CONFIG_BCM47XX
+# ifdef eret
+# undef eret
+# endif
+# define eret \
+ .set push; \
+ .set noreorder; \
+ nop; \
+ nop; \
+ eret; \
+ .set pop;
+#endif
+
#ifdef CONFIG_MIPS_MT_SMTC
#define PANIC_PIC(msg) \
.set push; \
@@ -48,7 +61,6 @@ NESTED(except_vec3_generic, 0, sp)
.set noat
#ifdef CONFIG_BCM47XX
nop
- nop
#endif
#if R5432_CP0_INTERRUPT_WAR
mfc0 k0, CP0_INDEX
@@ -73,6 +85,9 @@ NESTED(except_vec3_r4000, 0, sp)
.set push
.set mips3
.set noat
+#ifdef CONFIG_BCM47XX
+ nop
+#endif
mfc0 k1, CP0_CAUSE
li k0, 31<<2
andi k1, k1, 0x7c

View file

@ -0,0 +1,46 @@
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -920,6 +920,8 @@ static unsigned int yenta_probe_irq(stru
* Probe for usable interrupts using the force
* register to generate bogus card status events.
*/
+#ifndef CONFIG_BCM47XX
+ /* WRT54G3G does not like this */
cb_writel(socket, CB_SOCKET_EVENT, -1);
cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
reg = exca_readb(socket, I365_CSCINT);
@@ -935,6 +937,7 @@ static unsigned int yenta_probe_irq(stru
}
cb_writel(socket, CB_SOCKET_MASK, 0);
exca_writeb(socket, I365_CSCINT, reg);
+#endif
mask = probe_irq_mask(val) & 0xffff;
@@ -1019,6 +1022,10 @@ static void yenta_get_socket_capabilitie
else
socket->socket.irq_mask = 0;
+ /* irq mask probing is broken for the WRT54G3G */
+ if (socket->socket.irq_mask == 0)
+ socket->socket.irq_mask = 0x6f8;
+
dev_printk(KERN_INFO, &socket->dev->dev,
"ISA IRQ mask 0x%04x, PCI irq %d\n",
socket->socket.irq_mask, socket->cb_irq);
@@ -1257,6 +1264,15 @@ static int yenta_probe(struct pci_dev *d
dev_printk(KERN_INFO, &dev->dev,
"Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
+ /* Generate an interrupt on card insert/remove */
+ config_writew(socket, CB_SOCKET_MASK, CB_CSTSMASK | CB_CDMASK);
+
+ /* Set up Multifunction Routing Status Register */
+ config_writew(socket, 0x8C, 0x1000 /* MFUNC3 to GPIO3 */ | 0x2 /* MFUNC0 to INTA */);
+
+ /* Switch interrupts to parallelized */
+ config_writeb(socket, 0x92, 0x64);
+
yenta_fixup_parent_bridge(dev->subordinate);
/* Register it with the pcmcia layer.. */

View file

@ -0,0 +1,11 @@
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -375,7 +375,7 @@ static void ssb_pcicore_init_hostmode(st
set_io_port_base(ssb_pcicore_controller.io_map_base);
/* Give some time to the PCI controller to configure itself with the new
* values. Not waiting at this point causes crashes of the machine. */
- mdelay(10);
+ mdelay(300);
register_pci_controller(&ssb_pcicore_controller);
}

View file

@ -0,0 +1,13 @@
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -127,6 +127,10 @@ static int bcm47xx_get_invariants(struct
if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
+ /* Do not indicate cardbus for Netgear WNR834B V1 and V2 */
+ if (iv->boardinfo.type == 0x0472 && iv->has_cardbus_slot)
+ iv->has_cardbus_slot = 0;
+
return 0;
}

View file

@ -0,0 +1,22 @@
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -20,7 +20,8 @@
#include <bcm47xx_nvram.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
-static char nvram_buf[NVRAM_SPACE];
+char nvram_buf[NVRAM_SPACE];
+EXPORT_SYMBOL(nvram_buf);
static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
static int cfe_env;
extern char *cfe_env_get(char *nv_buf, const char *name);
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -58,6 +58,7 @@ void (*_dma_cache_wback)(unsigned long s
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_inv);
#endif /* CONFIG_DMA_NONCOHERENT */