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