1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016, NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #include "fsl_common.h"
9 #include "fsl_power.h"
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.power"
13 #endif
14
15 /*******************************************************************************
16 * Variables
17 ******************************************************************************/
18
19 /*******************************************************************************
20 * Definitions
21 ******************************************************************************/
22 /** @brief Low Power main structure */
23 typedef enum
24 {
25 VD_AON = 0x0, /*!< Digital Always On power domain */
26 VD_MEM = 0x1, /*!< Memories (SRAM) power domain */
27 VD_DCDC = 0x2, /*!< Core logic power domain */
28 VD_DEEPSLEEP = 0x3 /*!< Core logic power domain */
29 } LPC_POWER_DOMAIN_T;
30
31 /**
32 * @brief LDO_FLASH_NV & LDO_USB voltage settings
33 */
34 typedef enum _v_flashnv
35 {
36 V_LDOFLASHNV_1P650 = 0, /*!< 0.95 V */
37 V_LDOFLASHNV_1P700 = 1, /*!< 0.975 V */
38 V_LDOFLASHNV_1P750 = 2, /*!< 1 V */
39 V_LDOFLASHNV_0P800 = 3, /*!< 1.025 V */
40 V_LDOFLASHNV_1P850 = 4, /*!< 1.050 V */
41 V_LDOFLASHNV_1P900 = 5, /*!< 1.075 V */
42 V_LDOFLASHNV_1P950 = 6, /*!< 1.1 V */
43 V_LDOFLASHNV_2P000 = 7 /*!< 1.125 V */
44 } v_flashnv_t;
45
46 /** @brief Low Power main structure */
47 typedef struct
48 { /* */
49 __IO uint32_t CFG; /*!< Low Power Mode Configuration, and miscallenous options */
50 __IO uint32_t PDCTRL0; /*!< Power Down control : controls power of various modules
51 in the different Low power modes, including ROM */
52 __IO uint32_t SRAMRETCTRL; /*!< Power Down control : controls power SRAM instances
53 in the different Low power modes */
54 __IO uint32_t CPURETCTRL; /*!< CPU0 retention control : controls CPU retention parameters in POWER DOWN modes */
55 __IO uint64_t VOLTAGE; /*!< Voltage control in Low Power Modes */
56 __IO uint64_t WAKEUPSRC; /*!< Wake up sources control for sleepcon */
57 __IO uint64_t WAKEUPINT; /*!< Wake up sources control for ARM */
58 __IO uint32_t HWWAKE; /*!< Interrupt that can postpone power down modes
59 in case an interrupt is pending when the processor request deepsleep */
60 __IO uint32_t WAKEUPIOSRC; /*!< Wake up I/O sources in DEEP POWER DOWN mode */
61 __IO uint32_t TIMERCFG; /*!< Wake up timers configuration */
62 __IO uint32_t TIMERCOUNT; /*!< Wake up Timer count*/
63 __IO uint32_t POWERCYCLE; /*!< Cancels entry in Low Power mode if set with 0xDEADABBA (might be used by some
64 interrupt handlers)*/
65 } LPC_LOWPOWER_T;
66
67 /* */
68 #define LOWPOWER_POWERCYCLE_CANCELLED 0xDEADABBAUL /*!< */
69
70 /**
71 * @brief SRAM Low Power Modes
72 */
73 #define LOWPOWER_SRAM_LPMODE_MASK (0xFUL)
74 #define LOWPOWER_SRAM_LPMODE_ACTIVE (0x6UL) /*!< SRAM functional mode */
75 #define LOWPOWER_SRAM_LPMODE_SLEEP (0xFUL) /*!< SRAM Sleep mode (Data retention, fast wake up) */
76 #define LOWPOWER_SRAM_LPMODE_DEEPSLEEP (0x8UL) /*!< SRAM Deep Sleep mode (Data retention, slow wake up) */
77 #define LOWPOWER_SRAM_LPMODE_SHUTDOWN (0x9UL) /*!< SRAM Shut Down mode (no data retention) */
78 #define LOWPOWER_SRAM_LPMODE_POWERUP (0xAUL) /*!< SRAM is powering up */
79
80 /**
81 * @brief Wake up timers configuration in Low Power Modes
82 */
83 #define LOWPOWER_TIMERCFG_CTRL_INDEX 0
84 #define LOWPOWER_TIMERCFG_CTRL_MASK (0x1UL << LOWPOWER_TIMERCFG_CTRL_INDEX)
85 #define LOWPOWER_TIMERCFG_TIMER_INDEX 1
86 #define LOWPOWER_TIMERCFG_TIMER_MASK (0x7UL << LOWPOWER_TIMERCFG_TIMER_INDEX)
87 #define LOWPOWER_TIMERCFG_OSC32K_INDEX 4
88 #define LOWPOWER_TIMERCFG_OSC32K_MASK (0x1UL << LOWPOWER_TIMERCFG_OSC32K_INDEX)
89
90 #define LOWPOWER_TIMERCFG_CTRL_DISABLE 0 /*!< Wake Timer Disable */
91 #define LOWPOWER_TIMERCFG_CTRL_ENABLE 1 /*!< Wake Timer Enable */
92
93 /**
94 * @brief Primary Wake up timers configuration in Low Power Modes
95 */
96 #define LOWPOWER_TIMERCFG_TIMER_RTC1KHZ 0 /*!< 1 KHz Real Time Counter (RTC) used as wake up source */
97 #define LOWPOWER_TIMERCFG_TIMER_RTC1HZ 1 /*!< 1 Hz Real Time Counter (RTC) used as wake up source */
98 #define LOWPOWER_TIMERCFG_TIMER_OSTIMER 2 /*!< OS Event Timer used as wake up source */
99
100 #define LOWPOWER_TIMERCFG_OSC32K_FRO32KHZ 0 /*!< Wake up Timers uses FRO 32 KHz as clock source */
101 #define LOWPOWER_TIMERCFG_OSC32K_XTAL32KHZ 1 /*!< Wake up Timers uses Chrystal 32 KHz as clock source */
102
103 //! @brief Interface for lowpower functions
104 typedef struct LowpowerDriverInterface
105 {
106 void (*power_cycle_cpu_and_flash)(void);
107 void (*set_lowpower_mode)(LPC_LOWPOWER_T *p_lowpower_cfg);
108 } lowpower_driver_interface_t;
109
110 /**< DCDC Power Profiles */
111 typedef enum
112 {
113 DCDC_POWER_PROFILE_LOW, /**< LOW (for CPU frequencies below DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ) */
114 DCDC_POWER_PROFILE_MEDIUM, /**< MEDIUM (for CPU frequencies between DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ and
115 DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ) */
116 DCDC_POWER_PROFILE_HIGH, /**< HIGH (for CPU frequencies between DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ and
117 DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ) */
118 } lowpower_dcdc_power_profile_enum;
119
120 /**< Manufacturing Process Corners */
121 typedef enum
122 {
123 PROCESS_CORNER_SSS, /**< Slow Corner Process */
124 PROCESS_CORNER_NNN, /**< Nominal Corner Process */
125 PROCESS_CORNER_FFF, /**< Fast Corner Process */
126 PROCESS_CORNER_OTHERS, /**< SFN, SNF, NFS, Poly Res ... Corner Process */
127 } lowpower_process_corner_enum;
128
129 /**
130 * @brief DCDC voltage settings
131 */
132 typedef enum _v_dcdc
133 {
134 V_DCDC_0P950 = 0, /*!< 0.95 V */
135 V_DCDC_0P975 = 1, /*!< 0.975 V */
136 V_DCDC_1P000 = 2, /*!< 1 V */
137 V_DCDC_1P025 = 3, /*!< 1.025 V */
138 V_DCDC_1P050 = 4, /*!< 1.050 V */
139 V_DCDC_1P075 = 5, /*!< 1.075 V */
140 V_DCDC_1P100 = 6, /*!< 1.1 V */
141 V_DCDC_1P125 = 7, /*!< 1.125 V */
142 V_DCDC_1P150 = 8, /*!< 1.150 V */
143 V_DCDC_1P175 = 9, /*!< 1.175 V */
144 V_DCDC_1P200 = 10 /*!< 1.2 V */
145 } v_dcdc_t;
146
147 /**
148 * @brief Deep Sleep LDO voltage settings
149 */
150 typedef enum _v_deepsleep
151 {
152 V_DEEPSLEEP_0P900 = 0, /*!< 0.9 V */
153 V_DEEPSLEEP_0P925 = 1, /*!< 0.925 V */
154 V_DEEPSLEEP_0P950 = 2, /*!< 0.95 V */
155 V_DEEPSLEEP_0P975 = 3, /*!< 0.975 V */
156 V_DEEPSLEEP_1P000 = 4, /*!< 1.000 V */
157 V_DEEPSLEEP_1P025 = 5, /*!< 1.025 V */
158 V_DEEPSLEEP_1P050 = 6, /*!< 1.050 V */
159 V_DEEPSLEEP_1P075 = 7 /*!< 1.075 V */
160 } v_deepsleep_t;
161
162 /**
163 * @brief Always On and Memories LDO voltage settings
164 */
165 typedef enum _v_ao
166 {
167 V_AO_0P700 = 1, /*!< 0.7 V */
168 V_AO_0P725 = 2, /*!< 0.725 V */
169 V_AO_0P750 = 3, /*!< 0.75 V */
170 V_AO_0P775 = 4, /*!< 0.775 V */
171 V_AO_0P800 = 5, /*!< 0.8 V */
172 V_AO_0P825 = 6, /*!< 0.825 V */
173 V_AO_0P850 = 7, /*!< 0.85 V */
174 V_AO_0P875 = 8, /*!< 0.875 V */
175 V_AO_0P900 = 9, /*!< 0.9 V */
176 V_AO_0P960 = 10, /*!< 0.96 V */
177 V_AO_0P970 = 11, /*!< 0.97 V */
178 V_AO_0P980 = 12, /*!< 0.98 V */
179 V_AO_0P990 = 13, /*!< 0.99 V */
180 V_AO_1P000 = 14, /*!< 1 V */
181 V_AO_1P010 = 15, /*!< 1.01 V */
182 V_AO_1P020 = 16, /*!< 1.02 V */
183 V_AO_1P030 = 17, /*!< 1.03 V */
184 V_AO_1P040 = 18, /*!< 1.04 V */
185 V_AO_1P050 = 19, /*!< 1.05 V */
186 V_AO_1P060 = 20, /*!< 1.06 V */
187 V_AO_1P070 = 21, /*!< 1.07 V */
188 V_AO_1P080 = 22, /*!< 1.08 V */
189 V_AO_1P090 = 23, /*!< 1.09 V */
190 V_AO_1P100 = 24, /*!< 1.1 V */
191 V_AO_1P110 = 25, /*!< 1.11 V */
192 V_AO_1P120 = 26, /*!< 1.12 V */
193 V_AO_1P130 = 27, /*!< 1.13 V */
194 V_AO_1P140 = 28, /*!< 1.14 V */
195 V_AO_1P150 = 29, /*!< 1.15 V */
196 V_AO_1P160 = 30, /*!< 1.16 V */
197 V_AO_1P220 = 31 /*!< 1.22 V */
198 } v_ao_t;
199
200 /* Low Power modes */
201 #define LOWPOWER_CFG_LPMODE_INDEX 0
202 #define LOWPOWER_CFG_LPMODE_MASK (0x3UL << LOWPOWER_CFG_LPMODE_INDEX)
203 #define LOWPOWER_CFG_SELCLOCK_INDEX 2
204 #define LOWPOWER_CFG_SELCLOCK_MASK (0x1UL << LOWPOWER_CFG_SELCLOCK_INDEX)
205 #define LOWPOWER_CFG_SELMEMSUPPLY_INDEX 3
206 #define LOWPOWER_CFG_SELMEMSUPPLY_MASK (0x1UL << LOWPOWER_CFG_SELMEMSUPPLY_INDEX)
207 #define LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX 4
208 #define LOWPOWER_CFG_MEMLOWPOWERMODE_MASK (0x1UL << LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX)
209 #define LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX 5
210 #define LOWPOWER_CFG_LDODEEPSLEEPREF_MASK (0x1UL << LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX)
211
212 #define LOWPOWER_CFG_LPMODE_ACTIVE 0 /*!< ACTIVE mode */
213 #define LOWPOWER_CFG_LPMODE_DEEPSLEEP 1 /*!< DEEP SLEEP mode */
214 #define LOWPOWER_CFG_LPMODE_POWERDOWN 2 /*!< POWER DOWN mode */
215 #define LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN 3 /*!< DEEP POWER DOWN mode */
216 #define LOWPOWER_CFG_LPMODE_SLEEP 4 /*!< SLEEP mode */
217
218 #define LOWPOWER_CFG_SELCLOCK_1MHZ 0 /*!< The 1 MHz clock is used during the configuration of the PMC */
219 #define LOWPOWER_CFG_SELCLOCK_12MHZ \
220 1 /*!< The 12 MHz clock is used during the configuration of the PMC (to speed up PMC configuration process)*/
221
222 #define LOWPOWER_CFG_SELMEMSUPPLY_LDOMEM 0 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_MEM */
223 #define LOWPOWER_CFG_SELMEMSUPPLY_LDODEEPSLEEP \
224 1 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_DEEP_SLEEP (or DCDC) */
225
226 #define LOWPOWER_CFG_MEMLOWPOWERMODE_SOURCEBIASING \
227 0 /*!< All SRAM instances use "Source Biasing" as low power mode technic (it is recommended to set LDO_MEM as high \
228 as possible -- 1.1V typical -- during low power mode) */
229 #define LOWPOWER_CFG_MEMLOWPOWERMODE_VOLTAGESCALING \
230 1 /*!< All SRAM instances use "Voltage Scaling" as low power mode technic (it is recommended to set LDO_MEM as low \
231 as possible -- down to 0.7V -- during low power mode) */
232
233 #define LOWPOWER_CFG_LDODEEPSLEEPREF_FLASHBUFFER 0 /*!< LDO DEEP SLEEP uses Flash Buffer as reference */
234 #define LOWPOWER_CFG_LDODEEPSLEEPREF_BANDGAG0P8V 1 /*!< LDO DEEP SLEEP uses Band Gap 0.8V as reference */
235
236 /* CPU Retention Control*/
237 #define LOWPOWER_CPURETCTRL_ENA_INDEX 0
238 #define LOWPOWER_CPURETCTRL_ENA_MASK (0x1UL << LOWPOWER_CPURETCTRL_ENA_INDEX)
239 #define LOWPOWER_CPURETCTRL_MEMBASE_INDEX 1
240 #define LOWPOWER_CPURETCTRL_MEMBASE_MASK (0x1FFFUL << LOWPOWER_CPURETCTRL_MEMBASE_INDEX)
241 #define LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX 14
242 #define LOWPOWER_CPURETCTRL_RETDATALENGTH_MASK (0x3FFUL << LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX)
243
244 /* Voltgae setting*/
245 #define DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ \
246 (100000000U) /* Maximum System Frequency allowed with DCDC Power Profile LOW */
247 #define DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ \
248 (130000000U) /* Maximum System Frequency allowed with DCDC Power Profile MEDIUM */
249 #define DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ \
250 (150000000U) /* Maximum System Frequency allowed with DCDC Power Profile HIGH */
251 #define PROCESS_NNN_AVG_HZ (19300000U) /* Average Ring OScillator value for Nominal (NNN) Manufacturing Process */
252 #define PROCESS_NNN_STD_HZ \
253 (400000U) /* Standard Deviation Ring OScillator value for Nominal (NNN) Manufacturing Process */
254 #define PROCESS_NNN_LIMITS \
255 (6U) /* Nominal (NNN) Manufacturing Process Ring Oscillator values limit (with respect to the Average value) */
256 #define PROCESS_NNN_MIN_HZ \
257 (PROCESS_NNN_AVG_HZ - \
258 (PROCESS_NNN_LIMITS * \
259 PROCESS_NNN_STD_HZ)) /* Minimum Ring OScillator value for Nominal (NNN) Manufacturing Process */
260 #define PROCESS_NNN_MAX_HZ \
261 (PROCESS_NNN_AVG_HZ + \
262 (PROCESS_NNN_LIMITS * \
263 PROCESS_NNN_STD_HZ)) /* Maximum Ring OScillator value for Nominal (NNN) Manufacturing Process */
264 #define VOLTAGE_SSS_LOW_MV (1075U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=LOW */
265 #define VOLTAGE_SSS_MED_MV (1150U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=MEDIUM */
266 #define VOLTAGE_SSS_HIG_MV (1200U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=HIGH */
267 #define VOLTAGE_NNN_LOW_MV (1000U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=LOW */
268 #define VOLTAGE_NNN_MED_MV (1100U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=MEDIUM */
269 #define VOLTAGE_NNN_HIG_MV (1150U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=HIGH */
270 #define VOLTAGE_FFF_LOW_MV (1000U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=LOW */
271 #define VOLTAGE_FFF_MED_MV (1025U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=MEDIUM */
272 #define VOLTAGE_FFF_HIG_MV (1050U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=HIGH */
273
274 /**
275 * @brief LDO Voltage control in Low Power Modes
276 */
277 #define LOWPOWER_VOLTAGE_LDO_PMU_INDEX 0
278 #define LOWPOWER_VOLTAGE_LDO_PMU_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_INDEX)
279 #define LOWPOWER_VOLTAGE_LDO_MEM_INDEX 5
280 #define LOWPOWER_VOLTAGE_LDO_MEM_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_INDEX)
281 #define LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX 10
282 #define LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_MASK (0x7ULL << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX)
283 #define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX 19
284 #define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX)
285 #define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX 24
286 #define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX)
287 #define LOWPOWER_VOLTAGE_DCDC_INDEX 29
288 #define LOWPOWER_VOLTAGE_DCDC_MASK (0xFULL << LOWPOWER_VOLTAGE_DCDC_INDEX)
289
290 /*! @brief set and clear bit MACRO's. */
291 #define U32_SET_BITS(P, B) ((*(uint32_t *)P) |= (B))
292 #define U32_CLR_BITS(P, B) ((*(uint32_t *)P) &= ~(B))
293 /* Return values from Config (N-2) page of flash */
294 #define GET_16MXO_TRIM() (*(uint32_t *)0x9FCC8)
295 #define GET_32KXO_TRIM() (*(uint32_t *)0x9FCCC)
296
297 #define CPU_RETENTION_RAMX_STORAGE_START_ADDR (0x04006000)
298
299 #define XO_SLAVE_EN (1)
300 /*******************************************************************************
301 * Codes
302 ******************************************************************************/
303
304 /*******************************************************************************
305 * LOCAL FUNCTIONS PROTOTYPES
306 ******************************************************************************/
307 static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage);
308 static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage);
309 static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl);
310 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
311
312 static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile);
313 static lowpower_process_corner_enum lowpower_get_part_process_corner(void);
314 static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile);
315
316 /**
317 * @brief Configures and enters in low power mode
318 * @param p_lowpower_cfg: pointer to a structure that contains all low power mode parameters
319 * @return Nothing
320 *
321 * !!! IMPORTANT NOTES :
322 * 1 - CPU Interrupt Enable registers are updated with p_lowpower_cfg->WAKEUPINT. They are NOT restored by the
323 * API.
324 * 2 - The Non Maskable Interrupt (NMI) should be disable before calling this API (otherwise, there is a risk
325 * of Dead Lock).
326 * 3 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
327 * reset)
328 */
329 static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg);
330
331 /**
332 * @brief
333 * @param
334 * @return
335 */
lf_set_dcdc_power_profile_low(void)336 static void lf_set_dcdc_power_profile_low(void)
337 {
338 #define DCDC_POWER_PROFILE_LOW_0_ADDRS (0x9FCE0U)
339 #define DCDC_POWER_PROFILE_LOW_1_ADDRS (0x9FCE4U)
340
341 uint32_t dcdcTrimValue0 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_0_ADDRS)));
342 uint32_t dcdcTrimValue1 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_1_ADDRS)));
343
344 if (0UL != (dcdcTrimValue0 & 0x1UL))
345 {
346 PMC->DCDC0 = dcdcTrimValue0 >> 1;
347 PMC->DCDC1 = dcdcTrimValue1;
348 }
349 }
350
351 /**
352 * @brief Configures and enters in low power mode
353 * @param : p_lowpower_cfg
354 * @return Nothing
355 */
POWER_EnterLowPower(LPC_LOWPOWER_T * p_lowpower_cfg)356 static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg)
357 {
358 lowpower_driver_interface_t *s_lowpowerDriver;
359 /* Judging the core and call the corresponding API base address*/
360 if (0UL == Chip_GetVersion())
361 {
362 s_lowpowerDriver = (lowpower_driver_interface_t *)(0x130010d4UL);
363 }
364 else
365 {
366 s_lowpowerDriver = (lowpower_driver_interface_t *)(0x13001204UL);
367 }
368 /* PMC clk set to 12 MHZ */
369 p_lowpower_cfg->CFG |= (uint32_t)LOWPOWER_CFG_SELCLOCK_12MHZ << LOWPOWER_CFG_SELCLOCK_INDEX;
370
371 /* Enable Analog References fast wake-up in case of wake-up from a low power mode (DEEP SLEEP, POWER DOWN and DEEP
372 * POWER DOWN) and Hardware Pin reset */
373 PMC->REFFASTWKUP = (PMC->REFFASTWKUP & (~PMC_REFFASTWKUP_LPWKUP_MASK) & (~PMC_REFFASTWKUP_HWWKUP_MASK)) |
374 PMC_REFFASTWKUP_LPWKUP(1) | PMC_REFFASTWKUP_HWWKUP(1);
375
376 /* SRAM uses Voltage Scaling in all Low Power modes */
377 PMC->SRAMCTRL = (PMC->SRAMCTRL & (~PMC_SRAMCTRL_SMB_MASK)) | PMC_SRAMCTRL_SMB(3);
378
379 /* CPU Retention configuration : preserve the value of FUNCRETENTIONCTRL.RET_LENTH which is a Hardware defined
380 * parameter. */
381 p_lowpower_cfg->CPURETCTRL = (SYSCON->FUNCRETENTIONCTRL & SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK) |
382 (p_lowpower_cfg->CPURETCTRL & (~SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK));
383
384 /* Switch System Clock to FRO12Mhz (the configuration before calling this function will not be restored back) */
385 CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /* Switch main clock to FRO12MHz */
386 CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /* Main clock divided by 1 */
387 SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0000UL) | 0x201AUL; /* Adjust FMC waiting time cycles */
388 lf_set_dcdc_power_profile_low(); /* Align DCDC Power profile with the 12 MHz clock (DCDC Power Profile LOW) */
389
390 (*(s_lowpowerDriver->set_lowpower_mode))(p_lowpower_cfg);
391
392 /* Restore the configuration of the MISCCTRL Register : LOWPWR_FLASH_BUF = 0, LDOMEMBLEEDDSLP = 0, LDOMEMHIGHZMODE =
393 * 0 */
394 PMC->MISCCTRL &= (~PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK) & (~PMC_MISCCTRL_DISABLE_BLEED_MASK) &
395 (~PMC_MISCCTRL_LDOMEMHIGHZMODE_MASK);
396 }
397
398 /**
399 * @brief Shut off the Flash and execute the _WFI(), then power up the Flash after wake-up event
400 * @param None
401 * @return Nothing
402 */
POWER_CycleCpuAndFlash(void)403 void POWER_CycleCpuAndFlash(void)
404 {
405 /* Judging the core and call the corresponding API base address*/
406 lowpower_driver_interface_t *s_lowpowerDriver;
407 if (0UL == Chip_GetVersion())
408 {
409 s_lowpowerDriver = (lowpower_driver_interface_t *)(0x130010d4UL);
410 }
411 else
412 {
413 s_lowpowerDriver = (lowpower_driver_interface_t *)(0x13001204UL);
414 }
415 (*(s_lowpowerDriver->power_cycle_cpu_and_flash))();
416 };
417
418 /**
419 * brief PMC Deep Sleep function call
420 * return nothing
421 */
POWER_EnterDeepSleep(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t hardware_wake_ctrl)422 void POWER_EnterDeepSleep(uint32_t exclude_from_pd,
423 uint32_t sram_retention_ctrl,
424 uint64_t wakeup_interrupts,
425 uint32_t hardware_wake_ctrl)
426 {
427 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
428 uint32_t cpu0_nmi_enable;
429 uint32_t cpu0_int_enable_0;
430 uint32_t cpu0_int_enable_1;
431 uint32_t dcdc_voltage;
432 uint32_t pmc_reset_ctrl;
433 /* Clear Low Power Mode configuration variable */
434 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
435
436 /* Configure Low Power Mode configuration variable */
437 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPSLEEP
438 << LOWPOWER_CFG_LPMODE_INDEX; /* DEEPSLEEP mode */
439
440 lf_get_deepsleep_core_supply_cfg(exclude_from_pd, &dcdc_voltage);
441
442 if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
443 ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
444 {
445 /* USB High Speed is required as wake-up source in Deep Sleep mode: make sure LDO FLASH NV stays powered during
446 * deep-sleep */
447 exclude_from_pd = exclude_from_pd | (uint32_t)kPDRUNCFG_PD_LDOFLASHNV;
448 }
449
450 /* DCDC will be always used during Deep Sleep (instead of LDO Deep Sleep); Make sure LDO MEM & Analog references
451 * will stay powered, Shut down ROM */
452 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd & ~(uint32_t)kPDRUNCFG_PD_DCDC & ~(uint32_t)kPDRUNCFG_PD_LDOMEM &
453 ~(uint32_t)kPDRUNCFG_PD_BIAS) |
454 (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP | (uint32_t)kPDRUNCFG_PD_ROM;
455
456 /* Voltage control in DeepSleep Low Power Modes */
457 /* The Memories Voltage settings below are for voltage scaling */
458 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, dcdc_voltage);
459
460 /* SRAM retention control during POWERDOWN */
461 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
462
463 /* CPU Wake up & Interrupt sources control */
464 lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts;
465 lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts;
466
467 /* Interrupts that allow DMA transfers with Flexcomm without waking up the Processor */
468 if (0UL != (hardware_wake_ctrl & (LOWPOWER_HWWAKE_PERIPHERALS | LOWPOWER_HWWAKE_SDMA0 | LOWPOWER_HWWAKE_SDMA1)))
469 {
470 lv_low_power_mode_cfg.HWWAKE = (hardware_wake_ctrl & ~LOWPOWER_HWWAKE_FORCED) | LOWPOWER_HWWAKE_ENABLE_FRO192M;
471 }
472
473 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
474 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
475
476 /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
477 * API */
478 cpu0_int_enable_0 = NVIC->ISER[0];
479 cpu0_int_enable_1 = NVIC->ISER[1];
480
481 pmc_reset_ctrl = PMC->RESETCTRL;
482 if (0UL != (pmc_reset_ctrl & PMC_RESETCTRL_BODCORERESETENABLE_MASK))
483 {
484 /* BoD CORE reset is activated, so make sure BoD Core won't be shutdown */
485 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODCORE;
486 }
487 if (0UL != (pmc_reset_ctrl & PMC_RESETCTRL_BODVBATRESETENABLE_MASK))
488 {
489 /* BoD VBAT reset is activated, so make sure BoD VBAT won't be shutdown */
490 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODVBAT;
491 }
492
493 /* Enter low power mode */
494 POWER_EnterLowPower(&lv_low_power_mode_cfg);
495
496 /* Restore the configuration of the NMI Register */
497 SYSCON->NMISRC |= cpu0_nmi_enable;
498
499 /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
500 * low power API */
501 NVIC->ISER[0] = cpu0_int_enable_0;
502 NVIC->ISER[1] = cpu0_int_enable_1;
503 }
504
505 /**
506 * brief PMC power Down function call
507 * return nothing
508 */
POWER_EnterPowerDown(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t cpu_retention_ctrl)509 void POWER_EnterPowerDown(uint32_t exclude_from_pd,
510 uint32_t sram_retention_ctrl,
511 uint64_t wakeup_interrupts,
512 uint32_t cpu_retention_ctrl)
513 {
514 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
515 uint32_t cpu0_nmi_enable;
516 uint32_t cpu0_int_enable_0;
517 uint32_t cpu0_int_enable_1;
518 uint64_t wakeup_src_int;
519 uint32_t pmc_reset_ctrl;
520
521 uint32_t analog_ctrl_regs[12]; /* To store Analog Controller Regristers */
522
523 /* Clear Low Power Mode configuration variable */
524 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
525
526 /* Configure Low Power Mode configuration variable */
527 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_POWERDOWN
528 << LOWPOWER_CFG_LPMODE_INDEX; /* POWER DOWN mode */
529
530 /* Only FRO32K, XTAL32K, COMP, BIAS and LDO_MEM can be stay powered during POWERDOWN (valid from application point
531 * of view; Hardware allows BODVBAT, LDODEEPSLEEP and FRO1M to stay powered, that's why they are excluded below) */
532 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BODVBAT | (uint32_t)kPDRUNCFG_PD_FRO1M |
533 (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP;
534
535 /* SRAM retention control during POWERDOWN */
536 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
537
538 /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
539 if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
540 {
541 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
542 }
543
544 /* Voltage control in Low Power Modes */
545 /* The Memories Voltage settings below are for voltage scaling */
546 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, 0);
547
548 /* CPU0 retention Ctrl.
549 * For the time being, we do not allow customer to relocate the CPU retention area in SRAMX, meaning that the
550 * retention area range is [0x0400_6000 - 0x0400_6600] (beginning of RAMX2) If required by customer,
551 * cpu_retention_ctrl[13:1] will be used for that to modify the default retention area
552 */
553 lv_low_power_mode_cfg.CPURETCTRL =
554 (cpu_retention_ctrl & LOWPOWER_CPURETCTRL_ENA_MASK) |
555 ((((uint32_t)CPU_RETENTION_RAMX_STORAGE_START_ADDR >> 2UL) << LOWPOWER_CPURETCTRL_MEMBASE_INDEX) &
556 LOWPOWER_CPURETCTRL_MEMBASE_MASK);
557 if (0UL != (cpu_retention_ctrl & 0x1UL))
558 {
559 /* CPU retention is required: store Analog Controller Registers */
560 analog_ctrl_regs[0] = ANACTRL->FRO192M_CTRL;
561 analog_ctrl_regs[1] = ANACTRL->ANALOG_CTRL_CFG;
562 analog_ctrl_regs[2] = ANACTRL->ADC_CTRL;
563 analog_ctrl_regs[3] = ANACTRL->XO32M_CTRL;
564 analog_ctrl_regs[4] = ANACTRL->BOD_DCDC_INT_CTRL;
565 analog_ctrl_regs[5] = ANACTRL->RINGO0_CTRL;
566 analog_ctrl_regs[6] = ANACTRL->RINGO1_CTRL;
567 analog_ctrl_regs[7] = ANACTRL->RINGO2_CTRL;
568 analog_ctrl_regs[8] = ANACTRL->LDO_XO32M;
569 analog_ctrl_regs[9] = ANACTRL->AUX_BIAS;
570 analog_ctrl_regs[10] = ANACTRL->USBHS_PHY_CTRL;
571 analog_ctrl_regs[11] = ANACTRL->USBHS_PHY_TRIM;
572 }
573
574 /* CPU Wake up & Interrupt sources control : only WAKEUP_GPIO_GLOBALINT0, WAKEUP_GPIO_GLOBALINT1, WAKEUP_FLEXCOMM3,
575 * WAKEUP_ACMP_CAPT, WAKEUP_RTC_LITE_ALARM_WAKEUP, WAKEUP_OS_EVENT_TIMER, WAKEUP_ALLWAKEUPIOS */
576 wakeup_src_int = (uint64_t)(WAKEUP_GPIO_GLOBALINT0 | WAKEUP_GPIO_GLOBALINT1 | WAKEUP_FLEXCOMM3 | WAKEUP_ACMP_CAPT |
577 WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER | WAKEUP_ALLWAKEUPIOS);
578 lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts & wakeup_src_int;
579 lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts & wakeup_src_int;
580
581 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
582 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
583
584 /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
585 * API */
586 cpu0_int_enable_0 = NVIC->ISER[0];
587 cpu0_int_enable_1 = NVIC->ISER[1];
588
589 pmc_reset_ctrl = PMC->RESETCTRL;
590 /* Disable BoD VBAT and BoD Core resets */
591 PMC->RESETCTRL =
592 pmc_reset_ctrl & (~(PMC_RESETCTRL_BODVBATRESETENABLE_MASK | PMC_RESETCTRL_BODCORERESETENABLE_MASK));
593
594 /* Enter low power mode */
595 POWER_EnterLowPower(&lv_low_power_mode_cfg);
596
597 /*** We'll reach this point in case of POWERDOWN with CPU retention or if the POWERDOWN has not been taken (for
598 instance because an interrupt is pending). In case of CPU retention, assumption is that the SRAM containing the
599 stack used to call this function shall be preserved during low power ***/
600
601 /* Restore the configuration of the NMI Register */
602 SYSCON->NMISRC |= cpu0_nmi_enable;
603
604 /* Restore PMC RESETCTRL register */
605 PMC->RESETCTRL = pmc_reset_ctrl;
606
607 /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
608 * low power API */
609 NVIC->ISER[0] = cpu0_int_enable_0;
610 NVIC->ISER[1] = cpu0_int_enable_1;
611
612 if (0UL != (cpu_retention_ctrl & 0x1UL))
613 {
614 /* Restore Analog Controller Registers */
615 ANACTRL->FRO192M_CTRL = analog_ctrl_regs[0] | ANACTRL_FRO192M_CTRL_WRTRIM_MASK;
616 ANACTRL->ANALOG_CTRL_CFG = analog_ctrl_regs[1];
617 ANACTRL->ADC_CTRL = analog_ctrl_regs[2];
618 ANACTRL->XO32M_CTRL = analog_ctrl_regs[3];
619 ANACTRL->BOD_DCDC_INT_CTRL = analog_ctrl_regs[4];
620 ANACTRL->RINGO0_CTRL = analog_ctrl_regs[5];
621 ANACTRL->RINGO1_CTRL = analog_ctrl_regs[6];
622 ANACTRL->RINGO2_CTRL = analog_ctrl_regs[7];
623 ANACTRL->LDO_XO32M = analog_ctrl_regs[8];
624 ANACTRL->AUX_BIAS = analog_ctrl_regs[9];
625 ANACTRL->USBHS_PHY_CTRL = analog_ctrl_regs[10];
626 ANACTRL->USBHS_PHY_TRIM = analog_ctrl_regs[11];
627 }
628 }
629
630 /**
631 * brief PMC Deep Sleep Power Down function call
632 * return nothing
633 */
POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t wakeup_io_ctrl)634 void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,
635 uint32_t sram_retention_ctrl,
636 uint64_t wakeup_interrupts,
637 uint32_t wakeup_io_ctrl)
638 {
639 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
640 uint32_t cpu0_nmi_enable;
641 uint32_t cpu0_int_enable_0;
642 uint32_t cpu0_int_enable_1;
643 uint32_t pmc_reset_ctrl;
644
645 /* Clear Low Power Mode configuration variable */
646 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
647
648 /* Configure Low Power Mode configuration variable */
649 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN
650 << LOWPOWER_CFG_LPMODE_INDEX; /* DEEP POWER DOWN mode */
651
652 /* Only FRO32K, XTAL32K and LDO_MEM can be stay powered during DEEPPOWERDOWN (valid from application point of view;
653 * Hardware allows BODVBAT, BIAS FRO1M and COMP to stay powered, that's why they are excluded below) */
654 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BIAS | (uint32_t)kPDRUNCFG_PD_BODVBAT |
655 (uint32_t)kPDRUNCFG_PD_FRO1M | (uint32_t)kPDRUNCFG_PD_COMP;
656
657 /* SRAM retention control during DEEPPOWERDOWN */
658 sram_retention_ctrl =
659 sram_retention_ctrl &
660 (~(LOWPOWER_SRAMRETCTRL_RETEN_RAMX0 | LOWPOWER_SRAMRETCTRL_RETEN_RAMX1 | LOWPOWER_SRAMRETCTRL_RETEN_RAM00));
661
662 /* SRAM retention control during DEEPPOWERDOWN */
663 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
664
665 /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
666 if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
667 {
668 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
669 }
670
671 /* Voltage control in Low Power Modes */
672 /* The Memories Voltage settings below are for voltage scaling */
673 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN, 0);
674
675 lv_low_power_mode_cfg.WAKEUPINT =
676 wakeup_interrupts & (WAKEUP_RTC_LITE_ALARM_WAKEUP |
677 WAKEUP_OS_EVENT_TIMER); /* CPU Wake up sources control : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
678 WAKEUP_OS_EVENT_TIMER */
679 lv_low_power_mode_cfg.WAKEUPSRC =
680 wakeup_interrupts &
681 (WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER |
682 WAKEUP_ALLWAKEUPIOS); /*!< Hardware Wake up sources control: : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
683 WAKEUP_OS_EVENT_TIMER and WAKEUP_ALLWAKEUPIOS */
684
685 /* Wake up I/O sources */
686 lv_low_power_mode_cfg.WAKEUPIOSRC = lf_wakeup_io_ctrl(wakeup_io_ctrl);
687
688 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
689 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
690
691 /* Save the configuration of the CPU interrupt enable Registers */
692 cpu0_int_enable_0 = NVIC->ISER[0];
693 cpu0_int_enable_1 = NVIC->ISER[1];
694
695 /* Save the configuration of the PMC RESETCTRL register */
696 pmc_reset_ctrl = PMC->RESETCTRL;
697 /* Disable BoD VBAT and BoD Core resets */
698 PMC->RESETCTRL =
699 pmc_reset_ctrl & (~(PMC_RESETCTRL_BODVBATRESETENABLE_MASK | PMC_RESETCTRL_BODCORERESETENABLE_MASK));
700
701 /* Disable LDO MEM bleed current */
702 // PMC->MISCCTRL |= PMC_MISCCTRL_DISABLE_BLEED_MASK;
703
704 /* Enter low power mode */
705 POWER_EnterLowPower(&lv_low_power_mode_cfg);
706
707 /* Restore the configuration of the NMI Register */
708 SYSCON->NMISRC |= cpu0_nmi_enable;
709
710 /* Restore PMC RESETCTRL register */
711 PMC->RESETCTRL = pmc_reset_ctrl;
712
713 /* Restore the configuration of the CPU interrupt enable Registers */
714 NVIC->ISER[0] = cpu0_int_enable_0;
715 NVIC->ISER[1] = cpu0_int_enable_1;
716 }
717
718 /**
719 * brief PMC Sleep function call
720 * return nothing
721 */
POWER_EnterSleep(void)722 void POWER_EnterSleep(void)
723 {
724 uint32_t pmsk;
725 pmsk = __get_PRIMASK();
726 __disable_irq();
727 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
728 __WFI();
729 __set_PRIMASK(pmsk);
730 }
731
732 /**
733 * @brief Get Digital Core logic supply source to be used during Deep Sleep.
734 * @param [in] exclude_from_pd: COmpoenents NOT to be powered down during Deep Sleep
735 * @param [out] core_supply: 0 = LDO DEEPSLEEP will be used / 1 = DCDC will be used
736 * @param [out] dcdc_voltage: as defined by V_DCDC_* in fsl_power.h
737
738 * @return Nothing
739 */
lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd,uint32_t * dcdc_voltage)740 static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage)
741 {
742 *dcdc_voltage = (uint32_t)V_DCDC_0P950; /* Default value */
743
744 if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
745 ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
746 {
747 /* USB High Speed is required as wake-up source in Deep Sleep mode */
748 PMC->MISCCTRL |= PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK; /* Force flash buffer in low power mode */
749 *dcdc_voltage =
750 (uint32_t)V_DCDC_1P000; /* Set DCDC voltage to be 1.000 V (USB HS IP cannot work below 0.990 V) */
751 }
752 }
753
754 /**
755 * @brief
756 * @param
757 * @return
758 */
lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode,uint32_t p_dcdc_voltage)759 static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage)
760 {
761 #define FLASH_NMPA_LDO_AO_ADDRS (0x9FCF4U)
762 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK (0x100U)
763 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK (0x3E00U)
764 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT (9U)
765 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK (0x10000U)
766 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK (0x3E0000U)
767 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT (17U)
768 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK (0x1000000U)
769 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK (0x3E000000U)
770 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT (25U)
771
772 uint32_t ldo_ao_trim, voltage;
773 uint32_t lv_v_ldo_pmu, lv_v_ldo_pmu_boost;
774
775 ldo_ao_trim = (*((volatile unsigned int *)(FLASH_NMPA_LDO_AO_ADDRS)));
776
777 switch (p_lp_mode)
778 {
779 case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
780 {
781 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK) != 0UL)
782 {
783 /* Apply settings coming from Flash */
784 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT;
785 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
786 }
787 else
788 {
789 /* Apply default settings */
790 lv_v_ldo_pmu = (uint32_t)V_AO_0P900;
791 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P850;
792 }
793 }
794 break;
795
796 case LOWPOWER_CFG_LPMODE_POWERDOWN:
797 {
798 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK) != 0UL)
799 {
800 /* Apply settings coming from Flash */
801 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK) >> FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT;
802 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
803 }
804 else
805 {
806 /* Apply default settings */
807 lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
808 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
809 }
810 }
811 break;
812
813 case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
814 {
815 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK) != 0UL)
816 {
817 /* Apply settings coming from Flash */
818 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT;
819 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
820 }
821 else
822 {
823 /* Apply default settings */
824 lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
825 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
826 }
827 }
828 break;
829
830 default:
831 /* Should never reach this point */
832 lv_v_ldo_pmu = (uint32_t)V_AO_1P100;
833 lv_v_ldo_pmu_boost = (uint32_t)V_AO_1P050;
834 break;
835 }
836
837 /* The Memories Voltage settings below are for voltage scaling */
838 voltage =
839 (lv_v_ldo_pmu << LOWPOWER_VOLTAGE_LDO_PMU_INDEX) | /* */
840 (lv_v_ldo_pmu_boost << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX) | /* */
841 ((uint32_t)V_AO_0P750 << LOWPOWER_VOLTAGE_LDO_MEM_INDEX) | /* Set to 0.75V (voltage Scaling) */
842 ((uint32_t)V_AO_0P700 << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX) | /* Set to 0.7V (voltage Scaling) */
843 ((uint32_t)V_DEEPSLEEP_0P900
844 << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX) | /* Set to 0.90 V (Not used because LDO_DEEP_SLEEP is disabled)*/
845 (p_dcdc_voltage << LOWPOWER_VOLTAGE_DCDC_INDEX) /* */
846 ;
847
848 return (voltage);
849 }
850
851 /**
852 * @brief
853 * @param
854 * @return
855 */
lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)856 static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)
857 {
858 uint32_t wake_up_type;
859 uint32_t misc_ctrl_reg;
860 uint8_t use_external_pullupdown = 0;
861
862 /* Configure Pull up & Pull down based on the required wake-up edge */
863 CLOCK_EnableClock(kCLOCK_Iocon);
864
865 misc_ctrl_reg = 0UL;
866
867 /* Wake-up I/O 0 */
868 wake_up_type = (p_wakeup_io_ctrl & 0x3UL) >> LOWPOWER_WAKEUPIOSRC_PIO0_INDEX;
869 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_MASK) >>
870 LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX);
871
872 if (use_external_pullupdown == 0UL)
873 {
874 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
875 {
876 /* Rising edge and both rising and falling edges */
877 IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
878 misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
879 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
880 }
881 else
882 {
883 if (wake_up_type == 2UL)
884 {
885 /* Falling edge only */
886 IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
887 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
888 p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
889 }
890 else
891 {
892 /* Wake-up I/O is disabled : set it as required by the user */
893 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) != 0UL)
894 {
895 /* Wake-up I/O is configured as Plain Input */
896 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
897 }
898 else
899 {
900 /* Wake-up I/O is configured as pull-up or pull-down */
901 misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
902 }
903 }
904 }
905 }
906 else
907 {
908 /* MISCCTRL[8]:WAKEUPIOCTRL[8]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
909 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
910 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
911 }
912
913 /* Wake-up I/O 1 */
914 wake_up_type = (p_wakeup_io_ctrl & 0xCUL) >> LOWPOWER_WAKEUPIOSRC_PIO1_INDEX;
915 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_MASK) >>
916 LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX);
917
918 if (use_external_pullupdown == 0UL)
919 {
920 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
921 {
922 /* Rising edge and both rising and falling edges */
923 IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
924 misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
925 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
926 }
927 else
928 {
929 if (wake_up_type == 2UL)
930 {
931 /* Falling edge only */
932 IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
933 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
934 p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
935 }
936 else
937 {
938 /* Wake-up I/O is disabled : set it as required by the user */
939 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) != 0UL)
940 {
941 /* Wake-up I/O is configured as Plain Input */
942 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
943 }
944 else
945 {
946 /* Wake-up I/O is configured as pull-up or pull-down */
947 misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
948 }
949 }
950 }
951 }
952 else
953 {
954 /* MISCCTRL[9]:WAKEUPIOCTRL[9]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
955 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
956 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
957 }
958
959 /* Wake-up I/O 2 */
960 wake_up_type = (p_wakeup_io_ctrl & 0x30UL) >> LOWPOWER_WAKEUPIOSRC_PIO2_INDEX;
961 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_MASK) >>
962 LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX);
963
964 if (use_external_pullupdown == 0UL)
965 {
966 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
967 {
968 /* Rising edge and both rising and falling edges */
969 IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
970 misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
971 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
972 }
973 else
974 {
975 if (wake_up_type == 2UL)
976 {
977 /* Falling edge only */
978 IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
979 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
980 p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
981 }
982 else
983 {
984 /* Wake-up I/O is disabled : set it as required by the user */
985 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) != 0UL)
986 {
987 /* Wake-up I/O is configured as Plain Input */
988 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
989 }
990 else
991 {
992 /* Wake-up I/O is configured as pull-up or pull-down */
993 misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
994 }
995 }
996 }
997 }
998 else
999 {
1000 /* MISCCTRL[10]:WAKEUPIOCTRL[10]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
1001 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
1002 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
1003 }
1004
1005 /* Wake-up I/O 3 */
1006 wake_up_type = (p_wakeup_io_ctrl & 0xC0UL) >> LOWPOWER_WAKEUPIOSRC_PIO3_INDEX;
1007 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_MASK) >>
1008 LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX);
1009
1010 if (use_external_pullupdown == 0UL)
1011 {
1012 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
1013 {
1014 /* Rising edge and both rising and falling edges */
1015 IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
1016 misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1017 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1018 }
1019 else
1020 {
1021 if (wake_up_type == 2UL)
1022 {
1023 /* Falling edge only */
1024 IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
1025 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1026 p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1027 }
1028 else
1029 {
1030 /* Wake-up I/O is disabled : set it as required by the user */
1031 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) != 0UL)
1032 {
1033 /* Wake-up I/O is configured as Plain Input */
1034 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1035 }
1036 else
1037 {
1038 /* Wake-up I/O is configured as pull-up or pull-down */
1039 misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1040 }
1041 }
1042 }
1043 }
1044 else
1045 {
1046 /* MISCCTRL[11]:WAKEUPIOCTRL[11]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
1047 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1048 misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1049 }
1050
1051 PMC->MISCCTRL = (PMC->MISCCTRL & 0xFFFFF0FFUL) | misc_ctrl_reg;
1052 PMC->WAKEUPIOCTRL = p_wakeup_io_ctrl & 0xFFFUL;
1053
1054 /*
1055 * Defined according to :
1056 * - LOWPOWER_WAKEUPIOSRC_<DISABLE,RISING,FALLING,RISING_FALLING> in fsl_power.h
1057 * - LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_<...> in fsl_power.h
1058 */
1059 return (p_wakeup_io_ctrl & 0xFFFUL);
1060 }
1061
1062 /**
1063 * @brief
1064 * @param
1065 * @return
1066 */
CLOCK_u8OscCapConvert(uint8_t u8OscCap,uint8_t u8CapBankDiscontinuity)1067 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
1068 {
1069 /* Compensate for discontinuity in the capacitor banks */
1070 if (u8OscCap < 64U)
1071 {
1072 if (u8OscCap >= u8CapBankDiscontinuity)
1073 {
1074 u8OscCap -= u8CapBankDiscontinuity;
1075 }
1076 else
1077 {
1078 u8OscCap = 0U;
1079 }
1080 }
1081 else
1082 {
1083 if (u8OscCap <= (127U - u8CapBankDiscontinuity))
1084 {
1085 u8OscCap += u8CapBankDiscontinuity;
1086 }
1087 else
1088 {
1089 u8OscCap = 127U;
1090 }
1091 }
1092 return u8OscCap;
1093 }
1094
1095 /**
1096 * @brief Described in fsl_common.h
1097 * @param
1098 * @return
1099 */
lowpower_set_system_voltage(uint32_t system_voltage_mv)1100 static void lowpower_set_system_voltage(uint32_t system_voltage_mv)
1101 {
1102 /*
1103 * Set system voltage
1104 */
1105 uint32_t lv_ldo_ao = (uint32_t)V_AO_1P100; /* <ldo_ao> */
1106 uint32_t lv_ldo_ao_boost = (uint32_t)V_AO_1P150; /* <ldo_ao_boost> */
1107 uint32_t lv_dcdc = (uint32_t)V_DCDC_1P100; /* <dcdc> */
1108
1109 if (system_voltage_mv <= 950UL)
1110 {
1111 lv_dcdc = (uint32_t)V_DCDC_0P950;
1112 lv_ldo_ao = (uint32_t)V_AO_0P960;
1113 lv_ldo_ao_boost = (uint32_t)V_AO_1P010;
1114 }
1115 else if (system_voltage_mv <= 975UL)
1116 {
1117 lv_dcdc = (uint32_t)V_DCDC_0P975;
1118 lv_ldo_ao = (uint32_t)V_AO_0P980;
1119 lv_ldo_ao_boost = (uint32_t)V_AO_1P030;
1120 }
1121 else if (system_voltage_mv <= 1000UL)
1122 {
1123 lv_dcdc = (uint32_t)V_DCDC_1P000;
1124 lv_ldo_ao = (uint32_t)V_AO_1P000;
1125 lv_ldo_ao_boost = (uint32_t)V_AO_1P050;
1126 }
1127 else if (system_voltage_mv <= 1025UL)
1128 {
1129 lv_dcdc = (uint32_t)V_DCDC_1P025;
1130 lv_ldo_ao = (uint32_t)V_AO_1P030;
1131 lv_ldo_ao_boost = (uint32_t)V_AO_1P080;
1132 }
1133 else if (system_voltage_mv <= 1050UL)
1134 {
1135 lv_dcdc = (uint32_t)V_DCDC_1P050;
1136 lv_ldo_ao = (uint32_t)V_AO_1P060;
1137 lv_ldo_ao_boost = (uint32_t)V_AO_1P110;
1138 }
1139 else if (system_voltage_mv <= 1075UL)
1140 {
1141 lv_dcdc = (uint32_t)V_DCDC_1P075;
1142 lv_ldo_ao = (uint32_t)V_AO_1P080;
1143 lv_ldo_ao_boost = (uint32_t)V_AO_1P130;
1144 }
1145 else if (system_voltage_mv <= 1100UL)
1146 {
1147 lv_dcdc = (uint32_t)V_DCDC_1P100;
1148 lv_ldo_ao = (uint32_t)V_AO_1P100;
1149 lv_ldo_ao_boost = (uint32_t)V_AO_1P150;
1150 }
1151 else if (system_voltage_mv <= 1125UL)
1152 {
1153 lv_dcdc = (uint32_t)V_DCDC_1P125;
1154 lv_ldo_ao = (uint32_t)V_AO_1P130;
1155 lv_ldo_ao_boost = (uint32_t)V_AO_1P160;
1156 }
1157 else if (system_voltage_mv <= 1150UL)
1158 {
1159 lv_dcdc = (uint32_t)V_DCDC_1P150;
1160 lv_ldo_ao = (uint32_t)V_AO_1P160;
1161 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1162 }
1163 else if (system_voltage_mv <= 1175UL)
1164 {
1165 lv_dcdc = (uint32_t)V_DCDC_1P175;
1166 lv_ldo_ao = (uint32_t)V_AO_1P160;
1167 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1168 }
1169 else
1170 {
1171 lv_dcdc = (uint32_t)V_DCDC_1P200;
1172 lv_ldo_ao = (uint32_t)V_AO_1P160;
1173 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1174 }
1175
1176 /* Set up LDO Always-On voltages */
1177 PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_MASK) & (~PMC_LDOPMU_VADJ_BOOST_MASK)) | PMC_LDOPMU_VADJ(lv_ldo_ao) |
1178 PMC_LDOPMU_VADJ_BOOST(lv_ldo_ao_boost);
1179
1180 /* Set up DCDC voltage */
1181 PMC->DCDC0 = (PMC->DCDC0 & (~PMC_DCDC0_VOUT_MASK)) | PMC_DCDC0_VOUT(lv_dcdc);
1182 }
1183
1184 /**
1185 * @brief Described in fsl_common.h
1186 * @param
1187 * @return
1188 */
lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)1189 static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)
1190 {
1191 #define FLASH_NMPA_BASE (0x9FC00u)
1192 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U) // (0x9FCE0U)
1193 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U) // (0x9FCE4U)
1194 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS (FLASH_NMPA_BASE + 0xE8U) // (0x9FCE8U)
1195 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS (FLASH_NMPA_BASE + 0xECU) // (0x9FCECU)
1196 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS (FLASH_NMPA_BASE + 0xD8U) // (0x9FCD8U)
1197 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS (FLASH_NMPA_BASE + 0xDCU) // (0x9FCDCU)
1198
1199 const uint32_t PMC_DCDC0_DEFAULT = 0x010C4E68;
1200 const uint32_t PMC_DCDC1_DEFAULT = 0x01803A98;
1201
1202 uint32_t dcdcTrimValue0;
1203 uint32_t dcdcTrimValue1;
1204
1205 switch (dcdc_power_profile)
1206 {
1207 case DCDC_POWER_PROFILE_LOW:
1208 /* Low */
1209 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS)));
1210 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS)));
1211
1212 if (0UL != (dcdcTrimValue0 & 0x1UL))
1213 {
1214 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1215
1216 PMC->DCDC0 = dcdcTrimValue0;
1217 PMC->DCDC1 = dcdcTrimValue1;
1218 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1219 PRINTF(
1220 "\nINFO : DCDC Power Profile set to "
1221 "LOW"
1222 "\n");
1223 #endif
1224 }
1225 break;
1226
1227 case DCDC_POWER_PROFILE_MEDIUM:
1228 /* Medium */
1229 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS)));
1230 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS)));
1231
1232 if (0UL != (dcdcTrimValue0 & 0x1UL))
1233 {
1234 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1235
1236 PMC->DCDC0 = dcdcTrimValue0;
1237 PMC->DCDC1 = dcdcTrimValue1;
1238 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1239 PRINTF(
1240 "\nINFO : DCDC Power Profile set to "
1241 "MEDIUM"
1242 "\n");
1243 #endif
1244 }
1245 break;
1246
1247 case DCDC_POWER_PROFILE_HIGH:
1248 /* High */
1249 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS)));
1250 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS)));
1251
1252 if (0UL != (dcdcTrimValue0 & 0x1UL))
1253 {
1254 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1255
1256 PMC->DCDC0 = dcdcTrimValue0;
1257 PMC->DCDC1 = dcdcTrimValue1;
1258 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1259 PRINTF(
1260 "\nINFO : DCDC Power Profile set to "
1261 "HIGH"
1262 "\n");
1263 #endif
1264 }
1265 break;
1266
1267 default:
1268 /* Low */
1269 PMC->DCDC0 = PMC_DCDC0_DEFAULT;
1270 PMC->DCDC1 = PMC_DCDC1_DEFAULT;
1271 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1272 PRINTF(
1273 "\nINFO : DCDC Power Profile set to "
1274 "LOW"
1275 "\n");
1276 #endif
1277 break;
1278 }
1279 }
1280
1281 /**
1282 * @brief
1283 * @param
1284 * @return
1285 */
lowpower_get_part_process_corner(void)1286 static lowpower_process_corner_enum lowpower_get_part_process_corner(void)
1287 {
1288 #define FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS (FLASH_NMPA_BASE + 0x130U)
1289 #define FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS (FLASH_NMPA_BASE + 0x140U)
1290
1291 lowpower_process_corner_enum part_process_corner;
1292 uint32_t pvt_ringo_hz;
1293 uint32_t pvt_ringo_0 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS)));
1294 uint32_t pvt_ringo_1 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS)));
1295
1296 /*
1297 * Check that the PVT Monitors Trimmings in flash are valid.
1298 */
1299 if (0UL != (pvt_ringo_0 & 0x1UL))
1300 {
1301 /* PVT Trimmings in Flash are valid */
1302 pvt_ringo_0 = pvt_ringo_0 >> 1;
1303 }
1304 else
1305 {
1306 /* PVT Trimmings in Flash are NOT valid (average value assumed) */
1307 pvt_ringo_0 = PROCESS_NNN_AVG_HZ;
1308 }
1309
1310 if (0UL != (pvt_ringo_1 & 0x1UL))
1311 {
1312 /* PVT Trimmings in Flash are valid */
1313 pvt_ringo_1 = pvt_ringo_1 >> 1;
1314 }
1315 else
1316 {
1317 /* PVT Trimmings in Flash are NOT valid (average value assumed) */
1318 pvt_ringo_1 = PROCESS_NNN_AVG_HZ;
1319 }
1320
1321 if (pvt_ringo_1 <= pvt_ringo_0)
1322 {
1323 pvt_ringo_hz = pvt_ringo_1;
1324 }
1325 else
1326 {
1327 pvt_ringo_hz = pvt_ringo_0;
1328 }
1329
1330 /*
1331 * Determine the process corner based on the value of the Ring Oscillator frequency
1332 */
1333 if (pvt_ringo_hz <= PROCESS_NNN_MIN_HZ)
1334 {
1335 /* SSS Process Corner */
1336 part_process_corner = PROCESS_CORNER_SSS;
1337 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1338 PRINTF(
1339 "\nINFO : Process Corner : "
1340 "SSS"
1341 "\n");
1342 #endif
1343 }
1344 else
1345 {
1346 if (pvt_ringo_hz <= PROCESS_NNN_MAX_HZ)
1347 {
1348 /* NNN Process Corner */
1349 part_process_corner = PROCESS_CORNER_NNN;
1350 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1351 PRINTF(
1352 "\nINFO : Process Corner : "
1353 "NNN"
1354 "\n");
1355 #endif
1356 }
1357 else
1358 {
1359 /* FFF Process Corner */
1360 part_process_corner = PROCESS_CORNER_FFF;
1361 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1362 PRINTF(
1363 "\nINFO : Process Corner : "
1364 "FFF"
1365 "\n");
1366 #endif
1367 }
1368 }
1369
1370 return (part_process_corner);
1371 }
1372
1373 /**
1374 * @brief Described in fsl_common.h
1375 * @param
1376 * @return
1377 */
lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)1378 static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)
1379 {
1380 /* Get Sample Process Corner */
1381 lowpower_process_corner_enum part_process_corner = lowpower_get_part_process_corner();
1382
1383 switch (part_process_corner)
1384 {
1385 case PROCESS_CORNER_SSS:
1386 /* Slow Corner */
1387 {
1388 switch (dcdc_power_profile)
1389 {
1390 case DCDC_POWER_PROFILE_MEDIUM:
1391 /* Medium */
1392 lowpower_set_system_voltage(VOLTAGE_SSS_MED_MV);
1393 break;
1394
1395 case DCDC_POWER_PROFILE_HIGH:
1396 /* High */
1397 lowpower_set_system_voltage(VOLTAGE_SSS_HIG_MV);
1398 break;
1399
1400 default:
1401 /* DCDC_POWER_PROFILE_LOW */
1402 lowpower_set_system_voltage(VOLTAGE_SSS_LOW_MV);
1403 break;
1404 } // switch(dcdc_power_profile)
1405 }
1406 break;
1407
1408 case PROCESS_CORNER_FFF:
1409 /* Fast Corner */
1410 {
1411 switch (dcdc_power_profile)
1412 {
1413 case DCDC_POWER_PROFILE_MEDIUM:
1414 /* Medium */
1415 lowpower_set_system_voltage(VOLTAGE_FFF_MED_MV);
1416 break;
1417
1418 case DCDC_POWER_PROFILE_HIGH:
1419 /* High */
1420 lowpower_set_system_voltage(VOLTAGE_FFF_HIG_MV);
1421 break;
1422
1423 default:
1424 /* DCDC_POWER_PROFILE_LOW */
1425 lowpower_set_system_voltage(VOLTAGE_FFF_LOW_MV);
1426 break;
1427 } // switch(dcdc_power_profile)
1428 }
1429 break;
1430
1431 default:
1432 /* Nominal (NNN) and all others Process Corners : assume Nominal Corner */
1433 {
1434 switch (dcdc_power_profile)
1435 {
1436 case DCDC_POWER_PROFILE_MEDIUM:
1437 /* Medium */
1438 lowpower_set_system_voltage(VOLTAGE_NNN_MED_MV);
1439 break;
1440
1441 case DCDC_POWER_PROFILE_HIGH:
1442 /* High */
1443 lowpower_set_system_voltage(VOLTAGE_NNN_HIG_MV);
1444 break;
1445
1446 default:
1447 /* DCDC_POWER_PROFILE_LOW */
1448 lowpower_set_system_voltage(VOLTAGE_NNN_LOW_MV);
1449 break;
1450 } // switch(dcdc_power_profile)
1451 break;
1452 }
1453 } // switch(part_process_corner)
1454 }
1455
1456 /**
1457 * @brief Described in fsl_common.h
1458 * @param
1459 * @return
1460 */
POWER_SetVoltageForFreq(uint32_t system_freq_hz)1461 void POWER_SetVoltageForFreq(uint32_t system_freq_hz)
1462 {
1463 if (system_freq_hz <= DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ)
1464 {
1465 /* [0 Hz - DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz] */
1466 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_LOW); /* DCDC VOUT = 1.05 V by default */
1467 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_LOW);
1468 }
1469 else
1470 {
1471 if (system_freq_hz <= DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ)
1472 {
1473 /* ]DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz - DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz] */
1474 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_MEDIUM); /* DCDC VOUT = 1.15 V by default */
1475 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_MEDIUM);
1476 }
1477 else
1478 {
1479 /* > DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz */
1480 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_HIGH); /* DCDC VOUT = 1.2 V by default */
1481 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_HIGH);
1482 }
1483 }
1484 }
1485
POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,int32_t pi32_16MfXtalPPcbParCappF_x100,int32_t pi32_16MfXtalNPcbParCappF_x100)1486 void POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,
1487 int32_t pi32_16MfXtalPPcbParCappF_x100,
1488 int32_t pi32_16MfXtalNPcbParCappF_x100)
1489 {
1490 uint32_t u32XOTrimValue;
1491 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
1492 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
1493 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
1494 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
1495 uint32_t u32RegVal;
1496 int32_t i32Tmp;
1497
1498 /* Enable and set LDO, if not already done */
1499 POWER_SetXtal16mhzLdo();
1500 /* Get Cal values from Flash */
1501 u32XOTrimValue = GET_16MXO_TRIM();
1502 /* Check validity and apply */
1503 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
1504 {
1505 /* These fields are 7 bits, unsigned */
1506 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
1507 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
1508 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
1509 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
1510 /* This field is 1 bit */
1511 u8XOSlave = (uint8_t)((u32XOTrimValue >> 30UL) & 0x1UL);
1512 /* Linear fit coefficients calculation */
1513 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
1514 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
1515 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
1516 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
1517 }
1518 else
1519 {
1520 iaXin_x4 = 20; // gain in LSB/pF
1521 ibXin = -9; // offset in LSB
1522 iaXout_x4 = 20; // gain in LSB/pF
1523 ibXout = -13; // offset in LSB
1524 u8XOSlave = 0;
1525 }
1526 /* In & out load cap calculation with derating */
1527 iXOCapInpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalNPcbParCappF_x100 +
1528 39 * ((int32_t)XO_SLAVE_EN - (int32_t)u8XOSlave) - 15;
1529 iXOCapOutpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalPPcbParCappF_x100 - 21;
1530 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
1531 i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
1532 u8XOCapInCtrl = (uint8_t)i32Tmp;
1533 i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
1534 u8XOCapOutCtrl = (uint8_t)i32Tmp;
1535 /* Read register and clear fields to be written */
1536 u32RegVal = ANACTRL->XO32M_CTRL;
1537 u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
1538 /* Configuration of 32 MHz XO output buffers */
1539 #if (XO_SLAVE_EN == 0)
1540 u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
1541 #else
1542 u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
1543 #endif
1544 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
1545 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
1546 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
1547 /* Write back to register */
1548 ANACTRL->XO32M_CTRL = u32RegVal;
1549 }
1550
POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,int32_t pi32_32kfXtalPPcbParCappF_x100,int32_t pi32_32kfXtalNPcbParCappF_x100)1551 void POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
1552 int32_t pi32_32kfXtalPPcbParCappF_x100,
1553 int32_t pi32_32kfXtalNPcbParCappF_x100)
1554 {
1555 uint32_t u32XOTrimValue;
1556 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
1557 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
1558 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
1559 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
1560 uint32_t u32RegVal;
1561 int32_t i32Tmp;
1562 /* Get Cal values from Flash */
1563 u32XOTrimValue = GET_32KXO_TRIM();
1564 /* check validity and apply */
1565 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
1566 {
1567 /* These fields are 7 bits, unsigned */
1568 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
1569 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
1570 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
1571 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
1572 /* Linear fit coefficients calculation */
1573 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
1574 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
1575 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
1576 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
1577 }
1578 else
1579 {
1580 iaXin_x4 = 16; // gain in LSB/pF
1581 ibXin = 12; // offset in LSB
1582 iaXout_x4 = 16; // gain in LSB/pF
1583 ibXout = 11; // offset in LSB
1584 }
1585
1586 /* In & out load cap calculation with derating */
1587 iXOCapInpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
1588 iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
1589
1590 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
1591 i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
1592 u8XOCapInCtrl = (uint8_t)i32Tmp;
1593 i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
1594 u8XOCapOutCtrl = (uint8_t)i32Tmp;
1595
1596 /* Read register and clear fields to be written */
1597 u32RegVal = PMC->XTAL32K;
1598 u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
1599
1600 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
1601 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23) << PMC_XTAL32K_CAPBANKIN_SHIFT;
1602 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
1603
1604 /* Write back to register */
1605 PMC->XTAL32K = u32RegVal;
1606 }
1607
POWER_SetXtal16mhzLdo(void)1608 void POWER_SetXtal16mhzLdo(void)
1609 {
1610 uint32_t temp;
1611 const uint32_t u32Mask =
1612 (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
1613
1614 const uint32_t u32Value =
1615 (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
1616
1617 /* Enable & set-up XTAL 32 MHz clock LDO */
1618 temp = ANACTRL->LDO_XO32M;
1619
1620 if ((temp & u32Mask) != u32Value)
1621 {
1622 temp &= ~u32Mask;
1623
1624 /*
1625 * Enable the XTAL32M LDO
1626 * Adjust the output voltage level, 0x5 for 1.1V
1627 * Adjust the biasing current, 0x2 value
1628 * Stability configuration, 0x1 default mode
1629 */
1630 temp |= u32Value;
1631
1632 ANACTRL->LDO_XO32M = temp;
1633
1634 /* Delay for LDO to be up */
1635 // CLOCK_uDelay(20);
1636 }
1637
1638 /* Enable LDO XO32M */
1639 PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXO32M_MASK;
1640 }
1641
1642 /**
1643 * @brief Return some key information related to the device reset causes / wake-up sources, for all power modes.
1644 * @param p_reset_cause : the device reset cause, according to the definition of power_device_reset_cause_t type.
1645 * @param p_boot_mode : the device boot mode, according to the definition of power_device_boot_mode_t type.
1646 * @param p_wakeupio_cause: the wake-up pin sources, according to the definition of register PMC->WAKEIOCAUSE[3:0].
1647
1648 * @return Nothing
1649 *
1650 * !!! IMPORTANT ERRATA - IMPORTANT ERRATA - IMPORTANT ERRATA !!!
1651 * !!! valid ONLY for LPC55S69 (not for LPC55S16 and LPC55S06) !!!
1652 * !!! when FALLING EDGE DETECTION is enabled on wake-up pins: !!!
1653 * - 1. p_wakeupio_cause is NOT ACCURATE
1654 * - 2. Spurious kRESET_CAUSE_DPDRESET_WAKEUPIO* event is reported when
1655 * several wake-up sources are enabled during DEEP-POWER-DOWN
1656 * (like enabling wake-up on RTC and Falling edge wake-up pins)
1657 *
1658 */
POWER_GetWakeUpCause(power_device_reset_cause_t * p_reset_cause,power_device_boot_mode_t * p_boot_mode,uint32_t * p_wakeupio_cause)1659 void POWER_GetWakeUpCause(power_device_reset_cause_t *p_reset_cause,
1660 power_device_boot_mode_t *p_boot_mode,
1661 uint32_t *p_wakeupio_cause)
1662 {
1663 uint32_t reset_cause_reg;
1664 uint32_t boot_mode_reg;
1665
1666 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1667 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1668 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1669 reset_cause_reg = (PMC->AOREG1) & 0x3FF0UL;
1670 #else /* LPC55S69/28 */
1671 reset_cause_reg = (PMC->AOREG1) & 0x1FF0UL;
1672 #endif
1673
1674 /*
1675 * Prioritize interrupts source with respect to their critical level
1676 */
1677 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1678 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1679 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1680 if (0UL != (reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK))
1681 { /* Code Watchdog Reset */
1682 *p_reset_cause = kRESET_CAUSE_CDOGRESET;
1683 *p_boot_mode = kBOOT_MODE_POWER_UP;
1684 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1685 }
1686 else
1687 #endif
1688 {
1689 if (0UL != (reset_cause_reg & PMC_AOREG1_WDTRESET_MASK))
1690 { /* Watchdog Timer Reset */
1691 *p_reset_cause = kRESET_CAUSE_WDTRESET;
1692 *p_boot_mode = kBOOT_MODE_POWER_UP;
1693 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1694 }
1695 else
1696 {
1697 if (0UL != (reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK))
1698 { /* ARM System Reset */
1699 *p_reset_cause = kRESET_CAUSE_ARMSYSTEMRESET;
1700 *p_boot_mode = kBOOT_MODE_POWER_UP;
1701 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1702 }
1703 else
1704 {
1705 boot_mode_reg = (PMC->STATUS & PMC_STATUS_BOOTMODE_MASK) >> PMC_STATUS_BOOTMODE_SHIFT;
1706
1707 if (boot_mode_reg == 0UL) /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset */
1708 {
1709 *p_boot_mode = kBOOT_MODE_POWER_UP; /* All non wake-up from a Low Power mode */
1710 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1711
1712 /*
1713 * Prioritise Reset causes, starting from the strongest (Power On Reset)
1714 */
1715 if (0UL != (reset_cause_reg & PMC_AOREG1_POR_MASK))
1716 { /* Power On Reset */
1717 *p_reset_cause = kRESET_CAUSE_POR;
1718 }
1719 else
1720 {
1721 if (0UL != (reset_cause_reg & PMC_AOREG1_BODRESET_MASK))
1722 { /* Brown-out Detector reset (either BODVBAT or BODCORE) */
1723 *p_reset_cause = kRESET_CAUSE_BODRESET;
1724 }
1725 else
1726 {
1727 if (0UL != (reset_cause_reg & PMC_AOREG1_PADRESET_MASK))
1728 { /* Hardware Pin Reset */
1729 *p_reset_cause = kRESET_CAUSE_PADRESET;
1730 }
1731 else
1732 {
1733 if (0UL != (reset_cause_reg & PMC_AOREG1_SWRRESET_MASK))
1734 { /* Software triggered Reset */
1735 *p_reset_cause = kRESET_CAUSE_SWRRESET;
1736 }
1737 else
1738 { /* Unknown Reset Cause */
1739 *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1740 }
1741 }
1742 }
1743 }
1744
1745 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1746 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1747 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1748 /* Transfer the control of the 4 wake-up pins to IOCON (instead of the Power Management Controller
1749 */
1750 PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1751 #endif
1752 }
1753 else /* DEEP-SLEEP, POWER-DOWN and DEEP-POWER-DOWN */
1754 {
1755 /*
1756 * 1- First, save wakeup_io_cause register ...
1757 */
1758 *p_wakeupio_cause = PMC->WAKEIOCAUSE;
1759
1760 if (boot_mode_reg == 3UL) /* DEEP-POWER-DOWN */
1761 {
1762 *p_boot_mode = kBOOT_MODE_LP_DEEP_POWER_DOWN;
1763
1764 switch (((reset_cause_reg >> PMC_AOREG1_DPDRESET_WAKEUPIO_SHIFT) & 0x7UL))
1765 {
1766 case 1:
1767 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO;
1768 break;
1769 case 2:
1770 *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC;
1771 break;
1772 case 3:
1773 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC;
1774 break;
1775 case 4:
1776 *p_reset_cause = kRESET_CAUSE_DPDRESET_OSTIMER;
1777 break;
1778 case 5:
1779 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER;
1780 break;
1781 case 6:
1782 *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC_OSTIMER;
1783 break;
1784 case 7:
1785 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER;
1786 break;
1787 default:
1788 /* Unknown Reset Cause */
1789 *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1790 break;
1791 }
1792
1793 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1794 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1795 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1796 /*
1797 * 2- Next, transfer the control of the 4 wake-up pins
1798 * to IOCON (instead of the Power Management Controller)
1799 */
1800 PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1801 #endif
1802 }
1803 else /* DEEP-SLEEP and POWER-DOWN */
1804 {
1805 *p_reset_cause = kRESET_CAUSE_NOT_RELEVANT;
1806
1807 /*
1808 * The control of the 4 wake-up pins is already in IOCON,
1809 * so there is nothing special to do.
1810 */
1811
1812 if (boot_mode_reg == 1UL) /* DEEP-SLEEP */
1813 {
1814 *p_boot_mode = kBOOT_MODE_LP_DEEP_SLEEP;
1815 }
1816 else /* POWER-DOWN */
1817 {
1818 *p_boot_mode = kBOOT_MODE_LP_POWER_DOWN;
1819
1820 } /* if ( boot_mode_reg == 1 ) DEEP-SLEEP */
1821
1822 } /* if ( boot_mode == 3 ) DEEP-POWER-DOWN */
1823
1824 } /* if ( boot_mode == 0 ) POWER-UP */
1825
1826 } /* if ( reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK ) */
1827
1828 } /* if ( reset_cause_reg & PMC_AOREG1_WDTRESET_MASK ) */
1829
1830 } /* if ( reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK ) */
1831 }
1832