]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/deh/Watchdog.c
53b5c502df3d2522e19eada86715bd3f98c248b3
[ipc/ipcdev.git] / packages / ti / deh / Watchdog.c
1 /*
2  * Copyright (c) 2012-2014, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  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  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
34 /*
35  *  ======== Watchdog.c ========
36  *
37  */
39 #include <xdc/runtime/Assert.h>
40 #include <xdc/runtime/System.h>
41 #include <xdc/runtime/Error.h>
42 #include <xdc/runtime/System.h>
43 #include <xdc/runtime/Startup.h>
44 #include <xdc/runtime/Memory.h>
45 #include <xdc/runtime/Types.h>
47 #include <ti/sysbios/BIOS.h>
48 #include <ti/sysbios/knl/Swi.h>
49 #include <ti/sysbios/knl/Task.h>
50 #include <ti/sysbios/interfaces/ITimer.h>
51 #include <ti/sysbios/timers/dmtimer/Timer.h>
53 #ifdef DSP
54 #include <ti/sysbios/family/c64p/Hwi.h>
55 #ifdef OMAP5
56 #include <ti/sysbios/family/c64p/tesla/Wugen.h>
57 #endif
58 #endif
60 #ifdef IPU
61 #include <ti/sysbios/family/arm/m3/Hwi.h>
62 #endif
64 #ifdef SMP
65 #include <ti/sysbios/hal/Core.h>
66 #endif
68 #include <ti/pm/IpcPower.h>
70 #include "package/internal/Watchdog.xdc.h"
72 /* Macro to write to GP timer registers */
73 #define REG32(A)   (*(volatile UInt32 *) (A))
75 /* Bit mask for writing into GP timer TGRR reg for posted write mode */
76 #define WATCHDOG_TIMER_TWPS_W_PEND_TGRR     0x8
78 /* Bit mask for writing into GP timer TLDR reg for posted write mode */
79 #define WATCHDOG_TIMER_TWPS_W_PEND_TLDR     0x4
81 /* Bit mask for writing into GP timer TCRR reg for posted write mode */
82 #define WATCHDOG_TIMER_TWPS_W_PEND_TCRR     0x2
84 /* Bit mask for writing into GP timer TCLR reg for posted write mode */
85 #define WATCHDOG_TIMER_TWPS_W_PEND_TCLR     0x1
87 /* GP Timers Clock Control register bit mask */
88 #define WATCHDOG_WDT_CLKCTRL_IDLEST_MASK    (3 << 16)
90 #if defined(IPU) && defined(OMAP5)
91 /* OMAP IDCode Register to find the version id, 0x4A002204 */
92 #define IDCODE_REGISTER                     (0xAA002204)
94 /*
95  *  ======== adjustGptClkCtrlAddr ========
96  *  Adjust the GPTimer PRCM Clock Register Addresses on OMAP5 ES2.x
97  */
98 static Void adjustGptClkCtrlAddr()
99 {
100     Int     i;
101     Bool    adjust = FALSE;
102     UInt32  idCode = REG32(IDCODE_REGISTER);
103     UInt32  ramp = (idCode >> 12) & 0xFFFF;
104     UInt32  version = (idCode >> 28) & 0xF;
106     /* Change the addresses only for OMAP5 ES2.x */
107     if (ramp == 0xB942 || ramp == 0xB998) {
108         if (version == 1) {
109             adjust = TRUE;
110         }
111     }
113     /*
114      * OMAP5 ES 2.x has PER GPT PRCM addresses moved up by 0x400
115      * w.r.t OMAP4 and OMAP5 ES 1.0
116      */
117     if (adjust == TRUE) {
118         for (i = 0; i < Watchdog_module->wdtCores; i++) {
119             Watchdog_module->device[i].clkCtrl =
120                     (Ptr)((UInt32)Watchdog_module->device[i].clkCtrl - 0x400);
121         }
122     }
124 #endif
126 /*
127  *  ======== initTimer ========
128  */
129 static Void initTimer(Watchdog_TimerRegs *timer, Bool boot)
131     Timer_Handle    tHandle;
132     Types_FreqHz    tFreq;
134     /* Get timer frequency */
135     tHandle = Timer_Object_get(NULL, 0);
136     Timer_getFreq(tHandle, &tFreq);
138     timer->tisr = ~0;
139     timer->tier = 2;
140     timer->twer = 2;
141     timer->tldr = (0 - (tFreq.lo * Watchdog_TIME_SEC));
143     /* Booting can take more time, so set CRR to WDT_BOOT_TIME */
144     if (boot) {
145         timer->tcrr = (0 - (tFreq.lo * Watchdog_BOOT_TIME_SEC));
146     }
147     else {
148         timer->tcrr = (0 - (tFreq.lo * Watchdog_TIME_SEC));
149     }
151     timer->tsicr |= 4; /* enable posted write mode */
154 /*
155  *  ======== Watchdog_init ========
156  */
157 Void Watchdog_init( Void (*timerFxn)(Void) )
159     Hwi_Params          hwiParams;
160     UInt                key;
161     Timer_Handle        tHandle;
162     Types_FreqHz        tFreq;
163     Watchdog_TimerRegs  *timer;
164     Int                 i;
165     static Bool         first = TRUE;
167     tHandle = Timer_Object_get(NULL, 0);
168     Timer_getFreq(tHandle, &tFreq);  /* get timer frequency */
170 #if defined(IPU) && defined(OMAP5)
171     if (first) {
172         adjustGptClkCtrlAddr();
173     }
174 #endif
175     for (i = 0; i < Watchdog_module->wdtCores; i++) {  /* loop for SMP cores */
176         timer = (Watchdog_TimerRegs *) Watchdog_module->device[i].baseAddr;
178         /* Check if timer is enabled by host-side */
179         if ((REG32(Watchdog_module->device[i].clkCtrl) &
180             WATCHDOG_WDT_CLKCTRL_IDLEST_MASK) ==
181                                     WATCHDOG_WDT_CLKCTRL_IDLEST_MASK) {
182             System_printf("Watchdog disabled: TimerBase = 0x%x ClkCtrl = 0x%x\n",
183                                     timer, Watchdog_module->device[i].clkCtrl);
184             continue;  /* for next core */
185         }
187         if (Watchdog_module->status[i] != Watchdog_Mode_ENABLED) {
188             /* Configure the timer */
189             initTimer(timer, TRUE);
191             /* Enable interrupt in BIOS */
192             Hwi_Params_init(&hwiParams);
193             hwiParams.priority = 1;
194             hwiParams.eventId = Watchdog_module->device[i].eventId;
195             hwiParams.maskSetting = Hwi_MaskingOption_LOWER;
196             hwiParams.arg = 1;     /* Exception_handler(abortFlag) */
197             key = Hwi_disable();
198             Hwi_create(Watchdog_module->device[i].intNum, (Hwi_FuncPtr) timerFxn,
199                                                             &hwiParams, NULL);
200             Hwi_enableInterrupt(Watchdog_module->device[i].intNum);
201 #if defined(DSP) && defined(OMAP5)
202             Wugen_enableEvent(Watchdog_module->device[i].eventId);
203 #endif
204             Hwi_restore(key);
206             /* Enable timer */
207             while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
208             timer->tclr |= 1;
209             Watchdog_module->status[i] = Watchdog_Mode_ENABLED;
211 #ifdef SMP
212             System_printf("Watchdog enabled: TimerBase = 0x%x SMP-Core = %d "
213                                             "Freq = %d\n", timer, i, tFreq.lo);
214 #else
215             System_printf("Watchdog enabled: TimerBase = 0x%x Freq = %d\n",
216                                                             timer, tFreq.lo);
217 #endif
218         }
219     }
221 #if defined(OMAP5) || defined(IPU)
222     if (first) {
223         /* Register callback function */
224         if (!IpcPower_registerCallback(IpcPower_Event_RESUME, Watchdog_restore,
225                                     NULL)) {
226             System_printf("Watchdog_restore registered as a resume callback\n");
227         }
228     }
229 #endif
231     if (first) {
232         first = FALSE;
233     }
235     return;
238 /*
239  *  ======== Watchdog_idleBegin ========
240  */
241 Void Watchdog_idleBegin(Void)
243     Int core = 0;
245 #ifdef SMP
246     core = Core_getId();
248     if (core != 0) {
249         Watchdog_stop(core);
250     }
251     else
252 #endif
253     {
254         Watchdog_kick(core);
255     }
258 /*
259  *  ======== Watchdog_swiPrehook ========
260  */
261 Void Watchdog_swiPrehook(Swi_Handle swi)
263     Int core = 0;
265 #ifdef SMP
266     core = Core_getId();
268     if (core != 0) {
269         Watchdog_start(core);
270     }
271     else
272 #endif
273     {
274         Watchdog_kick(core);
275     }
278 /*
279  *  ======== Watchdog_taskSwitch ========
280  *  Refresh/restart watchdog timer whenever task switch scheduling happens
281  */
282 Void Watchdog_taskSwitch(Task_Handle p, Task_Handle n)
284     Int core = 0;
286 #ifdef SMP
287     core = Core_getId();
289     if (core != 0) {
290         Watchdog_start(core);
291     }
292     else
293 #endif
294     {
295         Watchdog_kick(core);
296     }
299 /*
300  *  ======== Watchdog_isException ========
301  */
302 Bool Watchdog_isException(UInt excNum)
304     Int i;
305     Bool found = FALSE;
307     for (i = 0; i < Watchdog_module->wdtCores; i++) {
308         if (excNum == Watchdog_module->device[i].intNum) {
309             found = TRUE;
310             break;
311         }
312     }
314     return found;
317 /*
318  *  ======== Watchdog_stop ========
319  */
320 Void Watchdog_stop(Int core)
322     Watchdog_TimerRegs *timer = Watchdog_module->device[core].baseAddr;
324     if ((Watchdog_module->status[core] == Watchdog_Mode_ENABLED) && timer) {
325         while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
326         timer->tclr &= ~1;
327     }
330 /*
331  *  ======== Watchdog_start ========
332  */
333 Void Watchdog_start(Int core)
335     Watchdog_TimerRegs *timer = Watchdog_module->device[core].baseAddr;
337     if ((Watchdog_module->status[core] == Watchdog_Mode_ENABLED) && timer) {
338         while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
339         timer->tclr |= 1;
341         while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TGRR);
342         timer->ttgr = 0;
343     }
346 /*
347  *  ======== Watchdog_kick ========
348  *  Refresh/restart the watchdog timer
349  */
350 Void Watchdog_kick(Int core)
352     Watchdog_TimerRegs *timer = Watchdog_module->device[core].baseAddr;
354     if ((Watchdog_module->status[core] == Watchdog_Mode_ENABLED) && timer) {
355         while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TGRR);
356         timer->ttgr = 0;
357     }
360 /*
361  *  ======== Watchdog_restore ========
362  *  Refresh/restart the watchdog timer
363  */
364 Void Watchdog_restore(Int event, Ptr data)
366     Int                 i;
367     Watchdog_TimerRegs  *timer;
369     for (i = 0; i < Watchdog_module->wdtCores; i++) {  /* loop for SMP cores */
370         timer = (Watchdog_TimerRegs *) Watchdog_module->device[i].baseAddr;
372         if (Watchdog_module->status[i] == Watchdog_Mode_ENABLED) {
373             /* Configure the timer */
374             initTimer(timer, FALSE);
376             /* Enable timer */
377             while (timer->twps & WATCHDOG_TIMER_TWPS_W_PEND_TCLR);
378             timer->tclr |= 1;
379         }
380     }