1 /* $OpenBSD: exdog.c,v 1.8 2021/10/24 17:52:27 mpi Exp $ */
2 /*
3 * Copyright (c) 2012-2013 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
22 #include <machine/bus.h>
23 #include <machine/fdt.h>
24
25 #include <armv7/armv7/armv7_machdep.h>
26
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/fdt.h>
29
30 /* registers */
31 #define WTCON 0x00
32 #define WTDAT 0x04
33 #define WTCNT 0x08
34 #define WTCLRINT 0x0C
35
36 /* bits and bytes */
37 #define WTCON_RESET (1 << 0)
38 #define WTCON_INT (1 << 2)
39 #define WTCON_CLKSEL_16 (0x0 << 3)
40 #define WTCON_CLKSEL_32 (0x1 << 3)
41 #define WTCON_CLKSEL_64 (0x2 << 3)
42 #define WTCON_CLKSEL_128 (0x3 << 3)
43 #define WTCON_EN (1 << 5)
44 #define WTCON_PRESCALER(x) (((x) & 0xff) << 8)
45
46 struct exdog_softc {
47 struct device sc_dev;
48 bus_space_tag_t sc_iot;
49 bus_space_handle_t sc_ioh;
50 };
51
52 struct exdog_softc *exdog_sc;
53
54 int exdog_match(struct device *parent, void *v, void *aux);
55 void exdog_attach(struct device *parent, struct device *self, void *args);
56 void exdog_stop(void);
57 void exdog_reset(void);
58
59 const struct cfattach exdog_ca = {
60 sizeof (struct exdog_softc), exdog_match, exdog_attach
61 };
62
63 struct cfdriver exdog_cd = {
64 NULL, "exdog", DV_DULL
65 };
66
67 int
exdog_match(struct device * parent,void * cfdata,void * aux)68 exdog_match(struct device *parent, void *cfdata, void *aux)
69 {
70 struct fdt_attach_args *fa = aux;
71
72 return (OF_is_compatible(fa->fa_node, "samsung,exynos5250-wdt") ||
73 OF_is_compatible(fa->fa_node, "samsung,exynos5420-wdt"));
74 }
75
76 void
exdog_attach(struct device * parent,struct device * self,void * aux)77 exdog_attach(struct device *parent, struct device *self, void *aux)
78 {
79 struct exdog_softc *sc = (struct exdog_softc *)self;
80 struct fdt_attach_args *fa = aux;
81
82 sc->sc_iot = fa->fa_iot;
83
84 if (bus_space_map(sc->sc_iot, fa->fa_reg[0].addr,
85 fa->fa_reg[0].size, 0, &sc->sc_ioh))
86 panic("%s: bus_space_map failed!", __func__);
87
88 printf("\n");
89
90 exdog_sc = sc;
91 if (cpuresetfn == NULL)
92 cpuresetfn = exdog_reset;
93 }
94
95 void
exdog_stop(void)96 exdog_stop(void)
97 {
98 uint32_t wtcon;
99
100 if (exdog_sc == NULL)
101 return;
102
103 wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON);
104
105 wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET);
106
107 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon);
108 }
109
110 void
exdog_reset(void)111 exdog_reset(void)
112 {
113 uint32_t wtcon;
114
115 if (exdog_sc == NULL)
116 return;
117
118 /* disable watchdog */
119 exdog_stop();
120
121 wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON);
122
123 wtcon |= WTCON_EN | WTCON_CLKSEL_128;
124 wtcon &= ~WTCON_INT;
125 wtcon |= WTCON_RESET;
126 wtcon |= WTCON_PRESCALER(0xff);
127
128 /* set timeout to 1 */
129 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTDAT, 1);
130 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCNT, 1);
131
132 /* kick off the watchdog */
133 bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon);
134
135 delay(100000);
136 }
137