initial commit, pull in sys/arch/armv7/omap
[bbb-pru.git] / omdog.c
CommitLineData
cf3c20ae 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
49struct 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
57struct omdog_softc *omdog_sc;
58
59void omdog_attach(struct device *, struct device *, void *);
60int omdog_activate(struct device *, int);
61void omdog_start(struct omdog_softc *);
62void omdog_stop(struct omdog_softc *);
63void omdog_sync(struct omdog_softc *);
64int omdog_cb(void *, int);
65void omdog_reset(void);
66
67struct cfattach omdog_ca = {
68 sizeof (struct omdog_softc), NULL, omdog_attach, NULL, omdog_activate
69};
70
71struct cfdriver omdog_cd = {
72 NULL, "omdog", DV_DULL
73};
74
75void
76omdog_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
99int
100omdog_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
113void
114omdog_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
123void
124omdog_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
133void
134omdog_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
141int
142omdog_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
175void
176omdog_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}