[PATCH 36 v2] LEON3: GPTIMER timer watchdog driver

Daniel Hellstrom daniel at gaisler.com
Thu Apr 19 13:21:27 UTC 2012


Last timer instance of GPTIMER is sometimes a watchdog timer that
can reset the system on timer underflow.

Signed-off-by: Daniel Hellstrom <daniel at gaisler.com>
---
 c/src/lib/libbsp/sparc/leon3/Makefile.am        |    2 +
 c/src/lib/libbsp/sparc/leon3/include/watchdog.h |   49 ++++++++++++
 c/src/lib/libbsp/sparc/leon3/preinstall.am      |    4 +
 c/src/lib/libbsp/sparc/leon3/timer/watchdog.c   |   90 +++++++++++++++++++++++
 4 files changed, 145 insertions(+), 0 deletions(-)
 create mode 100644 c/src/lib/libbsp/sparc/leon3/include/watchdog.h
 create mode 100644 c/src/lib/libbsp/sparc/leon3/timer/watchdog.c

diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index cc25993..09d8b8e 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -115,6 +115,8 @@ libbsp_a_SOURCES += ../../sparc/shared/i2c/i2cmst.c
 
 # timer
 libbsp_a_SOURCES += timer/timer.c
+libbsp_a_SOURCES += timer/watchdog.c
+include_HEADERS += include/watchdog.h
 
 if HAS_SMP
 libbsp_a_SOURCES += smp/getcpuid.c
diff --git a/c/src/lib/libbsp/sparc/leon3/include/watchdog.h b/c/src/lib/libbsp/sparc/leon3/include/watchdog.h
new file mode 100644
index 0000000..8110efd
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/include/watchdog.h
@@ -0,0 +1,49 @@
+/*  watchdog.h
+ *
+ *  The LEON3 BSP timer watch-dog interface
+ *
+ *  COPYRIGHT (c) 2012
+ *  Aeroflex Gaisler
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef __WATCHDOG_H__
+#define __WATCHDOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initialize BSP watchdog routines. Returns number of watchdog timers found.
+ * Currently only one is supported.
+ */
+int bsp_watchdog_init(void);
+
+/* Reload watchdog (last timer on the first GPTIMER core), all systems does not
+ * feature a watchdog, it is expected that if this function is called the
+ * user knows that there is a watchdog available.
+ *
+ * The prescaler is normally set to number of MHz of system, this is to
+ * make the system clock tick be stable.
+ *
+ * Arguments
+ *  watchdog       - Always 0 for now
+ *  reload_value   - Number of timer clocks (after prescaler) to count before 
+ *                   watchdog is woken.
+ */
+void bsp_watchdog_reload(int watchdog, unsigned int reload_value);
+
+/* Stop watchdog timer */
+void bsp_watchdog_stop(int watchdog);
+
+/* Use watchdog0 timer to reset the system */
+void bsp_watchdog_system_reset(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/c/src/lib/libbsp/sparc/leon3/preinstall.am b/c/src/lib/libbsp/sparc/leon3/preinstall.am
index dffbb5a..b55cf35 100644
--- a/c/src/lib/libbsp/sparc/leon3/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon3/preinstall.am
@@ -149,3 +149,7 @@ $(PROJECT_INCLUDE)/i2cmst.h: ../../sparc/shared/include/i2cmst.h $(PROJECT_INCLU
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h
 
+$(PROJECT_INCLUDE)/watchdog.h: include/watchdog.h $(PROJECT_INCLUDE)/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/watchdog.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/watchdog.h
+
diff --git a/c/src/lib/libbsp/sparc/leon3/timer/watchdog.c b/c/src/lib/libbsp/sparc/leon3/timer/watchdog.c
new file mode 100644
index 0000000..b09ab9c
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/timer/watchdog.c
@@ -0,0 +1,90 @@
+/*  GPTIMER Watchdog timer routines. On some systems the first GPTIMER
+ *  core's last Timer instance underflow signal is connected to system
+ *  reset.
+ *
+ *  COPYRIGHT (c) 2012
+ *  Aeroflex Gaisler
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <watchdog.h>
+#include <grlib.h>
+
+extern volatile struct gptimer_regs *LEON3_Timer_Regs;
+
+struct gptimer_watchdog_priv {
+  struct gptimer_regs *regs;
+  struct gptimer_timer_regs *timer;
+  int timerno;
+};
+
+struct gptimer_watchdog_priv bsp_watchdogs[1];
+int bsp_watchdog_count = 0;
+
+int bsp_watchdog_init(void)
+{
+  int timercnt;
+
+  if (!LEON3_Timer_Regs)
+    return 0;
+
+  /* Get Watchdogs in system, this is implemented for one GPTIMER core
+   * only.
+   *
+   * First watchdog is a special case, we can get the first timer core by
+   * looking at LEON3_Timer_Regs, the watchdog within a timer core is
+   * always the last timer. Unfortunately we can not know it the watchdog
+   * functionality is available or not, we assume that it is if we
+   * reached this function.
+   */
+  bsp_watchdogs[0].regs = (struct gptimer_regs *)LEON3_Timer_Regs;
+
+  /* Find Timer that has watchdog functionality */
+  timercnt = bsp_watchdogs[0].regs->cfg & 0x7;
+  if (timercnt < 2) /* First timer system clock timer */
+    return 0;
+
+  bsp_watchdogs[0].timerno = timercnt - 1;
+  bsp_watchdogs[0].timer = &bsp_watchdogs[0].regs->timer[bsp_watchdogs[0].timerno];
+
+  bsp_watchdog_count = 1;
+  return bsp_watchdog_count;
+}
+
+void bsp_watchdog_reload(int watchdog, unsigned int reload_value)
+{
+  if (bsp_watchdog_count == 0)
+    bsp_watchdog_init();
+
+  if (bsp_watchdog_count <= watchdog)
+    return;
+
+  /* Kick watchdog, and clear interrupt pending bit */
+  bsp_watchdogs[watchdog].timer->reload = reload_value;
+  bsp_watchdogs[watchdog].timer->ctrl =
+    (LEON3_GPTIMER_LD | LEON3_GPTIMER_EN) |
+    (bsp_watchdogs[watchdog].timer->ctrl & ~(1<<4));
+}
+
+void bsp_watchdog_stop(int watchdog)
+{
+  if (bsp_watchdog_count == 0)
+    bsp_watchdog_init();
+
+  if (bsp_watchdog_count <= watchdog)
+    return;
+
+  /* Stop watchdog timer */
+  bsp_watchdogs[watchdog].timer->ctrl = 0;
+}
+
+/* Use watchdog timer to reset system */
+void bsp_watchdog_system_reset(void)
+{
+  sparc_disable_interrupts();
+  bsp_watchdog_reload(0, 1);
+}
-- 
1.7.0.4




More information about the devel mailing list