brcm47xx: Add support for Huawei E970

This patch adds support for Huawei E970 wireless gateway devices.
It has been tested on an E970 labelled as T-Mobile web'n'walk Box IV.
E960/B970 should work too, from what I know it's basically the same hardware.

The device has a Broadcom BCM5354 SoC and a built-in 3G USB modem.

It uses a hardware watchdog which needs GPIO-7 to be toggled at least
every 1-2 seconds. This patch uses gpio_wdt module (see my previous
patch today) to take care of this.

Tested and works:  3G wan,  wlan+LED,  VLAN config,  failsafe using reset
button,   image to be used for upgrade from OEM firmware's web interface

Link to the wiki page I've created:  <http://wiki.openwrt.org/toh/huawei/e970>

Issue:

* lzma-loader crashes, so gzipped kernel is used. Presumably due to watchdog
  reset during kernel decompress.

Signed-off-by: Mathias Adam <m.adam--openwrt@adamis.de>

SVN-Revision: 38011
This commit is contained in:
Hauke Mehrtens 2013-09-16 21:09:10 +00:00
parent 0294358e11
commit c78e4fb220
4 changed files with 121 additions and 1 deletions

View File

@ -59,6 +59,7 @@ 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

View File

@ -13,6 +13,7 @@ endef
define Image/Prepare
cat $(KDIR)/vmlinux | $(STAGING_DIR_HOST)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
gzip -nc9 $(KDIR)/vmlinux > $(KDIR)/vmlinux.gz
ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
cat $(KDIR)/vmlinux-initramfs | $(STAGING_DIR_HOST)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux-initramfs.lzma
endif
@ -59,6 +60,12 @@ define Image/Build/Edi
$(STAGING_DIR_HOST)/bin/trx2edips $(BIN_DIR)/$(IMG_PREFIX)-$(1).trx $(BIN_DIR)/openwrt-$(2)-$(3).bin
endef
define Image/Build/Huawei
dd if=/dev/zero of=$(BIN_DIR)/openwrt-$(2)-$(3)-gz.bin bs=92 count=1
echo -ne 'HDR0\x08\x00\x00\x00' >> $(BIN_DIR)/openwrt-$(2)-$(3)-gz.bin
cat $(BIN_DIR)/$(IMG_PREFIX)-$(1)-gz.trx >> $(BIN_DIR)/openwrt-$(2)-$(3)-gz.bin
endef
define trxalign/jffs2-128k
-a 0x20000 -f $(KDIR)/root.$(1)
endef
@ -134,9 +141,13 @@ define Image/Build
$(STAGING_DIR_HOST)/bin/trx -o $(BIN_DIR)/$(IMG_PREFIX)-$(1).trx \
-f $(KDIR)/loader.gz -f $(KDIR)/vmlinux.lzma \
$(call trxalign/$(1),$(1))
$(STAGING_DIR_HOST)/bin/trx -o $(BIN_DIR)/$(IMG_PREFIX)-$(1)-gz.trx \
-f $(KDIR)/vmlinux.gz \
$(call trxalign/$(1),$(1))
$(call Image/Build/$(1),$(1))
$(call Image/Build/Motorola,$(1),wr850g,1,$(1))
$(call Image/Build/USR,$(1),usr5461,$(1))
$(call Image/Build/Huawei,$(1),e970,$(1))
$(call Image/Build/Chk,$(1),wgr614_v8,U12H072T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))
# $(call Image/Build/Chk,$(1),wgr614_v9,U12H094T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))
$(call Image/Build/Chk,$(1),wndr3300_v1,U12H093T00_NETGEAR,2,$(patsubst jffs2-%,jffs2,$(1)))

View File

@ -0,0 +1,108 @@
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -33,11 +33,13 @@
#include <linux/bcma/bcma_soc.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
+#include <linux/gpio_wdt.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <bcm47xx.h>
#include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
union bcm47xx_bus bcm47xx_bus;
EXPORT_SYMBOL(bcm47xx_bus);
@@ -254,6 +256,33 @@ void __init plat_mem_setup(void)
pm_power_off = bcm47xx_machine_halt;
}
+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) {
@@ -268,6 +297,8 @@ static int __init bcm47xx_register_bus_c
break;
#endif
}
+ bcm47xx_register_gpio_watchdog();
+
return 0;
}
device_initcall(bcm47xx_register_bus_complete);
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -379,6 +379,7 @@ CONFIG_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_NOWAYOUT=y
CONFIG_BCM47XX_WDT=y
+CONFIG_GPIO_WDT=y
CONFIG_SSB_DRIVER_GIGE=y
CONFIG_DISPLAY_SUPPORT=m
CONFIG_SOUND=m
--- 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

@ -1,6 +1,6 @@
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -120,6 +120,10 @@ static int bcm47xx_get_invariants(struct
@@ -122,6 +122,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);