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--open...@adamis.de>

---

diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c
index 997fbe8..362cb73 100644
--- a/package/broadcom-diag/src/diag.c
+++ b/package/broadcom-diag/src/diag.c
@@ -150,6 +150,9 @@ enum {
 
        /* Edimax */
        PS1208MFG,
+
+       /* Huawei */
+       HUAWEI_E970,
 };
 
 static void __init bcm4780_init(void) {
@@ -1036,6 +1039,16 @@ static struct platform_t __initdata platforms[] = {
                        { .name = "wlan",       .gpio = 1 << 0, .polarity = 
NORMAL },
                },
        },
+       /* Huawei */
+       [HUAWEI_E970] = {
+               .name   = "Huawei E970",
+               .buttons        = {
+                       { .name = "reset",      .gpio = 1 << 6 },
+               },
+               .leds     = {
+                       { .name = "wlan",       .gpio = 1 << 0, .polarity = 
NORMAL },
+               },
+       },
 };
 
 static struct platform_t __init *platform_detect(void)
@@ -1306,6 +1319,9 @@ static struct platform_t __init *platform_detect(void)
                !strcmp(getvar("status_gpio"), "1")) /* gpio based detection */
                return &platforms[PS1208MFG];
 
+       if (!strcmp(boardnum, "0x5347") && !strcmp(boardtype, "0x048e"))  /* 
Huawei E970 */
+               return &platforms[HUAWEI_E970];
+
        /* not found */
        return NULL;
 }
diff --git a/target/linux/brcm47xx/config-3.6 b/target/linux/brcm47xx/config-3.6
index 7f1ea7d..93fdeb9 100644
--- a/target/linux/brcm47xx/config-3.6
+++ b/target/linux/brcm47xx/config-3.6
@@ -143,3 +143,4 @@ CONFIG_USB_ARCH_HAS_XHCI=y
 CONFIG_USB_SUPPORT=y
 CONFIG_WATCHDOG_CORE=y
 CONFIG_ZONE_DMA_FLAG=0
+CONFIG_GPIO_WDT=y
diff --git a/target/linux/brcm47xx/image/Makefile 
b/target/linux/brcm47xx/image/Makefile
index f45fb56..9a716f4 100644
--- a/target/linux/brcm47xx/image/Makefile
+++ b/target/linux/brcm47xx/image/Makefile
@@ -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
        rm -f $(KDIR)/loader.gz
        $(MAKE) -C lzma-loader \
                BUILD_DIR="$(KDIR)" \
