--- a/drivers/watchdog/bcm47xx_wdt.c +++ b/drivers/watchdog/bcm47xx_wdt.c @@ -31,6 +31,7 @@ #define WDT_DEFAULT_TIME 30 /* seconds */ #define WDT_MAX_TIME 255 /* seconds */ +#define WDT_SHIFT 15 /* 32.768 KHz on cores with slow WDT clock */ static int wdt_time = WDT_DEFAULT_TIME; static int nowayout = WATCHDOG_NOWAYOUT; @@ -50,20 +51,20 @@ static unsigned long bcm47xx_wdt_busy; static char expect_release; static struct timer_list wdt_timer; static atomic_t ticks; +static int needs_sw_scale; -static inline void bcm47xx_wdt_hw_start(void) +static inline void bcm47xx_wdt_hw_start(u32 ticks) { - /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ switch (bcm47xx_bus_type) { #ifdef CONFIG_BCM47XX_SSB case BCM47XX_BUS_TYPE_SSB: - ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); + ssb_watchdog_timer_set(&bcm47xx_bus.ssb, ticks); break; #endif #ifdef CONFIG_BCM47XX_BCMA case BCM47XX_BUS_TYPE_BCMA: bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, - 0xfffffff); + ticks); break; #endif } @@ -88,33 +89,34 @@ static inline int bcm47xx_wdt_hw_stop(vo static void bcm47xx_timer_tick(unsigned long unused) { if (!atomic_dec_and_test(&ticks)) { - bcm47xx_wdt_hw_start(); + /* This is 2,5s on 100Mhz clock and 2s on 133 Mhz */ + bcm47xx_wdt_hw_start(0xfffffff); mod_timer(&wdt_timer, jiffies + HZ); } else { - printk(KERN_CRIT DRV_NAME "Watchdog will fire soon!!!\n"); + printk(KERN_CRIT DRV_NAME ": Watchdog will fire soon!!!\n"); } } -static inline void bcm47xx_wdt_pet(void) +static void bcm47xx_wdt_pet(void) { - atomic_set(&ticks, wdt_time); + if(needs_sw_scale) + atomic_set(&ticks, wdt_time); + else + bcm47xx_wdt_hw_start(wdt_time << WDT_SHIFT); } static void bcm47xx_wdt_start(void) { bcm47xx_wdt_pet(); - bcm47xx_timer_tick(0); -} - -static void bcm47xx_wdt_pause(void) -{ - del_timer_sync(&wdt_timer); - bcm47xx_wdt_hw_stop(); + if(needs_sw_scale) + bcm47xx_timer_tick(0); } static void bcm47xx_wdt_stop(void) { - bcm47xx_wdt_pause(); + if(needs_sw_scale) + del_timer_sync(&wdt_timer); + bcm47xx_wdt_hw_stop(); } static int bcm47xx_wdt_settimeout(int new_time) @@ -266,7 +268,20 @@ static int __init bcm47xx_wdt_init(void) if (bcm47xx_wdt_hw_stop() < 0) return -ENODEV; - setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); + /* FIXME Other cores */ +#ifdef BCM47XX_BUS_TYPE_BCMA + if(bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA && + bcm47xx_bus.ssb.chip_id == 0x5354) { + /* Slow WDT clock, no pre-scaling */ + needs_sw_scale = 0; + } else { +#endif + /* Fast WDT clock, needs software pre-scaling */ + needs_sw_scale = 1; + setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); +#ifdef BCM47XX_BUS_TYPE_BCMA + } +#endif if (bcm47xx_wdt_settimeout(wdt_time)) { bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);