]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/watchdog/arm/at91/v2_0/src/watchdog_at91.cxx
Initial revision
[karo-tx-redboot.git] / packages / devs / watchdog / arm / at91 / v2_0 / src / watchdog_at91.cxx
1 //==========================================================================
2 //
3 //      devs/watchdog/arm/at91/watchdog_at91.cxx
4 //
5 //      Watchdog implementation for ARM AT91 CPU
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    tkoeller
45 // Contributors: tkoeller, nickg
46 // Date:         2002-05-05
47 // Purpose:      Watchdog class implementation
48 // Description:  Contains an implementation of the Watchdog class for use
49 //               with the ATMEL AT91 watchdog timer.
50 //
51 //####DESCRIPTIONEND####
52 //
53 //==========================================================================
54
55 #include <pkgconf/kernel.h>
56 #include <pkgconf/infra.h>
57 #include <pkgconf/kernel.h>
58 #include <pkgconf/watchdog.h>
59 #include <pkgconf/devs_watchdog_arm_at91.h>
60
61 #include <cyg/infra/cyg_type.h>
62 #include <cyg/infra/cyg_ass.h>
63 #include <cyg/infra/cyg_trac.h>
64 #include <cyg/hal/hal_io.h>
65 #include <cyg/hal/hal_diag.h>
66
67 #include <cyg/io/watchdog.hxx>
68
69 #if !defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT)
70 #include <cyg/hal/hal_platform_ints.h>
71 #include <cyg/kernel/intr.hxx>
72 #endif
73
74 //==========================================================================
75
76 #define MCLK_FREQUENCY_KHZ  (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/1000)
77 #define MAX_TICKS           0x0000ffff
78 #define BASE_TICKS          (MCLK_FREQUENCY_KHZ * CYGNUM_DEVS_WATCHDOG_ARM_AT91_DESIRED_TIMEOUT_MS)
79
80 #if defined(CYGHWR_HAL_ARM_AT91_R40008) || \
81     defined(CYGHWR_HAL_ARM_AT91_R40807)
82
83 #if   BASE_TICKS / 8 <= MAX_TICKS
84 #define DIVIDER 0
85 #define DIV_FACTOR 8
86 #elif BASE_TICKS / 32 <= MAX_TICKS
87 #define DIVIDER 1
88 #define DIV_FACTOR 32
89 #elif BASE_TICKS / 128 <= MAX_TICKS
90 #define DIVIDER 2
91 #define DIV_FACTOR 128
92 #elif BASE_TICKS / 1024 <= MAX_TICKS
93 #define DIVIDER 3
94 #define DIV_FACTOR 1024
95 #else
96 #error Desired resolution beyond hardware capabilities
97 #endif
98
99 #elif defined(CYGHWR_HAL_ARM_AT91_M55800A)
100
101 #if   BASE_TICKS / 32 <= MAX_TICKS
102 #define DIVIDER 0
103 #define DIV_FACTOR 32
104 #elif BASE_TICKS / 128 <= MAX_TICKS
105 #define DIVIDER 1
106 #define DIV_FACTOR 128
107 #elif BASE_TICKS / 1024 <= MAX_TICKS
108 #define DIVIDER 2
109 #define DIV_FACTOR 1024
110 #elif BASE_TICKS / 4096 <= MAX_TICKS
111 #define DIVIDER 3
112 #define DIV_FACTOR 4096
113 #else
114 #error Desired resolution beyond hardware capabilities
115 #endif
116 #elif defined(CYGHWR_HAL_ARM_AT91_JTST)
117 #if   BASE_TICKS / 32 <= MAX_TICKS
118 #define DIVIDER 0
119 #define DIV_FACTOR 32
120 #elif BASE_TICKS / 128 <= MAX_TICKS
121 #define DIVIDER 1
122 #define DIV_FACTOR 128
123 #elif BASE_TICKS / 1024 <= MAX_TICKS
124 #define DIVIDER 2
125 #define DIV_FACTOR 1024
126 #elif BASE_TICKS / 2046 <= MAX_TICKS
127 #define DIVIDER 3
128 #define DIV_FACTOR 2046
129 #else
130 #error Desired resolution beyond hardware capabilities
131 #endif
132
133 #endif
134
135 #define TICKS       ((BASE_TICKS / DIV_FACTOR) | 0xfff)
136 #define RESOLUTION  ((cyg_uint64) (TICKS * DIV_FACTOR ) * 1000000 / MCLK_FREQUENCY_KHZ)
137
138 //==========================================================================
139
140 #if defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT)
141
142 #define OMRVAL  (AT91_WD_OMR_OKEY | AT91_WD_OMR_RSTEN | AT91_WD_OMR_WDEN)
143
144 void
145 Cyg_Watchdog::init_hw(void)
146 {
147   CYG_REPORT_FUNCTION();
148   CYG_REPORT_FUNCARGVOID();
149   resolution = RESOLUTION;
150   CYG_REPORT_RETURN();
151 }
152
153 #else /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */
154
155 //==========================================================================
156
157 #define OMRVAL  (AT91_WD_OMR_OKEY | AT91_WD_OMR_IRQEN | AT91_WD_OMR_WDEN)
158 #define INT_PRIO    7
159
160 //==========================================================================
161
162 static Cyg_Watchdog *wd;
163
164 //==========================================================================
165
166 static cyg_uint32
167 isr(cyg_vector vector, CYG_ADDRWORD data)
168 {
169   CYG_REPORT_FUNCTION();
170   CYG_REPORT_FUNCARG2XV(vector, data);
171
172   wd->trigger();
173   Cyg_Interrupt::acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG);
174   CYG_REPORT_RETVAL(Cyg_Interrupt::HANDLED);
175   return Cyg_Interrupt::HANDLED;
176 }
177
178 //==========================================================================
179
180 static Cyg_Interrupt wdint(
181     CYGNUM_HAL_INTERRUPT_WATCHDOG,
182     INT_PRIO,
183     0,
184     isr,
185     NULL
186   );
187
188 //==========================================================================
189
190 void
191 Cyg_Watchdog::init_hw(void)
192 {
193   CYG_REPORT_FUNCTION();
194   CYG_REPORT_FUNCARGVOID();
195
196   wd = this;
197   resolution = RESOLUTION;
198   wdint.configure_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG, false, true);
199   wdint.attach();
200   wdint.acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG);
201   wdint.unmask_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG);
202   CYG_REPORT_RETURN();
203 }
204
205 #endif  /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */
206
207 //==========================================================================
208 /*
209  * Reset watchdog timer. This needs to be called regularly to prevent
210  * the watchdog from firing.
211  */
212
213 void
214 Cyg_Watchdog::reset(void)
215 {
216   CYG_REPORT_FUNCTION();
217   CYG_REPORT_FUNCARGVOID();
218
219   /* Write magic code to reset the watchdog. */
220   HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
221   CYG_REPORT_RETURN();
222 }
223
224 //==========================================================================
225 /*
226  * Start watchdog to generate a hardware reset
227  * or interrupt when expiring.
228  */
229
230 void
231 Cyg_Watchdog::start(void)
232 {
233   CYG_REPORT_FUNCTION();
234   CYG_REPORT_FUNCARGVOID();
235   
236   HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY);
237   HAL_WRITE_UINT32(
238     AT91_WD + AT91_WD_CMR,
239     AT91_WD_CMR_CKEY | ((TICKS >> 10) & AT91_WD_CMR_HPCV) | DIVIDER
240   );
241   HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
242   HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, OMRVAL);
243   CYG_REPORT_RETURN();
244 }
245
246 //==========================================================================
247 // End of watchdog_at91.cxx