xref: /openbsd-src/sys/arch/armv7/omap/omdog.c (revision 9fdf0c627b1fec102f212f847a6f7676c1829e65)
1*9fdf0c62Smpi /*	$OpenBSD: omdog.c,v 1.10 2021/10/24 17:52:27 mpi Exp $	*/
28eda2d14Spatrick /*
3e062047fSfgsch  * Copyright (c) 2013 Federico G. Schwindt <fgsch@openbsd.org>
48eda2d14Spatrick  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
58eda2d14Spatrick  *
68eda2d14Spatrick  * Permission to use, copy, modify, and distribute this software for any
78eda2d14Spatrick  * purpose with or without fee is hereby granted, provided that the above
88eda2d14Spatrick  * copyright notice and this permission notice appear in all copies.
98eda2d14Spatrick  *
108eda2d14Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
118eda2d14Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
128eda2d14Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
138eda2d14Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
148eda2d14Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
158eda2d14Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
168eda2d14Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
178eda2d14Spatrick  */
188eda2d14Spatrick 
198eda2d14Spatrick #include <sys/param.h>
208eda2d14Spatrick #include <sys/systm.h>
218eda2d14Spatrick #include <sys/device.h>
227f0748ebSjsg 
238eda2d14Spatrick #include <machine/bus.h>
247f0748ebSjsg #include <machine/fdt.h>
257f0748ebSjsg 
267f0748ebSjsg #include <dev/ofw/openfirm.h>
27ac7c670eSpatrick #include <dev/ofw/fdt.h>
287f0748ebSjsg 
29e062047fSfgsch #define WIDR		0x00			/* Identification Register */
30e062047fSfgsch #define WCLR		0x24			/* Control Register */
31e062047fSfgsch #define  WCLR_PRE		(1 << 5)
32e062047fSfgsch #define  WCLR_PTV		(0 << 2)
33e062047fSfgsch #define WCRR		0x28			/* Counter Register */
34e062047fSfgsch #define WLDR		0x2c			/* Load Register */
35e062047fSfgsch #define WTGR		0x30			/* Trigger Register */
36e062047fSfgsch #define WWPS		0x34			/* Write Posting Bits Reg. */
37e062047fSfgsch #define  WWPS_WSPR		(1 << 4)
38e062047fSfgsch #define  WWPS_WTGR		(1 << 3)
39e062047fSfgsch #define  WWPS_WLDR		(1 << 2)
40e062047fSfgsch #define  WWPS_WCRR		(1 << 1)
41e062047fSfgsch #define  WWPS_WCLR		(1 << 0)
42e062047fSfgsch #define WSPR		0x48			/* Start/Stop Register */
43e062047fSfgsch 
44e062047fSfgsch #define OMDOG_VAL(secs)	(0xffffffff - ((secs) * (32768 / (1 << 0))) + 1)
458eda2d14Spatrick 
468eda2d14Spatrick 
478eda2d14Spatrick struct omdog_softc {
488eda2d14Spatrick 	struct device		sc_dev;
498eda2d14Spatrick 	bus_space_tag_t		sc_iot;
508eda2d14Spatrick 	bus_space_handle_t	sc_ioh;
51e062047fSfgsch 
52e062047fSfgsch 	int			sc_period;
538eda2d14Spatrick };
548eda2d14Spatrick 
558eda2d14Spatrick struct omdog_softc *omdog_sc;
568eda2d14Spatrick 
577f0748ebSjsg int	omdog_match(struct device *, void *, void *);
58e062047fSfgsch void	omdog_attach(struct device *, struct device *, void *);
593b06f262Smikeb int	omdog_activate(struct device *, int);
60e062047fSfgsch void	omdog_start(struct omdog_softc *);
61e062047fSfgsch void	omdog_stop(struct omdog_softc *);
62e062047fSfgsch void	omdog_sync(struct omdog_softc *);
63e062047fSfgsch int	omdog_cb(void *, int);
64e062047fSfgsch void	omdog_reset(void);
658eda2d14Spatrick 
66*9fdf0c62Smpi const struct cfattach	omdog_ca = {
677f0748ebSjsg 	sizeof (struct omdog_softc), omdog_match, omdog_attach, NULL,
687f0748ebSjsg 	omdog_activate
698eda2d14Spatrick };
708eda2d14Spatrick 
718eda2d14Spatrick struct cfdriver omdog_cd = {
728eda2d14Spatrick 	NULL, "omdog", DV_DULL
738eda2d14Spatrick };
748eda2d14Spatrick 
757f0748ebSjsg int
omdog_match(struct device * parent,void * match,void * aux)767f0748ebSjsg omdog_match(struct device *parent, void *match, void *aux)
778eda2d14Spatrick {
787f0748ebSjsg 	struct fdt_attach_args *faa = aux;
797f0748ebSjsg 
807f0748ebSjsg 	return OF_is_compatible(faa->fa_node, "ti,omap3-wdt");
817f0748ebSjsg }
827f0748ebSjsg 
837f0748ebSjsg void
omdog_attach(struct device * parent,struct device * self,void * aux)847f0748ebSjsg omdog_attach(struct device *parent, struct device *self, void *aux)
857f0748ebSjsg {
867f0748ebSjsg 	struct fdt_attach_args *faa = aux;
878eda2d14Spatrick 	struct omdog_softc *sc = (struct omdog_softc *) self;
888eda2d14Spatrick 	u_int32_t rev;
898eda2d14Spatrick 
90ac7c670eSpatrick 	if (faa->fa_nreg < 1)
917f0748ebSjsg 		return;
927f0748ebSjsg 
937f0748ebSjsg 	sc->sc_iot = faa->fa_iot;
94ac7c670eSpatrick 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
95ac7c670eSpatrick 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
96e062047fSfgsch 		panic("%s: bus_space_map failed!", __func__);
978eda2d14Spatrick 
988eda2d14Spatrick 	rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR);
998eda2d14Spatrick 
1008eda2d14Spatrick 	printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
101e062047fSfgsch 
102e062047fSfgsch 	omdog_stop(sc);
103e062047fSfgsch 
104ac5fc12cSjsg 	/* only register one watchdog, OMAP4 has two */
105ac5fc12cSjsg 	if (omdog_sc != NULL)
106ac5fc12cSjsg 		return;
107ac5fc12cSjsg 
108ac5fc12cSjsg 	omdog_sc = sc;
109ac5fc12cSjsg 
11020598bedSjsg #ifndef SMALL_KERNEL
111e062047fSfgsch 	wdog_register(omdog_cb, sc);
11220598bedSjsg #endif
1138eda2d14Spatrick }
1148eda2d14Spatrick 
1153b06f262Smikeb int
omdog_activate(struct device * self,int act)1163b06f262Smikeb omdog_activate(struct device *self, int act)
1173b06f262Smikeb {
1183b06f262Smikeb 	switch (act) {
1193b06f262Smikeb 	case DVACT_POWERDOWN:
1203b06f262Smikeb #ifndef SMALL_KERNEL
1213b06f262Smikeb 		wdog_shutdown(self);
1223b06f262Smikeb #endif
1233b06f262Smikeb 		break;
1243b06f262Smikeb 	}
1253b06f262Smikeb 
1263b06f262Smikeb 	return (0);
1273b06f262Smikeb }
1283b06f262Smikeb 
1298eda2d14Spatrick void
omdog_start(struct omdog_softc * sc)130e062047fSfgsch omdog_start(struct omdog_softc *sc)
1318eda2d14Spatrick {
132e062047fSfgsch 	/* Write the enable sequence data BBBBh followed by 4444h */
133e062047fSfgsch 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xbbbb);
134e062047fSfgsch 	omdog_sync(sc);
135e062047fSfgsch 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x4444);
136e062047fSfgsch 	omdog_sync(sc);
1378eda2d14Spatrick }
1388eda2d14Spatrick 
139e062047fSfgsch void
omdog_stop(struct omdog_softc * sc)140e062047fSfgsch omdog_stop(struct omdog_softc *sc)
141e062047fSfgsch {
142e062047fSfgsch 	/* Write the disable sequence data AAAAh followed by 5555h */
143e062047fSfgsch 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xaaaa);
144e062047fSfgsch 	omdog_sync(sc);
145e062047fSfgsch 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x5555);
146e062047fSfgsch 	omdog_sync(sc);
147e062047fSfgsch }
1488eda2d14Spatrick 
1498eda2d14Spatrick void
omdog_sync(struct omdog_softc * sc)150e062047fSfgsch omdog_sync(struct omdog_softc *sc)
151e062047fSfgsch {
152e062047fSfgsch 	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, WWPS) &
153e062047fSfgsch 	    (WWPS_WSPR|WWPS_WTGR|WWPS_WLDR|WWPS_WCRR|WWPS_WCLR))
154e062047fSfgsch 		delay(10);
155e062047fSfgsch }
156e062047fSfgsch 
157e062047fSfgsch int
omdog_cb(void * self,int period)158e062047fSfgsch omdog_cb(void *self, int period)
159e062047fSfgsch {
160e062047fSfgsch 	struct omdog_softc *sc = self;
161e062047fSfgsch 
162e062047fSfgsch 	if (sc->sc_period != 0 && sc->sc_period != period)
163e062047fSfgsch 		omdog_stop(sc);
164e062047fSfgsch 
165e062047fSfgsch 	if (period != 0) {
166e062047fSfgsch 		if (sc->sc_period != period) {
167e062047fSfgsch 			/* Set the prescaler */
168e062047fSfgsch 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, WCLR,
169e062047fSfgsch 			    (WCLR_PRE|WCLR_PTV));
170e062047fSfgsch 
171e062047fSfgsch 			/* Set the reload counter */
172e062047fSfgsch 			bus_space_write_4(sc->sc_iot, sc->sc_ioh, WLDR,
173e062047fSfgsch 			    OMDOG_VAL(period));
174e062047fSfgsch 		}
175e062047fSfgsch 
176e062047fSfgsch 		omdog_sync(sc);
177e062047fSfgsch 
178e062047fSfgsch 		/* Trigger the reload */
179e062047fSfgsch 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, WTGR,
180e062047fSfgsch 		    ~bus_space_read_4(sc->sc_iot, sc->sc_ioh, WTGR));
181e062047fSfgsch 
182e062047fSfgsch 		if (sc->sc_period != period)
183e062047fSfgsch 			omdog_start(sc);
184e062047fSfgsch 	}
185e062047fSfgsch 
186e062047fSfgsch 	sc->sc_period = period;
187e062047fSfgsch 
188e062047fSfgsch 	return (period);
189e062047fSfgsch }
190e062047fSfgsch 
191e062047fSfgsch void
omdog_reset(void)192e062047fSfgsch omdog_reset(void)
1938eda2d14Spatrick {
1948eda2d14Spatrick 	if (omdog_sc == NULL)
1958eda2d14Spatrick 		return;
1968eda2d14Spatrick 
197e062047fSfgsch 	if (omdog_sc->sc_period != 0)
198e062047fSfgsch 		omdog_stop(omdog_sc);
1998eda2d14Spatrick 
200e062047fSfgsch 	bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WCRR,
201e062047fSfgsch 	    0xffffff80);
202e062047fSfgsch 
203e062047fSfgsch 	omdog_start(omdog_sc);
204e062047fSfgsch 
2058eda2d14Spatrick 	delay(100000);
2068eda2d14Spatrick }
207