1 /*
2 * Copyright (c) 2015-2017, 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 * ======== PowerCC32XX.c ========
34 */
35
36 #include <stdint.h>
37
38 /*
39 * By default disable both asserts and log for this module.
40 * This must be done before DebugP.h is included.
41 */
42 #ifndef DebugP_ASSERT_ENABLED
43 #define DebugP_ASSERT_ENABLED 0
44 #endif
45 #ifndef DebugP_LOG_ENABLED
46 #define DebugP_LOG_ENABLED 0
47 #endif
48 #include <ti/drivers/dpl/DebugP.h>
49 #include <ti/drivers/dpl/HwiP.h>
50
51 #include <ti/drivers/utils/List.h>
52
53 #include <ti/drivers/Power.h>
54 #include <ti/drivers/power/PowerCC32XX.h>
55
56 #if defined(__IAR_SYSTEMS_ICC__)
57 #include <intrinsics.h>
58 #endif
59
60 /* driverlib header files */
61 #include <ti/devices/cc32xx/driverlib/rom.h>
62 #include <ti/devices/cc32xx/driverlib/rom_map.h>
63 #include <ti/devices/cc32xx/inc/hw_types.h>
64 #include <ti/devices/cc32xx/inc/hw_gprcm.h>
65 #include <ti/devices/cc32xx/inc/hw_apps_rcm.h>
66 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
67 #include <ti/devices/cc32xx/driverlib/prcm.h>
68 #include <ti/devices/cc32xx/inc/hw_nvic.h>
69 #include <ti/devices/cc32xx/inc/hw_memmap.h>
70 #include <ti/devices/cc32xx/inc/hw_ints.h>
71 #include <ti/devices/cc32xx/driverlib/pin.h>
72 #include <ti/devices/cc32xx/driverlib/cpu.h>
73 #include <ti/devices/cc32xx/driverlib/hwspinlock.h>
74 #include <ti/devices/cc32xx/driverlib/spi.h>
75
76 #define TRUE 1
77 #define FALSE 0
78 #define STATUS_BUSY 0x01
79
80 #define PowerCC32XX_SSPIReadStatusInstruction (0x05)
81 #define PowerCC32XX_SSPIPowerDownInstruction (0xB9)
82 #define PowerCC32XX_SSPISemaphoreTakeTries (4000000)
83 #define PowerCC32XX_SSPICSDelay 33
84 #define uSEC_DELAY(x) (ROM_UtilsDelayDirect(x*80/3))
85
86 #define SYNCBARRIER() { \
87 __asm(" dsb \n" \
88 " isb \n"); \
89 }
90
91 /* Externs */
92 extern const PowerCC32XX_ConfigV1 PowerCC32XX_config;
93
94 /* Module_State */
95 PowerCC32XX_ModuleState PowerCC32XX_module = {
96 { NULL, NULL}, /* list */
97 0, /* constraintsMask */
98 Power_ACTIVE, /* state */
99 /* dbRecords */
100 {
101 PRCM_CAMERA, /* PERIPH_CAMERA */
102 PRCM_I2S, /* PERIPH_MCASP */
103 PRCM_SDHOST, /* PERIPH_MMCHS */
104 PRCM_GSPI, /* PERIPH_MCSPI_A1 */
105 PRCM_LSPI, /* PERIPH_MCSPI_A2 */
106 PRCM_UDMA, /* PERIPH_UDMA_A */
107 PRCM_GPIOA0, /* PERIPH_GPIO_A */
108 PRCM_GPIOA1, /* PERIPH_GPIO_B */
109 PRCM_GPIOA2, /* PERIPH_GPIO_C */
110 PRCM_GPIOA3, /* PERIPH_GPIO_D */
111 PRCM_GPIOA4, /* PERIPH_GPIO_E */
112 PRCM_WDT, /* PERIPH_WDOG_A */
113 PRCM_UARTA0, /* PERIPH_UART_A0 */
114 PRCM_UARTA1, /* PERIPH_UART_A1 */
115 PRCM_TIMERA0, /* PERIPH_GPT_A0 */
116 PRCM_TIMERA1, /* PERIPH_GPT_A1 */
117 PRCM_TIMERA2, /* PERIPH_GPT_A2 */
118 PRCM_TIMERA3, /* PERIPH_GPT_A3 */
119 PRCM_DTHE, /* PERIPH_CRYPTO */
120 PRCM_SSPI, /* PERIPH_MCSPI_S0 */
121 PRCM_I2CA0 /* PERIPH_I2C */
122 },
123 /* enablePolicy */
124 FALSE,
125 /* initialized */
126 FALSE,
127 /* refCount */
128 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
129 /* constraintCounts */
130 { 0, 0 },
131 /* policyFxn */
132 NULL
133 };
134
135 /* context save variable */
136 PowerCC32XX_SaveRegisters PowerCC32XX_contextSave;
137
138 typedef void (*LPDSFunc)(void);
139
140 /* enter LPDS is an assembly function */
141 extern void PowerCC32XX_enterLPDS(LPDSFunc driverlibFunc);
142
143 /* pin parking functions */
144 void PowerCC32XX_parkPin(PowerCC32XX_Pin pin, PowerCC32XX_ParkState parkState,
145 uint32_t * previousState, uint16_t * previousDirection);
146 void PowerCC32XX_restoreParkedPin(PowerCC32XX_Pin pin, uint32_t type,
147 uint16_t direction);
148 void PowerCC32XX_shutdownSSPI(void);
149
150 /* internal functions */
151 static int_fast16_t notify(uint_fast16_t eventType);
152 static void restoreNVICRegs(void);
153 static void restorePeriphClocks(void);
154 static void saveNVICRegs(void);
155 static void parkPins(void);
156 static void restoreParkedPins(void);
157
158 /*
159 * ======== Power_disablePolicy ========
160 * Do not run the configured policy
161 */
Power_disablePolicy(void)162 bool Power_disablePolicy(void)
163 {
164 bool enablePolicy = PowerCC32XX_module.enablePolicy;
165 PowerCC32XX_module.enablePolicy = FALSE;
166
167 DebugP_log0("Power: disable policy");
168
169 return (enablePolicy);
170 }
171
172 /*
173 * ======== Power_enablePolicy ========
174 * Run the configured policy
175 */
Power_enablePolicy(void)176 void Power_enablePolicy(void)
177 {
178 PowerCC32XX_module.enablePolicy = TRUE;
179
180 DebugP_log0("Power: enable policy");
181 }
182
183 /*
184 * ======== Power_getConstraintMask ========
185 * Get a bitmask indicating the constraints that have been registered with
186 * Power.
187 */
Power_getConstraintMask(void)188 uint_fast32_t Power_getConstraintMask(void)
189 {
190 return (PowerCC32XX_module.constraintMask);
191 }
192
193 /*
194 * ======== Power_getDependencyCount ========
195 * Get the count of dependencies that are currently declared upon a resource.
196 */
Power_getDependencyCount(uint_fast16_t resourceId)197 int_fast16_t Power_getDependencyCount(uint_fast16_t resourceId)
198 {
199 int_fast16_t status;
200
201 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
202 status = Power_EINVALIDINPUT;
203 }
204 else {
205 status = PowerCC32XX_module.refCount[resourceId];
206 }
207
208 return (status);
209 }
210
211 /*
212 * ======== Power_getTransitionLatency ========
213 * Get the transition latency for a sleep state. The latency is reported
214 * in units of microseconds.
215 */
Power_getTransitionLatency(uint_fast16_t sleepState,uint_fast16_t type)216 uint_fast32_t Power_getTransitionLatency(uint_fast16_t sleepState,
217 uint_fast16_t type)
218 {
219 uint32_t latency = 0;
220
221 if (type == Power_RESUME) {
222 latency = PowerCC32XX_RESUMETIMELPDS;
223 }
224 else {
225 latency = PowerCC32XX_TOTALTIMELPDS;
226 }
227
228 return (latency);
229 }
230
231 /*
232 * ======== Power_getTransitionState ========
233 * Get the current sleep transition state.
234 */
Power_getTransitionState(void)235 uint_fast16_t Power_getTransitionState(void)
236 {
237 return (PowerCC32XX_module.state);
238 }
239
240 /*
241 * ======== Power_idleFunc ========
242 * Function needs to be plugged into the idle loop.
243 * It calls the configured policy function if the
244 * 'enablePolicy' flag is set.
245 */
Power_idleFunc()246 void Power_idleFunc()
247 {
248 if (PowerCC32XX_module.enablePolicy) {
249 if (PowerCC32XX_module.policyFxn != NULL) {
250 DebugP_log1("Power: calling policy function (%p)",
251 (uintptr_t) PowerCC32XX_module.policyFxn);
252 (*(PowerCC32XX_module.policyFxn))();
253 }
254 }
255 }
256
257 /*
258 * ======== Power_init ========
259 */
Power_init()260 int_fast16_t Power_init()
261 {
262 /* if this function has already been called, just return */
263 if (PowerCC32XX_module.initialized) {
264 return (Power_SOK);
265 }
266
267 /* set module state field 'initialized' to true */
268 PowerCC32XX_module.initialized = TRUE;
269
270 /* set the module state enablePolicy field */
271 PowerCC32XX_module.enablePolicy = PowerCC32XX_config.enablePolicy;
272
273 /* call the config policy init function if its not null */
274 if (PowerCC32XX_config.policyInitFxn != NULL) {
275 (*(PowerCC32XX_config.policyInitFxn))();
276 }
277
278 /* copy wakeup settings to module state */
279 PowerCC32XX_module.wakeupConfig.enableGPIOWakeupLPDS =
280 PowerCC32XX_config.enableGPIOWakeupLPDS;
281 PowerCC32XX_module.wakeupConfig.enableGPIOWakeupShutdown =
282 PowerCC32XX_config.enableGPIOWakeupShutdown;
283 PowerCC32XX_module.wakeupConfig.enableNetworkWakeupLPDS =
284 PowerCC32XX_config.enableNetworkWakeupLPDS;
285 PowerCC32XX_module.wakeupConfig.wakeupGPIOSourceLPDS =
286 PowerCC32XX_config.wakeupGPIOSourceLPDS;
287 PowerCC32XX_module.wakeupConfig.wakeupGPIOTypeLPDS =
288 PowerCC32XX_config.wakeupGPIOTypeLPDS;
289 PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDS =
290 PowerCC32XX_config.wakeupGPIOFxnLPDS;
291 PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDSArg =
292 PowerCC32XX_config.wakeupGPIOFxnLPDSArg;
293 PowerCC32XX_module.wakeupConfig.wakeupGPIOSourceShutdown =
294 PowerCC32XX_config.wakeupGPIOSourceShutdown;
295 PowerCC32XX_module.wakeupConfig.wakeupGPIOTypeShutdown =
296 PowerCC32XX_config.wakeupGPIOTypeShutdown;
297
298 /* now configure these wakeup settings in the device... */
299 PowerCC32XX_configureWakeup(&PowerCC32XX_module.wakeupConfig);
300
301 /* copy the Power policy function to module state */
302 PowerCC32XX_module.policyFxn = PowerCC32XX_config.policyFxn;
303
304 /* spin if too many pins were specified in the pin park array */
305 if (PowerCC32XX_config.numPins > PowerCC32XX_NUMPINS) {
306 while(1){}
307 }
308
309 /* Initialize CLK GPIO */
310 HWREG(OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_18) = 0x281;
311
312 /* Initialize DOUT GPIO */
313 HWREG(OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_19) = 0x281;
314
315 return (Power_SOK);
316 }
317
318 /*
319 * ======== Power_registerNotify ========
320 * Register a function to be called on a specific power event.
321 */
Power_registerNotify(Power_NotifyObj * pNotifyObj,uint_fast16_t eventTypes,Power_NotifyFxn notifyFxn,uintptr_t clientArg)322 int_fast16_t Power_registerNotify(Power_NotifyObj * pNotifyObj,
323 uint_fast16_t eventTypes, Power_NotifyFxn notifyFxn, uintptr_t clientArg)
324 {
325 int_fast16_t status = Power_SOK;
326
327 /* check for NULL pointers */
328 if ((pNotifyObj == NULL) || (notifyFxn == NULL)) {
329 status = Power_EINVALIDPOINTER;
330 }
331
332 else {
333 /* fill in notify object elements */
334 pNotifyObj->eventTypes = eventTypes;
335 pNotifyObj->notifyFxn = notifyFxn;
336 pNotifyObj->clientArg = clientArg;
337
338 /* place notify object on event notification queue */
339 List_put(&PowerCC32XX_module.notifyList, (List_Elem*)pNotifyObj);
340 }
341
342 DebugP_log3(
343 "Power: register notify (%p), eventTypes (0x%x), notifyFxn (%p)",
344 (uintptr_t) pNotifyObj, eventTypes, (uintptr_t) notifyFxn);
345
346 return (status);
347 }
348
349 /*
350 * ======== Power_releaseConstraint ========
351 * Release a previously declared constraint.
352 */
Power_releaseConstraint(uint_fast16_t constraintId)353 int_fast16_t Power_releaseConstraint(uint_fast16_t constraintId)
354 {
355 int_fast16_t status = Power_SOK;
356 uintptr_t key;
357 uint8_t count;
358
359 /* first ensure constraintId is valid */
360 if (constraintId >= PowerCC32XX_NUMCONSTRAINTS) {
361 status = Power_EINVALIDINPUT;
362 }
363
364 /* if constraintId is OK ... */
365 else {
366
367 /* disable interrupts */
368 key = HwiP_disable();
369
370 /* get the count of the constraint */
371 count = PowerCC32XX_module.constraintCounts[constraintId];
372
373 /* ensure constraint count is not already zero */
374 if (count == 0) {
375 status = Power_EFAIL;
376 }
377
378 /* if not already zero ... */
379 else {
380 /* decrement the count */
381 count--;
382
383 /* save the updated count */
384 PowerCC32XX_module.constraintCounts[constraintId] = count;
385
386 /* if constraint count reaches zero, remove constraint from mask */
387 if (count == 0) {
388 PowerCC32XX_module.constraintMask &= ~(1 << constraintId);
389 }
390 }
391
392 /* restore interrupts */
393 HwiP_restore(key);
394
395 DebugP_log1("Power: release constraint (%d)", constraintId);
396 }
397
398 return (status);
399 }
400
401 /*
402 * ======== Power_releaseDependency ========
403 * Release a previously declared dependency.
404 */
Power_releaseDependency(uint_fast16_t resourceId)405 int_fast16_t Power_releaseDependency(uint_fast16_t resourceId)
406 {
407 int_fast16_t status = Power_SOK;
408 uint8_t count;
409 uint32_t id;
410 uintptr_t key;
411
412 /* first check that resourceId is valid */
413 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
414 status = Power_EINVALIDINPUT;
415 }
416
417 /* if resourceId is OK ... */
418 else {
419
420 /* disable interrupts */
421 key = HwiP_disable();
422
423 /* read the reference count */
424 count = PowerCC32XX_module.refCount[resourceId];
425
426 /* ensure dependency count is not already zero */
427 if (count == 0) {
428 status = Power_EFAIL;
429 }
430
431 /* if not already zero ... */
432 else {
433
434 /* decrement the reference count */
435 count--;
436
437 /* if this was the last dependency being released.., */
438 if (count == 0) {
439 /* deactivate this resource ... */
440 id = PowerCC32XX_module.dbRecords[resourceId];
441
442 /* disable clk to peripheral */
443 MAP_PRCMPeripheralClkDisable(id,
444 PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
445 }
446
447 /* save the updated count */
448 PowerCC32XX_module.refCount[resourceId] = count;
449 }
450
451 /* restore interrupts */
452 HwiP_restore(key);
453
454 DebugP_log1("Power: release dependency (%d)", resourceId);
455 }
456
457 return (status);
458 }
459
460 /*
461 * ======== Power_setConstraint ========
462 * Declare an operational constraint.
463 */
Power_setConstraint(uint_fast16_t constraintId)464 int_fast16_t Power_setConstraint(uint_fast16_t constraintId)
465 {
466 int_fast16_t status = Power_SOK;
467 uintptr_t key;
468
469 /* ensure that constraintId is valid */
470 if (constraintId >= PowerCC32XX_NUMCONSTRAINTS) {
471 status = Power_EINVALIDINPUT;
472 }
473
474 else {
475
476 /* disable interrupts */
477 key = HwiP_disable();
478
479 /* set the specified constraint in the constraintMask */
480 PowerCC32XX_module.constraintMask |= 1 << constraintId;
481
482 /* increment the specified constraint count */
483 PowerCC32XX_module.constraintCounts[constraintId]++;
484
485 /* restore interrupts */
486 HwiP_restore(key);
487
488 DebugP_log1("Power: set constraint (%d)", constraintId);
489 }
490
491 return (status);
492 }
493
494 /*
495 * ======== Power_setDependency ========
496 * Declare a dependency upon a resource.
497 */
Power_setDependency(uint_fast16_t resourceId)498 int_fast16_t Power_setDependency(uint_fast16_t resourceId)
499 {
500 int_fast16_t status = Power_SOK;
501 uint8_t count;
502 uint32_t id;
503 uintptr_t key;
504
505 /* ensure resourceId is valid */
506 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
507 status = Power_EINVALIDINPUT;
508 }
509
510 /* resourceId is OK ... */
511 else {
512
513 /* disable interrupts */
514 key = HwiP_disable();
515
516 /* read and increment reference count */
517 count = PowerCC32XX_module.refCount[resourceId]++;
518
519 /* if resource was NOT activated previously ... */
520 if (count == 0) {
521 /* now activate this resource ... */
522 id = PowerCC32XX_module.dbRecords[resourceId];
523
524 /*
525 * When the periphery is LSPI, choose PLL or XTAL according
526 * to the generation of the NWP
527 */
528 if(id == PowerCC32XX_PERIPH_LSPI)
529 {
530 /* Check NWP generation */
531 if((HWREG(GPRCM_BASE + GPRCM_O_GPRCM_DIEID_READ_REG4) >> 24) & 0x02)
532 {
533 /* Configure PLL and divide the speed by 8 for LSPI */
534 HWREG(ARCM_BASE + APPS_RCM_O_MCSPI_A2_CLK_GEN) = 0x10303;
535 }
536 else
537 {
538 /* Configure XTAL for LSPI */
539 HWREG(ARCM_BASE + APPS_RCM_O_MCSPI_A2_CLK_GEN) = 0x00;
540 }
541 }
542
543 /* enable the peripheral clock to the resource */
544 MAP_PRCMPeripheralClkEnable(id,
545 PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
546
547 /* spin here until status returns TRUE */
548 while(!MAP_PRCMPeripheralStatusGet(id)) {
549 }
550 }
551
552 /* restore interrupts */
553 HwiP_restore(key);
554 DebugP_log1("Power: set dependency (%d)", resourceId);
555 }
556
557 return (status);
558 }
559
560 /*
561 * ======== Power_setPolicy ========
562 * Set the Power policy function
563 */
Power_setPolicy(Power_PolicyFxn policy)564 void Power_setPolicy(Power_PolicyFxn policy)
565 {
566 PowerCC32XX_module.policyFxn = policy;
567 }
568
569 /*
570 * ======== Power_shutdown ========
571 */
Power_shutdown(uint_fast16_t shutdownState,uint_fast32_t shutdownTime)572 int_fast16_t Power_shutdown(uint_fast16_t shutdownState,
573 uint_fast32_t shutdownTime)
574 {
575 int_fast16_t status = Power_EFAIL;
576 uint32_t constraints;
577 uintptr_t hwiKey;
578 uint64_t counts;
579
580 /* disable interrupts */
581 hwiKey = HwiP_disable();
582
583 /* make sure shutdown request doesn't violate a constraint */
584 constraints = Power_getConstraintMask();
585 if (constraints & (1 << PowerCC32XX_DISALLOW_SHUTDOWN)) {
586 status = Power_ECHANGE_NOT_ALLOWED;
587 }
588 else {
589 if (PowerCC32XX_module.state == Power_ACTIVE) {
590 /* set new transition state to entering shutdown */
591 PowerCC32XX_module.state = Power_ENTERING_SHUTDOWN;
592
593 /* signal all clients registered for pre-shutdown notification */
594 status = notify(PowerCC32XX_ENTERING_SHUTDOWN);
595 /* check for timeout or any other error */
596 if (status != Power_SOK) {
597 PowerCC32XX_module.state = Power_ACTIVE;
598 HwiP_restore(hwiKey);
599 return (status);
600 }
601 /* shutdown the flash */
602 PowerCC32XX_shutdownSSPI();
603 /* if shutdown wakeup time was configured to be large enough */
604 if (shutdownTime > (PowerCC32XX_TOTALTIMESHUTDOWN / 1000)) {
605 /* calculate the wakeup time for hibernate in RTC counts */
606 counts =
607 (((uint64_t)(shutdownTime -
608 (PowerCC32XX_TOTALTIMESHUTDOWN / 1000))
609 * 32768) / 1000);
610
611 /* set the hibernate wakeup time */
612 MAP_PRCMHibernateIntervalSet(counts);
613
614 /* enable the wake source to be RTC */
615 MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
616 }
617
618 /* enable IO retention */
619 if (PowerCC32XX_config.ioRetentionShutdown) {
620 MAP_PRCMIORetentionEnable(
621 PowerCC32XX_config.ioRetentionShutdown);
622 }
623
624 DebugP_log2(
625 "Power: entering shutdown state (%d), shutdownTime (%d)",
626 shutdownState, shutdownTime);
627
628 /* enter hibernate - we should never return from here */
629 MAP_PRCMHibernateEnter();
630 }
631 else {
632 status = Power_EBUSY;
633 }
634 }
635
636 /* set state to Power_ACTIVE */
637 PowerCC32XX_module.state = Power_ACTIVE;
638
639 /* re-enable interrupts */
640 HwiP_restore(hwiKey);
641
642 /* if get here, failed to shutdown, return error code */
643 return (status);
644 }
645
646 /*
647 * ======== Power_sleep ========
648 */
Power_sleep(uint_fast16_t sleepState)649 int_fast16_t Power_sleep(uint_fast16_t sleepState)
650 {
651 int_fast16_t status = Power_SOK;
652 uint32_t romMajorVer;
653 uint32_t romMinorVer;
654 uint32_t preEvent;
655 uint32_t postEvent;
656 uint32_t semBits;
657 bool earlyPG = true;
658
659 /* first validate the sleep state */
660 if (sleepState != PowerCC32XX_LPDS) {
661 status = Power_EINVALIDINPUT;
662 }
663
664 else if (PowerCC32XX_module.state == Power_ACTIVE) {
665
666 /* set transition state to entering sleep */
667 PowerCC32XX_module.state = Power_ENTERING_SLEEP;
668
669 /* setup sleep vars */
670 preEvent = PowerCC32XX_ENTERING_LPDS;
671 postEvent = PowerCC32XX_AWAKE_LPDS;
672
673 /* signal all clients registered for pre-sleep notification */
674 status = notify(preEvent);
675
676 /* check for timeout or any other error */
677 if (status != Power_SOK) {
678 PowerCC32XX_module.state = Power_ACTIVE;
679 return (status);
680 }
681
682 /* indicate to the MAC layer through register that the
683 APPS layer is going to sleep this is needed because
684 the MAC cannot do DC2DC clock sync when the application
685 processor waking up from sleep and running through its
686 ROM bootloader because it is also touching the DC2DC
687 of the top die FLASH */
688
689 HWREG(OCP_SHARED_BASE + OCP_SHARED_O_ALT_PC_VAL_APPS) = 1;
690
691 DebugP_log1("Power: sleep, sleepState (%d)", sleepState);
692
693 /* invoke specific sequence to activate LPDS ...*/
694
695 /* enable RAM retention */
696 MAP_PRCMSRAMRetentionEnable(
697 PowerCC32XX_config.ramRetentionMaskLPDS,
698 PRCM_SRAM_LPDS_RET);
699
700 /* call the enter LPDS hook function if configured */
701 if (PowerCC32XX_config.enterLPDSHookFxn != NULL) {
702 (*(PowerCC32XX_config.enterLPDSHookFxn))();
703 }
704
705 /* park pins, based upon board file definitions */
706 if (PowerCC32XX_config.pinParkDefs != NULL) {
707 parkPins();
708 }
709
710 /* save the NVIC registers */
711 saveNVICRegs();
712
713 /* check if PG >= 2.01 */
714 romMajorVer = HWREG(0x00000400) & 0xFFFF;
715 romMinorVer = HWREG(0x00000400) >> 16;
716 if ((romMajorVer >= 3) || ((romMajorVer == 2) && (romMinorVer >= 1))) {
717 earlyPG = false;
718 }
719
720 /* call sync barrier */
721 SYNCBARRIER();
722
723 /* now enter LPDS - function does not return... */
724 if (PowerCC32XX_config.keepDebugActiveDuringLPDS == TRUE) {
725 if (earlyPG) {
726 PowerCC32XX_enterLPDS(PRCMLPDSEnterKeepDebugIf);
727 }
728 else {
729 PowerCC32XX_enterLPDS(ROM_PRCMLPDSEnterKeepDebugIfDirect);
730 }
731 }
732 else {
733 if (earlyPG) {
734 PowerCC32XX_enterLPDS(PRCMLPDSEnter);
735 }
736 else {
737 PowerCC32XX_enterLPDS(ROM_PRCMLPDSEnterDirect);
738 }
739 }
740
741 /* return here after reset, from Power_resumeLPDS() */
742
743 /* restore NVIC registers */
744 restoreNVICRegs();
745
746 /* restore clock to those peripherals with dependecy set */
747 restorePeriphClocks();
748
749 /* call PRCMCC3200MCUInit() for any necessary post-LPDS restore */
750 MAP_PRCMCC3200MCUInit();
751
752 /* take the GPIO semaphore bits for the MCU */
753 semBits = HWREG(0x400F703C);
754 semBits = (semBits & ~0x3FF) | 0x155;
755 HWREG(0x400F703C) = semBits;
756
757 /* call the resume LPDS hook function if configured */
758 if (PowerCC32XX_config.resumeLPDSHookFxn != NULL) {
759 (*(PowerCC32XX_config.resumeLPDSHookFxn))();
760 }
761
762 /* re-enable Slow Clock Counter Interrupt */
763 MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
764
765 /* set transition state to EXITING_SLEEP */
766 PowerCC32XX_module.state = Power_EXITING_SLEEP;
767
768 /* indicate to the MAC layer that the application processor is
769 up and running */
770 HWREG(OCP_SHARED_BASE + OCP_SHARED_O_ALT_PC_VAL_APPS) = 0;
771
772 /*
773 * signal clients registered for post-sleep notification; for example,
774 * a driver that needs to reinitialize its peripheral state, that was
775 * lost during LPDS
776 */
777 status = notify(postEvent);
778
779 /* restore pins parked before LPDS to their previous states */
780 if (PowerCC32XX_config.pinParkDefs != NULL) {
781 restoreParkedPins();
782 }
783
784 /* if wake source was GPIO, optionally call wakeup function */
785 if (MAP_PRCMLPDSWakeupCauseGet() == PRCM_LPDS_GPIO) {
786 if (PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDS != NULL) {
787 (*(PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDS))
788 (PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDSArg);
789 }
790 }
791
792 /* now clear the transition state before re-enabling scheduler */
793 PowerCC32XX_module.state = Power_ACTIVE;
794 }
795 else {
796 status = Power_EBUSY;
797 }
798
799 return (status);
800 }
801
802 /*
803 * ======== Power_unregisterNotify ========
804 * Unregister for a power notification.
805 *
806 */
Power_unregisterNotify(Power_NotifyObj * pNotifyObj)807 void Power_unregisterNotify(Power_NotifyObj * pNotifyObj)
808 {
809 uintptr_t key;
810
811 /* disable interrupts */
812 key = HwiP_disable();
813
814 /* remove notify object from its event queue */
815 List_remove(&PowerCC32XX_module.notifyList, (List_Elem *)pNotifyObj);
816
817 /* re-enable interrupts */
818 HwiP_restore(key);
819
820 DebugP_log1("Power: unregister notify (%p)", (uintptr_t) pNotifyObj);
821 }
822
823 /*********************** CC32XX-specific functions **************************/
824
825 /*
826 * ======== PowerCC32XX_configureWakeup ========
827 * Configure LPDS and shutdown wakeups; copy settings into driver state
828 */
PowerCC32XX_configureWakeup(PowerCC32XX_Wakeup * wakeup)829 void PowerCC32XX_configureWakeup(PowerCC32XX_Wakeup *wakeup)
830 {
831 /* configure network (Host IRQ) as wakeup source for LPDS */
832 if (wakeup->enableNetworkWakeupLPDS) {
833 MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_HOST_IRQ);
834 }
835 else {
836 MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_HOST_IRQ);
837 }
838 PowerCC32XX_module.wakeupConfig.enableNetworkWakeupLPDS =
839 wakeup->enableNetworkWakeupLPDS;
840
841 /* configure GPIO as wakeup source for LPDS */
842 if (wakeup->enableGPIOWakeupLPDS) {
843 MAP_PRCMLPDSWakeUpGPIOSelect(
844 wakeup->wakeupGPIOSourceLPDS,
845 wakeup->wakeupGPIOTypeLPDS);
846 MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_GPIO);
847 }
848 else {
849 MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO);
850 }
851 PowerCC32XX_module.wakeupConfig.enableGPIOWakeupLPDS =
852 wakeup->enableGPIOWakeupLPDS;
853 PowerCC32XX_module.wakeupConfig.wakeupGPIOSourceLPDS =
854 wakeup->wakeupGPIOSourceLPDS;
855 PowerCC32XX_module.wakeupConfig.wakeupGPIOTypeLPDS =
856 wakeup->wakeupGPIOTypeLPDS;
857
858 /* configure GPIO as wakeup source for Shutdown */
859 if (wakeup->enableGPIOWakeupShutdown) {
860 MAP_PRCMHibernateWakeUpGPIOSelect(
861 wakeup->wakeupGPIOSourceShutdown,
862 wakeup->wakeupGPIOTypeShutdown);
863 MAP_PRCMHibernateWakeupSourceEnable(
864 wakeup->wakeupGPIOSourceShutdown);
865 }
866 else {
867 MAP_PRCMHibernateWakeupSourceDisable(
868 wakeup->wakeupGPIOSourceShutdown);
869 }
870 PowerCC32XX_module.wakeupConfig.enableGPIOWakeupShutdown =
871 wakeup->enableGPIOWakeupShutdown;
872 PowerCC32XX_module.wakeupConfig.wakeupGPIOSourceShutdown =
873 wakeup->wakeupGPIOSourceShutdown;
874 PowerCC32XX_module.wakeupConfig.wakeupGPIOTypeShutdown =
875 wakeup->wakeupGPIOTypeShutdown;
876
877 /* copy the LPDS GPIO wakeup function and arg to module state */
878 PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDS =
879 wakeup->wakeupGPIOFxnLPDS;
880 PowerCC32XX_module.wakeupConfig.wakeupGPIOFxnLPDSArg =
881 wakeup->wakeupGPIOFxnLPDSArg;
882 }
883
884 /*
885 * ======== PowerCC32XX_disableIORetention ========
886 * Disable IO retention and unlock pins after exit from Shutdown
887 */
PowerCC32XX_disableIORetention(unsigned long groupFlags)888 void PowerCC32XX_disableIORetention(unsigned long groupFlags)
889 {
890 MAP_PRCMIORetentionDisable(groupFlags);
891 }
892
893 /*
894 * ======== PowerCC32XX_getParkState ========
895 * Get the current LPDS park state for a pin
896 */
PowerCC32XX_getParkState(PowerCC32XX_Pin pin)897 PowerCC32XX_ParkState PowerCC32XX_getParkState(PowerCC32XX_Pin pin)
898 {
899 PowerCC32XX_ParkInfo parkInfo;
900 PowerCC32XX_ParkState state = PowerCC32XX_DONT_PARK;
901 uint32_t i;
902
903 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
904
905 /* step thru the pin park array until find the pin */
906 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
907
908 parkInfo = PowerCC32XX_config.pinParkDefs[i];
909
910 /* if this is the pin to be checked... */
911 if (parkInfo.pin == pin) {
912 state = (PowerCC32XX_ParkState) parkInfo.parkState;
913 break;
914 }
915 }
916
917 return (state);
918 }
919
920 /*
921 * ======== PowerCC32XX_getWakeup ========
922 * Get the current LPDS and shutdown wakeup configuration
923 */
PowerCC32XX_getWakeup(PowerCC32XX_Wakeup * wakeup)924 void PowerCC32XX_getWakeup(PowerCC32XX_Wakeup *wakeup)
925 {
926 *wakeup = PowerCC32XX_module.wakeupConfig;
927 }
928
929 /*
930 * ======== PowerCC32XX_parkPin ========
931 * Park a device pin in preparation for LPDS
932 */
PowerCC32XX_parkPin(PowerCC32XX_Pin pin,PowerCC32XX_ParkState parkState,uint32_t * previousType,uint16_t * previousDirection)933 void PowerCC32XX_parkPin(PowerCC32XX_Pin pin, PowerCC32XX_ParkState parkState,
934 uint32_t * previousType, uint16_t * previousDirection)
935 {
936 unsigned long strength;
937 unsigned long type;
938
939 /* get the current pin configuration */
940 MAP_PinConfigGet(pin, &strength, &type);
941
942 /* stash the current pin type */
943 *previousType = type;
944
945 /* get and stash the current pin direction */
946 *previousDirection = (uint16_t)MAP_PinDirModeGet(pin);
947
948 /* set pin type to the parking state */
949 MAP_PinConfigSet(pin, strength, (unsigned long) parkState);
950
951 /* set pin direction to input to HiZ the pin */
952 MAP_PinDirModeSet(pin, PIN_DIR_MODE_IN);
953 }
954
955 /*
956 * ======== PowerCC32XX_restoreParkedPin ========
957 * Restore a pin that was previously parked with PowerCC32XX_parkPin
958 */
PowerCC32XX_restoreParkedPin(PowerCC32XX_Pin pin,uint32_t type,uint16_t direction)959 void PowerCC32XX_restoreParkedPin(PowerCC32XX_Pin pin, uint32_t type,
960 uint16_t direction)
961 {
962 unsigned long strength;
963 unsigned long currentType;
964
965 /* get the current pin configuration */
966 MAP_PinConfigGet(pin, &strength, ¤tType);
967
968 /* restore the pin type */
969 MAP_PinConfigSet(pin, strength, type);
970
971 /* restore the pin direction */
972 MAP_PinDirModeSet(pin, (unsigned long)direction);
973 }
974
975 /*
976 * ======== PowerCC32XX_restoreParkState ========
977 * Restore the LPDS park state for a pin
978 */
PowerCC32XX_restoreParkState(PowerCC32XX_Pin pin,PowerCC32XX_ParkState state)979 void PowerCC32XX_restoreParkState(PowerCC32XX_Pin pin,
980 PowerCC32XX_ParkState state)
981 {
982 PowerCC32XX_ParkInfo parkInfo;
983 uint32_t i;
984
985 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
986
987 /* step thru the park array until find the pin to be updated */
988 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
989
990 parkInfo = PowerCC32XX_config.pinParkDefs[i];
991
992 /* if this is the pin to be restored... */
993 if (parkInfo.pin == pin) {
994 parkInfo.parkState = state;
995 PowerCC32XX_config.pinParkDefs[i] = parkInfo;
996 break;
997 }
998 }
999 }
1000
1001 /*
1002 * ======== PowerCC32XX_setParkState ========
1003 * Set a new LPDS park state for a pin
1004 */
PowerCC32XX_setParkState(PowerCC32XX_Pin pin,uint32_t level)1005 void PowerCC32XX_setParkState(PowerCC32XX_Pin pin, uint32_t level)
1006 {
1007 PowerCC32XX_ParkInfo parkInfo;
1008 PowerCC32XX_ParkState state;
1009 uint32_t i;
1010
1011 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
1012
1013 /* first check if level indicates "don't park" */
1014 if (level == ~1) {
1015 state = PowerCC32XX_DONT_PARK;
1016 }
1017
1018 /* else, check device revision to choose park state */
1019 /* if ES2.00 or later, drive the pin */
1020 else if((HWREG(0x00000400) & 0xFFFF) >= 2) {
1021 state = (level) ? PowerCC32XX_DRIVE_HIGH : PowerCC32XX_DRIVE_LOW;
1022 }
1023 /* else, for earlier devices use the weak pull resistor */
1024 else {
1025 state = (level) ? PowerCC32XX_WEAK_PULL_UP_STD :
1026 PowerCC32XX_WEAK_PULL_DOWN_STD;
1027 }
1028
1029 /* step thru the park array until find the pin to be updated */
1030 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
1031
1032 parkInfo = PowerCC32XX_config.pinParkDefs[i];
1033
1034 /* if this is the pin to be updated... */
1035 if (parkInfo.pin == pin) {
1036 parkInfo.parkState = state;
1037 PowerCC32XX_config.pinParkDefs[i] = parkInfo;
1038 break;
1039 }
1040 }
1041 }
1042
1043 /*
1044 * ======== PowerCC32XX_shutdownSSPI ========
1045 * Put SPI flash into Deep Power Down mode
1046 */
PowerCC32XX_shutdownSSPI(void)1047 void PowerCC32XX_shutdownSSPI(void)
1048 {
1049 unsigned long status = 0;
1050
1051 /* Acquire SSPI HwSpinlock. */
1052 if (0 != MAP_HwSpinLockTryAcquire(HWSPINLOCK_SSPI, PowerCC32XX_SSPISemaphoreTakeTries)){
1053 return;
1054 }
1055
1056 /* Gate MCSPI clock */
1057 HWREG(ARCM_BASE + APPS_RCM_O_MCSPI_S0_CLK_GATING) = 0x0;
1058
1059 /* Enable clock for SSPI module */
1060 MAP_PRCMPeripheralClkEnable(PRCM_SSPI, PRCM_RUN_MODE_CLK);
1061
1062 /* Reset SSPI at PRCM level and wait for reset to complete */
1063 MAP_PRCMPeripheralReset(PRCM_SSPI);
1064 while(MAP_PRCMPeripheralStatusGet(PRCM_SSPI)== false){
1065 }
1066
1067 /* Reset SSPI at module level */
1068 MAP_SPIReset(SSPI_BASE);
1069
1070 /* Configure SSPI module */
1071 MAP_SPIConfigSetExpClk(SSPI_BASE,PRCMPeripheralClockGet(PRCM_SSPI),
1072 20000000,SPI_MODE_MASTER,SPI_SUB_MODE_0,
1073 (SPI_SW_CTRL_CS |
1074 SPI_4PIN_MODE |
1075 SPI_TURBO_OFF |
1076 SPI_CS_ACTIVELOW |
1077 SPI_WL_8));
1078
1079 /* Enable SSPI module */
1080 MAP_SPIEnable(SSPI_BASE);
1081
1082 /* Ungate MCSPI clock */
1083 HWREG(ARCM_BASE + APPS_RCM_O_MCSPI_S0_CLK_GATING) = 0x1;
1084
1085 /* Allow settling before enabling chip select */
1086 uSEC_DELAY(PowerCC32XX_SSPICSDelay);
1087
1088 /* Enable chip select for the spi flash. */
1089 MAP_SPICSEnable(SSPI_BASE);
1090
1091 /* Wait for spi flash. */
1092 do{
1093 /* Send status register read instruction and read back a dummy byte. */
1094 MAP_SPIDataPut(SSPI_BASE,PowerCC32XX_SSPIReadStatusInstruction);
1095 MAP_SPIDataGet(SSPI_BASE,&status);
1096
1097 /* Write a dummy byte then read back the actual status. */
1098 MAP_SPIDataPut(SSPI_BASE,0xFF);
1099 MAP_SPIDataGet(SSPI_BASE,&status);
1100 } while((status & 0xFF )== STATUS_BUSY);
1101
1102 /* Disable chip select for the spi flash. */
1103 MAP_SPICSDisable(SSPI_BASE);
1104
1105 /* Start another CS enable sequence for Power down command. */
1106 MAP_SPICSEnable(SSPI_BASE);
1107
1108 /* Send Deep Power Down command to spi flash */
1109 MAP_SPIDataPut(SSPI_BASE,PowerCC32XX_SSPIPowerDownInstruction);
1110
1111 /* Disable chip select for the spi flash. */
1112 MAP_SPICSDisable(SSPI_BASE);
1113
1114 /* Release SSPI HwSpinlock. */
1115 MAP_HwSpinLockRelease(HWSPINLOCK_SSPI);
1116
1117 return;
1118 }
1119
1120 /*
1121 * ======== PowerCC32XX_reset ========
1122 * Software reset of specific peripheral.
1123 */
PowerCC32XX_reset(uint_fast16_t resourceId)1124 int_fast16_t PowerCC32XX_reset(uint_fast16_t resourceId)
1125 {
1126 int_fast16_t status = Power_SOK;
1127 uint32_t id;
1128
1129 /* Ensure resourceId is valid */
1130 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
1131 status = Power_EINVALIDINPUT;
1132 }
1133
1134 /* resourceId is OK ... */
1135 else {
1136
1137 id = PowerCC32XX_module.dbRecords[resourceId];
1138 /* Reset the peripheral */
1139 MAP_PRCMPeripheralReset(id);
1140 }
1141 return (status);
1142 }
1143
1144 /*************************internal functions ****************************/
1145
1146 /*
1147 * ======== notify ========
1148 * Note: When this function is called hardware interrupts are disabled
1149 */
notify(uint_fast16_t eventType)1150 static int_fast16_t notify(uint_fast16_t eventType)
1151 {
1152 int_fast16_t notifyStatus;
1153 Power_NotifyFxn notifyFxn;
1154 uintptr_t clientArg;
1155 List_Elem *elem;
1156
1157 /* if queue is empty, return immediately */
1158 if (!List_empty(&PowerCC32XX_module.notifyList)) {
1159 /* point to first client notify object */
1160 elem = List_head(&PowerCC32XX_module.notifyList);
1161
1162 /* walk the queue and notify each registered client of the event */
1163 do {
1164 if (((Power_NotifyObj *)elem)->eventTypes & eventType) {
1165 /* pull params from notify object */
1166 notifyFxn = ((Power_NotifyObj *)elem)->notifyFxn;
1167 clientArg = ((Power_NotifyObj *)elem)->clientArg;
1168
1169 /* call the client's notification function */
1170 notifyStatus = (int_fast16_t) (*(Power_NotifyFxn)notifyFxn)(
1171 eventType, 0, clientArg);
1172
1173 /* if client declared error stop all further notifications */
1174 if (notifyStatus != Power_NOTIFYDONE) {
1175 return (Power_EFAIL);
1176 }
1177 }
1178
1179 /* get next element in the notification queue */
1180 elem = List_next(elem);
1181
1182 } while (elem != NULL);
1183 }
1184
1185 return (Power_SOK);
1186 }
1187
1188 /*
1189 * ======== restoreNVICRegs ========
1190 * Restore the NVIC registers
1191 */
restoreNVICRegs(void)1192 static void restoreNVICRegs(void)
1193 {
1194 uint32_t i;
1195 uint32_t *base_reg_addr;
1196
1197 /* Restore the NVIC control registers */
1198 HWREG(NVIC_VTABLE) = PowerCC32XX_contextSave.nvicRegs.vectorTable;
1199 HWREG(NVIC_ACTLR) = PowerCC32XX_contextSave.nvicRegs.auxCtrl;
1200 HWREG(NVIC_APINT) = PowerCC32XX_contextSave.nvicRegs.appInt;
1201 HWREG(NVIC_INT_CTRL) = PowerCC32XX_contextSave.nvicRegs.intCtrlState;
1202 HWREG(NVIC_SYS_CTRL) = PowerCC32XX_contextSave.nvicRegs.sysCtrl;
1203 HWREG(NVIC_CFG_CTRL) = PowerCC32XX_contextSave.nvicRegs.configCtrl;
1204 HWREG(NVIC_SYS_PRI1) = PowerCC32XX_contextSave.nvicRegs.sysPri1;
1205 HWREG(NVIC_SYS_PRI2) = PowerCC32XX_contextSave.nvicRegs.sysPri2;
1206 HWREG(NVIC_SYS_PRI3) = PowerCC32XX_contextSave.nvicRegs.sysPri3;
1207 HWREG(NVIC_SYS_HND_CTRL) = PowerCC32XX_contextSave.nvicRegs.sysHcrs;
1208
1209 /* Systick registers */
1210 HWREG(NVIC_ST_CTRL) = PowerCC32XX_contextSave.nvicRegs.systickCtrl;
1211 HWREG(NVIC_ST_RELOAD) = PowerCC32XX_contextSave.nvicRegs.systickReload;
1212 HWREG(NVIC_ST_CAL) = PowerCC32XX_contextSave.nvicRegs.systickCalib;
1213
1214 /* Restore the interrupt priority registers */
1215 base_reg_addr = (uint32_t *)NVIC_PRI0;
1216 for(i = 0; i < PowerCC32XX_numNVICIntPriority; i++) {
1217 base_reg_addr[i] = PowerCC32XX_contextSave.nvicRegs.intPriority[i];
1218 }
1219
1220 /* Restore the interrupt enable registers */
1221 base_reg_addr = (uint32_t *)NVIC_EN0;
1222 for(i = 0; i < PowerCC32XX_numNVICSetEnableRegs; i++) {
1223 base_reg_addr[i] = PowerCC32XX_contextSave.nvicRegs.intSetEn[i];
1224 }
1225
1226 /* Data and instruction sync barriers */
1227 SYNCBARRIER();
1228 }
1229
1230 /*
1231 * ======== restorePeriphClocks ========
1232 * Restores the peripheral clocks that had dependency set
1233 */
restorePeriphClocks(void)1234 static void restorePeriphClocks(void)
1235 {
1236 uint32_t dependCount;
1237 uint32_t i;
1238
1239 /* need to re-enable peripheral clocks to those with set dependency */
1240 for (i = 0; i < PowerCC32XX_NUMRESOURCES; i++) {
1241 dependCount = Power_getDependencyCount(i);
1242 if (dependCount > 0) {
1243 MAP_PRCMPeripheralClkEnable(PowerCC32XX_module.dbRecords[i],
1244 PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
1245
1246 while(!MAP_PRCMPeripheralStatusGet(PowerCC32XX_module.dbRecords[i])) {
1247 }
1248 }
1249 }
1250 }
1251
1252 /*
1253 * ======== saveNVICRegs ========
1254 * Save away the NVIC registers for LPDS mode.
1255 */
saveNVICRegs(void)1256 static void saveNVICRegs(void)
1257 {
1258 uint32_t i;
1259 uint32_t *base_reg_addr;
1260
1261 /* Save the NVIC control registers */
1262 PowerCC32XX_contextSave.nvicRegs.vectorTable = HWREG(NVIC_VTABLE);
1263 PowerCC32XX_contextSave.nvicRegs.auxCtrl = HWREG(NVIC_ACTLR);
1264 PowerCC32XX_contextSave.nvicRegs.intCtrlState = HWREG(NVIC_INT_CTRL);
1265 PowerCC32XX_contextSave.nvicRegs.appInt = HWREG(NVIC_APINT);
1266 PowerCC32XX_contextSave.nvicRegs.sysCtrl = HWREG(NVIC_SYS_CTRL);
1267 PowerCC32XX_contextSave.nvicRegs.configCtrl = HWREG(NVIC_CFG_CTRL);
1268 PowerCC32XX_contextSave.nvicRegs.sysPri1 = HWREG(NVIC_SYS_PRI1);
1269 PowerCC32XX_contextSave.nvicRegs.sysPri2 = HWREG(NVIC_SYS_PRI2);
1270 PowerCC32XX_contextSave.nvicRegs.sysPri3 = HWREG(NVIC_SYS_PRI3);
1271 PowerCC32XX_contextSave.nvicRegs.sysHcrs = HWREG(NVIC_SYS_HND_CTRL);
1272
1273 /* Systick registers */
1274 PowerCC32XX_contextSave.nvicRegs.systickCtrl = HWREG(NVIC_ST_CTRL);
1275 PowerCC32XX_contextSave.nvicRegs.systickReload = HWREG(NVIC_ST_RELOAD);
1276 PowerCC32XX_contextSave.nvicRegs.systickCalib = HWREG(NVIC_ST_CAL);
1277
1278 /* Save the interrupt enable registers */
1279 base_reg_addr = (uint32_t *)NVIC_EN0;
1280 for (i = 0; i < PowerCC32XX_numNVICSetEnableRegs; i++) {
1281 PowerCC32XX_contextSave.nvicRegs.intSetEn[i] = base_reg_addr[i];
1282 }
1283
1284 /* Save the interrupt priority registers */
1285 base_reg_addr = (uint32_t *)NVIC_PRI0;
1286 for (i = 0; i < PowerCC32XX_numNVICIntPriority; i++) {
1287 PowerCC32XX_contextSave.nvicRegs.intPriority[i] = base_reg_addr[i];
1288 }
1289 }
1290
1291 /*
1292 * ======== parkPins ========
1293 */
parkPins(void)1294 static void parkPins(void)
1295 {
1296 PowerCC32XX_ParkInfo parkInfo;
1297 uint32_t antpadreg;
1298 uint32_t i;
1299
1300 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
1301
1302 /* for each pin in the park array ... */
1303 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
1304
1305 parkInfo = PowerCC32XX_config.pinParkDefs[i];
1306
1307 /* skip this pin if "don't park" is specified */
1308 if (parkInfo.parkState == PowerCC32XX_DONT_PARK) {
1309 continue;
1310 }
1311
1312 /* if this is a special antenna select pin, stash current pad state */
1313 if (parkInfo.pin == PowerCC32XX_PIN29) {
1314 antpadreg = 0x4402E108;
1315 PowerCC32XX_module.stateAntPin29 = (uint16_t) HWREG(antpadreg);
1316 }
1317 else if (parkInfo.pin == PowerCC32XX_PIN30) {
1318 antpadreg = 0x4402E10C;
1319 PowerCC32XX_module.stateAntPin30 = (uint16_t) HWREG(antpadreg);
1320 }
1321 else {
1322 antpadreg = 0;
1323 }
1324
1325 /* if this is antenna select pin, park via direct writes to pad reg */
1326 if (antpadreg != 0) {
1327 HWREG(antpadreg) &= 0xFFFFF0EF; /* first clear bits 4, 8-11 */
1328 if (parkInfo.parkState == PowerCC32XX_NO_PULL_HIZ) {
1329 HWREG(antpadreg) |= 0x00000C00;
1330 }
1331 else if (parkInfo.parkState == PowerCC32XX_WEAK_PULL_UP_STD) {
1332 HWREG(antpadreg) |= 0x00000D00;
1333 }
1334 else if (parkInfo.parkState == PowerCC32XX_WEAK_PULL_DOWN_STD) {
1335 HWREG(antpadreg) |= 0x00000E00;
1336 }
1337 else if (parkInfo.parkState == PowerCC32XX_WEAK_PULL_UP_OPENDRAIN) {
1338 HWREG(antpadreg) |= 0x00000D10;
1339 }
1340 else if (parkInfo.parkState ==
1341 PowerCC32XX_WEAK_PULL_DOWN_OPENDRAIN) {
1342 HWREG(antpadreg) |= 0x00000E10;
1343 }
1344 }
1345
1346 /* else, for all other pins */
1347 else {
1348
1349 /* if pin is NOT to be driven, park it to the specified state... */
1350 if ((parkInfo.parkState != PowerCC32XX_DRIVE_LOW) &&
1351 (parkInfo.parkState != PowerCC32XX_DRIVE_HIGH)) {
1352
1353 PowerCC32XX_parkPin(
1354 (PowerCC32XX_Pin)parkInfo.pin,
1355 (PowerCC32XX_ParkState)parkInfo.parkState,
1356 &PowerCC32XX_module.pinType[i],
1357 &PowerCC32XX_module.pinDir[i]);
1358 }
1359
1360 /*
1361 * else, now check if the pin CAN be driven (pins 45, 53, and 55
1362 * can't be driven)
1363 */
1364 else if ((parkInfo.pin != PowerCC32XX_PIN45) &&
1365 (parkInfo.pin != PowerCC32XX_PIN53) &&
1366 (parkInfo.pin != PowerCC32XX_PIN55)){
1367
1368 /*
1369 * must ensure pin mode is zero; first get/stash current mode,
1370 * then set mode to zero
1371 */
1372 PowerCC32XX_module.pinMode[i] =
1373 (uint8_t)MAP_PinModeGet(parkInfo.pin);
1374 MAP_PinModeSet(parkInfo.pin, 0);
1375
1376 /* if pin is to be driven low, set the lock level to 0 */
1377 if (parkInfo.parkState == PowerCC32XX_DRIVE_LOW) {
1378 MAP_PinLockLevelSet((PowerCC32XX_Pin)parkInfo.pin, 0);
1379 PowerCC32XX_module.pinLockMask |= 1 <<
1380 PinToPadGet(parkInfo.pin);
1381 }
1382
1383 /* else, pin to be driven high, set lock level to 1 */
1384 else {
1385 MAP_PinLockLevelSet((PowerCC32XX_Pin)parkInfo.pin, 1);
1386 PowerCC32XX_module.pinLockMask |= 1 <<
1387 PinToPadGet(parkInfo.pin);
1388 }
1389 }
1390 }
1391 }
1392
1393 /* if any pins are to be driven, lock them now */
1394 if (PowerCC32XX_module.pinLockMask) {
1395 MAP_PinLock(PowerCC32XX_module.pinLockMask);
1396 }
1397 }
1398
1399 /*
1400 * ======== restoreParkedPins ========
1401 */
restoreParkedPins(void)1402 static void restoreParkedPins(void)
1403 {
1404 PowerCC32XX_ParkInfo parkInfo;
1405 uint32_t i;
1406
1407 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
1408
1409 /* first, unlock any locked pins (that were driven high or low) */
1410 if (PowerCC32XX_module.pinLockMask) {
1411 MAP_PinUnlock();
1412 }
1413
1414 /* now, for each pin in the park array ... */
1415 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
1416
1417 parkInfo = PowerCC32XX_config.pinParkDefs[i];
1418
1419 /* skip this pin if "don't park" is specified */
1420 if (parkInfo.parkState == PowerCC32XX_DONT_PARK) {
1421 continue;
1422 }
1423
1424 /* if this is special antenna select pin: restore the saved pad state */
1425 if (parkInfo.pin == PowerCC32XX_PIN29) {
1426 HWREG(0x4402E108) = ((HWREG(0x4402E108) & 0xFFFFF000) |
1427 (PowerCC32XX_module.stateAntPin29 & 0x00000FFF));
1428 }
1429
1430 else if (parkInfo.pin == PowerCC32XX_PIN30) {
1431 HWREG(0x4402E10C) = ((HWREG(0x4402E10C) & 0xFFFFF000) |
1432 (PowerCC32XX_module.stateAntPin30 & 0x00000FFF));
1433 }
1434
1435 /* else if pin was driven during LPDS, restore the pin mode */
1436 else if ((parkInfo.parkState == PowerCC32XX_DRIVE_LOW) ||
1437 (parkInfo.parkState == PowerCC32XX_DRIVE_HIGH)) {
1438 MAP_PinModeSet(parkInfo.pin,
1439 (unsigned long)PowerCC32XX_module.pinMode[i]);
1440 }
1441
1442 /* else, restore all others */
1443 else {
1444 /* if pin parked in a non-driven state, restore type & direction */
1445 if ((parkInfo.parkState != PowerCC32XX_DRIVE_LOW) &&
1446 (parkInfo.parkState != PowerCC32XX_DRIVE_HIGH)) {
1447
1448 PowerCC32XX_restoreParkedPin(
1449 (PowerCC32XX_Pin)parkInfo.pin,
1450 PowerCC32XX_module.pinType[i],
1451 PowerCC32XX_module.pinDir[i]);
1452 }
1453 }
1454 }
1455 }
1456