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