2 * Copyright (c) 2015-2016, Texas Instruments Incorporated
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
33 * ======== PowerCC32XX.c ========
39 * By default disable both asserts and log for this module.
40 * This must be done before DebugP.h is included.
42 #ifndef DebugP_ASSERT_ENABLED
43 #define DebugP_ASSERT_ENABLED 0
45 #ifndef DebugP_LOG_ENABLED
46 #define DebugP_LOG_ENABLED 0
48 #include <ti/drivers/dpl/DebugP.h>
49 #include <ti/drivers/dpl/HwiP.h>
51 #include <ti/drivers/utils/List.h>
53 #include <ti/drivers/Power.h>
54 #include <ti/drivers/power/PowerCC32XX.h>
56 #if defined(__IAR_SYSTEMS_ICC__)
57 #include <intrinsics.h>
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>
76 #define STATUS_BUSY 0x01
78 #define PowerCC32XX_SSPIReadStatusInstruction (0x05)
79 #define PowerCC32XX_SSPIPowerDownInstruction (0xB9)
80 #define PowerCC32XX_SSPISemaphoreTakeTries (4000000)
82 #define SYNCBARRIER() { \
88 extern const PowerCC32XX_ConfigV1 PowerCC32XX_config;
91 PowerCC32XX_ModuleState PowerCC32XX_module = {
92 { NULL, NULL}, /* list */
93 0, /* constraintsMask */
94 Power_ACTIVE, /* state */
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 */
124 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
125 /* constraintCounts */
131 /* context save variable */
132 PowerCC32XX_SaveRegisters PowerCC32XX_contextSave;
134 typedef void (*LPDSFunc)(void);
136 /* enter LPDS is an assembly function */
137 extern void PowerCC32XX_enterLPDS(LPDSFunc driverlibFunc);
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,
144 void PowerCC32XX_shutdownSSPI(void);
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);
155 * ======== Power_disablePolicy ========
156 * Do not run the configured policy
158 void Power_disablePolicy(void)
160 PowerCC32XX_module.enablePolicy = FALSE;
162 DebugP_log0("Power: disable policy");
166 * ======== Power_enablePolicy ========
167 * Run the configured policy
169 void Power_enablePolicy(void)
171 PowerCC32XX_module.enablePolicy = TRUE;
173 DebugP_log0("Power: enable policy");
177 * ======== Power_getConstraintMask ========
178 * Get a bitmask indicating the constraints that have been registered with
181 uint_fast32_t Power_getConstraintMask(void)
183 return (PowerCC32XX_module.constraintMask);
187 * ======== Power_getDependencyCount ========
188 * Get the count of dependencies that are currently declared upon a resource.
190 int_fast16_t Power_getDependencyCount(uint_fast16_t resourceId)
194 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
195 status = Power_EINVALIDINPUT;
198 status = PowerCC32XX_module.refCount[resourceId];
205 * ======== Power_getTransitionLatency ========
206 * Get the transition latency for a sleep state. The latency is reported
207 * in units of microseconds.
209 uint_fast32_t Power_getTransitionLatency(uint_fast16_t sleepState,
212 uint32_t latency = 0;
214 if (type == Power_RESUME) {
215 latency = PowerCC32XX_RESUMETIMELPDS;
218 latency = PowerCC32XX_TOTALTIMELPDS;
225 * ======== Power_getTransitionState ========
226 * Get the current sleep transition state.
228 uint_fast16_t Power_getTransitionState(void)
230 return (PowerCC32XX_module.state);
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.
239 void Power_idleFunc()
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))();
251 * ======== Power_init ========
253 int_fast16_t Power_init()
255 /* if this function has already been called, just return */
256 if (PowerCC32XX_module.initialized) {
260 /* set module state field 'initialized' to true */
261 PowerCC32XX_module.initialized = TRUE;
263 /* set the module state enablePolicy field */
264 PowerCC32XX_module.enablePolicy = PowerCC32XX_config.enablePolicy;
266 /* call the config policy init function if its not null */
267 if (PowerCC32XX_config.policyInitFxn != NULL) {
268 (*(PowerCC32XX_config.policyInitFxn))();
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;
291 /* now configure these wakeup settings in the device... */
292 PowerCC32XX_configureWakeup(&PowerCC32XX_module.wakeupConfig);
294 /* copy the Power policy function to module state */
295 PowerCC32XX_module.policyFxn = PowerCC32XX_config.policyFxn;
297 /* spin if too many pins were specified in the pin park array */
298 if (PowerCC32XX_config.numPins > PowerCC32XX_NUMPINS) {
306 * ======== Power_registerNotify ========
307 * Register a function to be called on a specific power event.
309 int_fast16_t Power_registerNotify(Power_NotifyObj * pNotifyObj,
310 uint_fast16_t eventTypes, Power_NotifyFxn notifyFxn, uintptr_t clientArg)
312 int_fast16_t status = Power_SOK;
314 /* check for NULL pointers */
315 if ((pNotifyObj == NULL) || (notifyFxn == NULL)) {
316 status = Power_EINVALIDPOINTER;
320 /* fill in notify object elements */
321 pNotifyObj->eventTypes = eventTypes;
322 pNotifyObj->notifyFxn = notifyFxn;
323 pNotifyObj->clientArg = clientArg;
325 /* place notify object on event notification queue */
326 List_put(&PowerCC32XX_module.notifyList, (List_Elem*)pNotifyObj);
330 "Power: register notify (%p), eventTypes (0x%x), notifyFxn (%p)",
331 (uintptr_t) pNotifyObj, eventTypes, (uintptr_t) notifyFxn);
337 * ======== Power_releaseConstraint ========
338 * Release a previously declared constraint.
340 int_fast16_t Power_releaseConstraint(uint_fast16_t constraintId)
342 int_fast16_t status = Power_SOK;
346 /* first ensure constraintId is valid */
347 if (constraintId >= PowerCC32XX_NUMCONSTRAINTS) {
348 status = Power_EINVALIDINPUT;
351 /* if constraintId is OK ... */
354 /* disable interrupts */
355 key = HwiP_disable();
357 /* get the count of the constraint */
358 count = PowerCC32XX_module.constraintCounts[constraintId];
360 /* ensure constraint count is not already zero */
362 status = Power_EFAIL;
365 /* if not already zero ... */
367 /* decrement the count */
370 /* save the updated count */
371 PowerCC32XX_module.constraintCounts[constraintId] = count;
373 /* if constraint count reaches zero, remove constraint from mask */
375 PowerCC32XX_module.constraintMask &= ~(1 << constraintId);
379 /* restore interrupts */
382 DebugP_log1("Power: release constraint (%d)", constraintId);
389 * ======== Power_releaseDependency ========
390 * Release a previously declared dependency.
392 int_fast16_t Power_releaseDependency(uint_fast16_t resourceId)
394 int_fast16_t status = Power_SOK;
399 /* first check that resourceId is valid */
400 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
401 status = Power_EINVALIDINPUT;
404 /* if resourceId is OK ... */
407 /* disable interrupts */
408 key = HwiP_disable();
410 /* read the reference count */
411 count = PowerCC32XX_module.refCount[resourceId];
413 /* ensure dependency count is not already zero */
415 status = Power_EFAIL;
418 /* if not already zero ... */
421 /* decrement the reference count */
424 /* if this was the last dependency being released.., */
426 /* deactivate this resource ... */
427 id = PowerCC32XX_module.dbRecords[resourceId];
429 /* disable clk to peripheral */
430 MAP_PRCMPeripheralClkDisable(id,
431 PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
434 /* save the updated count */
435 PowerCC32XX_module.refCount[resourceId] = count;
438 /* restore interrupts */
441 DebugP_log1("Power: release dependency (%d)", resourceId);
448 * ======== Power_setConstraint ========
449 * Declare an operational constraint.
451 int_fast16_t Power_setConstraint(uint_fast16_t constraintId)
453 int_fast16_t status = Power_SOK;
456 /* ensure that constraintId is valid */
457 if (constraintId >= PowerCC32XX_NUMCONSTRAINTS) {
458 status = Power_EINVALIDINPUT;
463 /* disable interrupts */
464 key = HwiP_disable();
466 /* set the specified constraint in the constraintMask */
467 PowerCC32XX_module.constraintMask |= 1 << constraintId;
469 /* increment the specified constraint count */
470 PowerCC32XX_module.constraintCounts[constraintId]++;
472 /* restore interrupts */
475 DebugP_log1("Power: set constraint (%d)", constraintId);
482 * ======== Power_setDependency ========
483 * Declare a dependency upon a resource.
485 int_fast16_t Power_setDependency(uint_fast16_t resourceId)
487 int_fast16_t status = Power_SOK;
492 /* ensure resourceId is valid */
493 if (resourceId >= PowerCC32XX_NUMRESOURCES) {
494 status = Power_EINVALIDINPUT;
497 /* resourceId is OK ... */
500 /* disable interrupts */
501 key = HwiP_disable();
503 /* read and increment reference count */
504 count = PowerCC32XX_module.refCount[resourceId]++;
506 /* if resource was NOT activated previously ... */
508 /* now activate this resource ... */
509 id = PowerCC32XX_module.dbRecords[resourceId];
511 /* enable the peripheral clock to the resource */
512 MAP_PRCMPeripheralClkEnable(id,
513 PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
515 /* spin here until status returns TRUE */
516 while(!MAP_PRCMPeripheralStatusGet(id)) {
520 /* restore interrupts */
522 DebugP_log1("Power: set dependency (%d)", resourceId);
529 * ======== Power_setPolicy ========
530 * Set the Power policy function
532 void Power_setPolicy(Power_PolicyFxn policy)
534 PowerCC32XX_module.policyFxn = policy;
538 * ======== Power_shutdown ========
540 int_fast16_t Power_shutdown(uint_fast16_t shutdownState,
541 uint_fast32_t shutdownTime)
543 int_fast16_t status = Power_EFAIL;
544 uint32_t constraints;
548 /* disable interrupts */
549 hwiKey = HwiP_disable();
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;
557 if (PowerCC32XX_module.state == Power_ACTIVE) {
558 /* set new transition state to entering shutdown */
559 PowerCC32XX_module.state = Power_ENTERING_SHUTDOWN;
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);
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 */
575 (((uint64_t)(shutdownTime -
576 (PowerCC32XX_TOTALTIMESHUTDOWN / 1000))
579 /* set the hibernate wakeup time */
580 MAP_PRCMHibernateIntervalSet(counts);
582 /* enable the wake source to be RTC */
583 MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
586 /* enable IO retention */
587 if (PowerCC32XX_config.ioRetentionShutdown) {
588 MAP_PRCMIORetentionEnable(
589 PowerCC32XX_config.ioRetentionShutdown);
593 "Power: entering shutdown state (%d), shutdownTime (%d)",
594 shutdownState, shutdownTime);
596 /* enter hibernate - we should never return from here */
597 MAP_PRCMHibernateEnter();
600 status = Power_EBUSY;
604 /* set state to Power_ACTIVE */
605 PowerCC32XX_module.state = Power_ACTIVE;
607 /* re-enable interrupts */
608 HwiP_restore(hwiKey);
610 /* if get here, failed to shutdown, return error code */
615 * ======== Power_sleep ========
617 int_fast16_t Power_sleep(uint_fast16_t sleepState)
619 int_fast16_t status = Power_SOK;
620 uint32_t romMajorVer;
621 uint32_t romMinorVer;
626 /* first validate the sleep state */
627 if (sleepState != PowerCC32XX_LPDS) {
628 status = Power_EINVALIDINPUT;
631 else if (PowerCC32XX_module.state == Power_ACTIVE) {
633 /* set transition state to entering sleep */
634 PowerCC32XX_module.state = Power_ENTERING_SLEEP;
636 /* setup sleep vars */
637 preEvent = PowerCC32XX_ENTERING_LPDS;
638 postEvent = PowerCC32XX_AWAKE_LPDS;
640 /* signal all clients registered for pre-sleep notification */
641 status = notify(preEvent);
643 /* check for timeout or any other error */
644 if (status != Power_SOK) {
645 PowerCC32XX_module.state = Power_ACTIVE;
649 DebugP_log1("Power: sleep, sleepState (%d)", sleepState);
651 /* invoke specific sequence to activate LPDS ...*/
653 /* enable RAM retention */
654 MAP_PRCMSRAMRetentionEnable(
655 PowerCC32XX_config.ramRetentionMaskLPDS,
658 /* call the enter LPDS hook function if configured */
659 if (PowerCC32XX_config.enterLPDSHookFxn != NULL) {
660 (*(PowerCC32XX_config.enterLPDSHookFxn))();
663 /* park pins, based upon board file definitions */
664 if (PowerCC32XX_config.pinParkDefs != NULL) {
668 /* save the NVIC registers */
671 /* check if PG >= 2.01 */
672 romMajorVer = HWREG(0x00000400) & 0xFFFF;
673 romMinorVer = HWREG(0x00000400) >> 16;
674 if ((romMajorVer >= 3) || ((romMajorVer == 2) && (romMinorVer >= 1))) {
678 /* call sync barrier */
681 /* now enter LPDS - function does not return... */
682 if (PowerCC32XX_config.keepDebugActiveDuringLPDS == TRUE) {
684 PowerCC32XX_enterLPDS(PRCMLPDSEnterKeepDebugIf);
687 PowerCC32XX_enterLPDS(ROM_PRCMLPDSEnterKeepDebugIfDirect);
692 PowerCC32XX_enterLPDS(PRCMLPDSEnter);
695 PowerCC32XX_enterLPDS(ROM_PRCMLPDSEnterDirect);
699 /* return here after reset, from Power_resumeLPDS() */
701 /* restore NVIC registers */
704 /* restore clock to those peripherals with dependecy set */
705 restorePeriphClocks();
707 /* call PRCMCC3200MCUInit() for any necessary post-LPDS restore */
708 MAP_PRCMCC3200MCUInit();
710 /* call the resume LPDS hook function if configured */
711 if (PowerCC32XX_config.resumeLPDSHookFxn != NULL) {
712 (*(PowerCC32XX_config.resumeLPDSHookFxn))();
715 /* re-enable Slow Clock Counter Interrupt */
716 MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
718 /* set transition state to EXITING_SLEEP */
719 PowerCC32XX_module.state = Power_EXITING_SLEEP;
722 * signal clients registered for post-sleep notification; for example,
723 * a driver that needs to reinitialize its peripheral state, that was
726 status = notify(postEvent);
728 /* restore pins parked before LPDS to their previous states */
729 if (PowerCC32XX_config.pinParkDefs != NULL) {
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);
741 /* now clear the transition state before re-enabling scheduler */
742 PowerCC32XX_module.state = Power_ACTIVE;
745 status = Power_EBUSY;
752 * ======== Power_unregisterNotify ========
753 * Unregister for a power notification.
756 void Power_unregisterNotify(Power_NotifyObj * pNotifyObj)
760 /* disable interrupts */
761 key = HwiP_disable();
763 /* remove notify object from its event queue */
764 List_remove(&PowerCC32XX_module.notifyList, (List_Elem *)pNotifyObj);
766 /* re-enable interrupts */
769 DebugP_log1("Power: unregister notify (%p)", (uintptr_t) pNotifyObj);
772 /*********************** CC32XX-specific functions **************************/
775 * ======== PowerCC32XX_configureWakeup ========
776 * Configure LPDS and shutdown wakeups; copy settings into driver state
778 void PowerCC32XX_configureWakeup(PowerCC32XX_Wakeup *wakeup)
780 /* configure network (Host IRQ) as wakeup source for LPDS */
781 if (wakeup->enableNetworkWakeupLPDS) {
782 MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_HOST_IRQ);
785 MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_HOST_IRQ);
787 PowerCC32XX_module.wakeupConfig.enableNetworkWakeupLPDS =
788 wakeup->enableNetworkWakeupLPDS;
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);
798 MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO);
800 PowerCC32XX_module.wakeupConfig.enableGPIOWakeupLPDS =
801 wakeup->enableGPIOWakeupLPDS;
802 PowerCC32XX_module.wakeupConfig.wakeupGPIOSourceLPDS =
803 wakeup->wakeupGPIOSourceLPDS;
804 PowerCC32XX_module.wakeupConfig.wakeupGPIOTypeLPDS =
805 wakeup->wakeupGPIOTypeLPDS;
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);
816 MAP_PRCMHibernateWakeupSourceDisable(
817 wakeup->wakeupGPIOSourceShutdown);
819 PowerCC32XX_module.wakeupConfig.enableGPIOWakeupShutdown =
820 wakeup->enableGPIOWakeupShutdown;
821 PowerCC32XX_module.wakeupConfig.wakeupGPIOSourceShutdown =
822 wakeup->wakeupGPIOSourceShutdown;
823 PowerCC32XX_module.wakeupConfig.wakeupGPIOTypeShutdown =
824 wakeup->wakeupGPIOTypeShutdown;
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;
834 * ======== PowerCC32XX_disableIORetention ========
835 * Disable IO retention and unlock pins after exit from Shutdown
837 void PowerCC32XX_disableIORetention(unsigned long groupFlags)
839 MAP_PRCMIORetentionDisable(groupFlags);
843 * ======== PowerCC32XX_getWakeup ========
844 * Get the current LPDS and shutdown wakeup configuration
846 void PowerCC32XX_getWakeup(PowerCC32XX_Wakeup *wakeup)
848 *wakeup = PowerCC32XX_module.wakeupConfig;
852 * ======== PowerCC32XX_parkPin ========
853 * Park a device pin in preparation for LPDS
855 void PowerCC32XX_parkPin(PowerCC32XX_Pin pin, PowerCC32XX_ParkState parkState,
856 uint32_t * previousType, uint16_t * previousDirection)
858 unsigned long strength;
861 /* get the current pin configuration */
862 MAP_PinConfigGet(pin, &strength, &type);
864 /* stash the current pin type */
865 *previousType = type;
867 /* get and stash the current pin direction */
868 *previousDirection = (uint16_t)MAP_PinDirModeGet(pin);
870 /* set pin type to the parking state */
871 MAP_PinConfigSet(pin, strength, (unsigned long) parkState);
873 /* set pin direction to input to HiZ the pin */
874 MAP_PinDirModeSet(pin, PIN_DIR_MODE_IN);
878 * ======== PowerCC32XX_restoreParkedPin ========
879 * Restore a pin that was previously parked with PowerCC32XX_parkPin
881 void PowerCC32XX_restoreParkedPin(PowerCC32XX_Pin pin, uint32_t type,
884 unsigned long strength;
885 unsigned long currentType;
887 /* get the current pin configuration */
888 MAP_PinConfigGet(pin, &strength, ¤tType);
890 /* restore the pin type */
891 MAP_PinConfigSet(pin, strength, type);
893 /* restore the pin direction */
894 MAP_PinDirModeSet(pin, (unsigned long)direction);
898 * ======== PowerCC32XX_setParkState ========
899 * Set a new LPDS park state for a pin
901 void PowerCC32XX_setParkState(PowerCC32XX_Pin pin, uint32_t level)
903 PowerCC32XX_ParkInfo parkInfo;
904 PowerCC32XX_ParkState state;
907 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
909 /* if ES2.00 or later, drive the pin */
910 if((HWREG(0x00000400) & 0xFFFF) >= 2) {
911 state = (level) ? PowerCC32XX_DRIVE_HIGH : PowerCC32XX_DRIVE_LOW;
913 /* else, for earlier devices use the weak pull resistor */
915 state = (level) ? PowerCC32XX_WEAK_PULL_UP_STD :
916 PowerCC32XX_WEAK_PULL_DOWN_STD;
919 /* step thru the park array until find the pin to be updated */
920 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
922 parkInfo = PowerCC32XX_config.pinParkDefs[i];
924 /* if this is the pin to be updated... */
925 if (parkInfo.pin == pin) {
926 parkInfo.parkState = state;
927 PowerCC32XX_config.pinParkDefs[i] = parkInfo;
933 * ======== PowerCC32XX_shutdownSSPI ========
934 * Put SPI flash into Deep Power Down mode
936 void PowerCC32XX_shutdownSSPI(void)
938 unsigned long status = 0;
940 /* Acquire SSPI HwSpinlock. */
941 if (0 != MAP_HwSpinLockTryAcquire(HWSPINLOCK_SSPI, PowerCC32XX_SSPISemaphoreTakeTries)){
945 /* Enable clock for SSPI module */
946 MAP_PRCMPeripheralClkEnable(PRCM_SSPI, PRCM_RUN_MODE_CLK);
948 /* Reset SSPI at PRCM level and wait for reset to complete */
949 MAP_PRCMPeripheralReset(PRCM_SSPI);
950 while(MAP_PRCMPeripheralStatusGet(PRCM_SSPI)== false){
953 /* Reset SSPI at module level */
954 MAP_SPIReset(SSPI_BASE);
956 /* Configure SSPI module */
957 MAP_SPIConfigSetExpClk(SSPI_BASE,PRCMPeripheralClockGet(PRCM_SSPI),
958 20000000,SPI_MODE_MASTER,SPI_SUB_MODE_0,
965 /* Enable SSPI module */
966 MAP_SPIEnable(SSPI_BASE);
968 /* Enable chip select for the spi flash. */
969 MAP_SPICSEnable(SSPI_BASE);
971 /* Wait for spi flash. */
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);
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);
982 /* Disable chip select for the spi flash. */
983 MAP_SPICSDisable(SSPI_BASE);
985 /* Start another CS enable sequence for Power down command. */
986 MAP_SPICSEnable(SSPI_BASE);
988 /* Send Deep Power Down command to spi flash */
989 MAP_SPIDataPut(SSPI_BASE,PowerCC32XX_SSPIPowerDownInstruction);
991 /* Disable chip select for the spi flash. */
992 MAP_SPICSDisable(SSPI_BASE);
994 /* Release SSPI HwSpinlock. */
995 MAP_HwSpinLockRelease(HWSPINLOCK_SSPI);
1000 /*************************internal functions ****************************/
1003 * ======== notify ========
1004 * Note: When this function is called hardware interrupts are disabled
1006 static int_fast16_t notify(uint_fast16_t eventType)
1008 int_fast16_t notifyStatus;
1009 Power_NotifyFxn notifyFxn;
1010 uintptr_t clientArg;
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);
1018 /* walk the queue and notify each registered client of the event */
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;
1025 /* call the client's notification function */
1026 notifyStatus = (int_fast16_t) (*(Power_NotifyFxn)notifyFxn)(
1027 eventType, 0, clientArg);
1029 /* if client declared error stop all further notifications */
1030 if (notifyStatus != Power_NOTIFYDONE) {
1031 return (Power_EFAIL);
1035 /* get next element in the notification queue */
1036 elem = List_next(elem);
1038 } while (elem != NULL);
1045 * ======== restoreNVICRegs ========
1046 * Restore the NVIC registers
1048 static void restoreNVICRegs(void)
1051 uint32_t *base_reg_addr;
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;
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;
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];
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];
1082 /* Data and instruction sync barriers */
1087 * ======== restorePeriphClocks ========
1088 * Restores the peripheral clocks that had dependency set
1090 static void restorePeriphClocks(void)
1092 uint32_t dependCount;
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);
1102 while(!MAP_PRCMPeripheralStatusGet(PowerCC32XX_module.dbRecords[i])) {
1109 * ======== saveNVICRegs ========
1110 * Save away the NVIC registers for LPDS mode.
1112 static void saveNVICRegs(void)
1115 uint32_t *base_reg_addr;
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);
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);
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];
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];
1148 * ======== parkPins ========
1150 static void parkPins(void)
1152 PowerCC32XX_ParkInfo parkInfo;
1156 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
1158 /* for each pin in the park array ... */
1159 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
1161 parkInfo = PowerCC32XX_config.pinParkDefs[i];
1163 /* skip this pin if "don't park" is specified */
1164 if (parkInfo.parkState == PowerCC32XX_DONT_PARK) {
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);
1173 else if (parkInfo.pin == PowerCC32XX_PIN30) {
1174 antpadreg = 0x4402E10C;
1175 PowerCC32XX_module.stateAntPin30 = (uint16_t) HWREG(antpadreg);
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;
1187 else if (parkInfo.parkState == PowerCC32XX_WEAK_PULL_UP_STD) {
1188 HWREG(antpadreg) |= 0x00000D00;
1190 else if (parkInfo.parkState == PowerCC32XX_WEAK_PULL_DOWN_STD) {
1191 HWREG(antpadreg) |= 0x00000E00;
1193 else if (parkInfo.parkState == PowerCC32XX_WEAK_PULL_UP_OPENDRAIN) {
1194 HWREG(antpadreg) |= 0x00000D10;
1196 else if (parkInfo.parkState ==
1197 PowerCC32XX_WEAK_PULL_DOWN_OPENDRAIN) {
1198 HWREG(antpadreg) |= 0x00000E10;
1202 /* else, for all other pins */
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)) {
1209 PowerCC32XX_parkPin(
1210 (PowerCC32XX_Pin)parkInfo.pin,
1211 (PowerCC32XX_ParkState)parkInfo.parkState,
1212 &PowerCC32XX_module.pinType[i],
1213 &PowerCC32XX_module.pinDir[i]);
1217 * else, now check if the pin CAN be driven (pins 45, 53, and 55
1220 else if ((parkInfo.pin != PowerCC32XX_PIN45) &&
1221 (parkInfo.pin != PowerCC32XX_PIN53) &&
1222 (parkInfo.pin != PowerCC32XX_PIN55)){
1225 * must ensure pin mode is zero; first get/stash current mode,
1226 * then set mode to zero
1228 PowerCC32XX_module.pinMode[i] =
1229 (uint8_t)MAP_PinModeGet(parkInfo.pin);
1230 MAP_PinModeSet(parkInfo.pin, 0);
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);
1239 /* else, pin to be driven high, set lock level to 1 */
1241 MAP_PinLockLevelSet((PowerCC32XX_Pin)parkInfo.pin, 1);
1242 PowerCC32XX_module.pinLockMask |= 1 <<
1243 PinToPadGet(parkInfo.pin);
1249 /* if any pins are to be driven, lock them now */
1250 if (PowerCC32XX_module.pinLockMask) {
1251 MAP_PinLock(PowerCC32XX_module.pinLockMask);
1256 * ======== restoreParkedPins ========
1258 static void restoreParkedPins(void)
1260 PowerCC32XX_ParkInfo parkInfo;
1263 DebugP_assert(PowerCC32XX_config.numPins < PowerCC32XX_NUMPINS + 1);
1265 /* first, unlock any locked pins (that were driven high or low) */
1266 if (PowerCC32XX_module.pinLockMask) {
1270 /* now, for each pin in the park array ... */
1271 for (i = 0; i < PowerCC32XX_config.numPins; i++) {
1273 parkInfo = PowerCC32XX_config.pinParkDefs[i];
1275 /* skip this pin if "don't park" is specified */
1276 if (parkInfo.parkState == PowerCC32XX_DONT_PARK) {
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));
1286 else if (parkInfo.pin == PowerCC32XX_PIN30) {
1287 HWREG(0x4402E10C) = ((HWREG(0x4402E10C) & 0xFFFFF000) |
1288 (PowerCC32XX_module.stateAntPin30 & 0x00000FFF));
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]);
1298 /* else, restore all others */
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)) {
1304 PowerCC32XX_restoreParkedPin(
1305 (PowerCC32XX_Pin)parkInfo.pin,
1306 PowerCC32XX_module.pinType[i],
1307 PowerCC32XX_module.pinDir[i]);