initial commit, pull in sys/arch/armv7/omap
[bbb-pru.git] / omdog.c
1 /* $OpenBSD: omdog.c,v 1.5 2014/12/10 12:27:56 mikeb Exp $ */
2 /*
3 * Copyright (c) 2013 Federico G. Schwindt <fgsch@openbsd.org>
4 * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/queue.h>
22 #include <sys/malloc.h>
23 #include <sys/device.h>
24 #include <sys/evcount.h>
25 #include <sys/socket.h>
26 #include <sys/timeout.h>
27 #include <machine/intr.h>
28 #include <machine/bus.h>
29 #include <armv7/armv7/armv7var.h>
30
31 #define WIDR 0x00 /* Identification Register */
32 #define WCLR 0x24 /* Control Register */
33 #define WCLR_PRE (1 << 5)
34 #define WCLR_PTV (0 << 2)
35 #define WCRR 0x28 /* Counter Register */
36 #define WLDR 0x2c /* Load Register */
37 #define WTGR 0x30 /* Trigger Register */
38 #define WWPS 0x34 /* Write Posting Bits Reg. */
39 #define WWPS_WSPR (1 << 4)
40 #define WWPS_WTGR (1 << 3)
41 #define WWPS_WLDR (1 << 2)
42 #define WWPS_WCRR (1 << 1)
43 #define WWPS_WCLR (1 << 0)
44 #define WSPR 0x48 /* Start/Stop Register */
45
46 #define OMDOG_VAL(secs) (0xffffffff - ((secs) * (32768 / (1 << 0))) + 1)
47
48
49 struct omdog_softc {
50 struct device sc_dev;
51 bus_space_tag_t sc_iot;
52 bus_space_handle_t sc_ioh;
53
54 int sc_period;
55 };
56
57 struct omdog_softc *omdog_sc;
58
59 void omdog_attach(struct device *, struct device *, void *);
60 int omdog_activate(struct device *, int);
61 void omdog_start(struct omdog_softc *);
62 void omdog_stop(struct omdog_softc *);
63 void omdog_sync(struct omdog_softc *);
64 int omdog_cb(void *, int);
65 void omdog_reset(void);
66
67 struct cfattach omdog_ca = {
68 sizeof (struct omdog_softc), NULL, omdog_attach, NULL, omdog_activate
69 };
70
71 struct cfdriver omdog_cd = {
72 NULL, "omdog", DV_DULL
73 };
74
75 void
76 omdog_attach(struct device *parent, struct device *self, void *args)
77 {
78 struct armv7_attach_args *aa = args;
79 struct omdog_softc *sc = (struct omdog_softc *) self;
80 u_int32_t rev;
81
82 sc->sc_iot = aa->aa_iot;
83 if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
84 aa->aa_dev->mem[0].size, 0, &sc->sc_ioh))
85 panic("%s: bus_space_map failed!", __func__);
86
87 rev = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR);
88
89 printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf);
90 omdog_sc = sc;
91
92 omdog_stop(sc);
93
94 #ifndef SMALL_KERNEL
95 wdog_register(omdog_cb, sc);
96 #endif
97 }
98
99 int
100 omdog_activate(struct device *self, int act)
101 {
102 switch (act) {
103 case DVACT_POWERDOWN:
104 #ifndef SMALL_KERNEL
105 wdog_shutdown(self);
106 #endif
107 break;
108 }
109
110 return (0);
111 }
112
113 void
114 omdog_start(struct omdog_softc *sc)
115 {
116 /* Write the enable sequence data BBBBh followed by 4444h */
117 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xbbbb);
118 omdog_sync(sc);
119 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x4444);
120 omdog_sync(sc);
121 }
122
123 void
124 omdog_stop(struct omdog_softc *sc)
125 {
126 /* Write the disable sequence data AAAAh followed by 5555h */
127 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xaaaa);
128 omdog_sync(sc);
129 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0x5555);
130 omdog_sync(sc);
131 }
132
133 void
134 omdog_sync(struct omdog_softc *sc)
135 {
136 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, WWPS) &
137 (WWPS_WSPR|WWPS_WTGR|WWPS_WLDR|WWPS_WCRR|WWPS_WCLR))
138 delay(10);
139 }
140
141 int
142 omdog_cb(void *self, int period)
143 {
144 struct omdog_softc *sc = self;
145
146 if (sc->sc_period != 0 && sc->sc_period != period)
147 omdog_stop(sc);
148
149 if (period != 0) {
150 if (sc->sc_period != period) {
151 /* Set the prescaler */
152 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WCLR,
153 (WCLR_PRE|WCLR_PTV));
154
155 /* Set the reload counter */
156 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WLDR,
157 OMDOG_VAL(period));
158 }
159
160 omdog_sync(sc);
161
162 /* Trigger the reload */
163 bus_space_write_4(sc->sc_iot, sc->sc_ioh, WTGR,
164 ~bus_space_read_4(sc->sc_iot, sc->sc_ioh, WTGR));
165
166 if (sc->sc_period != period)
167 omdog_start(sc);
168 }
169
170 sc->sc_period = period;
171
172 return (period);
173 }
174
175 void
176 omdog_reset(void)
177 {
178 if (omdog_sc == NULL)
179 return;
180
181 if (omdog_sc->sc_period != 0)
182 omdog_stop(omdog_sc);
183
184 bus_space_write_4(omdog_sc->sc_iot, omdog_sc->sc_ioh, WCRR,
185 0xffffff80);
186
187 omdog_start(omdog_sc);
188
189 delay(100000);
190 }