@@ -56,6 +57,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
@@ -117,9 +124,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,U12H093T00_NETGEAR,2,$(patsubst 
jffs2-%,jffs2,$(1)))
diff --git a/target/linux/brcm47xx/patches-3.6/830-huawei_e970_support.patch 
b/target/linux/brcm47xx/patches-3.6/830-huawei_e970_support.patch
new file mode 100644
index 0000000..c6c14d1
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.6/830-huawei_e970_support.patch
@@ -0,0 +1,174 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -33,6 +33,7 @@
+ #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>
+@@ -45,6 +46,29 @@ EXPORT_SYMBOL(bcm47xx_bus);
+ enum bcm47xx_bus_type bcm47xx_bus_type;
+ EXPORT_SYMBOL(bcm47xx_bus_type);
+ 
++
++#define ROUTER_HUAWEI_E970            1
++
++static int get_router(void)
++{
++      char buf[20];
++      u32 boardnum = 0;
++      u16 boardtype = 0;
++
++      if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) >= 0)
++              boardnum = simple_strtoul(buf, NULL, 0);
++      if (bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
++              boardtype = simple_strtoul(buf, NULL, 0);
++
++      if (boardnum == 0x5347 && boardtype == 0x048e) {
++              /* Huawei E970 */
++              return ROUTER_HUAWEI_E970;
++      }
++
++      return 0;
++}
++
++
+ static void bcm47xx_machine_restart(char *command)
+ {
+       printk(KERN_ALERT "Please stand by while rebooting the system...\n");
+@@ -254,8 +278,24 @@ void __init plat_mem_setup(void)
+       pm_power_off = bcm47xx_machine_halt;
+ }
+ 
++static struct gpio_wdt_platform_data gpio_wdt_data = {
++      .gpio           = 7,
++      .interval       = HZ,
++      .first_interval = HZ/5,
++};
++
++static struct platform_device gpio_wdt_device = {
++      .name                   = "gpio-wdt",
++      .id                     = 0,
++      .dev                    = {
++              .platform_data  = &gpio_wdt_data,
++      },
++};
++
+ static int __init bcm47xx_register_bus_complete(void)
+ {
++      int err = 0;
++
+       switch (bcm47xx_bus_type) {
+ #ifdef CONFIG_BCM47XX_SSB
+       case BCM47XX_BUS_TYPE_SSB:
+@@ -268,6 +308,14 @@ static int __init bcm47xx_register_bus_c
+               break;
+ #endif
+       }
+-      return 0;
++
++      /* device-specific initializations */
++      switch (get_router()) {
++      case ROUTER_HUAWEI_E970:
++              printk(KERN_INFO "bcm47xx: detected Huawei E970 or similar, 
starting early gpio_wdt timer\n");
++              err = platform_device_register(&gpio_wdt_device);
++      }
++
++      return err;
+ }
+ device_initcall(bcm47xx_register_bus_complete);
+--- a/arch/mips/configs/bcm47xx_defconfig
++++ b/arch/mips/configs/bcm47xx_defconfig
+@@ -380,6 +380,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/watchdog/bcm47xx_wdt.c
++++ b/drivers/watchdog/bcm47xx_wdt.c
+@@ -26,6 +26,7 @@
+ #include <linux/watchdog.h>
+ #include <linux/timer.h>
+ #include <linux/jiffies.h>
++#include <bcm47xx_nvram.h>
+ 
+ #define DRV_NAME              "bcm47xx_wdt"
+ 
+@@ -45,6 +46,29 @@ MODULE_PARM_DESC(nowayout,
+               "Watchdog cannot be stopped once started (default="
+                               __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+ 
++
++#define ROUTER_HUAWEI_E970            1
++
++static int get_router(void)
++{
++      char buf[20];
++      u32 boardnum = 0;
++      u16 boardtype = 0;
++
++      if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) >= 0)
++              boardnum = simple_strtoul(buf, NULL, 0);
++      if (bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
++              boardtype = simple_strtoul(buf, NULL, 0);
++
++      if (boardnum == 0x5347 && boardtype == 0x048e) {
++              /* Huawei E970 */
++              return ROUTER_HUAWEI_E970;
++      }
++
++      return 0;
++}
++
++
+ static inline struct bcm47xx_wdt *bcm47xx_wdt_get(struct watchdog_device *wdd)
+ {
+       return container_of(wdd, struct bcm47xx_wdt, wdd);
+@@ -187,6 +211,12 @@ static int __devinit bcm47xx_wdt_probe(s
+       if (!wdt)
+               return -ENXIO;
+ 
++      switch (get_router()) {
++      case ROUTER_HUAWEI_E970:
++              dev_info(&pdev->dev, "detected Huawei E970 or similar, not 
enabling BCM47xx Watchdog Timer\n");
++              return 0;
++      }
++
+       soft = wdt->max_timer_ms < WDT_SOFTTIMER_THRESHOLD * 1000;
+ 
+       if (soft) {
+--- a/drivers/mtd/bcm47xxpart.c
++++ b/drivers/mtd/bcm47xxpart.c
+@@ -84,6 +84,7 @@ struct trx_header {
+ #define ROUTER_NETGEAR_WNR3500L               4
+ #define ROUTER_SIMPLETECH_SIMPLESHARE 5
+ #define ROUTER_NETGEAR_WNDR3400               6
++#define ROUTER_HUAWEI_E970            7
+ 
+ static int
+ find_cfe_size(struct mtd_info *mtd)
+@@ -404,6 +405,11 @@ static int get_router(void)
+               return ROUTER_SIMPLETECH_SIMPLESHARE;
+       }
+ 
++      if (boardnum == 0x5347 && boardtype == 0x048e) {
++              /* Huawei E970 */
++                return ROUTER_HUAWEI_E970;
++      }
++
+       return 0;
+ }
+ 
+@@ -445,6 +451,7 @@ static int parse_bcm47xx_partitions(stru
+               case ROUTER_NETGEAR_WNDR3300:
+               case ROUTER_NETGEAR_WNR3500L:
+               case ROUTER_NETGEAR_WNDR3400:
++              case ROUTER_HUAWEI_E970:
+                       /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or 
checksum
+                        * is @ 0x007AFFF8 for 8M flash
+                        */
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to