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