1 //==========================================================================
3 // devs/watchdog/arm/at91/watchdog_at91.cxx
5 // Watchdog implementation for ARM AT91 CPU
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>
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.
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
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.
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.
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.
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####
44 // Author(s): tkoeller
45 // Contributors: tkoeller, nickg
47 // Purpose: Watchdog class implementation
48 // Description: Contains an implementation of the Watchdog class for use
49 // with the ATMEL AT91 watchdog timer.
51 //####DESCRIPTIONEND####
53 //==========================================================================
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>
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>
67 #include <cyg/io/watchdog.hxx>
69 #if !defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT)
70 #include <cyg/hal/hal_platform_ints.h>
71 #include <cyg/kernel/intr.hxx>
74 //==========================================================================
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)
80 #if defined(CYGHWR_HAL_ARM_AT91_R40008) || \
81 defined(CYGHWR_HAL_ARM_AT91_R40807)
83 #if BASE_TICKS / 8 <= MAX_TICKS
86 #elif BASE_TICKS / 32 <= MAX_TICKS
89 #elif BASE_TICKS / 128 <= MAX_TICKS
91 #define DIV_FACTOR 128
92 #elif BASE_TICKS / 1024 <= MAX_TICKS
94 #define DIV_FACTOR 1024
96 #error Desired resolution beyond hardware capabilities
99 #elif defined(CYGHWR_HAL_ARM_AT91_M55800A)
101 #if BASE_TICKS / 32 <= MAX_TICKS
103 #define DIV_FACTOR 32
104 #elif BASE_TICKS / 128 <= MAX_TICKS
106 #define DIV_FACTOR 128
107 #elif BASE_TICKS / 1024 <= MAX_TICKS
109 #define DIV_FACTOR 1024
110 #elif BASE_TICKS / 4096 <= MAX_TICKS
112 #define DIV_FACTOR 4096
114 #error Desired resolution beyond hardware capabilities
116 #elif defined(CYGHWR_HAL_ARM_AT91_JTST)
117 #if BASE_TICKS / 32 <= MAX_TICKS
119 #define DIV_FACTOR 32
120 #elif BASE_TICKS / 128 <= MAX_TICKS
122 #define DIV_FACTOR 128
123 #elif BASE_TICKS / 1024 <= MAX_TICKS
125 #define DIV_FACTOR 1024
126 #elif BASE_TICKS / 2046 <= MAX_TICKS
128 #define DIV_FACTOR 2046
130 #error Desired resolution beyond hardware capabilities
135 #define TICKS ((BASE_TICKS / DIV_FACTOR) | 0xfff)
136 #define RESOLUTION ((cyg_uint64) (TICKS * DIV_FACTOR ) * 1000000 / MCLK_FREQUENCY_KHZ)
138 //==========================================================================
140 #if defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT)
142 #define OMRVAL (AT91_WD_OMR_OKEY | AT91_WD_OMR_RSTEN | AT91_WD_OMR_WDEN)
145 Cyg_Watchdog::init_hw(void)
147 CYG_REPORT_FUNCTION();
148 CYG_REPORT_FUNCARGVOID();
149 resolution = RESOLUTION;
153 #else /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */
155 //==========================================================================
157 #define OMRVAL (AT91_WD_OMR_OKEY | AT91_WD_OMR_IRQEN | AT91_WD_OMR_WDEN)
160 //==========================================================================
162 static Cyg_Watchdog *wd;
164 //==========================================================================
167 isr(cyg_vector vector, CYG_ADDRWORD data)
169 CYG_REPORT_FUNCTION();
170 CYG_REPORT_FUNCARG2XV(vector, data);
173 Cyg_Interrupt::acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG);
174 CYG_REPORT_RETVAL(Cyg_Interrupt::HANDLED);
175 return Cyg_Interrupt::HANDLED;
178 //==========================================================================
180 static Cyg_Interrupt wdint(
181 CYGNUM_HAL_INTERRUPT_WATCHDOG,
188 //==========================================================================
191 Cyg_Watchdog::init_hw(void)
193 CYG_REPORT_FUNCTION();
194 CYG_REPORT_FUNCARGVOID();
197 resolution = RESOLUTION;
198 wdint.configure_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG, false, true);
200 wdint.acknowledge_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG);
201 wdint.unmask_interrupt(CYGNUM_HAL_INTERRUPT_WATCHDOG);
205 #endif /* defined(CYGSEM_WATCHDOG_RESETS_ON_TIMEOUT) */
207 //==========================================================================
209 * Reset watchdog timer. This needs to be called regularly to prevent
210 * the watchdog from firing.
214 Cyg_Watchdog::reset(void)
216 CYG_REPORT_FUNCTION();
217 CYG_REPORT_FUNCARGVOID();
219 /* Write magic code to reset the watchdog. */
220 HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
224 //==========================================================================
226 * Start watchdog to generate a hardware reset
227 * or interrupt when expiring.
231 Cyg_Watchdog::start(void)
233 CYG_REPORT_FUNCTION();
234 CYG_REPORT_FUNCARGVOID();
236 HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY);
238 AT91_WD + AT91_WD_CMR,
239 AT91_WD_CMR_CKEY | ((TICKS >> 10) & AT91_WD_CMR_HPCV) | DIVIDER
241 HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
242 HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, OMRVAL);
246 //==========================================================================
247 // End of watchdog_at91.cxx