1 /*
2 * Copyright (c) 2017-2019, 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 <stddef.h>
35 #include <stdbool.h>
36
37 #include <ti/drivers/dpl/HwiP.h>
38 #include <ti/drivers/dpl/SemaphoreP.h>
39 #include <ti/drivers/dpl/ClockP.h>
40
41 #include <ti/drivers/Timer.h>
42 #include <ti/drivers/power/PowerCC32XX.h>
43 #include <ti/drivers/timer/TimerCC32XX.h>
44
45 #include <ti/devices/cc32xx/inc/hw_types.h>
46 #include <ti/devices/cc32xx/inc/hw_memmap.h>
47 #include <ti/devices/cc32xx/inc/hw_timer.h>
48 #include <ti/devices/cc32xx/driverlib/timer.h>
49
50 /*
51 * This macro is used to determine a logical shift value for the
52 * timerState.bitMask. Each timer peripheral occupies two bits in
53 * timerState.bitMask.
54 *
55 * The timer peripherals' base addresses have an offset of 0x1000 starting at
56 * 0x40030000. That byte is masked using 0xF000 which can result in a value
57 * ranging from 0x0000 to 0x3000 for this particular hardware instance. This
58 * value is then shifted right by 12 into the LSB. Lastly, the value is
59 * multiplied by two because there are two bits in the timerState.bitMask for
60 * each timer. The value returned is used for the logical shift.
61 */
62 #define timerMaskShift(baseAddress) ((((baseAddress) & 0XF000) >> 12) * 2)
63
64 void TimerCC32XX_close(Timer_Handle handle);
65 int_fast16_t TimerCC32XX_control(Timer_Handle handle,
66 uint_fast16_t cmd, void *arg);
67 uint32_t TimerCC32XX_getCount(Timer_Handle handle);
68 void TimerCC32XX_init(Timer_Handle handle);
69 Timer_Handle TimerCC32XX_open(Timer_Handle handle, Timer_Params *params);
70 int32_t TimerCC32XX_setPeriod(Timer_Handle handle, Timer_PeriodUnits periodUnits, uint32_t period);
71 int32_t TimerCC32XX_start(Timer_Handle handle);
72 void TimerCC32XX_stop(Timer_Handle handle);
73
74 /* Internal static Functions */
75 static void initHw(Timer_Handle handle);
76 static void getPrescaler(Timer_Handle handle);
77 static uint32_t getPowerMgrId(uint32_t baseAddress);
78 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
79 uintptr_t clientArg);
80 static void TimerCC32XX_hwiIntFunction(uintptr_t arg);
81
82 /* Function table for TimerCC32XX implementation */
83 const Timer_FxnTable TimerCC32XX_fxnTable = {
84 .closeFxn = TimerCC32XX_close,
85 .openFxn = TimerCC32XX_open,
86 .startFxn = TimerCC32XX_start,
87 .stopFxn = TimerCC32XX_stop,
88 .initFxn = TimerCC32XX_init,
89 .getCountFxn = TimerCC32XX_getCount,
90 .controlFxn = TimerCC32XX_control,
91 .setPeriodFxn = TimerCC32XX_setPeriod
92 };
93
94 /*
95 * Internal Timer status structure
96 *
97 * bitMask: Each timer peripheral occupies two bits in the bitMask. The least
98 * significant bit represents the first half width timer, TimerCC32XX_timer16A
99 * and the most significant bit represents the second half width timer,
100 * TimerCC32XX_timer16B. If the full width timer, TimerCC32XX_timer32, is used,
101 * both bits are set to 1.
102
103 * 31 - 8 7 - 6 5 - 4 3 - 2 1 - 0
104 * ------------------------------------------------
105 * | Reserved | Timer3 | Timer2 | Timer1 | Timer0 |
106 * ------------------------------------------------
107 */
108 static struct {
109 uint32_t bitMask;
110 } timerState;
111
112 /*
113 * ======== initHw ========
114 */
initHw(Timer_Handle handle)115 static void initHw(Timer_Handle handle)
116 {
117 TimerCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
118 TimerCC32XX_Object const *object = handle->object;
119
120 /* Ensure the timer is disabled */
121 TimerDisable(hwAttrs->baseAddress, object->timer);
122
123 if (object->timer == TIMER_A) {
124
125 HWREG(hwAttrs->baseAddress + TIMER_O_TAMR) = TIMER_TAMR_TAMR_PERIOD;
126 }
127 else {
128
129 HWREG(hwAttrs->baseAddress + TIMER_O_TBMR) = TIMER_TBMR_TBMR_PERIOD;
130 }
131
132 if (hwAttrs->subTimer == TimerCC32XX_timer32) {
133
134 HWREG(hwAttrs->baseAddress + TIMER_O_CFG) = TIMER_CFG_32_BIT_TIMER;
135 }
136 else {
137
138 HWREG(hwAttrs->baseAddress + TIMER_O_CFG) = TIMER_CFG_16_BIT;
139 }
140
141 /* Disable all interrupts */
142 HWREG(hwAttrs->baseAddress + TIMER_O_IMR) = ~object->timer;
143
144 /* Writing the PSR Register has no effect for full width 32-bit mode */
145 TimerPrescaleSet(hwAttrs->baseAddress, object->timer, object->prescaler);
146 TimerLoadSet(hwAttrs->baseAddress, object->timer, object->period);
147
148 /* This function controls the stall response for the timer. When true,
149 * the timer stops counting if the processor enters debug mode. The
150 * default setting for the hardware is false.
151 */
152 TimerControlStall(hwAttrs->baseAddress, object->timer, true);
153 }
154
155 /*
156 * ========= getPrescaler =========
157 * This function calculates the prescaler and timer interval load register
158 * for a half timer. The handle is assumed to contain a object->period which
159 * represents the number of clock cycles in the desired period. The calling
160 * function, TimerCC32XX_open() checks for overflow before calling this function.
161 * Therefore, this function is guaranteed to never fail.
162 */
getPrescaler(Timer_Handle handle)163 static void getPrescaler(Timer_Handle handle)
164 {
165 TimerCC32XX_Object *object = handle->object;
166 uint32_t bestDiff = ~0, bestPsr = 0, bestIload = 0;
167 uint32_t diff, intervalLoad, prescaler;
168
169 /* Loop over the 8-bit prescaler */
170 for (prescaler = 1; prescaler < 256; prescaler++) {
171
172 /* Calculate timer interval load */
173 intervalLoad = object->period / (prescaler + 1);
174
175 /* Will this fit in 16-bits? */
176 if (intervalLoad > (uint16_t) ~0) {
177 continue;
178 }
179
180 /* How close is the intervalLoad to what we actually want? */
181 diff = object->period - intervalLoad * (prescaler + 1);
182
183 /* If it is closer to what we want */
184 if (diff <= bestDiff) {
185
186 /* If its a perfect match */
187 if (diff == 0) {
188 object->period = intervalLoad;
189 object->prescaler = prescaler;
190
191 return;
192 }
193
194 /* Snapshot in case we don't find something better */
195 bestDiff = diff;
196 bestPsr = prescaler;
197 bestIload = intervalLoad;
198 }
199 }
200
201 /* Never found a perfect match, settle for the best */
202 object->period = bestIload;
203 object->prescaler = bestPsr;
204 }
205
206 /*
207 * ======== getPowerMgrId ========
208 */
getPowerMgrId(uint32_t baseAddress)209 static uint32_t getPowerMgrId(uint32_t baseAddress)
210 {
211 switch (baseAddress) {
212
213 case TIMERA0_BASE:
214
215 return (PowerCC32XX_PERIPH_TIMERA0);
216
217 case TIMERA1_BASE:
218
219 return (PowerCC32XX_PERIPH_TIMERA1);
220
221 case TIMERA2_BASE:
222
223 return (PowerCC32XX_PERIPH_TIMERA2);
224
225 case TIMERA3_BASE:
226
227 return (PowerCC32XX_PERIPH_TIMERA3);
228
229 default:
230
231 return ((uint32_t) -1);
232 }
233 }
234
235 /*
236 * ======== postNotifyFxn ========
237 * This functions is called when a transition from LPDS mode is made.
238 * clientArg should be a handle of a previously opened Timer instance.
239 */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)240 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
241 uintptr_t clientArg)
242 {
243 initHw((Timer_Handle) clientArg);
244
245 return (Power_NOTIFYDONE);
246 }
247
248 /*
249 * ======== TimerCC32XX_allocateTimerResource ========
250 */
TimerCC32XX_allocateTimerResource(uint32_t baseAddress,TimerCC32XX_SubTimer subTimer)251 bool TimerCC32XX_allocateTimerResource(uint32_t baseAddress,
252 TimerCC32XX_SubTimer subTimer)
253 {
254 uintptr_t key;
255 uint32_t mask;
256 uint32_t powerMgrId;
257 bool status;
258
259 powerMgrId = getPowerMgrId(baseAddress);
260
261 if (powerMgrId == (uint32_t) -1) {
262
263 return (false);
264 }
265
266 mask = subTimer << timerMaskShift(baseAddress);
267
268 key = HwiP_disable();
269
270 if (timerState.bitMask & mask) {
271
272 status = false;
273 }
274 else {
275
276 Power_setDependency(powerMgrId);
277 timerState.bitMask = timerState.bitMask | mask;
278 status = true;
279 }
280
281 HwiP_restore(key);
282
283 return (status);
284 }
285
286 /*
287 * ======== TimerCC32XX_close ========
288 */
TimerCC32XX_close(Timer_Handle handle)289 void TimerCC32XX_close(Timer_Handle handle)
290 {
291 TimerCC32XX_Object *object = handle->object;
292 TimerCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
293
294 /* Stopping the Timer before closing it */
295 TimerCC32XX_stop(handle);
296
297 Power_unregisterNotify(&(object->notifyObj));
298
299 if (object->hwiHandle) {
300
301 HwiP_clearInterrupt(hwAttrs->intNum);
302 HwiP_delete(object->hwiHandle);
303 object->hwiHandle = NULL;
304 }
305
306 if (object->timerSem) {
307
308 SemaphoreP_delete(object->timerSem);
309 object->timerSem = NULL;
310 }
311
312 TimerCC32XX_freeTimerResource(hwAttrs->baseAddress, hwAttrs->subTimer);
313 }
314
315 /*
316 * ======== TimerCC32XX_control ========
317 */
TimerCC32XX_control(Timer_Handle handle,uint_fast16_t cmd,void * arg)318 int_fast16_t TimerCC32XX_control(Timer_Handle handle,
319 uint_fast16_t cmd, void *arg)
320 {
321 return (Timer_STATUS_UNDEFINEDCMD);
322 }
323
324 /*
325 * ======== TimerCC32XX_freeTimerResource ========
326 */
TimerCC32XX_freeTimerResource(uint32_t baseAddress,TimerCC32XX_SubTimer subTimer)327 void TimerCC32XX_freeTimerResource(uint32_t baseAddress,
328 TimerCC32XX_SubTimer subTimer)
329 {
330 uintptr_t key;
331 uint32_t mask;
332
333 mask = subTimer << timerMaskShift(baseAddress);
334
335 key = HwiP_disable();
336
337 timerState.bitMask = (timerState.bitMask & ~mask);
338
339 Power_releaseDependency(getPowerMgrId(baseAddress));
340
341 HwiP_restore(key);
342 }
343
344 /*
345 * ======== TimerCC32XX_getCount ========
346 */
TimerCC32XX_getCount(Timer_Handle handle)347 uint32_t TimerCC32XX_getCount(Timer_Handle handle)
348 {
349 TimerCC32XX_HWAttrs const *hWAttrs = handle->hwAttrs;
350 TimerCC32XX_Object const *object = handle->object;
351 uint32_t count;
352
353 if (object->timer == TIMER_A) {
354 count = HWREG(hWAttrs->baseAddress + TIMER_O_TAR);
355 }
356 else {
357 count = HWREG(hWAttrs->baseAddress + TIMER_O_TBR);
358 }
359
360 /* Virtual up counter */
361 count = object->period - count;
362
363 return (count);
364 }
365
366 /*
367 * ======== TimerCC32XX_hwiIntFunction ========
368 */
TimerCC32XX_hwiIntFunction(uintptr_t arg)369 void TimerCC32XX_hwiIntFunction(uintptr_t arg)
370 {
371 Timer_Handle handle = (Timer_Handle) arg;
372 TimerCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
373 TimerCC32XX_Object const *object = handle->object;
374 uint32_t interruptMask;
375
376 /* Only clear the interrupt for this->object->timer */
377 interruptMask = object->timer & (TIMER_TIMA_TIMEOUT | TIMER_TIMB_TIMEOUT);
378 TimerIntClear(hwAttrs->baseAddress, interruptMask);
379
380 /* Hwi is not created when using Timer_FREE_RUNNING */
381 if (object->mode != Timer_CONTINUOUS_CALLBACK) {
382 TimerCC32XX_stop(handle);
383 }
384
385 if (object-> mode != Timer_ONESHOT_BLOCKING) {
386 object->callBack(handle, Timer_STATUS_SUCCESS);
387 }
388 }
389
390 /*
391 * ======== TimerCC32XX_init ========
392 */
TimerCC32XX_init(Timer_Handle handle)393 void TimerCC32XX_init(Timer_Handle handle)
394 {
395 return;
396 }
397
398 /*
399 * ======== TimerCC32XX_open ========
400 */
TimerCC32XX_open(Timer_Handle handle,Timer_Params * params)401 Timer_Handle TimerCC32XX_open(Timer_Handle handle, Timer_Params *params)
402 {
403 TimerCC32XX_Object *object = handle->object;
404 TimerCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
405 SemaphoreP_Params semParams;
406 HwiP_Params hwiParams;
407 ClockP_FreqHz clockFreq;
408
409 /* Check for valid parameters */
410 if (((params->timerMode == Timer_ONESHOT_CALLBACK ||
411 params->timerMode == Timer_CONTINUOUS_CALLBACK) &&
412 params->timerCallback == NULL) ||
413 params->period == 0) {
414
415 return (NULL);
416 }
417
418 if (!TimerCC32XX_allocateTimerResource(hwAttrs->baseAddress,
419 hwAttrs->subTimer)) {
420
421 return (NULL);
422 }
423
424 Power_registerNotify(&(object->notifyObj), PowerCC32XX_AWAKE_LPDS,
425 postNotifyFxn, (uintptr_t) handle);
426
427 object->mode = params->timerMode;
428 object->isRunning = false;
429 object->callBack = params->timerCallback;
430 object->period = params->period;
431 object->prescaler = 0;
432
433 if (hwAttrs->subTimer == TimerCC32XX_timer16B) {
434
435 object->timer = TIMER_B;
436 }
437 else {
438
439 object->timer = TIMER_A;
440 }
441
442 if (object->mode != Timer_FREE_RUNNING) {
443
444 HwiP_Params_init(&hwiParams);
445 hwiParams.arg = (uintptr_t) handle;
446 hwiParams.priority = hwAttrs->intPriority;
447 object->hwiHandle = HwiP_create(hwAttrs->intNum,
448 TimerCC32XX_hwiIntFunction, &hwiParams);
449
450 if (object->hwiHandle == NULL) {
451
452 TimerCC32XX_close(handle);
453
454 return (NULL);
455 }
456
457 }
458
459 /* Creating the semaphore if mode is blocking */
460 if (params->timerMode == Timer_ONESHOT_BLOCKING) {
461
462 SemaphoreP_Params_init(&semParams);
463 semParams.mode = SemaphoreP_Mode_BINARY;
464 object->timerSem = SemaphoreP_create(0, &semParams);
465
466 if (object->timerSem == NULL) {
467
468 TimerCC32XX_close(handle);
469
470 return (NULL);
471 }
472 }
473
474 /* Formality; CC32XX System Clock fixed to 80.0 MHz */
475 ClockP_getCpuFreq(&clockFreq);
476
477 if (params->periodUnits == Timer_PERIOD_US) {
478
479 /* Checks if the calculated period will fit in 32-bits */
480 if (object->period >= ((uint32_t) ~0) / (clockFreq.lo / 1000000)) {
481
482 TimerCC32XX_close(handle);
483
484 return (NULL);
485 }
486
487 object->period = object->period * (clockFreq.lo / 1000000);
488 }
489 else if (params->periodUnits == Timer_PERIOD_HZ) {
490
491 /* If (object->period) > clockFreq */
492 if ((object->period = clockFreq.lo / object->period) == 0) {
493
494 TimerCC32XX_close(handle);
495
496 return (NULL);
497 }
498 }
499
500 /* If using a half timer */
501 if (hwAttrs->subTimer != TimerCC32XX_timer32) {
502
503 if (object->period > 0xFFFF) {
504
505 /* 24-bit resolution for the half timer */
506 if (object->period >= (1 << 24)) {
507
508 TimerCC32XX_close(handle);
509
510 return (NULL);
511 }
512
513 getPrescaler(handle);
514 }
515 }
516
517 initHw(handle);
518
519 return (handle);
520 }
521
522 /*
523 * ======== TimerCC32XX_setPeriod =======
524 */
TimerCC32XX_setPeriod(Timer_Handle handle,Timer_PeriodUnits periodUnits,uint32_t period)525 int32_t TimerCC32XX_setPeriod(Timer_Handle handle, Timer_PeriodUnits periodUnits, uint32_t period)
526 {
527 TimerCC32XX_HWAttrs const *hwAttrs= handle->hwAttrs;
528 TimerCC32XX_Object *object = handle->object;
529 ClockP_FreqHz clockFreq;
530
531 /* Formality; CC32XX System Clock fixed to 80.0 MHz */
532 ClockP_getCpuFreq(&clockFreq);
533
534 if (periodUnits == Timer_PERIOD_US) {
535
536 /* Checks if the calculated period will fit in 32-bits */
537 if (period >= ((uint32_t) ~0) / (clockFreq.lo / 1000000)) {
538
539 return (Timer_STATUS_ERROR);
540 }
541
542 period = period * (clockFreq.lo / 1000000);
543 }
544 else if (periodUnits == Timer_PERIOD_HZ) {
545
546 /* If period > clockFreq */
547 if ((period = clockFreq.lo / period) == 0) {
548
549 return (Timer_STATUS_ERROR);
550 }
551 }
552
553 /* If using a half timer */
554 if (hwAttrs->subTimer != TimerCC32XX_timer32) {
555
556 if (period > 0xFFFF) {
557
558 /* 24-bit resolution for the half timer */
559 if (period >= (1 << 24)) {
560
561 return (Timer_STATUS_ERROR);
562 }
563 }
564 }
565
566 object->period = period;
567
568 if (hwAttrs->subTimer != TimerCC32XX_timer32) {
569 getPrescaler(handle);
570 }
571
572 /* Writing the PSR Register has no effect for full width 32-bit mode */
573 TimerPrescaleSet(hwAttrs->baseAddress, object->timer, object->prescaler);
574 TimerLoadSet(hwAttrs->baseAddress, object->timer, object->period);
575
576 return (Timer_STATUS_SUCCESS);
577
578
579 }
580
581 /*
582 * ======== TimerCC32XX_start ========
583 */
TimerCC32XX_start(Timer_Handle handle)584 int32_t TimerCC32XX_start(Timer_Handle handle)
585 {
586 TimerCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
587 TimerCC32XX_Object *object = handle->object;
588 uint32_t interruptMask;
589 uintptr_t key;
590
591 interruptMask = object->timer & (TIMER_TIMB_TIMEOUT | TIMER_TIMA_TIMEOUT);
592
593 key = HwiP_disable();
594
595 if (object->isRunning) {
596
597 HwiP_restore(key);
598
599 return (Timer_STATUS_ERROR);
600 }
601
602 object->isRunning = true;
603
604 if (object->hwiHandle) {
605
606 TimerIntEnable(hwAttrs->baseAddress, interruptMask);
607 }
608
609 Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
610
611 /* Reload the timer */
612 if (object->timer == TIMER_A) {
613 HWREG(hwAttrs->baseAddress + TIMER_O_TAMR) |= TIMER_TAMR_TAILD;
614 }
615 else {
616 HWREG(hwAttrs->baseAddress + TIMER_O_TBMR) |= TIMER_TBMR_TBILD;
617 }
618
619 TimerEnable(hwAttrs->baseAddress, object->timer);
620
621 HwiP_restore(key);
622
623 if (object->mode == Timer_ONESHOT_BLOCKING) {
624
625 /* Pend forever, ~0 */
626 SemaphoreP_pend(object->timerSem, ~0);
627 }
628
629 return (Timer_STATUS_SUCCESS);
630 }
631
632 /*
633 * ======== TimerCC32XX_stop ========
634 */
TimerCC32XX_stop(Timer_Handle handle)635 void TimerCC32XX_stop(Timer_Handle handle)
636 {
637 TimerCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
638 TimerCC32XX_Object *object = handle->object;
639 uint32_t interruptMask;
640 uintptr_t key;
641 bool flag = false;
642
643 interruptMask = object->timer & (TIMER_TIMB_TIMEOUT | TIMER_TIMA_TIMEOUT);
644
645 key = HwiP_disable();
646
647 if (object->isRunning) {
648
649 object->isRunning = false;
650
651 /* Post the Semaphore when called from the Hwi */
652 if (object->mode == Timer_ONESHOT_BLOCKING) {
653 flag = true;
654 }
655
656 TimerDisable(hwAttrs->baseAddress, object->timer);
657 TimerIntDisable(hwAttrs->baseAddress, interruptMask);
658 Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
659 }
660
661 HwiP_restore(key);
662
663 if (flag) {
664 SemaphoreP_post(object->timerSem);
665 }
666 }
667