bcma: add methods for watchdog driver
authorHauke Mehrtens <hauke@hauke-m.de>
Wed, 5 Dec 2012 17:46:01 +0000 (18:46 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 6 Dec 2012 19:58:56 +0000 (14:58 -0500)
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>
drivers/bcma/driver_chipcommon.c
include/linux/bcma/bcma_driver_chipcommon.h

index 7c132e5..1172226 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/bcm47xx_wdt.h>
 #include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
@@ -52,6 +53,39 @@ static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
                return (1 << nb) - 1;
 }
 
+static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
+                                             u32 ticks)
+{
+       struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
+
+       return bcma_chipco_watchdog_timer_set(cc, ticks);
+}
+
+static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
+                                                u32 ms)
+{
+       struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
+       u32 ticks;
+
+       ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
+       return ticks / cc->ticks_per_ms;
+}
+
+static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
+{
+       struct bcma_bus *bus = cc->core->bus;
+
+       if (cc->capabilities & BCMA_CC_CAP_PMU) {
+               if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
+                       /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
+                       return bcma_chipco_alp_clock(cc) / 4000;
+               else
+                       /* based on 32KHz ILP clock */
+                       return 32;
+       } else {
+               return bcma_chipco_alp_clock(cc) / 1000;
+       }
+}
 
 void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
 {
@@ -100,12 +134,13 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
                        ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
                         (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
        }
+       cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
 
        cc->setup_done = true;
 }
 
 /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
-void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
+u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
 {
        u32 maxt;
        enum bcma_clkmode clkmode;
@@ -125,6 +160,7 @@ void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
                /* instant NMI */
                bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
        }
+       return ticks;
 }
 
 void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
index 145f3c5..2f9b014 100644 (file)
@@ -570,6 +570,7 @@ struct bcma_drv_cc {
        int nr_serial_ports;
        struct bcma_serial_port serial_ports[4];
 #endif /* CONFIG_BCMA_DRIVER_MIPS */
+       u32 ticks_per_ms;
 };
 
 /* Register access */
@@ -593,8 +594,7 @@ extern void bcma_chipco_resume(struct bcma_drv_cc *cc);
 
 void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
 
-extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,
-                                         u32 ticks);
+extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks);
 
 void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value);