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