No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / arm / omap / omap_wdt.c
blob8b2a4873a2e80cdd169b2958a33385b7e07c4ee4
1 /*
2 * OMAP watchdog timers, common code
4 * Copyright (c) 2007 Microsoft
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Microsoft
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
34 #include <sys/param.h>
35 #include <sys/callout.h>
36 #include <sys/cdefs.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 #include <sys/wdog.h>
42 #include <machine/param.h>
43 #include <machine/bus.h>
44 #include <dev/sysmon/sysmonvar.h>
46 #include <arm/omap/omap_wdtvar.h>
47 #include <arm/omap/omap_wdtreg.h>
49 struct omapwdt32k_softc *omapwdt32k_sc;
50 int omapwdt_sysconfig;
52 static void
53 omapwdt32k_sync(void)
55 /* The WCLR, WCRR, WLDR, WTGR and WSPR registers are
56 * synchronized to the 32kHz clock. Each has an
57 * associated status bit that's set when there's
58 * a pending write. This function will wait for
59 * all of those status bits to become clear so
60 * the caller can safely write to any of the registers.
62 while (bus_space_read_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh,
63 WWPS) &
64 (W_PEND_WSPR | W_PEND_WTGR | W_PEND_WLDR | W_PEND_WCRR |
65 W_PEND_WCLR))
66 delay(10);
69 static void
70 omapwdt32k_start(void)
72 omapwdt32k_sync();
73 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
74 WD_ENABLE_WORD1);
75 omapwdt32k_sync();
76 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
77 WD_ENABLE_WORD2);
80 static void
81 omapwdt32k_stop(void)
83 omapwdt32k_sync();
84 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
85 WD_DISABLE_WORD1);
86 omapwdt32k_sync();
87 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
88 WD_DISABLE_WORD2);
91 static void
92 omapwdt32k_do_set_timeout(void)
94 if (omapwdt32k_sc->sc_armed) {
96 * The watchdog must be disabled before writing to
97 * the WCRR, WCLR:PTV, or WLDR registers.
99 omapwdt32k_stop();
102 /* Make sure WLDR, WCRR, and WCLR are ready to be written to.
104 omapwdt32k_sync();
106 /* Make sure that the prescaler is set.
108 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WCLR,
109 (WCLR_PTV(PTV) | WCLR_PRE(PRE)));
111 /* Write the new count value to the load and
112 * counter registers.
115 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WLDR,
116 omapwdt32k_sc->sc_smw.smw_period ?
117 WATCHDOG_COUNT(omapwdt32k_sc->sc_smw.smw_period)
118 : 0xffffffff);
119 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WCRR,
120 omapwdt32k_sc->sc_smw.smw_period ?
121 WATCHDOG_COUNT(omapwdt32k_sc->sc_smw.smw_period)
122 : 0xffffffff);
124 /* Wait for the pending writes to go through.
126 omapwdt32k_sync();
128 /* Resume the watchdog if we had stopped it.
130 if (omapwdt32k_sc->sc_armed)
131 omapwdt32k_start();
134 void
135 omapwdt32k_set_timeout(unsigned int period)
137 int s = splhigh();
139 if (period != omapwdt32k_sc->sc_smw.smw_period) {
140 omapwdt32k_sc->sc_smw.smw_period = period;
141 omapwdt32k_do_set_timeout();
144 splx(s);
148 omapwdt32k_enable(int enable)
150 int s;
151 int prev_state = omapwdt32k_sc->sc_armed;
153 /* Normalize the int to a boolean so we can compare values directly.
155 enable = !!enable;
157 s = splhigh();
159 if (enable != omapwdt32k_sc->sc_armed) {
160 if (enable) {
161 /* Make sure that the watchdog timeout is up to date.
163 omapwdt32k_do_set_timeout();
164 omapwdt32k_start();
165 } else {
166 omapwdt32k_stop();
168 omapwdt32k_sc->sc_armed = enable;
171 splx(s);
172 return prev_state;
176 omapwdt32k_setmode(struct sysmon_wdog *smw)
178 struct omapwdt32k_softc *sc = smw->smw_cookie;
179 int error = 0;
181 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
182 omapwdt32k_enable(0);
183 } else {
184 if (smw->smw_period == WDOG_PERIOD_DEFAULT)
185 sc->sc_smw.smw_period = OMAPWDT32K_DEFAULT_PERIOD;
186 else
187 sc->sc_smw.smw_period = smw->smw_period;
188 omapwdt32k_set_timeout(sc->sc_smw.smw_period);
189 omapwdt32k_enable(1);
191 return error;
195 omapwdt32k_tickle(struct sysmon_wdog *smw)
197 int s = splhigh();
200 * To reload the timer counter and reset the prescaler counter
201 * values without reaching overflow, a reload command can be
202 * executed by accessing the watchdog trigger register (WTGR)
203 * using a specific reload sequence.
205 * The specific reload sequence is performed when the written
206 * value on the watchdog trigger register (WTGR) is different
207 * from its previous value. In this case, reload is executed in
208 * the same way as overflow autoreload, without a reset pulse
209 * generation. The timer is loaded with the watchdog load register
210 * (WLDR) value and the prescaler counter is reset.
212 * Write a new value into WTGR to reload WCRR (counter register)
213 * with the value in WLDR (load register), thereby resetting the
214 * watchdog.
216 omapwdt32k_sync();
217 bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WTGR,
218 ~bus_space_read_4(omapwdt32k_sc->sc_iot,
219 omapwdt32k_sc->sc_ioh, WTGR));
221 splx(s);
222 return 0;
225 void
226 omapwdt32k_reboot(void)
228 int s = splhigh();
230 omapwdt32k_set_timeout(0);
231 omapwdt32k_start();
232 delay(100);
233 splx(s);