aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm47xx/patches-4.1/830-huawei_e970_support.patch
blob: aa0ccaec5d8b57c6d6febd16634aa14f88899b6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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>
@@ -262,6 +263,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) {
@@ -281,6 +309,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;