--- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -288,6 +288,24 @@ static u32 ssb_chipco_alp_clock(struct s return 20000000; } +static u32 ssb_chipco_watchdog_get_max_timer(struct ssb_chipcommon *cc) +{ + u32 nb; + + if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { + if (cc->dev->id.revision < 26) + nb = 16; + else + nb = (cc->dev->id.revision >= 37) ? 32 : 24; + } else { + nb = 28; + } + if (nb == 32) + return 0xffffffff; + else + return (1 << nb) - 1; +} + void ssb_chipcommon_init(struct ssb_chipcommon *cc) { if (!cc->dev) @@ -405,8 +423,24 @@ void ssb_chipco_timing_init(struct ssb_c /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks) { - /* instant NMI */ - chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); + u32 maxt; + enum ssb_clkmode clkmode; + + maxt = ssb_chipco_watchdog_get_max_timer(cc); + if (cc->capabilities & SSB_CHIPCO_CAP_PMU) { + if (ticks == 1) + ticks = 2; + else if (ticks > maxt) + ticks = maxt; + chipco_write32(cc, SSB_CHIPCO_PMU_WATCHDOG, ticks); + } else { + clkmode = ticks ? SSB_CLKMODE_FAST : SSB_CLKMODE_DYNAMIC; + ssb_chipco_set_clockmode(cc, clkmode); + if (ticks > maxt) + ticks = maxt; + /* instant NMI */ + chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); + } } void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)