xref: /openbsd/sys/arch/armv7/exynos/exdog.c (revision 4bdff4be)
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
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
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
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
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