1 /*
2 * Copyright (c) 2015-2018, 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
33 #include <stdint.h>
34 #include <stdlib.h>
35
36 #include <ti/drivers/dpl/HwiP.h>
37 #include <ti/drivers/dpl/ClockP.h>
38
39 #include <ti/drivers/Power.h>
40 #include <ti/drivers/power/PowerCC32XX.h>
41
42 #include <ti/drivers/watchdog/WatchdogCC32XX.h>
43
44 #include <ti/devices/cc32xx/inc/hw_types.h>
45 #include <ti/devices/cc32xx/driverlib/rom.h>
46 #include <ti/devices/cc32xx/driverlib/rom_map.h>
47 #include <ti/devices/cc32xx/driverlib/wdt.h>
48
49 /* Function prototypes */
50 void WatchdogCC32XX_clear(Watchdog_Handle handle);
51 void WatchdogCC32XX_close(Watchdog_Handle handle);
52 int_fast16_t WatchdogCC32XX_control(Watchdog_Handle handle,
53 uint_fast16_t cmd, void *arg);
54 void WatchdogCC32XX_init(Watchdog_Handle handle);
55 Watchdog_Handle WatchdogCC32XX_open(Watchdog_Handle handle, Watchdog_Params *params);
56 int_fast16_t WatchdogCC32XX_setReload(Watchdog_Handle handle,
57 uint32_t value);
58 uint32_t WatchdogCC32XX_convertMsToTicks(Watchdog_Handle handle,
59 uint32_t milliseconds);
60
61 /* Internal functions */
62 static void WatchdogCC32XX_initHardware(Watchdog_Handle handle);
63 static int WatchdogCC32XX_postNotifyFxn(unsigned int eventType,
64 uintptr_t eventArg, uintptr_t clientArg);
65
66 /* Watchdog function table for CC32XX implementation */
67 const Watchdog_FxnTable WatchdogCC32XX_fxnTable = {
68 WatchdogCC32XX_clear,
69 WatchdogCC32XX_close,
70 WatchdogCC32XX_control,
71 WatchdogCC32XX_init,
72 WatchdogCC32XX_open,
73 WatchdogCC32XX_setReload,
74 WatchdogCC32XX_convertMsToTicks
75 };
76
77 /* Maximum allowable setReload value */
78 #define MAX_RELOAD_VALUE 0xFFFFFFFF
79
80 /* Millisecond to second ratio */
81 #define MS_RATIO 1000
82
83 /*
84 * ======== WatchdogCC32XX_initHardware ========
85 */
WatchdogCC32XX_initHardware(Watchdog_Handle handle)86 static void WatchdogCC32XX_initHardware(Watchdog_Handle handle)
87 {
88 WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
89 WatchdogCC32XX_Object const *object = handle->object;
90
91 MAP_WatchdogUnlock(hwAttrs->baseAddr);
92 MAP_WatchdogReloadSet(hwAttrs->baseAddr, object->reloadValue);
93 MAP_WatchdogIntClear(hwAttrs->baseAddr);
94
95 /* Set debug stall mode */
96 if (object->debugMode == Watchdog_DEBUG_STALL_ON) {
97 MAP_WatchdogStallEnable(hwAttrs->baseAddr);
98 }
99 else {
100 MAP_WatchdogStallDisable(hwAttrs->baseAddr);
101 }
102
103 MAP_WatchdogEnable(hwAttrs->baseAddr);
104
105 MAP_WatchdogLock(hwAttrs->baseAddr);
106 }
107
108 /*
109 * ======== WatchdogCC32XX_postNotifyFxn ========
110 * This functions is called when a transition from LPDS mode is made.
111 * clientArg is a handle of a previously opened Watchdog instance.
112 */
WatchdogCC32XX_postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)113 static int WatchdogCC32XX_postNotifyFxn(unsigned int eventType,
114 uintptr_t eventArg, uintptr_t clientArg)
115 {
116 WatchdogCC32XX_initHardware((Watchdog_Handle) clientArg);
117
118 return (Power_NOTIFYDONE);
119 }
120
121 /*
122 * ======== WatchdogCC32XX_clear ========
123 */
WatchdogCC32XX_clear(Watchdog_Handle handle)124 void WatchdogCC32XX_clear(Watchdog_Handle handle)
125 {
126 WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
127
128 MAP_WatchdogIntClear(hwAttrs->baseAddr);
129 }
130
131 /*
132 * ======== WatchdogCC32XX_close ========
133 */
WatchdogCC32XX_close(Watchdog_Handle handle)134 void WatchdogCC32XX_close(Watchdog_Handle handle)
135 {
136 /*
137 * Not supported for CC32XX - Once the INTEN bit of the WDTCTL
138 * register has been set, it can only be cleared by a hardware
139 * reset.
140 */
141 }
142
143 /*
144 * ======== WatchdogCC32XX_control ========
145 * @pre Function assumes that the handle is not NULL
146 */
WatchdogCC32XX_control(Watchdog_Handle handle,uint_fast16_t cmd,void * arg)147 int_fast16_t WatchdogCC32XX_control(Watchdog_Handle handle, uint_fast16_t cmd,
148 void *arg)
149 {
150 WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
151
152 switch (cmd) {
153 /* Specific Watchdog CMDs */
154 case (WatchdogCC32XX_CMD_IS_TIMER_ENABLE):
155 *(bool *)arg = MAP_WatchdogRunning(hwAttrs->baseAddr);
156 return (Watchdog_STATUS_SUCCESS);
157
158 case (WatchdogCC32XX_CMD_GET_TIMER_VALUE):
159 *(uint32_t *)arg = MAP_WatchdogValueGet(hwAttrs->baseAddr);
160 return (Watchdog_STATUS_SUCCESS);
161
162 case (WatchdogCC32XX_CMD_IS_TIMER_LOCKED):
163 *(bool *)arg = MAP_WatchdogLockState(hwAttrs->baseAddr);
164 return (Watchdog_STATUS_SUCCESS);
165
166 case (WatchdogCC32XX_CMD_GET_TIMER_RELOAD_VALUE):
167 *(uint32_t *)arg = MAP_WatchdogReloadGet(hwAttrs->baseAddr);
168 return (Watchdog_STATUS_SUCCESS);
169
170 default:
171 return (Watchdog_STATUS_UNDEFINEDCMD);
172 }
173 }
174
175 /*
176 * ======== WatchdogCC32XX_init ========
177 */
WatchdogCC32XX_init(Watchdog_Handle handle)178 void WatchdogCC32XX_init(Watchdog_Handle handle)
179 {
180 WatchdogCC32XX_Object *object = handle->object;
181
182 object->isOpen = false;
183 }
184
185 /*
186 * ======== WatchdogCC32XX_open ========
187 */
WatchdogCC32XX_open(Watchdog_Handle handle,Watchdog_Params * params)188 Watchdog_Handle WatchdogCC32XX_open(Watchdog_Handle handle, Watchdog_Params *params)
189 {
190 uintptr_t key;
191 HwiP_Handle hwiHandle;
192 HwiP_Params hwiParams;
193 WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
194 WatchdogCC32XX_Object *object = handle->object;
195
196 key = HwiP_disable();
197
198 if (object->isOpen == true) {
199 HwiP_restore(key);
200 return (NULL);
201 }
202
203 object->isOpen = true;
204 HwiP_restore(key);
205
206 /* Register the hardware interrupt for this watchdog */
207 if (params->callbackFxn) {
208 HwiP_Params_init(&hwiParams);
209 hwiParams.arg = (uintptr_t) handle;
210 hwiParams.priority = hwAttrs->intPriority;
211 hwiHandle = HwiP_create(hwAttrs->intNum, params->callbackFxn,
212 &hwiParams);
213 if (hwiHandle == NULL) {
214 object->isOpen = false;
215 return (NULL);
216 }
217 }
218
219 Power_setDependency(PowerCC32XX_PERIPH_WDT);
220 Power_registerNotify(&(object->notifyObj), PowerCC32XX_AWAKE_LPDS,
221 WatchdogCC32XX_postNotifyFxn, (uintptr_t) handle);
222
223 object->debugMode = params->debugStallMode;
224 object->reloadValue = hwAttrs->reloadValue;
225
226 WatchdogCC32XX_initHardware(handle);
227
228 return (handle);
229 }
230
231 /*
232 * ======== WatchdogCC32XX_setReload ========
233 */
WatchdogCC32XX_setReload(Watchdog_Handle handle,uint32_t value)234 int_fast16_t WatchdogCC32XX_setReload(Watchdog_Handle handle, uint32_t value)
235 {
236 WatchdogCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
237 WatchdogCC32XX_Object *object = handle->object;
238
239 /* Set value */
240 MAP_WatchdogUnlock(hwAttrs->baseAddr);
241 MAP_WatchdogReloadSet(hwAttrs->baseAddr, value);
242 MAP_WatchdogLock(hwAttrs->baseAddr);
243 object->reloadValue = value;
244
245 return (Watchdog_STATUS_SUCCESS);
246 }
247
248 /*
249 * ======== WatchdogCC32XX_convertMsToTicks ========
250 * This function converts the input value from milliseconds to
251 * Watchdog clock ticks.
252 */
WatchdogCC32XX_convertMsToTicks(Watchdog_Handle handle,uint32_t milliseconds)253 uint32_t WatchdogCC32XX_convertMsToTicks(Watchdog_Handle handle,
254 uint32_t milliseconds)
255 {
256 uint32_t tickValue;
257 uint32_t convertRatio;
258 uint32_t maxConvertMs;
259 ClockP_FreqHz freq;
260
261 /* Determine milliseconds to clock ticks conversion ratio */
262 ClockP_getCpuFreq(&freq);
263
264 /* Watchdog clock ticks/ms = CPU clock / MS_RATIO */
265 convertRatio = freq.lo / MS_RATIO;
266 maxConvertMs = MAX_RELOAD_VALUE / convertRatio;
267
268 /* Convert milliseconds to watchdog timer ticks */
269 /* Check if value exceeds maximum */
270 if (milliseconds > maxConvertMs) {
271 tickValue = 0; /* Return zero to indicate overflow */
272 }
273 else {
274 tickValue = (uint32_t)(milliseconds * convertRatio);
275 }
276
277 return(tickValue);
278 }
279