Module Name:    src
Committed By:   hans
Date:           Tue Jun 19 16:50:44 UTC 2012

Modified Files:
        src/sys/arch/arm/marvell: files.marvell mvsoctmr.c

Log Message:
Add support for the watchdog timer in mvsoctmr.
Tested on DreamPlug system.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/marvell/files.marvell
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/marvell/mvsoctmr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/marvell/files.marvell
diff -u src/sys/arch/arm/marvell/files.marvell:1.4 src/sys/arch/arm/marvell/files.marvell:1.5
--- src/sys/arch/arm/marvell/files.marvell:1.4	Sat Mar 12 22:34:52 2011
+++ src/sys/arch/arm/marvell/files.marvell	Tue Jun 19 16:50:44 2012
@@ -1,4 +1,4 @@
-#       $NetBSD: files.marvell,v 1.4 2011/03/12 22:34:52 nonaka Exp $
+#       $NetBSD: files.marvell,v 1.5 2012/06/19 16:50:44 hans Exp $
 #
 # Configuration info for Marvell System on Chip support
 #
@@ -24,7 +24,7 @@ file	arch/arm/marvell/kirkwood.c		kirkwo
 include "dev/marvell/files.discovery"
 
 # Timers
-device	mvsoctmr
+device	mvsoctmr: sysmon_wdog
 attach	mvsoctmr at mvsoc
 file	arch/arm/marvell/mvsoctmr.c		mvsoctmr
 

Index: src/sys/arch/arm/marvell/mvsoctmr.c
diff -u src/sys/arch/arm/marvell/mvsoctmr.c:1.3 src/sys/arch/arm/marvell/mvsoctmr.c:1.4
--- src/sys/arch/arm/marvell/mvsoctmr.c:1.3	Sun Feb 12 16:34:07 2012
+++ src/sys/arch/arm/marvell/mvsoctmr.c	Tue Jun 19 16:50:44 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsoctmr.c,v 1.3 2012/02/12 16:34:07 matt Exp $	*/
+/*	$NetBSD: mvsoctmr.c,v 1.4 2012/06/19 16:50:44 hans Exp $	*/
 /*
  * Copyright (c) 2007, 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -25,7 +25,9 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mvsoctmr.c,v 1.3 2012/02/12 16:34:07 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mvsoctmr.c,v 1.4 2012/06/19 16:50:44 hans Exp $");
+
+#include "opt_ddb.h"
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -36,6 +38,7 @@ __KERNEL_RCSID(0, "$NetBSD: mvsoctmr.c,v
 #include <sys/time.h>
 #include <sys/timetc.h>
 #include <sys/systm.h>
+#include <sys/wdog.h>
 
 #include <machine/intr.h>
 
@@ -47,10 +50,21 @@ __KERNEL_RCSID(0, "$NetBSD: mvsoctmr.c,v
 
 #include <dev/marvell/marvellvar.h>
 
+#include <dev/sysmon/sysmonvar.h>
+
+#ifdef DDB
+#include <machine/db_machdep.h>
+#include <ddb/db_extern.h>
+#endif
+
 
 struct mvsoctmr_softc {
 	device_t sc_dev;
 
+	struct sysmon_wdog sc_wdog;
+	uint32_t sc_wdog_period;
+	uint32_t sc_wdog_armed;
+
 	bus_space_tag_t sc_iot;
 	bus_space_handle_t sc_ioh;
 };
@@ -65,6 +79,16 @@ static u_int mvsoctmr_get_timecount(stru
 
 static void mvsoctmr_cntl(struct mvsoctmr_softc *, int, u_int, int, int);
 
+static int mvsoctmr_wdog_tickle(struct sysmon_wdog *);
+static int mvsoctmr_wdog_setmode(struct sysmon_wdog *);
+
+#ifdef DDB
+static struct mvsoctmr_softc *mvsoctmr_softc;
+static void mvsoctmr_wdog_ddb_trap(int);
+#endif
+
+#define MVSOC_WDOG_MAX_PERIOD	21
+
 static struct mvsoctmr_softc *mvsoctmr_sc;
 static struct timecounter mvsoctmr_timecounter = {
 	mvsoctmr_get_timecount,	/* get_timecount */
