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