xref: /openbsd-src/sys/dev/fdt/imxdog.c (revision 471aeecfc619bc9b69519928152daf993376c2a1)
1*471aeecfSnaddy /* $OpenBSD: imxdog.c,v 1.4 2022/04/06 18:59:28 naddy Exp $ */
2ac62a9ebSpatrick /*
3fb6d2f89Spatrick  * Copyright (c) 2012-2013,2021 Patrick Wildt <patrick@blueri.se>
4ac62a9ebSpatrick  *
5ac62a9ebSpatrick  * Permission to use, copy, modify, and distribute this software for any
6ac62a9ebSpatrick  * purpose with or without fee is hereby granted, provided that the above
7ac62a9ebSpatrick  * copyright notice and this permission notice appear in all copies.
8ac62a9ebSpatrick  *
9ac62a9ebSpatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10ac62a9ebSpatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ac62a9ebSpatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12ac62a9ebSpatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ac62a9ebSpatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ac62a9ebSpatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15ac62a9ebSpatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16ac62a9ebSpatrick  */
17ac62a9ebSpatrick 
18ac62a9ebSpatrick #include <sys/param.h>
19ac62a9ebSpatrick #include <sys/systm.h>
20ac62a9ebSpatrick #include <sys/device.h>
21fb6d2f89Spatrick #include <sys/timeout.h>
22ac62a9ebSpatrick 
23ac62a9ebSpatrick #include <machine/bus.h>
24ac62a9ebSpatrick #include <machine/fdt.h>
25ac62a9ebSpatrick 
26ac62a9ebSpatrick #include <dev/ofw/openfirm.h>
27ac62a9ebSpatrick #include <dev/ofw/fdt.h>
28ac62a9ebSpatrick 
29fb6d2f89Spatrick extern void (*cpuresetfn)(void);
30fb6d2f89Spatrick 
31ac62a9ebSpatrick /* registers */
32ac62a9ebSpatrick #define WCR		0x00
33fb6d2f89Spatrick #define  WCR_WDE		(1 << 2)
34fb6d2f89Spatrick #define  WCR_WT_SEC(x)		(((x) * 2 - 1) << 8)
35fb6d2f89Spatrick #define  WCR_WT_MASK		(0xff << 8)
36ac62a9ebSpatrick #define WSR		0x02
37ac62a9ebSpatrick #define WRSR		0x04
38ac62a9ebSpatrick #define WICR		0x06
39ac62a9ebSpatrick #define WMCR		0x08
40ac62a9ebSpatrick 
41308e3b7aSpatrick #define WDOG_TIMEOUT_CALLBACK		60
42fb6d2f89Spatrick #define WDOG_MAX_TIMEOUT_SEC		128
43fb6d2f89Spatrick 
44ac62a9ebSpatrick struct imxdog_softc {
45ac62a9ebSpatrick 	struct device		sc_dev;
46ac62a9ebSpatrick 	bus_space_tag_t		sc_iot;
47ac62a9ebSpatrick 	bus_space_handle_t	sc_ioh;
48fb6d2f89Spatrick 	struct timeout		sc_tmo;
49ac62a9ebSpatrick };
50ac62a9ebSpatrick 
51ac62a9ebSpatrick struct imxdog_softc *imxdog_sc;
52ac62a9ebSpatrick 
53ac62a9ebSpatrick int	imxdog_match(struct device *, void *, void *);
54ac62a9ebSpatrick void	imxdog_attach(struct device *, struct device *, void *);
55ac62a9ebSpatrick void	imxdog_reset(void);
56fb6d2f89Spatrick void	imxdog_timeout(void *);
57ac62a9ebSpatrick 
58*471aeecfSnaddy const struct cfattach imxdog_ca = {
59ac62a9ebSpatrick 	sizeof (struct imxdog_softc), imxdog_match, imxdog_attach
60ac62a9ebSpatrick };
61ac62a9ebSpatrick 
62ac62a9ebSpatrick struct cfdriver imxdog_cd = {
63ac62a9ebSpatrick 	NULL, "imxdog", DV_DULL
64ac62a9ebSpatrick };
65ac62a9ebSpatrick 
66ac62a9ebSpatrick int
imxdog_match(struct device * parent,void * match,void * aux)67ac62a9ebSpatrick imxdog_match(struct device *parent, void *match, void *aux)
68ac62a9ebSpatrick {
69ac62a9ebSpatrick 	struct fdt_attach_args *faa = aux;
70ac62a9ebSpatrick 
71ac62a9ebSpatrick 	return OF_is_compatible(faa->fa_node, "fsl,imx21-wdt");
72ac62a9ebSpatrick }
73ac62a9ebSpatrick 
74ac62a9ebSpatrick void
imxdog_attach(struct device * parent,struct device * self,void * aux)75ac62a9ebSpatrick imxdog_attach(struct device *parent, struct device *self, void *aux)
76ac62a9ebSpatrick {
77ac62a9ebSpatrick 	struct fdt_attach_args *faa = aux;
78ac62a9ebSpatrick 	struct imxdog_softc *sc = (struct imxdog_softc *) self;
79fb6d2f89Spatrick 	uint16_t reg;
80ac62a9ebSpatrick 
81ac62a9ebSpatrick 	if (faa->fa_nreg < 1)
82ac62a9ebSpatrick 		return;
83ac62a9ebSpatrick 
84ac62a9ebSpatrick 	sc->sc_iot = faa->fa_iot;
85ac62a9ebSpatrick 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
86ac62a9ebSpatrick 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
87ac62a9ebSpatrick 		panic("imxdog_attach: bus_space_map failed!");
88ac62a9ebSpatrick 
89ac62a9ebSpatrick 	printf("\n");
90ac62a9ebSpatrick 
91fb6d2f89Spatrick 	timeout_set(&sc->sc_tmo, imxdog_timeout, sc);
92fb6d2f89Spatrick 
93fb6d2f89Spatrick 	/* Adjust timeout to maximum seconds */
94fb6d2f89Spatrick 	reg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, WCR);
95fb6d2f89Spatrick 	reg &= ~WCR_WT_MASK;
96fb6d2f89Spatrick 	reg |= WCR_WT_SEC(WDOG_MAX_TIMEOUT_SEC);
97fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WCR, reg);
98fb6d2f89Spatrick 
99fb6d2f89Spatrick 	/* Watchdog cannot be disabled, ping the watchdog if enabled */
100fb6d2f89Spatrick 	if (bus_space_read_2(sc->sc_iot, sc->sc_ioh, WCR) & WCR_WDE)
101fb6d2f89Spatrick 		imxdog_timeout(sc);
102fb6d2f89Spatrick 
103ac62a9ebSpatrick 	imxdog_sc = sc;
104fb6d2f89Spatrick 	if (cpuresetfn == NULL)
105ac62a9ebSpatrick 		cpuresetfn = imxdog_reset;
106ac62a9ebSpatrick }
107ac62a9ebSpatrick 
108ac62a9ebSpatrick void
imxdog_reset(void)109ac62a9ebSpatrick imxdog_reset(void)
110ac62a9ebSpatrick {
111fb6d2f89Spatrick 	struct imxdog_softc *sc = imxdog_sc;
112fb6d2f89Spatrick 
113fb6d2f89Spatrick 	if (sc == NULL)
114ac62a9ebSpatrick 		return;
115ac62a9ebSpatrick 
116ac62a9ebSpatrick 	/* disable watchdog and set timeout to 0 */
117fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WCR, 0);
118ac62a9ebSpatrick 
119ac62a9ebSpatrick 	/* sequence to reset timeout counter */
120fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WSR, 0x5555);
121fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WSR, 0xaaaa);
122ac62a9ebSpatrick 
123ac62a9ebSpatrick 	/* enable watchdog */
124fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WCR, 1);
125ac62a9ebSpatrick 	/* errata TKT039676 */
126fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WCR, 1);
127ac62a9ebSpatrick 
128ac62a9ebSpatrick 	delay(100000);
129ac62a9ebSpatrick }
130fb6d2f89Spatrick 
131fb6d2f89Spatrick void
imxdog_timeout(void * args)132fb6d2f89Spatrick imxdog_timeout(void *args)
133fb6d2f89Spatrick {
134fb6d2f89Spatrick 	struct imxdog_softc *sc = args;
135fb6d2f89Spatrick 
136fb6d2f89Spatrick 	/* Reload timeout counter */
137fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WSR, 0x5555);
138fb6d2f89Spatrick 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, WSR, 0xaaaa);
139fb6d2f89Spatrick 
140fb6d2f89Spatrick 	/* Schedule reload to trigger before counter runs out */
141fb6d2f89Spatrick 	timeout_add_sec(&sc->sc_tmo, WDOG_TIMEOUT_CALLBACK);
142fb6d2f89Spatrick }
143