@@ -102,6 +126,7 @@ mvsoctmr_attach(device_t parent, device_
 {
         struct mvsoctmr_softc *sc = device_private(self);
 	struct marvell_attach_args *mva = aux;
+	uint32_t rstoutn;
 
 	aprint_naive("\n");
 	aprint_normal(": Marvell SoC Timer\n");
@@ -117,6 +142,29 @@ mvsoctmr_attach(device_t parent, device_
 
 	mvsoctmr_timecounter.tc_name = device_xname(self);
 	mvsoctmr_cntl(sc, MVSOCTMR_TIMER1, 0xffffffff, 1, 1);
+
+	/*
+	 * stop watchdog timer, enable watchdog timer resets
+	 */
+	mvsoctmr_cntl(sc, MVSOCTMR_WATCHDOG, 0, 0, 0);
+	rstoutn = read_mlmbreg(MVSOC_MLMB_RSTOUTNMASKR);
+	write_mlmbreg(MVSOC_MLMB_RSTOUTNMASKR,
+		      rstoutn | MVSOC_MLMB_RSTOUTNMASKR_WDRSTOUTEN);
+
+#ifdef DDB
+	mvsoctmr_softc = sc;
+	db_trap_callback = mvsoctmr_wdog_ddb_trap;
+#endif
+
+	sc->sc_wdog.smw_name = device_xname(self);
+	sc->sc_wdog.smw_cookie = sc;
+	sc->sc_wdog.smw_setmode = mvsoctmr_wdog_setmode;
+	sc->sc_wdog.smw_tickle = mvsoctmr_wdog_tickle;
+	sc->sc_wdog.smw_period = MVSOC_WDOG_MAX_PERIOD;
+
+	if (sysmon_wdog_register(&sc->sc_wdog) != 0)
+		aprint_error_dev(self,
+				 "unable to register watchdog with sysmon\n");
 }
 
 /*
@@ -257,3 +305,54 @@ mvsoctmr_cntl(struct mvsoctmr_softc *sc,
 		ctrl &= ~MVSOCTMR_CTCR_CPUTIMERAUTO(num);
 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSOCTMR_CTCR, ctrl);
 }
+
+static int
+mvsoctmr_wdog_setmode(struct sysmon_wdog *smw)
+{
+	struct mvsoctmr_softc *sc = smw->smw_cookie;
+
+	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
+		sc->sc_wdog_armed = 0;
+		mvsoctmr_cntl(sc, MVSOCTMR_WATCHDOG, 0, 0, 0);
+	} else {
+		sc->sc_wdog_armed = 1;
+		if (smw->smw_period == WDOG_PERIOD_DEFAULT)
+			smw->smw_period = MVSOC_WDOG_MAX_PERIOD;
+		else if (smw->smw_period > MVSOC_WDOG_MAX_PERIOD ||
+			 smw->smw_period <= 0)
+			return (EOPNOTSUPP);
+		sc->sc_wdog_period = smw->smw_period * mvTclk;
+		mvsoctmr_cntl(sc, MVSOCTMR_WATCHDOG, sc->sc_wdog_period, 1, 0);
+	}
+
+	return (0);
+}
+
+static int
+mvsoctmr_wdog_tickle(struct sysmon_wdog *smw)
+{
+	struct mvsoctmr_softc *sc = smw->smw_cookie;
+
+	mvsoctmr_cntl(sc, MVSOCTMR_WATCHDOG, sc->sc_wdog_period, 1, 0);
+
+	return (0);
+}
+
+#ifdef DDB
+static void
+mvsoctmr_wdog_ddb_trap(int enter)
+{
+	struct mvsoctmr_softc *sc = mvsoctmr_softc;
+
+	if (sc == NULL)
+		return;
+
+	if (sc->sc_wdog_armed) {
+		if (enter)
+			mvsoctmr_cntl(sc, MVSOCTMR_WATCHDOG, 0, 0, 0);
+		else
+			mvsoctmr_cntl(sc, MVSOCTMR_WATCHDOG,
+				      sc->sc_wdog_period, 1, 0);
+	}
+}
+#endif

Reply via email to