aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT633S/drivers/fsl_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT633S/drivers/fsl_power.c')
-rw-r--r--lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT633S/drivers/fsl_power.c1087
1 files changed, 1087 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT633S/drivers/fsl_power.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT633S/drivers/fsl_power.c
new file mode 100644
index 000000000..e3271fb3e
--- /dev/null
+++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MIMXRT633S/drivers/fsl_power.c
@@ -0,0 +1,1087 @@
1/*
2 * Copyright 2018-2020, NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7#include "fsl_common.h"
8#include "fsl_power.h"
9
10/*******************************************************************************
11 * Variables
12 ******************************************************************************/
13AT_QUICKACCESS_SECTION_DATA(static uint32_t oscSettlingTime);
14AT_QUICKACCESS_SECTION_DATA(static uint32_t pmicVddcoreRecoveryTime);
15AT_QUICKACCESS_SECTION_DATA(static uint32_t lvdChangeFlag);
16
17#define MEGA (1000000U)
18
19const uint32_t powerLowCm33FreqLevel[2][3] = {
20 /* For part 0C - 85C */
21 {220U * MEGA, 150U * MEGA, 70U * MEGA},
22 /* For part -20C - 85C */
23 {215U * MEGA, 140U * MEGA, 60U * MEGA}};
24
25const uint32_t powerLowDspFreqLevel[2][3] = {
26 /* For part 0C - 85C */
27 {375U * MEGA, 260U * MEGA, 115U * MEGA},
28 /* For part -20C - 85C */
29 {355U * MEGA, 235U * MEGA, 95U * MEGA}};
30
31const uint32_t powerFullCm33FreqLevel[2][5] = {
32 /* For part 0C - 85C */
33 {300U * MEGA, 275U * MEGA, 210U * MEGA, 140U * MEGA, 65U * MEGA},
34 /* For part -20C - 85C */
35 {300U * MEGA, 270U * MEGA, 200U * MEGA, 135U * MEGA, 50U * MEGA}};
36
37const uint32_t powerFullDspFreqLevel[2][5] = {
38 /* For part 0C - 85C */
39 {600U * MEGA, 480U * MEGA, 300U * MEGA, 195U * MEGA, 70U * MEGA},
40 /* For part -20C - 85C */
41 {550U * MEGA, 440U * MEGA, 285U * MEGA, 170U * MEGA, 55U * MEGA}};
42
43static const uint32_t powerLdoVoltLevel[5] = {
44 0x32U, /* 1.13V */
45 0x26U, /* 1.0V */
46 0x1DU, /* 0.9V */
47 0x13U, /* 0.8V */
48 0x0AU, /* 0.7V */
49};
50
51/*******************************************************************************
52 * Definitions
53 ******************************************************************************/
54/* Component ID definition, used by tools. */
55#ifndef FSL_COMPONENT_ID
56#define FSL_COMPONENT_ID "platform.drivers.power"
57#endif
58
59#define PCFG0_XBB_MASK (SYSCTL0_PDSLEEPCFG0_RBB_PD_MASK | SYSCTL0_PDSLEEPCFG0_FBB_PD_MASK)
60
61/* DeepSleep PDSLEEP0 */
62#define PCFG0_DEEP_SLEEP \
63 (SYSCTL0_PDSLEEPCFG0_MAINCLK_SHUTOFF_MASK | SYSCTL0_PDSLEEPCFG0_VDDCOREREG_LP_MASK | \
64 SYSCTL0_PDSLEEPCFG0_PMCREF_LP_MASK | SYSCTL0_PDSLEEPCFG0_HVD1V8_PD_MASK | SYSCTL0_PDSLEEPCFG0_PORCORE_LP_MASK | \
65 SYSCTL0_PDSLEEPCFG0_LVDCORE_LP_MASK | SYSCTL0_PDSLEEPCFG0_HVDCORE_PD_MASK | SYSCTL0_PDSLEEPCFG0_RBB_PD_MASK | \
66 SYSCTL0_PDSLEEPCFG0_FBB_PD_MASK | SYSCTL0_PDSLEEPCFG0_SYSXTAL_PD_MASK | SYSCTL0_PDSLEEPCFG0_LPOSC_PD_MASK | \
67 SYSCTL0_PDSLEEPCFG0_SFRO_PD_MASK | SYSCTL0_PDSLEEPCFG0_FFRO_PD_MASK | SYSCTL0_PDSLEEPCFG0_SYSPLLLDO_PD_MASK | \
68 SYSCTL0_PDSLEEPCFG0_SYSPLLANA_PD_MASK | SYSCTL0_PDSLEEPCFG0_AUDPLLLDO_PD_MASK | \
69 SYSCTL0_PDSLEEPCFG0_AUDPLLANA_PD_MASK | SYSCTL0_PDSLEEPCFG0_ADC_PD_MASK | SYSCTL0_PDSLEEPCFG0_ADC_LP_MASK | \
70 SYSCTL0_PDSLEEPCFG0_ADCTEMPSNS_PD_MASK | SYSCTL0_PDSLEEPCFG0_ACMP_PD_MASK | \
71 SYSCTL0_PDSLEEPCFG0_HSPAD0_VDET_LP_MASK | SYSCTL0_PDSLEEPCFG0_HSPAD0_REF_PD_MASK | \
72 SYSCTL0_PDSLEEPCFG0_HSPAD2_VDET_LP_MASK | SYSCTL0_PDSLEEPCFG0_HSPAD2_REF_PD_MASK)
73
74/* DeepSleep PDSLEEP1 */
75#define PCFG1_DEEP_SLEEP \
76 (SYSCTL0_PDSLEEPCFG1_PQ_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_PQ_SRAM_PPD_MASK | \
77 SYSCTL0_PDSLEEPCFG1_FLEXSPI_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_FLEXSPI_SRAM_PPD_MASK | \
78 SYSCTL0_PDSLEEPCFG1_USBHS_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_USBHS_SRAM_PPD_MASK | \
79 SYSCTL0_PDSLEEPCFG1_USDHC0_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_USDHC0_SRAM_PPD_MASK | \
80 SYSCTL0_PDSLEEPCFG1_USDHC1_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_USDHC1_SRAM_PPD_MASK | \
81 SYSCTL0_PDSLEEPCFG1_CASPER_SRAM_APD_MASK | SYSCTL0_PDSLEEPCFG1_CASPER_SRAM_PPD_MASK | \
82 SYSCTL0_PDSLEEPCFG1_DSPCACHE_REGF_APD_MASK | SYSCTL0_PDSLEEPCFG1_DSPCACHE_REGF_PPD_MASK | \
83 SYSCTL0_PDSLEEPCFG1_DSPTCM_REGF_APD_MASK | SYSCTL0_PDSLEEPCFG1_DSPTCM_REGF_PPD_MASK | \
84 SYSCTL0_PDSLEEPCFG1_ROM_PD_MASK | SYSCTL0_PDSLEEPCFG1_SRAM_SLEEP_MASK)
85
86/* DeepSleep PDSLEEP2 */
87#define PCFG2_DEEP_SLEEP 0x3FFFFFFFU
88
89/* DeepSleep PDSLEEP3 */
90#define PCFG3_DEEP_SLEEP 0x3FFFFFFFU
91
92/*System PLL PFD mask*/
93#define SYSPLL0PFD_PFD_MASK \
94 (CLKCTL0_SYSPLL0PFD_PFD0_MASK | CLKCTL0_SYSPLL0PFD_PFD1_MASK | CLKCTL0_SYSPLL0PFD_PFD2_MASK | \
95 CLKCTL0_SYSPLL0PFD_PFD3_MASK)
96#define SYSPLL0PFD_PFD_CLKRDY_MASK \
97 (CLKCTL0_SYSPLL0PFD_PFD0_CLKRDY_MASK | CLKCTL0_SYSPLL0PFD_PFD1_CLKRDY_MASK | CLKCTL0_SYSPLL0PFD_PFD2_CLKRDY_MASK | \
98 CLKCTL0_SYSPLL0PFD_PFD3_CLKRDY_MASK)
99#define SYSPLL0PFD_PFD_CLKGATE_MASK \
100 (CLKCTL0_SYSPLL0PFD_PFD0_CLKGATE_MASK | CLKCTL0_SYSPLL0PFD_PFD1_CLKGATE_MASK | \
101 CLKCTL0_SYSPLL0PFD_PFD2_CLKGATE_MASK | CLKCTL0_SYSPLL0PFD_PFD3_CLKGATE_MASK)
102
103/*Audio PLL PFD mask*/
104#define AUDIOPLL0PFD_PFD_MASK \
105 (CLKCTL1_AUDIOPLL0PFD_PFD0_MASK | CLKCTL1_AUDIOPLL0PFD_PFD1_MASK | CLKCTL1_AUDIOPLL0PFD_PFD2_MASK | \
106 CLKCTL1_AUDIOPLL0PFD_PFD3_MASK)
107#define AUDIOPLL0PFD_PFD_CLKRDY_MASK \
108 (CLKCTL1_AUDIOPLL0PFD_PFD0_CLKRDY_MASK | CLKCTL1_AUDIOPLL0PFD_PFD1_CLKRDY_MASK | \
109 CLKCTL1_AUDIOPLL0PFD_PFD2_CLKRDY_MASK | CLKCTL1_AUDIOPLL0PFD_PFD3_CLKRDY_MASK)
110#define AUDIOPLL0PFD_PFD_CLKGATE_MASK \
111 (CLKCTL1_AUDIOPLL0PFD_PFD0_CLKGATE_MASK | CLKCTL1_AUDIOPLL0PFD_PFD1_CLKGATE_MASK | \
112 CLKCTL1_AUDIOPLL0PFD_PFD2_CLKGATE_MASK | CLKCTL1_AUDIOPLL0PFD_PFD3_CLKGATE_MASK)
113
114#define IS_SYSPLL_ON(pdruncfg) \
115 (((pdruncfg) & (SYSCTL0_PDRUNCFG0_SYSPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_SYSPLLANA_PD_MASK)) == 0U)
116#define IS_AUDPLL_ON(pdruncfg) \
117 (((pdruncfg) & (SYSCTL0_PDRUNCFG0_AUDPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_AUDPLLANA_PD_MASK)) == 0U)
118
119/* CPU running at 12 or 15 MHz, max 15 instructions per us, each loop includes 4 instructions. max 4 loops per us. */
120#define US2LOOP(x) ((x) * ((CLKCTL0->FFROCTL0 & CLKCTL0_FFROCTL0_TRIM_RANGE_MASK) == 0U ? 3U : 4U))
121/* Calculate the microsecond period with the maximum CPU frequency 300MHz. */
122#define US2FASTLOOP(x) ((x)*300U / 4U)
123
124#define IS_XIP_FLEXSPI() \
125 ((((uint32_t)POWER_ApplyPD >= 0x08000000U) && ((uint32_t)POWER_ApplyPD < 0x10000000U)) || \
126 (((uint32_t)POWER_ApplyPD >= 0x18000000U) && ((uint32_t)POWER_ApplyPD < 0x20000000U)))
127#define FLEXSPI_DLL_LOCK_RETRY (10U)
128
129#define PMC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(level) \
130 do \
131 { \
132 if (((PMC->LVDCORECTRL & PMC_LVDCORECTRL_LVDCORELVL_MASK) >> PMC_LVDCORECTRL_LVDCORELVL_SHIFT) > \
133 ((uint32_t)(level))) \
134 { \
135 PMC->LVDCORECTRL = PMC_LVDCORECTRL_LVDCORELVL(kLvdFallingTripVol_720); \
136 } \
137 } while (0)
138
139#define PMC_REG(off) (*((volatile uint32_t *)(void *)PMC + (off) / 4))
140
141#define PMU_MIN_CLOCK_MHZ (13U)
142/* Turn on all partitions in parallel.
143 * Be cautious to change the PMC_MEM_SEQ_NUM. To save code size, countPartitionSwitches() counted with 0x3F.
144 */
145#define PMC_MEM_SEQ_NUM (0x3FU)
146
147/*******************************************************************************
148 * Codes
149 ******************************************************************************/
150/*!
151 * @brief Configure bias voltage level and enable/disable pull-down.
152 *
153 * This function change the RBB&FBB voltage level and RBB pull-down.
154 */
155AT_QUICKACCESS_SECTION_CODE(static void POWER_SetBiasConfig(void))
156{
157 if (PMC_REG(0x20) != 0x04040808U)
158 {
159 PMC_REG(0x20) = 0x04040808U;
160 }
161 if (PMC->SLEEPCTRL != PMC_SLEEPCTRL_CORELVL(0xA))
162 {
163 /* Deep sleep core voltage 0.7V */
164 PMC->SLEEPCTRL = PMC_SLEEPCTRL_CORELVL(0xA);
165 }
166}
167
168static uint32_t POWER_CalcVoltLevel(const uint32_t *freqLevels, uint32_t num, uint32_t freq)
169{
170 uint32_t i;
171 uint32_t volt;
172
173 for (i = 0U; i < num; i++)
174 {
175 if (freq > freqLevels[i])
176 {
177 break;
178 }
179 }
180
181 if (i == 0U) /* Frequency exceed max supported */
182 {
183 volt = POWER_INVALID_VOLT_LEVEL;
184 }
185 else
186 {
187 volt = powerLdoVoltLevel[i + ARRAY_SIZE(powerLdoVoltLevel) - num - 1U];
188 }
189
190 return volt;
191}
192
193void POWER_DisableLVD(void)
194{
195 if ((PMC->CTRL & (PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK)) != 0U)
196 {
197 lvdChangeFlag = PMC->CTRL & (PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
198 PMC->CTRL &= ~(PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
199 }
200}
201
202void POWER_RestoreLVD(void)
203{
204 PMC->CTRL |= lvdChangeFlag & (PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
205 lvdChangeFlag = 0;
206}
207
208/**
209 * @brief API to update XTAL oscillator settling time .
210 * @param osc_delay : OSC stabilization time in unit of microsecond
211 */
212void POWER_UpdateOscSettlingTime(uint32_t osc_delay)
213{
214 oscSettlingTime = osc_delay;
215}
216
217/**
218 * @brief API to update on-board PMIC vddcore recovery time.
219 * @param pmic_delay : PMIC stabilization time in unit of microsecond
220 */
221void POWER_UpdatePmicRecoveryTime(uint32_t pmic_delay)
222{
223 pmicVddcoreRecoveryTime = pmic_delay;
224}
225
226/**
227 * @brief API to apply updated PMC PDRUNCFG bits in the Sysctl0.
228 */
229void POWER_ApplyPD(void)
230{
231 /* Cannot set APPLYCFG when ACTIVEFSM is 1 */
232 while ((PMC->STATUS & PMC_STATUS_ACTIVEFSM_MASK) != 0U)
233 {
234 }
235 PMC->CTRL |= PMC_CTRL_APPLYCFG_MASK;
236 /* Wait all PMC finite state machines finished. */
237 while ((PMC->STATUS & PMC_STATUS_ACTIVEFSM_MASK) != 0U)
238 {
239 }
240}
241
242/**
243 * @brief Clears the PMC event flags state.
244 * @param statusMask : A bitmask of event flags that are to be cleared.
245 */
246void POWER_ClearEventFlags(uint32_t statusMask)
247{
248 PMC->FLAGS = statusMask;
249}
250
251/**
252 * @brief Get the PMC event flags state.
253 * @return PMC FLAGS register value
254 */
255uint32_t POWER_GetEventFlags(void)
256{
257 return PMC->FLAGS;
258}
259
260/**
261 * @brief Enable the PMC interrupt requests.
262 * @param interruptMask : A bitmask of of interrupts to enable.
263 */
264void POWER_EnableInterrupts(uint32_t interruptMask)
265{
266 PMC->CTRL |= interruptMask;
267}
268
269/**
270 * @brief Disable the PMC interrupt requests.
271 * @param interruptMask : A bitmask of of interrupts to disable.
272 */
273void POWER_DisableInterrupts(uint32_t interruptMask)
274{
275 PMC->CTRL &= ~interruptMask;
276}
277
278/**
279 * @brief Set the PMC analog buffer for references or ATX2.
280 * @param enable : Set true to enable analog buffer for references or ATX2, false to disable.
281 */
282void POWER_SetAnalogBuffer(bool enable)
283{
284 if (enable)
285 {
286 PMC->CTRL |= PMC_CTRL_BUFEN_MASK;
287 }
288 else
289 {
290 PMC->CTRL &= ~PMC_CTRL_BUFEN_MASK;
291 }
292}
293
294/*!
295 * @brief Configure pad voltage level. Wide voltage range cost more power due to enabled voltage detector.
296 *
297 * NOTE: BE CAUTIOUS TO CALL THIS API. IF THE PAD SUPPLY IS BEYOND THE SET RANGE, SILICON MIGHT BE DAMAGED.
298 *
299 * @param config pad voltage range configuration.
300 */
301void POWER_SetPadVolRange(const power_pad_vrange_t *config)
302{
303 PMC->PADVRANGE = (*((const uint32_t *)(const void *)config)) & 0x3FU;
304}
305
306/**
307 * @brief PMC Enter Rbb mode function call
308 * @return nothing
309 */
310
311void POWER_EnterRbb(void)
312{
313 uint32_t pmsk;
314 bool irqEnabled;
315 uint32_t pmc_ctrl;
316 pmsk = __get_PRIMASK();
317 __disable_irq();
318 POWER_SetBiasConfig();
319 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
320 irqEnabled = NVIC_GetEnableIRQ(PMC_PMIC_IRQn) != 0U;
321 /* MAINCLK_SHUTOFF=1, RBB_PD=0 */
322 SYSCTL0->PDSLEEPCFG0 =
323 (SYSCTL0->PDRUNCFG0 | SYSCTL0_PDSLEEPCFG0_MAINCLK_SHUTOFF_MASK) & ~SYSCTL0_PDSLEEPCFG0_RBB_PD_MASK;
324 SYSCTL0->PDSLEEPCFG1 = SYSCTL0->PDRUNCFG1;
325 SYSCTL0->PDSLEEPCFG2 = SYSCTL0->PDRUNCFG2;
326 SYSCTL0->PDSLEEPCFG3 = SYSCTL0->PDRUNCFG3;
327 SYSCTL0->PDWAKECFG = SYSCTL0_PDWAKECFG_RBBKEEPST_MASK;
328 /* Add PMC count delay before auto wakeup (clocked by the PMC 16MHz oscillator) */
329 PMC->AUTOWKUP = 0x800;
330 /* Disable LVD core reset and eanbel PMC auto wakeup interrupt */
331 pmc_ctrl = PMC->CTRL;
332 PMC->CTRL = (pmc_ctrl | PMC_CTRL_AUTOWKEN_MASK) & ~(PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
333 SYSCTL0->STARTEN1_SET = 1UL << ((uint32_t)PMC_PMIC_IRQn - 32U);
334 if (!irqEnabled)
335 {
336 NVIC_EnableIRQ(PMC_PMIC_IRQn);
337 }
338 __WFI();
339 /* Restore PMC setting, clear interrupt flag */
340 PMC->CTRL = pmc_ctrl;
341 PMC->FLAGS = PMC_FLAGS_AUTOWKF_MASK;
342 SYSCTL0->STARTEN1_CLR = 1UL << ((uint32_t)PMC_PMIC_IRQn - 32U);
343 SYSCTL0->PDWAKECFG = 0;
344 NVIC_ClearPendingIRQ(PMC_PMIC_IRQn);
345 if (!irqEnabled)
346 {
347 /* Recover NVIC state. */
348 NVIC_DisableIRQ(PMC_PMIC_IRQn);
349 }
350 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
351 __set_PRIMASK(pmsk);
352}
353/**
354 * @brief PMC Enter Fbb mode function call
355 * @return nothing
356 */
357
358void POWER_EnterFbb(void)
359{
360 uint32_t pmsk;
361 bool irqEnabled;
362 uint32_t pmc_ctrl;
363 pmsk = __get_PRIMASK();
364 __disable_irq();
365 POWER_SetBiasConfig();
366 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
367 irqEnabled = NVIC_GetEnableIRQ(PMC_PMIC_IRQn) != 0U;
368 /* MAINCLK_SHUTOFF=1, FBB_PD=0 */
369 SYSCTL0->PDSLEEPCFG0 =
370 (SYSCTL0->PDRUNCFG0 | SYSCTL0_PDSLEEPCFG0_MAINCLK_SHUTOFF_MASK) & ~SYSCTL0_PDSLEEPCFG0_FBB_PD_MASK;
371 SYSCTL0->PDSLEEPCFG1 = SYSCTL0->PDRUNCFG1;
372 SYSCTL0->PDSLEEPCFG2 = SYSCTL0->PDRUNCFG2;
373 SYSCTL0->PDSLEEPCFG3 = SYSCTL0->PDRUNCFG3;
374 SYSCTL0->PDWAKECFG = SYSCTL0_PDWAKECFG_FBBKEEPST_MASK;
375 /* Add PMC count delay before auto wakeup (clocked by the PMC 16MHz oscillator) */
376 PMC->AUTOWKUP = 0x800;
377 /* Disable LVD core reset and eanbel PMC auto wakeup interrupt */
378 pmc_ctrl = PMC->CTRL;
379 PMC->CTRL = (pmc_ctrl | PMC_CTRL_AUTOWKEN_MASK) & ~(PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
380 SYSCTL0->STARTEN1_SET = 1UL << ((uint32_t)PMC_PMIC_IRQn - 32U);
381 if (!irqEnabled)
382 {
383 NVIC_EnableIRQ(PMC_PMIC_IRQn);
384 }
385 __WFI();
386 /* Restore PMC setting, clear interrupt flag */
387 PMC->CTRL = pmc_ctrl;
388 PMC->FLAGS = PMC_FLAGS_AUTOWKF_MASK;
389 SYSCTL0->STARTEN1_CLR = 1UL << ((uint32_t)PMC_PMIC_IRQn - 32U);
390 SYSCTL0->PDWAKECFG = 0;
391 NVIC_ClearPendingIRQ(PMC_PMIC_IRQn);
392 if (!irqEnabled)
393 {
394 /* Recover NVIC state. */
395 NVIC_DisableIRQ(PMC_PMIC_IRQn);
396 }
397 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
398 __set_PRIMASK(pmsk);
399}
400/**
401 * @brief PMC exit Rbb & Fbb mode function call
402 * @return nothing
403 */
404
405void POWER_EnterNbb(void)
406{
407 uint32_t pmsk;
408 bool irqEnabled;
409 uint32_t pmc_ctrl;
410 pmsk = __get_PRIMASK();
411 __disable_irq();
412 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
413 irqEnabled = NVIC_GetEnableIRQ(PMC_PMIC_IRQn) != 0U;
414 /* MAINCLK_SHUTOFF=1, RBB_PD=1 FBB_PD=1 */
415 SYSCTL0->PDSLEEPCFG0 = SYSCTL0->PDRUNCFG0 | SYSCTL0_PDSLEEPCFG0_MAINCLK_SHUTOFF_MASK |
416 SYSCTL0_PDSLEEPCFG0_RBB_PD_MASK | SYSCTL0_PDSLEEPCFG0_FBB_PD_MASK;
417 SYSCTL0->PDSLEEPCFG1 = SYSCTL0->PDRUNCFG1;
418 SYSCTL0->PDSLEEPCFG2 = SYSCTL0->PDRUNCFG2;
419 SYSCTL0->PDSLEEPCFG3 = SYSCTL0->PDRUNCFG3;
420 SYSCTL0->PDWAKECFG = SYSCTL0_PDWAKECFG_RBBKEEPST_MASK | SYSCTL0_PDWAKECFG_FBBKEEPST_MASK;
421 /* Add PMC count delay before auto wakeup (clocked by the PMC 16MHz oscillator) */
422 PMC->AUTOWKUP = 0x800;
423 /* Disable LVD core reset and eanbel PMC auto wakeup interrupt */
424 pmc_ctrl = PMC->CTRL;
425 PMC->CTRL = (pmc_ctrl | PMC_CTRL_AUTOWKEN_MASK) & ~(PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
426 SYSCTL0->STARTEN1_SET = 1UL << ((uint32_t)PMC_PMIC_IRQn - 32U);
427 if (!irqEnabled)
428 {
429 NVIC_EnableIRQ(PMC_PMIC_IRQn);
430 }
431 __WFI();
432 /* Restore PMC setting, clear interrupt flag */
433 PMC->CTRL = pmc_ctrl;
434 PMC->FLAGS = PMC_FLAGS_AUTOWKF_MASK;
435 SYSCTL0->STARTEN1_CLR = 1UL << ((uint32_t)PMC_PMIC_IRQn - 32U);
436 SYSCTL0->PDWAKECFG = 0;
437 NVIC_ClearPendingIRQ(PMC_PMIC_IRQn);
438 if (!irqEnabled)
439 {
440 /* Recover NVIC state. */
441 NVIC_DisableIRQ(PMC_PMIC_IRQn);
442 }
443 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
444 __set_PRIMASK(pmsk);
445}
446
447/**
448 * @brief PMC set Ldo volatage function call
449 * @return true for success.
450 */
451bool POWER_SetLdoVoltageForFreq(power_part_temp_range_t tempRange,
452 power_volt_op_range_t voltOpRange,
453 uint32_t cm33Freq,
454 uint32_t dspFreq)
455{
456 uint32_t pmsk;
457 uint32_t idx = (uint32_t)tempRange;
458 uint32_t cm33Volt, dspVolt, volt;
459 bool ret;
460
461 pmsk = __get_PRIMASK();
462 __disable_irq();
463
464 /* Enter FBB mode first */
465 if (POWER_GetBodyBiasMode(kCfg_Run) != kPmu_Fbb)
466 {
467 POWER_EnterFbb();
468 }
469
470 if (voltOpRange == kVoltOpLowRange)
471 {
472 cm33Volt = POWER_CalcVoltLevel(&powerLowCm33FreqLevel[idx][0], 3U, cm33Freq);
473 dspVolt = POWER_CalcVoltLevel(&powerLowDspFreqLevel[idx][0], 3U, dspFreq);
474 }
475 else
476 {
477 cm33Volt = POWER_CalcVoltLevel(&powerFullCm33FreqLevel[idx][0], 5U, cm33Freq);
478 dspVolt = POWER_CalcVoltLevel(&powerFullDspFreqLevel[idx][0], 5U, dspFreq);
479 }
480 volt = MAX(cm33Volt, dspVolt);
481 ret = volt != POWER_INVALID_VOLT_LEVEL;
482
483 if (ret)
484 {
485 if (volt < 0x13U) /* < 0.8V */
486 {
487 POWER_DisableLVD();
488 }
489 else
490 {
491 if (volt < 0x1DU) /* < 0.9V */
492 {
493 PMC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(kLvdFallingTripVol_795);
494 }
495 else if (volt < 0x26U) /* < 1.0V */
496 {
497 PMC_DECREASE_LVD_LEVEL_IF_HIGHER_THAN(kLvdFallingTripVol_885);
498 }
499 else
500 {
501 /* Do nothing */
502 }
503 }
504
505 /* Configure vddcore voltage value */
506 PMC->RUNCTRL = volt;
507 POWER_ApplyPD();
508
509 if (volt >= 0x13U) /* >= 0.8V */
510 {
511 POWER_RestoreLVD();
512 }
513 }
514
515 __set_PRIMASK(pmsk);
516
517 return ret;
518}
519
520void POWER_SetLvdFallingTripVoltage(power_lvd_falling_trip_vol_val_t volt)
521{
522 PMC->LVDCORECTRL = PMC_LVDCORECTRL_LVDCORELVL(volt);
523 POWER_ApplyPD();
524}
525
526power_lvd_falling_trip_vol_val_t POWER_GetLvdFallingTripVoltage(void)
527{
528 return (power_lvd_falling_trip_vol_val_t)((PMC->LVDCORECTRL & PMC_LVDCORECTRL_LVDCORELVL_MASK) >>
529 PMC_LVDCORECTRL_LVDCORELVL_SHIFT);
530}
531
532AT_QUICKACCESS_SECTION_CODE(static void delay(uint32_t count))
533{
534 uint32_t i = 0U;
535 for (i = 0U; i < count; ++i)
536 {
537 __NOP();
538 }
539}
540
541AT_QUICKACCESS_SECTION_CODE(static void deinitXip(void))
542{
543 if (IS_XIP_FLEXSPI())
544 { /* FlexSPI */
545 /* Wait until FLEXSPI is not busy */
546 while (!(((FLEXSPI->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) != 0U) &&
547 ((FLEXSPI->STS0 & FLEXSPI_STS0_SEQIDLE_MASK) != 0U)))
548 {
549 }
550 /* Disable module. */
551 FLEXSPI->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
552 /* Disable clock. */
553 CLKCTL0->PSCCTL0_CLR = CLKCTL0_PSCCTL0_CLR_FLEXSPI_OTFAD_CLK_MASK;
554 }
555}
556
557AT_QUICKACCESS_SECTION_CODE(static void initFlexSPI(FLEXSPI_Type *base))
558{
559 uint32_t status;
560 uint32_t lastStatus;
561 uint32_t retry;
562 uint32_t mask = 0;
563
564 /* Enable FLEXSPI module */
565 base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
566
567 base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK;
568 while ((base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) != 0U)
569 {
570 }
571
572 /* Need to wait DLL locked if DLL enabled */
573 if (0U != (base->DLLCR[0] & FLEXSPI_DLLCR_DLLEN_MASK))
574 {
575 lastStatus = base->STS2;
576 retry = FLEXSPI_DLL_LOCK_RETRY;
577 /* Flash on port A */
578 if (((base->FLSHCR0[0] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0U) ||
579 ((base->FLSHCR0[1] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0U))
580 {
581 mask |= FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK;
582 }
583 /* Flash on port B */
584 if (((base->FLSHCR0[2] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0U) ||
585 ((base->FLSHCR0[3] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0U))
586 {
587 mask |= FLEXSPI_STS2_BREFLOCK_MASK | FLEXSPI_STS2_BSLVLOCK_MASK;
588 }
589 /* Wait slave delay line locked and slave reference delay line locked. */
590 do
591 {
592 status = base->STS2;
593 if ((status & mask) == mask)
594 {
595 /* Locked */
596 retry = 100;
597 break;
598 }
599 else if (status == lastStatus)
600 {
601 /* Same delay cell number in calibration */
602 retry--;
603 }
604 else
605 {
606 retry = FLEXSPI_DLL_LOCK_RETRY;
607 lastStatus = status;
608 }
609 } while (retry > 0U);
610 /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */
611 for (; retry > 0U; retry--)
612 {
613 __NOP();
614 }
615 }
616}
617
618AT_QUICKACCESS_SECTION_CODE(static void initXip(void))
619{
620 if (IS_XIP_FLEXSPI())
621 { /* FlexSPI */
622 /* Enable FLEXSPI clock again */
623 CLKCTL0->PSCCTL0_SET = CLKCTL0_PSCCTL0_SET_FLEXSPI_OTFAD_CLK_MASK;
624 /* Re-enable FLEXSPI module */
625 initFlexSPI(FLEXSPI);
626 }
627}
628
629AT_QUICKACCESS_SECTION_CODE(static uint32_t countPartitionSwitches(uint32_t numPerSwitch))
630{
631 (void)numPerSwitch;
632
633 /* All partitions are turned on in parallel */
634 return 1U;
635}
636
637AT_QUICKACCESS_SECTION_CODE(static uint32_t POWER_CalculateSafetyCount(void))
638{
639 uint32_t ns = 0U;
640 bool flag;
641 uint32_t temp, groups, switches;
642
643 ns += 200U; /* PMU clock startup */
644 ns += 2000U / PMU_MIN_CLOCK_MHZ; /* Wakeup sync */
645 ns += 1000U / PMU_MIN_CLOCK_MHZ; /* Senquencer start */
646 /* Bandgap to HP mode */
647 flag = ((SYSCTL0->PDSLEEPCFG0 & 0x10017D0U) == 0x10017D0U);
648 ns += (flag ? 7000UL : 1000UL) / PMU_MIN_CLOCK_MHZ + (flag ? 9000UL : 0UL);
649
650 if (pmicVddcoreRecoveryTime == 0U)
651 {
652 /* Application uses internal LDO */
653 flag = (SYSCTL0->PDSLEEPCFG0 & 0x10U) == 0x10U;
654 ns += (flag ? 47000UL : 1000UL) / PMU_MIN_CLOCK_MHZ + (flag ? 1000UL : 0UL); /* Core Regulator LP to HP */
655 switches = (PMC->RUNCTRL & PMC_RUNCTRL_CORELVL_MASK) - (PMC->SLEEPCTRL & PMC_SLEEPCTRL_CORELVL_MASK);
656 ns += (switches * 32000U + 1000U) / PMU_MIN_CLOCK_MHZ + switches * 600U; /* Core Regulator Voltage adj */
657 ns += ((SYSCTL0->PDRUNCFG0 & 0x10U) == 0x10U ? 43000UL : 1000UL) / PMU_MIN_CLOCK_MHZ; /* Core Regulator mode */
658 }
659 else
660 {
661 /* Application uses on-board PMIC */
662 ns += 2000U / PMU_MIN_CLOCK_MHZ;
663 if (pmicVddcoreRecoveryTime != PMIC_VDDCORE_RECOVERY_TIME_IGNORE)
664 {
665 /* Application uses on-board PMIC */
666 ns += (((SYSCTL0->PDSLEEPCFG0 & 0x200U) == 0x200U) ? 39000U : 1300U) +
667 pmicVddcoreRecoveryTime * 1000U; /* PMIC vddcore recovery */
668 }
669 }
670
671 ns += 1000U / PMU_MIN_CLOCK_MHZ; /* ISO disable */
672
673 flag = (SYSCTL0->PDSLEEPCFG0 & 0x800U) == 0;
674 ns += (flag ? 6000U : (((SYSCTL0->PDSLEEPCFG0 & 0x1000U) == 0U) ? 88000U : 1000U)) / PMU_MIN_CLOCK_MHZ +
675 (flag ? 26000U : 0U); /* Body Bias disable */
676
677 /* SRAM power switches */
678 groups = (41U + PMC_MEM_SEQ_NUM - 1U) / PMC_MEM_SEQ_NUM;
679 switches = countPartitionSwitches(PMC_MEM_SEQ_NUM);
680 ns += (1000U + 47000U * switches +
681 (((SYSCTL0->PDSLEEPCFG1 & (1UL << 31)) != 0U) ? 8000U : 1000U) * (groups - switches)) /
682 PMU_MIN_CLOCK_MHZ;
683
684 ns += 1000U / PMU_MIN_CLOCK_MHZ; /* Monitor change */
685
686 /* Body Bias change */
687 if (((SYSCTL0->PDRUNCFG0 & 0x800U) == 0U) ||
688 (((SYSCTL0->PDSLEEPCFG0 & 0x800U) == 0U) && ((SYSCTL0->PDWAKECFG & SYSCTL0_PDWAKECFG_RBBKEEPST_MASK) != 0U)))
689 {
690 temp = 5000U;
691 ns += 251000U;
692 }
693 else if (((SYSCTL0->PDRUNCFG0 & 0x1000U) == 0U) ||
694 (((SYSCTL0->PDSLEEPCFG0 & 0x1000U) == 0U) &&
695 ((SYSCTL0->PDWAKECFG & SYSCTL0_PDWAKECFG_FBBKEEPST_MASK) != 0U)))
696 {
697 temp = 312000U;
698 }
699 else
700 {
701 temp = 1000U;
702 }
703 ns += temp / PMU_MIN_CLOCK_MHZ;
704
705 ns += 1000U / PMU_MIN_CLOCK_MHZ; /* ISO change */
706
707 /* Bandgap mode */
708 if (((SYSCTL0->PDRUNCFG0 & 0x10017D0U) == 0x10017D0U) &&
709 (((SYSCTL0->PDSLEEPCFG0 & 0x1000U) == 0x1000U) ||
710 (SYSCTL0->PDWAKECFG & SYSCTL0_PDWAKECFG_FBBKEEPST_MASK) == 0U))
711 {
712 ns += 7000U / PMU_MIN_CLOCK_MHZ + 50U;
713 }
714 else
715 {
716 ns += 1000U / PMU_MIN_CLOCK_MHZ;
717 }
718
719 /* FFRO/4 = 12 or 15MHz depending on trim range. */
720 temp = (CLKCTL0->FFROCTL0 & CLKCTL0_FFROCTL0_TRIM_RANGE_MASK) == 0U ? 12U : 15U;
721 return (ns * temp + 999U) / 1000U;
722}
723
724/**
725 * @brief PMC Sleep function call
726 * @return nothing
727 */
728
729void POWER_EnterSleep(void)
730{
731 uint32_t pmsk;
732 pmsk = __get_PRIMASK();
733 __disable_irq();
734 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
735 __WFI();
736 __set_PRIMASK(pmsk);
737}
738
739/**
740 * @brief PMC Deep Sleep function call
741 * @return nothing
742 */
743
744void POWER_EnterDeepSleep(const uint32_t exclude_from_pd[4])
745{
746 uint32_t cpu_div;
747 uint32_t mainclk_sel[2];
748 uint32_t dspclk_sel[2];
749 uint32_t pmsk = __get_PRIMASK();
750 uint32_t pll_need_pd;
751 uint32_t pll_need_rst[2];
752 uint32_t pfd_need_gate[2];
753 bool dsp_state = false;
754 bool ffro_state = true;
755 uint32_t pmc_ctrl;
756
757 __disable_irq();
758 POWER_SetBiasConfig();
759 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
760
761 mainclk_sel[0] = CLKCTL0->MAINCLKSELA;
762 mainclk_sel[1] = CLKCTL0->MAINCLKSELB;
763 dspclk_sel[0] = CLKCTL1->DSPCPUCLKSELA;
764 dspclk_sel[1] = CLKCTL1->DSPCPUCLKSELB;
765 cpu_div = CLKCTL0->SYSCPUAHBCLKDIV;
766
767 /* Power on mask bit correspond modules during Deep Sleep mode*/
768 SYSCTL0->PDSLEEPCFG0 = (PCFG0_DEEP_SLEEP & ~exclude_from_pd[0]) |
769 (SYSCTL0->PDRUNCFG0 & ~exclude_from_pd[0] &
770 ~(SYSCTL0_PDSLEEPCFG0_PMIC_MODE0_MASK | SYSCTL0_PDSLEEPCFG0_PMIC_MODE1_MASK));
771 SYSCTL0->PDSLEEPCFG1 = (PCFG1_DEEP_SLEEP & ~exclude_from_pd[1]) | (SYSCTL0->PDRUNCFG1 & ~exclude_from_pd[1]);
772 SYSCTL0->PDSLEEPCFG2 = (PCFG2_DEEP_SLEEP & ~exclude_from_pd[2]) | (SYSCTL0->PDRUNCFG2 & ~exclude_from_pd[2]);
773 SYSCTL0->PDSLEEPCFG3 = (PCFG3_DEEP_SLEEP & ~exclude_from_pd[3]) | (SYSCTL0->PDRUNCFG3 & ~exclude_from_pd[3]);
774
775 /* Configuration PMC to respond changes on pdruncfg[2:1] (PMIC mode select pin values) like below:
776 * 0b00 run mode, all supplies on.
777 * 0b01 deep sleep mode, all supplies on.
778 * 0b10 deep powerdown mode, vddcore off.
779 * 0b11 full deep powerdown mode vdd1v8 and vddcore off. */
780 PMC->PMICCFG = 0x73U;
781 /* Set PMIC mode pin as 0b01 to let PMC turn on vdd1v8 and vddcore*/
782 SYSCTL0->PDSLEEPCFG0 |= SYSCTL0_PDSLEEPCFG0_PMIC_MODE0(1) | SYSCTL0_PDSLEEPCFG0_PMIC_MODE1(0);
783
784 /* Stall DSP if shut off main clock*/
785 if (((SYSCTL0->PDSLEEPCFG0 & SYSCTL0_PDSLEEPCFG0_MAINCLK_SHUTOFF_MASK) != 0U) && (SYSCTL0->DSPSTALL == 0U))
786 {
787 SYSCTL0->DSPSTALL = SYSCTL0_DSPSTALL_DSPSTALL_MASK;
788 dsp_state = true;
789 }
790 /* Clear all event flags before enter deep sleep */
791 PMC->FLAGS = PMC->FLAGS;
792 /* Turn on all memory partitions simultaneously. */
793 PMC->MEMSEQCTRL = (PMC->MEMSEQCTRL & ~PMC_MEMSEQCTRL_MEMSEQNUM_MASK) | PMC_MEMSEQCTRL_MEMSEQNUM(PMC_MEM_SEQ_NUM);
794
795 /* Disable LVD core reset. */
796 pmc_ctrl = PMC->CTRL;
797 PMC->CTRL = pmc_ctrl & ~(PMC_CTRL_LVDCORERE_MASK | PMC_CTRL_LVDCOREIE_MASK);
798
799 /* Make sure ffro clock be power up*/
800 if ((SYSCTL0->PDRUNCFG0 & SYSCTL0_PDRUNCFG0_FFRO_PD_MASK) != 0U)
801 {
802 SYSCTL0->PDRUNCFG0_CLR = SYSCTL0_PDRUNCFG0_CLR_FFRO_PD_MASK;
803 ffro_state = false;
804 /* Delay at least 32us */
805 delay(US2FASTLOOP(32U));
806 }
807
808 /* Workaround for artf704338 */
809 if ((SYSCTL0->PDSLEEPCFG0 & SYSCTL0_PDSLEEPCFG0_FFRO_PD_MASK) == 0U)
810 {
811 /* Main clock source FFRO remains on in deep sleep */
812 SYSCTL0->MAINCLKSAFETY = POWER_CalculateSafetyCount();
813 }
814 else
815 {
816 SYSCTL0->MAINCLKSAFETY = 0U;
817 }
818
819 /* Deinit FlexSPI interface in case XIP */
820 deinitXip();
821 /* Let CPU/DSP run on ffro/4 before enter Deep Sleep mode*/
822 CLKCTL0->MAINCLKSELA = CLKCTL0_MAINCLKSELA_SEL(0);
823 CLKCTL0->MAINCLKSELB = CLKCTL0_MAINCLKSELB_SEL(0);
824 CLKCTL1->DSPCPUCLKSELA = CLKCTL1_DSPCPUCLKSELA_SEL(0);
825 CLKCTL1->DSPCPUCLKSELB = CLKCTL1_DSPCPUCLKSELB_SEL(0);
826 CLKCTL0->SYSCPUAHBCLKDIV = 0;
827 while ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_REQFLAG_MASK) != 0U)
828 {
829 }
830
831 /* PLL power down should not rely on PD_SLEEP_CFG auto loading.*/
832 pll_need_pd = (SYSCTL0->PDRUNCFG0 ^ SYSCTL0->PDSLEEPCFG0) &
833 (SYSCTL0_PDRUNCFG0_SYSPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_SYSPLLANA_PD_MASK |
834 SYSCTL0_PDRUNCFG0_AUDPLLLDO_PD_MASK | SYSCTL0_PDRUNCFG0_AUDPLLANA_PD_MASK);
835 pll_need_rst[0] =
836 IS_SYSPLL_ON(pll_need_pd) ? 0U : (CLKCTL0_SYSPLL0CTL0_RESET_MASK | CLKCTL0_SYSPLL0CTL0_HOLDRINGOFF_ENA_MASK);
837 pll_need_rst[1] = IS_AUDPLL_ON(pll_need_pd) ?
838 0U :
839 (CLKCTL1_AUDIOPLL0CTL0_RESET_MASK | CLKCTL1_AUDIOPLL0CTL0_HOLDRINGOFF_ENA_MASK);
840 pfd_need_gate[0] = IS_SYSPLL_ON(pll_need_pd) ? 0U : ((~CLKCTL0->SYSPLL0PFD) & SYSPLL0PFD_PFD_CLKGATE_MASK);
841 pfd_need_gate[1] = IS_AUDPLL_ON(pll_need_pd) ? 0U : ((~CLKCTL1->AUDIOPLL0PFD) & AUDIOPLL0PFD_PFD_CLKGATE_MASK);
842 /* Disable the PFD clock output first. */
843 CLKCTL0->SYSPLL0PFD |= pfd_need_gate[0];
844 CLKCTL1->AUDIOPLL0PFD |= pfd_need_gate[1];
845 /* Set the PLL RESET and HOLDRINGOFF_ENA bits. */
846 CLKCTL0->SYSPLL0CTL0 |= pll_need_rst[0];
847 CLKCTL1->AUDIOPLL0CTL0 |= pll_need_rst[1];
848 /* Power down the PLLs */
849 SYSCTL0->PDRUNCFG0_SET = pll_need_pd;
850
851 /* Enter deep sleep mode */
852 __WFI();
853
854 /* Wait OSC clock stable */
855 if (((SYSCTL0->PDRUNCFG0 ^ SYSCTL0->PDSLEEPCFG0) & SYSCTL0_PDRUNCFG0_SYSXTAL_PD_MASK) != 0U)
856 {
857 delay(US2LOOP(oscSettlingTime));
858 }
859
860 /* Restore PLL state*/
861 if (pll_need_pd != 0U)
862 {
863 /* Power up the PLLs */
864 SYSCTL0->PDRUNCFG0_CLR = pll_need_pd;
865 /* Delay (CLKCTL0-> SYSPLL0LOCKTIMEDIV2 / 2) us */
866 delay(US2LOOP((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 2U));
867
868 /* Clear System & Audio PLL reset with hold ring off enable*/
869 CLKCTL0->SYSPLL0CTL0 &= ~(pll_need_rst[0] & CLKCTL0_SYSPLL0CTL0_RESET_MASK);
870 CLKCTL1->AUDIOPLL0CTL0 &= ~(pll_need_rst[1] & CLKCTL1_AUDIOPLL0CTL0_RESET_MASK);
871 /* Delay (CLKCTL0-> SYSPLL0LOCKTIMEDIV2 / 6) us */
872 delay(US2LOOP((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 6U));
873
874 /* Clear System PLL HOLDRINGOFF_ENA*/
875 CLKCTL0->SYSPLL0CTL0 &= ~(pll_need_rst[0] & CLKCTL0_SYSPLL0CTL0_HOLDRINGOFF_ENA_MASK);
876 /* Clear Audio PLL HOLDRINGOFF_ENA*/
877 CLKCTL1->AUDIOPLL0CTL0 &= ~(pll_need_rst[1] & CLKCTL1_AUDIOPLL0CTL0_HOLDRINGOFF_ENA_MASK);
878 /* Make sure PLL's output is stable, delay (CLKCTL0-> SYSPLL0LOCKTIMEDIV2 / 3) us */
879 delay(US2LOOP((CLKCTL0->SYSPLL0LOCKTIMEDIV2 & CLKCTL0_SYSPLL0LOCKTIMEDIV2_LOCKTIMEDIV2_MASK) / 3U));
880
881 if (pfd_need_gate[0] != 0U)
882 {
883 /* Clear ready status flag and restore PFD output status. */
884 CLKCTL0->SYSPLL0PFD &= ~pfd_need_gate[0];
885 /* Wait for output becomes stable. */
886 while ((CLKCTL0->SYSPLL0PFD & SYSPLL0PFD_PFD_CLKRDY_MASK) != (pfd_need_gate[0] >> 1U))
887 {
888 }
889 }
890
891 if (pfd_need_gate[1] != 0U)
892 {
893 /* Clear ready status flag and restore PFD output status. */
894 CLKCTL1->AUDIOPLL0PFD &= ~pfd_need_gate[1];
895 /* Wait for output becomes stable. */
896 while ((CLKCTL1->AUDIOPLL0PFD & AUDIOPLL0PFD_PFD_CLKRDY_MASK) != (pfd_need_gate[1] >> 1U))
897 {
898 }
899 }
900 }
901
902 /* Restore CPU DIV clock configure*/
903 CLKCTL0->SYSCPUAHBCLKDIV = cpu_div;
904 while ((CLKCTL0->SYSCPUAHBCLKDIV & CLKCTL0_SYSCPUAHBCLKDIV_REQFLAG_MASK) != 0U)
905 {
906 }
907 /* Restore CPU/DSP clock configure*/
908 CLKCTL0->MAINCLKSELA = mainclk_sel[0] & CLKCTL0_MAINCLKSELA_SEL_MASK;
909 CLKCTL0->MAINCLKSELB = mainclk_sel[1] & CLKCTL0_MAINCLKSELB_SEL_MASK;
910 CLKCTL1->DSPCPUCLKSELA = dspclk_sel[0] & CLKCTL1_DSPCPUCLKSELA_SEL_MASK;
911 CLKCTL1->DSPCPUCLKSELB = dspclk_sel[1] & CLKCTL1_DSPCPUCLKSELB_SEL_MASK;
912
913 /* Restore ffro clock state*/
914 if (!ffro_state)
915 {
916 SYSCTL0->PDRUNCFG0_SET = SYSCTL0_PDRUNCFG0_SET_FFRO_PD_MASK;
917 }
918 /* Init FlexSPI in case XIP */
919 initXip();
920
921 /* Restore PMC LVD core reset setting */
922 PMC->CTRL = pmc_ctrl;
923
924 /* Restore DSP stall status */
925 if (dsp_state)
926 {
927 SYSCTL0->DSPSTALL &= ~SYSCTL0_DSPSTALL_DSPSTALL_MASK;
928 }
929
930 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
931 __set_PRIMASK(pmsk);
932}
933
934/**
935 * @brief PMC Deep Sleep Power Down function call
936 * @return nothing
937 */
938
939void POWER_EnterDeepPowerDown(const uint32_t exclude_from_pd[4])
940{
941 uint32_t state;
942
943 state = DisableGlobalIRQ();
944 POWER_EnableDeepSleep();
945
946 /* Set mask bit before enter Deep Power Down mode.*/
947 SYSCTL0->PDSLEEPCFG0 |= (~exclude_from_pd[0] & PCFG0_DEEP_SLEEP);
948 SYSCTL0->PDSLEEPCFG1 |= (~exclude_from_pd[1] & PCFG1_DEEP_SLEEP);
949 SYSCTL0->PDSLEEPCFG2 |= (~exclude_from_pd[2] & PCFG2_DEEP_SLEEP);
950 SYSCTL0->PDSLEEPCFG3 |= (~exclude_from_pd[3] & PCFG3_DEEP_SLEEP);
951
952 /* Set DEEPPD bit in PDSLEEPCFG0*/
953 SYSCTL0->PDSLEEPCFG0 |= SYSCTL0_PDSLEEPCFG0_DEEP_PD_MASK;
954 /* Configuration PMC to respond changes on pdruncfg[2:1] (PMIC mode select pin values) like below:
955 * 0b00 run mode, all supplies on.
956 * 0b01 deep sleep mode, all supplies on.
957 * 0b10 deep powerdown mode, vddcore off.
958 * 0b11 full deep powerdown mode vdd1v8 and vddcore off. */
959 PMC->PMICCFG = 0x73U;
960 /* Set PMIC mode pin as 0b10 to let PMC trun off VDDCORE */
961 POWER_SetPmicMode(0x2U, kCfg_Sleep);
962 /* Clear all event flags before enter deep powerdown */
963 PMC->FLAGS = PMC->FLAGS;
964 /* Enter deep powerdown mode */
965 __WFI();
966
967 /* Note that this code is never reached because we re-boot */
968 EnableGlobalIRQ(state);
969}
970
971/**
972 * @brief PMC Full Deep Sleep Power Down function call
973 * @return nothing
974 */
975
976void POWER_EnterFullDeepPowerDown(const uint32_t exclude_from_pd[4])
977{
978 uint32_t state;
979
980 state = DisableGlobalIRQ();
981 POWER_EnableDeepSleep();
982
983 /* Set mask bit before enter Full Deep Power Down mode.*/
984 SYSCTL0->PDSLEEPCFG0 |= (~exclude_from_pd[0] & PCFG0_DEEP_SLEEP);
985 SYSCTL0->PDSLEEPCFG1 |= (~exclude_from_pd[1] & PCFG1_DEEP_SLEEP);
986 SYSCTL0->PDSLEEPCFG2 |= (~exclude_from_pd[2] & PCFG2_DEEP_SLEEP);
987 SYSCTL0->PDSLEEPCFG3 |= (~exclude_from_pd[3] & PCFG3_DEEP_SLEEP);
988
989 /* Set DEEPPD bit in PDSLEEPCFG0*/
990 SYSCTL0->PDSLEEPCFG0 |= SYSCTL0_PDSLEEPCFG0_DEEP_PD_MASK;
991 /* Configuration PMC to respond changes on pdruncfg[2:1] (PMIC mode select pin values) like below:
992 * 0b00 run mode, all supplies on.
993 * 0b01 deep sleep mode, all supplies on.
994 * 0b10 deep powerdown mode, vddcore off.
995 * 0b11 full deep powerdown mode vdd1v8 and vddcore off. */
996 PMC->PMICCFG = 0x73U;
997 /* Set PMIC mode pin as 0b11 to let PMC trun off VDDCORE and VDD1V8*/
998 POWER_SetPmicMode(0x3U, kCfg_Sleep);
999 /* Clear all event flags before enter full deep powerdown */
1000 PMC->FLAGS = PMC->FLAGS;
1001 /* Enter full deep powerdown mode */
1002 __WFI();
1003
1004 /* Note that this code is never reached because we re-boot */
1005 EnableGlobalIRQ(state);
1006}
1007
1008/* Enter Power mode */
1009void POWER_EnterPowerMode(power_mode_cfg_t mode, const uint32_t exclude_from_pd[4])
1010{
1011 switch (mode)
1012 {
1013 case kPmu_Sleep:
1014 POWER_EnterSleep();
1015 break;
1016
1017 case kPmu_Deep_Sleep:
1018 POWER_EnterDeepSleep(exclude_from_pd);
1019 break;
1020
1021 case kPmu_Deep_PowerDown:
1022 POWER_EnterDeepPowerDown(exclude_from_pd);
1023 break;
1024
1025 case kPmu_Full_Deep_PowerDown:
1026 POWER_EnterFullDeepPowerDown(exclude_from_pd);
1027 break;
1028
1029 default:
1030 assert(false);
1031 break;
1032 }
1033}
1034
1035void POWER_SetPmicMode(uint32_t mode, pmic_mode_reg_t reg)
1036{
1037 __disable_irq();
1038
1039 SYSCTL0_TUPLE_REG(reg) =
1040 (SYSCTL0_TUPLE_REG(reg) & ~(SYSCTL0_PDRUNCFG0_PMIC_MODE1_MASK | SYSCTL0_PDRUNCFG0_PMIC_MODE0_MASK)) |
1041 (mode << SYSCTL0_PDRUNCFG0_PMIC_MODE0_SHIFT);
1042
1043 __enable_irq();
1044}
1045
1046void EnableDeepSleepIRQ(IRQn_Type interrupt)
1047{
1048 uint32_t intNumber = (uint32_t)interrupt;
1049
1050 if (intNumber >= 32U)
1051 {
1052 /* enable interrupt wake up in the STARTEN1 register */
1053 SYSCTL0->STARTEN1_SET = 1UL << (intNumber - 32U);
1054 }
1055 else
1056 {
1057 /* enable interrupt wake up in the STARTEN0 register */
1058 SYSCTL0->STARTEN0_SET = 1UL << intNumber;
1059 }
1060 /* also enable interrupt at NVIC */
1061 (void)EnableIRQ(interrupt);
1062}
1063
1064void DisableDeepSleepIRQ(IRQn_Type interrupt)
1065{
1066 uint32_t intNumber = (uint32_t)interrupt;
1067
1068 /* also disable interrupt at NVIC */
1069 (void)DisableIRQ(interrupt);
1070
1071 if (intNumber >= 32U)
1072 {
1073 /* disable interrupt wake up in the STARTEN1 register */
1074 SYSCTL0->STARTEN1_CLR = 1UL << (intNumber - 32U);
1075 }
1076 else
1077 {
1078 /* disable interrupt wake up in the STARTEN0 register */
1079 SYSCTL0->STARTEN0_CLR = 1UL << intNumber;
1080 }
1081}
1082
1083/* Get power lib version */
1084uint32_t POWER_GetLibVersion(void)
1085{
1086 return FSL_POWER_DRIVER_VERSION;
1087}