summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch')
-rw-r--r--target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch120
1 files changed, 120 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch b/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch
new file mode 100644
index 000000000..3e67ba2bb
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch
@@ -0,0 +1,120 @@
+--- a/drivers/watchdog/bcm47xx_wdt.c
++++ b/drivers/watchdog/bcm47xx_wdt.c
+@@ -31,6 +31,7 @@
+
+ #define WDT_DEFAULT_TIME 30 /* seconds */
+ #define WDT_SOFTTIMER_MAX 3600 /* seconds */
++#define WDT_SOFTTIMER_THRESHOLD 60 /* seconds */
+
+ static int timeout = WDT_DEFAULT_TIME;
+ static bool nowayout = WATCHDOG_NOWAYOUT;
+@@ -52,6 +53,53 @@ static inline struct bcm47xx_wdt *bcm47x
+ return container_of(wdd, struct bcm47xx_wdt, wdd);
+ }
+
++static int bcm47xx_wdt_hard_keepalive(struct watchdog_device *wdd)
++{
++ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
++
++ wdt->timer_set_ms(wdt, wdd->timeout * 1000);
++
++ return 0;
++}
++
++static int bcm47xx_wdt_hard_start(struct watchdog_device *wdd)
++{
++ return 0;
++}
++
++static int bcm47xx_wdt_hard_stop(struct watchdog_device *wdd)
++{
++ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
++
++ wdt->timer_set(wdt, 0);
++
++ return 0;
++}
++
++static int bcm47xx_wdt_hard_set_timeout(struct watchdog_device *wdd,
++ unsigned int new_time)
++{
++ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
++ u32 max_timer = wdt->max_timer_ms;
++
++ if (new_time < 1 || new_time > max_timer / 1000) {
++ pr_warn("timeout value must be 1<=x<=%d, using %d\n",
++ max_timer / 1000, new_time);
++ return -EINVAL;
++ }
++
++ wdd->timeout = new_time;
++ return 0;
++}
++
++static struct watchdog_ops bcm47xx_wdt_hard_ops = {
++ .owner = THIS_MODULE,
++ .start = bcm47xx_wdt_hard_start,
++ .stop = bcm47xx_wdt_hard_stop,
++ .ping = bcm47xx_wdt_hard_keepalive,
++ .set_timeout = bcm47xx_wdt_hard_set_timeout,
++};
++
+ static void bcm47xx_wdt_soft_timer_tick(unsigned long data)
+ {
+ struct bcm47xx_wdt *wdt = (struct bcm47xx_wdt *)data;
+@@ -136,15 +184,22 @@ static struct watchdog_ops bcm47xx_wdt_s
+ static int __devinit bcm47xx_wdt_probe(struct platform_device *pdev)
+ {
+ int ret;
++ bool soft;
+ struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev);
+
+ if (!wdt)
+ return -ENXIO;
+
+- setup_timer(&wdt->soft_timer, bcm47xx_wdt_soft_timer_tick,
+- (long unsigned int)wdt);
++ soft = wdt->max_timer_ms < WDT_SOFTTIMER_THRESHOLD * 1000;
++
++ if (soft) {
++ wdt->wdd.ops = &bcm47xx_wdt_soft_ops;
++ setup_timer(&wdt->soft_timer, bcm47xx_wdt_soft_timer_tick,
++ (long unsigned int)wdt);
++ } else {
++ wdt->wdd.ops = &bcm47xx_wdt_hard_ops;
++ }
+
+- wdt->wdd.ops = &bcm47xx_wdt_soft_ops;
+ wdt->wdd.info = &bcm47xx_wdt_info;
+ wdt->wdd.timeout = WDT_DEFAULT_TIME;
+ ret = wdt->wdd.ops->set_timeout(&wdt->wdd, timeout);
+@@ -162,14 +217,16 @@ static int __devinit bcm47xx_wdt_probe(s
+ if (ret)
+ goto err_notifier;
+
+- pr_info("BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
+- timeout, nowayout ? ", nowayout" : "");
++ dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n",
++ timeout, nowayout ? ", nowayout" : "",
++ soft ? ", Software Timer" : "");
+ return 0;
+
+ err_notifier:
+ unregister_reboot_notifier(&wdt->notifier);
+ err_timer:
+- del_timer_sync(&wdt->soft_timer);
++ if (soft)
++ del_timer_sync(&wdt->soft_timer);
+
+ return ret;
+ }
+--- a/include/linux/bcm47xx_wdt.h
++++ b/include/linux/bcm47xx_wdt.h
+@@ -10,6 +10,7 @@
+ struct bcm47xx_wdt {
+ u32 (*timer_set)(struct bcm47xx_wdt *, u32);
+ u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32);
++ u32 max_timer_ms;
+
+ void *driver_data;
+