diff options
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.c | 1087 |
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 | ******************************************************************************/ | ||
13 | AT_QUICKACCESS_SECTION_DATA(static uint32_t oscSettlingTime); | ||
14 | AT_QUICKACCESS_SECTION_DATA(static uint32_t pmicVddcoreRecoveryTime); | ||
15 | AT_QUICKACCESS_SECTION_DATA(static uint32_t lvdChangeFlag); | ||
16 | |||
17 | #define MEGA (1000000U) | ||
18 | |||
19 | const 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 | |||
25 | const 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 | |||
31 | const 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 | |||
37 | const 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 | |||
43 | static 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 | */ | ||
155 | AT_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 | |||
168 | static 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 | |||
193 | void 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 | |||
202 | void 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 | */ | ||
212 | void 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 | */ | ||
221 | void 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 | */ | ||
229 | void 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 | */ | ||
246 | void 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 | */ | ||
255 | uint32_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 | */ | ||
264 | void 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 | */ | ||
273 | void 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 | */ | ||
282 | void 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 | */ | ||
301 | void 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 | |||
311 | void 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 | |||
358 | void 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 | |||
405 | void 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 | */ | ||
451 | bool 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 | |||
520 | void POWER_SetLvdFallingTripVoltage(power_lvd_falling_trip_vol_val_t volt) | ||
521 | { | ||
522 | PMC->LVDCORECTRL = PMC_LVDCORECTRL_LVDCORELVL(volt); | ||
523 | POWER_ApplyPD(); | ||
524 | } | ||
525 | |||
526 | power_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 | |||
532 | AT_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 | |||
541 | AT_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 | |||
557 | AT_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 | |||
618 | AT_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 | |||
629 | AT_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 | |||
637 | AT_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 | |||
729 | void 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 | |||
744 | void 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 | |||
939 | void 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 | |||
976 | void 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 */ | ||
1009 | void 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 | |||
1035 | void 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 | |||
1046 | void 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 | |||
1064 | void 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 */ | ||
1084 | uint32_t POWER_GetLibVersion(void) | ||
1085 | { | ||
1086 | return FSL_POWER_DRIVER_VERSION; | ||
1087 | } | ||