| --- a/arch/mips/bcm47xx/setup.c |
| +++ b/arch/mips/bcm47xx/setup.c |
| @@ -37,6 +37,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> |
| @@ -254,6 +255,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) { |
| @@ -275,6 +303,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 |
| @@ -63,6 +63,7 @@ CONFIG_HW_RANDOM=y |
| CONFIG_GPIO_SYSFS=y |
| CONFIG_WATCHDOG=y |
| CONFIG_BCM47XX_WDT=y |
| +CONFIG_GPIO_WDT=y |
| CONFIG_SSB_DRIVER_GIGE=y |
| CONFIG_BCMA_DRIVER_GMAC_CMN=y |
| CONFIG_USB=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; |