Commit 7ffbffe37de3979d43c1105e38eb2918bf5d35fe

Authored by Hauke Mehrtens
Committed by John W. Linville
1 parent 26107309c0

ssb: add methods for watchdog driver

The watchdog driver wants to set the watchdog timeout in ms and not in
ticks, which is depending on the SoC type and the clock.
Calculate the number of ticks per millisecond and provide two functions
for the watchdog driver. Also return the ticks or millisecond the timer
was set to in case the provided value was bigger than the max allowed
value.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 3 changed files with 54 additions and 3 deletions Side-by-side Diff

drivers/ssb/driver_chipcommon.c
... ... @@ -4,6 +4,7 @@
4 4 *
5 5 * Copyright 2005, Broadcom Corporation
6 6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  7 + * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
7 8 *
8 9 * Licensed under the GNU/GPL. See COPYING for details.
9 10 */
... ... @@ -12,6 +13,7 @@
12 13 #include <linux/ssb/ssb_regs.h>
13 14 #include <linux/export.h>
14 15 #include <linux/pci.h>
  16 +#include <linux/bcm47xx_wdt.h>
15 17  
16 18 #include "ssb_private.h"
17 19  
... ... @@ -306,6 +308,43 @@
306 308 return (1 << nb) - 1;
307 309 }
308 310  
  311 +u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
  312 +{
  313 + struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
  314 +
  315 + if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
  316 + return 0;
  317 +
  318 + return ssb_chipco_watchdog_timer_set(cc, ticks);
  319 +}
  320 +
  321 +u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
  322 +{
  323 + struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
  324 + u32 ticks;
  325 +
  326 + if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
  327 + return 0;
  328 +
  329 + ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
  330 + return ticks / cc->ticks_per_ms;
  331 +}
  332 +
  333 +static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc)
  334 +{
  335 + struct ssb_bus *bus = cc->dev->bus;
  336 +
  337 + if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
  338 + /* based on 32KHz ILP clock */
  339 + return 32;
  340 + } else {
  341 + if (cc->dev->id.revision < 18)
  342 + return ssb_clockspeed(bus) / 1000;
  343 + else
  344 + return ssb_chipco_alp_clock(cc) / 1000;
  345 + }
  346 +}
  347 +
309 348 void ssb_chipcommon_init(struct ssb_chipcommon *cc)
310 349 {
311 350 if (!cc->dev)
... ... @@ -323,6 +362,11 @@
323 362 chipco_powercontrol_init(cc);
324 363 ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
325 364 calc_fast_powerup_delay(cc);
  365 +
  366 + if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) {
  367 + cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc);
  368 + cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
  369 + }
326 370 }
327 371  
328 372 void ssb_chipco_suspend(struct ssb_chipcommon *cc)
... ... @@ -421,7 +465,7 @@
421 465 }
422 466  
423 467 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
424   -void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
  468 +u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
425 469 {
426 470 u32 maxt;
427 471 enum ssb_clkmode clkmode;
... ... @@ -441,6 +485,7 @@
441 485 /* instant NMI */
442 486 chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
443 487 }
  488 + return ticks;
444 489 }
445 490  
446 491 void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
drivers/ssb/ssb_private.h
... ... @@ -3,6 +3,7 @@
3 3  
4 4 #include <linux/ssb/ssb.h>
5 5 #include <linux/types.h>
  6 +#include <linux/bcm47xx_wdt.h>
6 7  
7 8  
8 9 #define PFX "ssb: "
... ... @@ -211,6 +212,10 @@
211 212 extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
212 213 extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
213 214 extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc);
  215 +
  216 +extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
  217 + u32 ticks);
  218 +extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
214 219  
215 220 #endif /* LINUX_SSB_PRIVATE_H_ */
include/linux/ssb/ssb_driver_chipcommon.h
... ... @@ -591,6 +591,8 @@
591 591 /* Fast Powerup Delay constant */
592 592 u16 fast_pwrup_delay;
593 593 struct ssb_chipcommon_pmu pmu;
  594 + u32 ticks_per_ms;
  595 + u32 max_timer_ms;
594 596 };
595 597  
596 598 static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
... ... @@ -630,8 +632,7 @@
630 632 extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
631 633 enum ssb_clkmode mode);
632 634  
633   -extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
634   - u32 ticks);
  635 +extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks);
635 636  
636 637 void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
637 638