xref: /openbsd-src/sys/arch/armv7/exynos/exdog.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /* $OpenBSD: exdog.c,v 1.4 2016/07/26 22:10:10 patrick 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 #include <machine/bus.h>
27 #if NFDT > 0
28 #include <machine/fdt.h>
29 #endif
30 #include <machine/intr.h>
31 #include <armv7/armv7/armv7var.h>
32 
33 /* registers */
34 #define WTCON		0x00
35 #define WTDAT		0x04
36 #define WTCNT		0x08
37 #define WTCLRINT	0x0C
38 
39 /* bits and bytes */
40 #define WTCON_RESET		(1 << 0)
41 #define WTCON_INT		(1 << 2)
42 #define WTCON_CLKSEL_16		(0x0 << 3)
43 #define WTCON_CLKSEL_32		(0x1 << 3)
44 #define WTCON_CLKSEL_64		(0x2 << 3)
45 #define WTCON_CLKSEL_128	(0x3 << 3)
46 #define WTCON_EN		(1 << 5)
47 #define WTCON_PRESCALER(x)	(((x) & 0xff) << 8)
48 
49 struct exdog_softc {
50 	struct device		sc_dev;
51 	bus_space_tag_t		sc_iot;
52 	bus_space_handle_t	sc_ioh;
53 };
54 
55 struct exdog_softc *exdog_sc;
56 
57 int exdog_match(struct device *parent, void *v, void *aux);
58 void exdog_attach(struct device *parent, struct device *self, void *args);
59 void exdog_stop(void);
60 void exdog_reset(void);
61 
62 struct cfattach	exdog_ca = {
63 	sizeof (struct exdog_softc), NULL, exdog_attach
64 };
65 struct cfattach	exdog_fdt_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 *v, void *aux)
75 {
76 #if NFDT > 0
77 	struct armv7_attach_args *aa = aux;
78 
79 	if (fdt_node_compatible("samsung,exynos5250-wdt", aa->aa_node))
80 		return 1;
81 #endif
82 
83 	return 0;
84 }
85 
86 void
87 exdog_attach(struct device *parent, struct device *self, void *args)
88 {
89 	struct armv7_attach_args *aa = args;
90 	struct exdog_softc *sc = (struct exdog_softc *) self;
91 	struct armv7mem mem;
92 
93 	sc->sc_iot = aa->aa_iot;
94 #if NFDT > 0
95 	if (aa->aa_node) {
96 		struct fdt_reg reg;
97 		if (fdt_get_reg(aa->aa_node, 0, &reg))
98 			panic("%s: could not extract memory data from FDT",
99 			    __func__);
100 		mem.addr = reg.addr;
101 		mem.size = reg.size;
102 	} else
103 #endif
104 	{
105 		mem.addr = aa->aa_dev->mem[0].addr;
106 		mem.size = aa->aa_dev->mem[0].size;
107 	}
108 	if (bus_space_map(sc->sc_iot, mem.addr, mem.size, 0, &sc->sc_ioh))
109 		panic("%s: bus_space_map failed!", __func__);
110 
111 	printf("\n");
112 	exdog_sc = sc;
113 }
114 
115 void
116 exdog_stop()
117 {
118 	uint32_t wtcon;
119 
120 	if (exdog_sc == NULL)
121 		return;
122 
123 	wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON);
124 
125 	wtcon &= ~(WTCON_EN | WTCON_INT | WTCON_RESET);
126 
127 	bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon);
128 }
129 
130 void
131 exdog_reset()
132 {
133 	uint32_t wtcon;
134 
135 	if (exdog_sc == NULL)
136 		return;
137 
138 	/* disable watchdog */
139 	exdog_stop();
140 
141 	wtcon = bus_space_read_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON);
142 
143 	wtcon |= WTCON_EN | WTCON_CLKSEL_128;
144 	wtcon &= ~WTCON_INT;
145 	wtcon |= WTCON_RESET;
146 	wtcon |= WTCON_PRESCALER(0xff);
147 
148 	/* set timeout to 1 */
149 	bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTDAT, 1);
150 	bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCNT, 1);
151 
152 	/* kick off the watchdog */
153 	bus_space_write_4(exdog_sc->sc_iot, exdog_sc->sc_ioh, WTCON, wtcon);
154 
155 	delay(100000);
156 }
157