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 /* Following code is to reset PUF to remove over consumption */
592 /* Enable PUF register clock to access register */
593 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
594 /* Release PUF reset */
595 SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_PUF_RST_MASK;
596 /* Enable PUF SRAM */
597 PUF_SRAM_CTRL->CFG |= PUF_SRAM_CTRL_CFG_ENABLE_MASK | PUF_SRAM_CTRL_CFG_CKGATING_MASK;
598
599 /* Disable PUF register clock. */
600 // Delaying the line of code below until the PUF State Machine execution is completed:
601 // Shuting down the clock to early will prevent the state machine from reaching the end.
602 // => Wait for status bit in PUF Controller Registers before stop PUF clock.
603 while (0UL == (PUF_SRAM_CTRL->INT_STATUS & PUF_SRAM_CTRL_INT_STATUS_READY_MASK))
604 {
605 }
606
607 SYSCON->AHBCLKCTRLCLR[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
608
609 /* Restore the configuration of the NMI Register */
610 SYSCON->NMISRC |= cpu0_nmi_enable;
611
612 /* Restore PMC RESETCTRL register */
613 PMC->RESETCTRL = pmc_reset_ctrl;
614
615 /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
616 * low power API */
617 NVIC->ISER[0] = cpu0_int_enable_0;
618 NVIC->ISER[1] = cpu0_int_enable_1;
619
620 if ((cpu_retention_ctrl & 0x1UL) != 0UL)
621 {
622 /* Restore Analog Controller Registers */
623 ANACTRL->FRO192M_CTRL = analog_ctrl_regs[0] | ANACTRL_FRO192M_CTRL_WRTRIM_MASK;
624 ANACTRL->ANALOG_CTRL_CFG = analog_ctrl_regs[1];
625 ANACTRL->ADC_CTRL = analog_ctrl_regs[2];
626 ANACTRL->XO32M_CTRL = analog_ctrl_regs[3];
627 ANACTRL->BOD_DCDC_INT_CTRL = analog_ctrl_regs[4];
628 ANACTRL->RINGO0_CTRL = analog_ctrl_regs[5];
629 ANACTRL->RINGO1_CTRL = analog_ctrl_regs[6];
630 ANACTRL->RINGO2_CTRL = analog_ctrl_regs[7];
631 ANACTRL->LDO_XO32M = analog_ctrl_regs[8];
632 ANACTRL->AUX_BIAS = analog_ctrl_regs[9];
633 }
634
635 /* @TODO Guillaume: add save/restore entropy during PowerDown */
636 /* Restore Entropy for RNG */
637 if ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_RNG) != 0UL)
638 {
639 RNG->POWERDOWN &= ~RNG_POWERDOWN_POWERDOWN_MASK;
640 for (int i = 0; i < 6; i++)
641 {
642 RNG->ENTROPY_INJECT = rng_entropy_save[i];
643 }
644 }
645 }
646
647 /**
648 * brief PMC Deep Sleep Power Down function call
649 * return nothing
650 */
POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t wakeup_io_ctrl)651 void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,
652 uint32_t sram_retention_ctrl,
653 uint64_t wakeup_interrupts,
654 uint32_t wakeup_io_ctrl)
655 {
656 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
657 uint32_t cpu0_nmi_enable;
658 uint32_t cpu0_int_enable_0;
659 uint32_t cpu0_int_enable_1;
660 uint32_t pmc_reset_ctrl;
661
662 /* Clear Low Power Mode configuration variable */
663 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
664
665 /* Configure Low Power Mode configuration variable */
666 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN
667 << LOWPOWER_CFG_LPMODE_INDEX; /* DEEP POWER DOWN mode */
668
669 /* Only FRO32K, XTAL32K and LDO_MEM can be stay powered during DEEPPOWERDOWN */
670 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BIAS | (uint32_t)kPDRUNCFG_PD_BODVBAT |
671 (uint32_t)kPDRUNCFG_PD_FRO1M | (uint32_t)kPDRUNCFG_PD_COMP;
672
673 /* SRAM retention control during DEEPPOWERDOWN */
674 /* RAM00 used by ROM code to restart. */
675 sram_retention_ctrl = sram_retention_ctrl & (~(LOWPOWER_SRAMRETCTRL_RETEN_RAM00));
676
677 /* SRAM retention control during DEEPPOWERDOWN */
678 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
679
680 /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
681 if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
682 {
683 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
684 }
685
686 /* Voltage control in Low Power Modes */
687 /* The Memories Voltage settings below are for voltage scaling */
688 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN, 0);
689
690 lv_low_power_mode_cfg.WAKEUPINT =
691 wakeup_interrupts & (WAKEUP_RTC_LITE_ALARM_WAKEUP |
692 WAKEUP_OS_EVENT_TIMER); /* CPU Wake up sources control : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
693 WAKEUP_OS_EVENT_TIMER */
694 lv_low_power_mode_cfg.WAKEUPSRC =
695 wakeup_interrupts &
696 (WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER |
697 WAKEUP_ALLWAKEUPIOS); /*!< Hardware Wake up sources control: : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
698 WAKEUP_OS_EVENT_TIMER and WAKEUP_ALLWAKEUPIOS */
699
700 /* Wake up I/O sources */
701 lv_low_power_mode_cfg.WAKEUPIOSRC = lf_wakeup_io_ctrl(wakeup_io_ctrl);
702
703 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
704 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
705
706 /* Save the configuration of the CPU interrupt enable Registers */
707 cpu0_int_enable_0 = NVIC->ISER[0];
708 cpu0_int_enable_1 = NVIC->ISER[1];
709
710 /* Save the configuration of the PMC RESETCTRL register */
711 pmc_reset_ctrl = PMC->RESETCTRL;
712
713 /* Disable BoD VBAT and BoD Core resets */
714 /* BOD VBAT disable reset */
715 PMC->RESETCTRL &= (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
716 PMC->RESETCTRL |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
717 (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
718
719 /* BOD CORE disable reset */
720 PMC->RESETCTRL &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
721 PMC->RESETCTRL |= (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
722 (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
723
724 /* Enter low power mode */
725 POWER_EnterLowPower(&lv_low_power_mode_cfg);
726
727 /* Restore the configuration of the NMI Register */
728 SYSCON->NMISRC |= cpu0_nmi_enable;
729
730 /* Restore PMC RESETCTRL register */
731 PMC->RESETCTRL = pmc_reset_ctrl;
732
733 /* Restore the configuration of the CPU interrupt enable Registers */
734 NVIC->ISER[0] = cpu0_int_enable_0;
735 NVIC->ISER[1] = cpu0_int_enable_1;
736 }
737
738 /**
739 * brief PMC Sleep function call
740 * return nothing
741 */
POWER_EnterSleep(void)742 void POWER_EnterSleep(void)
743 {
744 uint32_t pmsk;
745 pmsk = __get_PRIMASK();
746 __disable_irq();
747 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
748 __WFI();
749 __set_PRIMASK(pmsk);
750 }
751
752 /**
753 * @brief
754 * @param
755 * @return
756 */
lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode,uint32_t p_dcdc_voltage)757 static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage)
758 {
759 #define FLASH_NMPA_LDO_AO_ADDRS (FLASH_NMPA_BASE + 0x0F4U)
760 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK (0x100U)
761 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK (0x3E00U)
762 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT (9U)
763 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK (0x10000U)
764 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK (0x3E0000U)
765 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT (17U)
766 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK (0x1000000U)
767 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK (0x3E000000U)
768 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT (25U)
769
770 uint32_t ldo_ao_trim, voltage;
771 uint32_t lv_v_ldo_pmu, lv_v_ldo_pmu_boost;
772
773 ldo_ao_trim = (*((volatile unsigned int *)(FLASH_NMPA_LDO_AO_ADDRS)));
774
775 switch (p_lp_mode)
776 {
777 case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
778 {
779 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK) != 0UL)
780 {
781 /* Apply settings coming from Flash */
782 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT;
783 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
784 }
785 else
786 {
787 /* Apply default settings */
788 lv_v_ldo_pmu = (uint32_t)V_AO_0P900;
789 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P850;
790 }
791 }
792 break;
793
794 case LOWPOWER_CFG_LPMODE_POWERDOWN:
795 {
796 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK) != 0UL)
797 {
798 /* Apply settings coming from Flash */
799 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK) >> FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT;
800 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
801 }
802 else
803 {
804 /* Apply default settings */
805 lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
806 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
807 }
808 }
809 break;
810
811 case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
812 {
813 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK) != 0UL)
814 {
815 /* Apply settings coming from Flash */
816 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT;
817 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
818 }
819 else
820 {
821 /* Apply default settings */
822 lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
823 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
824 }
825 }
826 break;
827
828 default:
829 /* Should never reach this point */
830 lv_v_ldo_pmu = (uint32_t)V_AO_1P100;
831 lv_v_ldo_pmu_boost = (uint32_t)V_AO_1P050;
832 break;
833 }
834
835 /* The Memories Voltage settings below are for voltage scaling */
836 voltage =
837 (lv_v_ldo_pmu << LOWPOWER_VOLTAGE_LDO_PMU_INDEX) | /* */
838 (lv_v_ldo_pmu_boost << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX) | /* */
839 ((uint32_t)V_AO_0P750 << LOWPOWER_VOLTAGE_LDO_MEM_INDEX) | /* Set to 0.75V (voltage Scaling) */
840 ((uint32_t)V_AO_0P700 << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX) | /* Set to 0.7V (voltage Scaling) */
841 ((uint32_t)V_DEEPSLEEP_0P900
842 << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX) | /* Set to 0.90 V (Not used because LDO_DEEP_SLEEP is disabled)*/
843 (p_dcdc_voltage << LOWPOWER_VOLTAGE_DCDC_INDEX) /* */
844 ;
845
846 return (voltage);
847 }
848
849 /**
850 * @brief
851 * @param
852 * @return
853 */
lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)854 static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)
855 {
856 uint32_t wake_up_type;
857 uint32_t wakeup_io_ctrl_reg;
858 uint8_t use_external_pullupdown = 0;
859
860 /* Configure Pull up & Pull down based on the required wake-up edge */
861 CLOCK_EnableClock(kCLOCK_Iocon);
862
863 wakeup_io_ctrl_reg = 0UL;
864
865 /* Wake-up I/O 0 */
866 wake_up_type = (p_wakeup_io_ctrl & 0x3UL) >> LOWPOWER_WAKEUPIOSRC_PIO0_INDEX;
867 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO0_INDEX);
868 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_MASK) >>
869 LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX);
870
871 if (use_external_pullupdown == 0UL)
872 {
873 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
874 {
875 /* Rising edge and both rising and falling edges */
876 IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
877 wakeup_io_ctrl_reg |=
878 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
879 }
880 else
881 {
882 if (wake_up_type == 2UL)
883 {
884 /* Falling edge only */
885 IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
886 wakeup_io_ctrl_reg |=
887 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
888 }
889 else
890 {
891 /* Wake-up I/O is disabled : set it as required by the user */
892 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) != 0UL)
893 {
894 /* Wake-up I/O is configured as Plain Input */
895 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
896 wakeup_io_ctrl_reg |=
897 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
898 }
899 else
900 {
901 /* Wake-up I/O is configured as pull-up or pull-down */
902 // @TODO update for mask name
903 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK) != 0UL)
904 {
905 /* Wake-up I/O is configured as pull-up */
906 wakeup_io_ctrl_reg |=
907 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
908 }
909 else
910 {
911 /* Wake-up I/O is configured as pull-down */
912 wakeup_io_ctrl_reg |=
913 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
914 }
915 }
916 }
917 }
918 }
919 else
920 {
921 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
922 }
923
924 /* Wake-up I/O 1 */
925 wake_up_type = (p_wakeup_io_ctrl & 0xCUL) >> LOWPOWER_WAKEUPIOSRC_PIO1_INDEX;
926 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO1_INDEX);
927 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_MASK) >>
928 LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX);
929
930 if (use_external_pullupdown == 0UL)
931 {
932 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
933 {
934 /* Rising edge and both rising and falling edges */
935 IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
936 wakeup_io_ctrl_reg |=
937 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
938 }
939 else
940 {
941 if (wake_up_type == 2UL)
942 {
943 /* Falling edge only */
944 IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
945 wakeup_io_ctrl_reg |=
946 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
947 }
948 else
949 {
950 /* Wake-up I/O is disabled : set it as required by the user */
951 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) != 0UL)
952 {
953 /* Wake-up I/O is configured as Plain Input */
954 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
955 wakeup_io_ctrl_reg |=
956 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
957 }
958 else
959 {
960 /* Wake-up I/O is configured as pull-up or pull-down */
961 // @TODO update for mask name
962 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK) != 0UL)
963 {
964 /* Wake-up I/O is configured as pull-up */
965 wakeup_io_ctrl_reg |=
966 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
967 }
968 else
969 {
970 /* Wake-up I/O is configured as pull-down */
971 wakeup_io_ctrl_reg |=
972 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
973 }
974 }
975 }
976 }
977 }
978 else
979 {
980 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
981 }
982
983 /* Wake-up I/O 2 */
984 wake_up_type = (p_wakeup_io_ctrl & 0x30UL) >> LOWPOWER_WAKEUPIOSRC_PIO2_INDEX;
985 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO2_INDEX);
986 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_MASK) >>
987 LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX);
988
989 if (use_external_pullupdown == 0UL)
990 {
991 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
992 {
993 /* Rising edge and both rising and falling edges */
994 IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
995 wakeup_io_ctrl_reg |=
996 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
997 }
998 else
999 {
1000 if (wake_up_type == 2UL)
1001 {
1002 /* Falling edge only */
1003 IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
1004 wakeup_io_ctrl_reg |=
1005 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1006 }
1007 else
1008 {
1009 /* Wake-up I/O is disabled : set it as required by the user */
1010 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) != 0UL)
1011 {
1012 /* Wake-up I/O is configured as Plain Input */
1013 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
1014 wakeup_io_ctrl_reg |=
1015 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1016 }
1017 else
1018 {
1019 /* Wake-up I/O is configured as pull-up or pull-down */
1020 // @TODO update for mask name
1021 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK) != 0UL)
1022 {
1023 /* Wake-up I/O is configured as pull-up */
1024 wakeup_io_ctrl_reg |=
1025 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1026 }
1027 else
1028 {
1029 /* Wake-up I/O is configured as pull-down */
1030 wakeup_io_ctrl_reg |=
1031 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1032 }
1033 }
1034 }
1035 }
1036 }
1037 else
1038 {
1039 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1040 }
1041
1042 /* Wake-up I/O 3 */
1043 wake_up_type = (p_wakeup_io_ctrl & 0xC0UL) >> LOWPOWER_WAKEUPIOSRC_PIO3_INDEX;
1044 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO3_INDEX);
1045 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_MASK) >>
1046 LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX);
1047
1048 if (use_external_pullupdown == 0UL)
1049 {
1050 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
1051 {
1052 /* Rising edge and both rising and falling edges */
1053 IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
1054 wakeup_io_ctrl_reg |=
1055 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1056 }
1057 else
1058 {
1059 if (wake_up_type == 2UL)
1060 {
1061 /* Falling edge only */
1062 IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
1063 wakeup_io_ctrl_reg |=
1064 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1065 }
1066 else
1067 {
1068 /* Wake-up I/O is disabled : set it as required by the user */
1069 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) != 0UL)
1070 {
1071 /* Wake-up I/O is configured as Plain Input */
1072 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1073 wakeup_io_ctrl_reg |=
1074 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1075 }
1076 else
1077 {
1078 /* Wake-up I/O is configured as pull-up or pull-down */
1079 // @TODO update for mask name
1080 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK) != 0UL)
1081 {
1082 /* Wake-up I/O is configured as pull-up */
1083 wakeup_io_ctrl_reg |=
1084 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1085 }
1086 else
1087 {
1088 /* Wake-up I/O is configured as pull-down */
1089 wakeup_io_ctrl_reg |=
1090 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1091 }
1092 }
1093 }
1094 }
1095 }
1096 else
1097 {
1098 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1099 }
1100
1101 return (wakeup_io_ctrl_reg);
1102 }
1103
1104 /**
1105 * @brief
1106 * @param
1107 * @return
1108 */
CLOCK_u8OscCapConvert(uint8_t u8OscCap,uint8_t u8CapBankDiscontinuity)1109 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
1110 {
1111 /* Compensate for discontinuity in the capacitor banks */
1112 if (u8OscCap < 64U)
1113 {
1114 if (u8OscCap >= u8CapBankDiscontinuity)
1115 {
1116 u8OscCap -= u8CapBankDiscontinuity;
1117 }
1118 else
1119 {
1120 u8OscCap = 0U;
1121 }
1122 }
1123 else
1124 {
1125 if (u8OscCap <= (127U - u8CapBankDiscontinuity))
1126 {
1127 u8OscCap += u8CapBankDiscontinuity;
1128 }
1129 else
1130 {
1131 u8OscCap = 127U;
1132 }
1133 }
1134 return u8OscCap;
1135 }
1136
1137 /**
1138 * @brief Described in fsl_common.h
1139 * @param
1140 * @return
1141 */
lowpower_set_system_voltage(uint32_t system_voltage_mv)1142 static void lowpower_set_system_voltage(uint32_t system_voltage_mv)
1143 {
1144 /*
1145 * Set system voltage
1146 */
1147 uint32_t lv_ldo_ao = (uint32_t)V_AO_1P100; /* <ldo_ao> */
1148 uint32_t lv_ldo_ao_boost = (uint32_t)V_AO_1P150; /* <ldo_ao_boost> */
1149 uint32_t lv_dcdc = (uint32_t)V_DCDC_1P100; /* <dcdc> */
1150
1151 if (system_voltage_mv <= 950UL)
1152 {
1153 lv_dcdc = (uint32_t)V_DCDC_0P950;
1154 lv_ldo_ao = (uint32_t)V_AO_0P960;
1155 lv_ldo_ao_boost = (uint32_t)V_AO_1P010;
1156 }
1157 else if (system_voltage_mv <= 975UL)
1158 {
1159 lv_dcdc = (uint32_t)V_DCDC_0P975;
1160 lv_ldo_ao = (uint32_t)V_AO_0P980;
1161 lv_ldo_ao_boost = (uint32_t)V_AO_1P030;
1162 }
1163 else if (system_voltage_mv <= 1000UL)
1164 {
1165 lv_dcdc = (uint32_t)V_DCDC_1P000;
1166 lv_ldo_ao = (uint32_t)V_AO_1P000;
1167 lv_ldo_ao_boost = (uint32_t)V_AO_1P050;
1168 }
1169 else if (system_voltage_mv <= 1025UL)
1170 {
1171 lv_dcdc = (uint32_t)V_DCDC_1P025;
1172 lv_ldo_ao = (uint32_t)V_AO_1P030;
1173 lv_ldo_ao_boost = (uint32_t)V_AO_1P080;
1174 }
1175 else if (system_voltage_mv <= 1050UL)
1176 {
1177 lv_dcdc = (uint32_t)V_DCDC_1P050;
1178 lv_ldo_ao = (uint32_t)V_AO_1P060;
1179 lv_ldo_ao_boost = (uint32_t)V_AO_1P110;
1180 }
1181 else if (system_voltage_mv <= 1075UL)
1182 {
1183 lv_dcdc = (uint32_t)V_DCDC_1P075;
1184 lv_ldo_ao = (uint32_t)V_AO_1P080;
1185 lv_ldo_ao_boost = (uint32_t)V_AO_1P130;
1186 }
1187 else if (system_voltage_mv <= 1100UL)
1188 {
1189 lv_dcdc = (uint32_t)V_DCDC_1P100;
1190 lv_ldo_ao = (uint32_t)V_AO_1P100;
1191 lv_ldo_ao_boost = (uint32_t)V_AO_1P150;
1192 }
1193 else if (system_voltage_mv <= 1125UL)
1194 {
1195 lv_dcdc = (uint32_t)V_DCDC_1P125;
1196 lv_ldo_ao = (uint32_t)V_AO_1P130;
1197 lv_ldo_ao_boost = (uint32_t)V_AO_1P160;
1198 }
1199 else if (system_voltage_mv <= 1150UL)
1200 {
1201 lv_dcdc = (uint32_t)V_DCDC_1P150;
1202 lv_ldo_ao = (uint32_t)V_AO_1P160;
1203 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1204 }
1205 else if (system_voltage_mv <= 1175UL)
1206 {
1207 lv_dcdc = (uint32_t)V_DCDC_1P175;
1208 lv_ldo_ao = (uint32_t)V_AO_1P160;
1209 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1210 }
1211 else
1212 {
1213 lv_dcdc = (uint32_t)V_DCDC_1P200;
1214 lv_ldo_ao = (uint32_t)V_AO_1P160;
1215 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1216 }
1217
1218 /* Set up LDO Always-On voltages */
1219 PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_MASK) & (~PMC_LDOPMU_VADJ_BOOST_MASK)) | PMC_LDOPMU_VADJ(lv_ldo_ao) |
1220 PMC_LDOPMU_VADJ_BOOST(lv_ldo_ao_boost);
1221
1222 /* Set up DCDC voltage */
1223 PMC->DCDC0 = (PMC->DCDC0 & (~PMC_DCDC0_VOUT_MASK)) | PMC_DCDC0_VOUT(lv_dcdc);
1224 }
1225
1226 /**
1227 * @brief Described in fsl_common.h
1228 * @param
1229 * @return
1230 */
lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)1231 static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)
1232 {
1233 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U)
1234 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U)
1235 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS (FLASH_NMPA_BASE + 0xE8U)
1236 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS (FLASH_NMPA_BASE + 0xECU)
1237 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS (FLASH_NMPA_BASE + 0xD8U)
1238 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS (FLASH_NMPA_BASE + 0xDCU)
1239
1240 const uint32_t PMC_DCDC0_DEFAULT = 0x010C4E68;
1241 const uint32_t PMC_DCDC1_DEFAULT = 0x01803A98;
1242
1243 uint32_t dcdcTrimValue0;
1244 uint32_t dcdcTrimValue1;
1245
1246 switch (dcdc_power_profile)
1247 {
1248 case DCDC_POWER_PROFILE_LOW:
1249 /* Low */
1250 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS)));
1251 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS)));
1252
1253 if (0UL != (dcdcTrimValue0 & 0x1UL))
1254 {
1255 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1256
1257 PMC->DCDC0 = dcdcTrimValue0;
1258 PMC->DCDC1 = dcdcTrimValue1;
1259 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1260 PRINTF(
1261 "\nINFO : DCDC Power Profile set to "
1262 "LOW"
1263 "\n");
1264 #endif
1265 }
1266 break;
1267
1268 case DCDC_POWER_PROFILE_MEDIUM:
1269 /* Medium */
1270 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS)));
1271 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS)));
1272
1273 if (0UL != (dcdcTrimValue0 & 0x1UL))
1274 {
1275 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1276
1277 PMC->DCDC0 = dcdcTrimValue0;
1278 PMC->DCDC1 = dcdcTrimValue1;
1279 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1280 PRINTF(
1281 "\nINFO : DCDC Power Profile set to "
1282 "MEDIUM"
1283 "\n");
1284 #endif
1285 }
1286 break;
1287
1288 case DCDC_POWER_PROFILE_HIGH:
1289 /* High */
1290 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS)));
1291 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS)));
1292
1293 if (0UL != (dcdcTrimValue0 & 0x1UL))
1294 {
1295 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1296
1297 PMC->DCDC0 = dcdcTrimValue0;
1298 PMC->DCDC1 = dcdcTrimValue1;
1299 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1300 PRINTF(
1301 "\nINFO : DCDC Power Profile set to "
1302 "HIGH"
1303 "\n");
1304 #endif
1305 }
1306 break;
1307
1308 default:
1309 /* Low */
1310 PMC->DCDC0 = PMC_DCDC0_DEFAULT;
1311 PMC->DCDC1 = PMC_DCDC1_DEFAULT;
1312 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1313 PRINTF(
1314 "\nINFO : DCDC Power Profile set to "
1315 "LOW"
1316 "\n");
1317 #endif
1318 break;
1319 }
1320 }
1321
1322 /**
1323 * @brief
1324 * @param
1325 * @return
1326 */
lowpower_get_part_process_corner(void)1327 static lowpower_process_corner_enum lowpower_get_part_process_corner(void)
1328 {
1329 #define FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS (FLASH_NMPA_BASE + 0x130U)
1330 #define FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS (FLASH_NMPA_BASE + 0x140U)
1331
1332 lowpower_process_corner_enum part_process_corner;
1333 uint32_t pvt_ringo_hz;
1334 uint32_t pvt_ringo_0 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS)));
1335 uint32_t pvt_ringo_1 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS)));
1336
1337 /*
1338 * Check that the PVT Monitors Trimmings in flash are valid.
1339 */
1340 if (0UL != (pvt_ringo_0 & 0x1UL))
1341 {
1342 /* PVT Trimmings in Flash are valid */
1343 pvt_ringo_0 = pvt_ringo_0 >> 1;
1344 }
1345 else
1346 {
1347 /* PVT Trimmings in Flash are NOT valid (average value assumed) */
1348 pvt_ringo_0 = PROCESS_NNN_AVG_HZ;
1349 }
1350
1351 if (0UL != (pvt_ringo_1 & 0x1UL))
1352 {
1353 /* PVT Trimmings in Flash are valid */
1354 pvt_ringo_1 = pvt_ringo_1 >> 1;
1355 }
1356 else
1357 {
1358 /* PVT Trimmings in Flash are NOT valid (average value assumed) */
1359 pvt_ringo_1 = PROCESS_NNN_AVG_HZ;
1360 }
1361
1362 if (pvt_ringo_1 <= pvt_ringo_0)
1363 {
1364 pvt_ringo_hz = pvt_ringo_1;
1365 }
1366 else
1367 {
1368 pvt_ringo_hz = pvt_ringo_0;
1369 }
1370
1371 /*
1372 * Determine the process corner based on the value of the Ring Oscillator frequency
1373 */
1374 if (pvt_ringo_hz <= PROCESS_NNN_MIN_HZ)
1375 {
1376 /* SSS Process Corner */
1377 part_process_corner = PROCESS_CORNER_SSS;
1378 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1379 PRINTF(
1380 "\nINFO : Process Corner : "
1381 "SSS"
1382 "\n");
1383 #endif
1384 }
1385 else
1386 {
1387 if (pvt_ringo_hz <= PROCESS_NNN_MAX_HZ)
1388 {
1389 /* NNN Process Corner */
1390 part_process_corner = PROCESS_CORNER_NNN;
1391 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1392 PRINTF(
1393 "\nINFO : Process Corner : "
1394 "NNN"
1395 "\n");
1396 #endif
1397 }
1398 else
1399 {
1400 /* FFF Process Corner */
1401 part_process_corner = PROCESS_CORNER_FFF;
1402 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1403 PRINTF(
1404 "\nINFO : Process Corner : "
1405 "FFF"
1406 "\n");
1407 #endif
1408 }
1409 }
1410
1411 return (part_process_corner);
1412 }
1413
1414 /**
1415 * @brief Described in fsl_common.h
1416 * @param
1417 * @return
1418 */
lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)1419 static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)
1420 {
1421 /* Get Sample Process Corner */
1422 lowpower_process_corner_enum part_process_corner = lowpower_get_part_process_corner();
1423
1424 switch (part_process_corner)
1425 {
1426 case PROCESS_CORNER_SSS:
1427 /* Slow Corner */
1428 {
1429 switch (dcdc_power_profile)
1430 {
1431 case DCDC_POWER_PROFILE_MEDIUM:
1432 /* Medium */
1433 lowpower_set_system_voltage(VOLTAGE_SSS_MED_MV);
1434 break;
1435
1436 case DCDC_POWER_PROFILE_HIGH:
1437 /* High */
1438 lowpower_set_system_voltage(VOLTAGE_SSS_HIG_MV);
1439 break;
1440
1441 default:
1442 /* DCDC_POWER_PROFILE_LOW */
1443 lowpower_set_system_voltage(VOLTAGE_SSS_LOW_MV);
1444 break;
1445 } // switch(dcdc_power_profile)
1446 }
1447 break;
1448
1449 case PROCESS_CORNER_FFF:
1450 /* Fast Corner */
1451 {
1452 switch (dcdc_power_profile)
1453 {
1454 case DCDC_POWER_PROFILE_MEDIUM:
1455 /* Medium */
1456 lowpower_set_system_voltage(VOLTAGE_FFF_MED_MV);
1457 break;
1458
1459 case DCDC_POWER_PROFILE_HIGH:
1460 /* High */
1461 lowpower_set_system_voltage(VOLTAGE_FFF_HIG_MV);
1462 break;
1463
1464 default:
1465 /* DCDC_POWER_PROFILE_LOW */
1466 lowpower_set_system_voltage(VOLTAGE_FFF_LOW_MV);
1467 break;
1468 } // switch(dcdc_power_profile)
1469 }
1470 break;
1471
1472 default:
1473 /* Nominal (NNN) and all others Process Corners : assume Nominal Corner */
1474 {
1475 switch (dcdc_power_profile)
1476 {
1477 case DCDC_POWER_PROFILE_MEDIUM:
1478 /* Medium */
1479 lowpower_set_system_voltage(VOLTAGE_NNN_MED_MV);
1480 break;
1481
1482 case DCDC_POWER_PROFILE_HIGH:
1483 /* High */
1484 lowpower_set_system_voltage(VOLTAGE_NNN_HIG_MV);
1485 break;
1486
1487 default:
1488 /* DCDC_POWER_PROFILE_LOW */
1489 lowpower_set_system_voltage(VOLTAGE_NNN_LOW_MV);
1490 break;
1491 } // switch(dcdc_power_profile)
1492 break;
1493 }
1494 } // switch(part_process_corner)
1495 }
1496
1497 /**
1498 * @brief Described in fsl_common.h
1499 * @param
1500 * @return
1501 */
POWER_SetVoltageForFreq(uint32_t system_freq_hz)1502 void POWER_SetVoltageForFreq(uint32_t system_freq_hz)
1503 {
1504 if (system_freq_hz <= DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ)
1505 {
1506 /* [0 Hz - DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz] */
1507 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_LOW); /* DCDC VOUT = 1.05 V by default */
1508 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_LOW);
1509 }
1510 else
1511 {
1512 if (system_freq_hz <= DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ)
1513 {
1514 /* ]DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz - DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz] */
1515 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_MEDIUM); /* DCDC VOUT = 1.15 V by default */
1516 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_MEDIUM);
1517 }
1518 else
1519 {
1520 /* > DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz */
1521 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_HIGH); /* DCDC VOUT = 1.2 V by default */
1522 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_HIGH);
1523 }
1524 }
1525 }
1526
POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,int32_t pi32_16MfXtalPPcbParCappF_x100,int32_t pi32_16MfXtalNPcbParCappF_x100)1527 void POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,
1528 int32_t pi32_16MfXtalPPcbParCappF_x100,
1529 int32_t pi32_16MfXtalNPcbParCappF_x100)
1530 {
1531 uint32_t u32XOTrimValue;
1532 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
1533 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
1534 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
1535 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
1536 uint32_t u32RegVal;
1537 int32_t i32Tmp;
1538
1539 /* Enable and set LDO, if not already done */
1540 POWER_SetXtal16mhzLdo();
1541 /* Get Cal values from Flash */
1542 u32XOTrimValue = GET_16MXO_TRIM();
1543 /* Check validity and apply */
1544 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
1545 {
1546 /* These fields are 7 bits, unsigned */
1547 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
1548 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
1549 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
1550 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
1551 /* This field is 1 bit */
1552 u8XOSlave = (uint8_t)((u32XOTrimValue >> 30UL) & 0x1UL);
1553 /* Linear fit coefficients calculation */
1554 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
1555 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
1556 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
1557 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
1558 }
1559 else
1560 {
1561 iaXin_x4 = 20; // gain in LSB/pF
1562 ibXin = -9; // offset in LSB
1563 iaXout_x4 = 20; // gain in LSB/pF
1564 ibXout = -13; // offset in LSB
1565 u8XOSlave = 0;
1566 }
1567 /* In & out load cap calculation with derating */
1568 iXOCapInpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalNPcbParCappF_x100 +
1569 39 * ((int32_t)XO_SLAVE_EN - (int32_t)u8XOSlave) - 15;
1570 iXOCapOutpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalPPcbParCappF_x100 - 21;
1571 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
1572 i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
1573 u8XOCapInCtrl = (uint8_t)i32Tmp;
1574 i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
1575 u8XOCapOutCtrl = (uint8_t)i32Tmp;
1576 /* Read register and clear fields to be written */
1577 u32RegVal = ANACTRL->XO32M_CTRL;
1578 u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
1579 /* Configuration of 32 MHz XO output buffers */
1580 #if (XO_SLAVE_EN == 0)
1581 u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
1582 #else
1583 u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
1584 #endif
1585 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
1586 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
1587 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
1588 /* Write back to register */
1589 ANACTRL->XO32M_CTRL = u32RegVal;
1590 }
1591
POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,int32_t pi32_32kfXtalPPcbParCappF_x100,int32_t pi32_32kfXtalNPcbParCappF_x100)1592 void POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
1593 int32_t pi32_32kfXtalPPcbParCappF_x100,
1594 int32_t pi32_32kfXtalNPcbParCappF_x100)
1595 {
1596 uint32_t u32XOTrimValue;
1597 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
1598 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
1599 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
1600 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
1601 uint32_t u32RegVal;
1602 int32_t i32Tmp;
1603 /* Get Cal values from Flash */
1604 u32XOTrimValue = GET_32KXO_TRIM();
1605 /* check validity and apply */
1606 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
1607 {
1608 /* These fields are 7 bits, unsigned */
1609 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
1610 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
1611 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
1612 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
1613 /* Linear fit coefficients calculation */
1614 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
1615 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
1616 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
1617 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
1618 }
1619 else
1620 {
1621 iaXin_x4 = 16; // gain in LSB/pF
1622 ibXin = 12; // offset in LSB
1623 iaXout_x4 = 16; // gain in LSB/pF
1624 ibXout = 11; // offset in LSB
1625 }
1626
1627 /* In & out load cap calculation with derating */
1628 iXOCapInpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
1629 iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
1630
1631 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
1632 i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
1633 u8XOCapInCtrl = (uint8_t)i32Tmp;
1634 i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
1635 u8XOCapOutCtrl = (uint8_t)i32Tmp;
1636
1637 /* Read register and clear fields to be written */
1638 u32RegVal = PMC->XTAL32K;
1639 u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
1640
1641 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
1642 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23) << PMC_XTAL32K_CAPBANKIN_SHIFT;
1643 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
1644
1645 /* Write back to register */
1646 PMC->XTAL32K = u32RegVal;
1647 }
1648
POWER_SetXtal16mhzLdo(void)1649 void POWER_SetXtal16mhzLdo(void)
1650 {
1651 uint32_t temp;
1652 const uint32_t u32Mask =
1653 (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
1654
1655 const uint32_t u32Value =
1656 (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
1657
1658 /* Enable & set-up XTAL 32 MHz clock LDO */
1659 temp = ANACTRL->LDO_XO32M;
1660
1661 if ((temp & u32Mask) != u32Value)
1662 {
1663 temp &= ~u32Mask;
1664
1665 /*
1666 * Enable the XTAL32M LDO
1667 * Adjust the output voltage level, 0x5 for 1.1V
1668 * Adjust the biasing current, 0x2 value
1669 * Stability configuration, 0x1 default mode
1670 */
1671 temp |= u32Value;
1672
1673 ANACTRL->LDO_XO32M = temp;
1674
1675 /* Delay for LDO to be up */
1676 // CLOCK_uDelay(20);
1677 }
1678
1679 /* Enable LDO XO32M */
1680 PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXO32M_MASK;
1681 }
1682
POWER_SetXtal16mhzTrim(uint32_t amp,uint32_t gm)1683 void POWER_SetXtal16mhzTrim(uint32_t amp, uint32_t gm)
1684 {
1685 uint32_t temp;
1686 const uint32_t u32Mask = (ANACTRL_XO32M_CTRL_AMP_MASK | ANACTRL_XO32M_CTRL_GM_MASK);
1687 const uint32_t u32Value = (ANACTRL_XO32M_CTRL_AMP(amp) | ANACTRL_XO32M_CTRL_GM(gm));
1688
1689 /* Set-up XTAL 16-MHz Trimmings */
1690 temp = ANACTRL->XO32M_CTRL;
1691 temp &= ~u32Mask;
1692 temp |= u32Value;
1693 ANACTRL->XO32M_CTRL = temp;
1694 }
1695
1696 /*!
1697 * @brief set BOD VBAT level.
1698 *
1699 * @param level BOD detect level
1700 * @param hyst BoD Hysteresis control
1701 * @param enBodVbatReset VBAT brown out detect reset
1702 */
POWER_SetBodVbatLevel(power_bod_vbat_level_t level,power_bod_hyst_t hyst,bool enBodVbatReset)1703 void POWER_SetBodVbatLevel(power_bod_vbat_level_t level, power_bod_hyst_t hyst, bool enBodVbatReset)
1704 {
1705 uint32_t pmc_reset_ctrl;
1706 /* BOD VBAT disable reset */
1707 pmc_reset_ctrl =
1708 PMC->RESETCTRL & (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
1709 pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
1710 (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
1711
1712 PMC->RESETCTRL = pmc_reset_ctrl;
1713
1714 PMC->BODVBAT = (PMC->BODVBAT & (~(PMC_BODVBAT_TRIGLVL_MASK | PMC_BODVBAT_HYST_MASK))) | PMC_BODVBAT_TRIGLVL(level) |
1715 PMC_BODVBAT_HYST(hyst);
1716
1717 /* BOD VBAT enable reset */
1718 if ((uint32_t)enBodVbatReset == 1UL)
1719 {
1720 pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
1721 pmc_reset_ctrl |= (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
1722 (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
1723 PMC->RESETCTRL = pmc_reset_ctrl;
1724 }
1725 }
1726
1727 #if defined(PMC_BODCORE_TRIGLVL_MASK)
1728 /*!
1729 * @brief set BOD core level.
1730 *
1731 * @param level BOD detect level
1732 * @param hyst BoD Hysteresis control
1733 * @param enBodCoreReset core brown out detect reset
1734 */
POWER_SetBodCoreLevel(power_bod_core_level_t level,power_bod_hyst_t hyst,bool enBodCoreReset)1735 void POWER_SetBodCoreLevel(power_bod_core_level_t level, power_bod_hyst_t hyst, bool enBodCoreReset)
1736 {
1737 uint32_t pmc_reset_ctrl;
1738 /* BOD CORE disable reset */
1739 pmc_reset_ctrl =
1740 PMC->RESETCTRL & (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
1741 pmc_reset_ctrl |=
1742 (0x2 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) | (0x2 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
1743
1744 PMC->RESETCTRL = pmc_reset_ctrl;
1745
1746 PMC->BODCORE = (PMC->BODCORE & (~(PMC_BODCORE_TRIGLVL_MASK | PMC_BODCORE_HYST_MASK))) | PMC_BODCORE_TRIGLVL(level) |
1747 PMC_BODCORE_HYST(hyst);
1748
1749 /* BOD CORE enable reset */
1750 if (enBodCoreReset == 1)
1751 {
1752 pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
1753 pmc_reset_ctrl |= (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
1754 (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
1755 PMC->RESETCTRL = pmc_reset_ctrl;
1756 }
1757 }
1758 #endif
1759
1760 /**
1761 * @brief Return some key information related to the device reset causes / wake-up sources, for all power modes.
1762 * @param p_reset_cause : the device reset cause, according to the definition of power_device_reset_cause_t type.
1763 * @param p_boot_mode : the device boot mode, according to the definition of power_device_boot_mode_t type.
1764 * @param p_wakeupio_cause: the wake-up pin sources, according to the definition of register PMC->WAKEIOCAUSE[3:0].
1765
1766 * @return Nothing
1767 *
1768 * !!! IMPORTANT ERRATA - IMPORTANT ERRATA - IMPORTANT ERRATA !!!
1769 * !!! valid ONLY for LPC55S69 (not for LPC55S16 and LPC55S06) !!!
1770 * !!! when FALLING EDGE DETECTION is enabled on wake-up pins: !!!
1771 * - 1. p_wakeupio_cause is NOT ACCURATE
1772 * - 2. Spurious kRESET_CAUSE_DPDRESET_WAKEUPIO* event is reported when
1773 * several wake-up sources are enabled during DEEP-POWER-DOWN
1774 * (like enabling wake-up on RTC and Falling edge wake-up pins)
1775 *
1776 */
POWER_GetWakeUpCause(power_device_reset_cause_t * p_reset_cause,power_device_boot_mode_t * p_boot_mode,uint32_t * p_wakeupio_cause)1777 void POWER_GetWakeUpCause(power_device_reset_cause_t *p_reset_cause,
1778 power_device_boot_mode_t *p_boot_mode,
1779 uint32_t *p_wakeupio_cause)
1780 {
1781 uint32_t reset_cause_reg;
1782 uint32_t boot_mode_reg;
1783
1784 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1785 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1786 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1787 reset_cause_reg = (PMC->AOREG1) & 0x3FF0UL;
1788 #else /* LPC55S69/28 */
1789 reset_cause_reg = (PMC->AOREG1) & 0x1FF0UL;
1790 #endif
1791
1792 /*
1793 * Prioritize interrupts source with respect to their critical level
1794 */
1795 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1796 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1797 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1798 if (0UL != (reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK))
1799 { /* Code Watchdog Reset */
1800 *p_reset_cause = kRESET_CAUSE_CDOGRESET;
1801 *p_boot_mode = kBOOT_MODE_POWER_UP;
1802 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1803 }
1804 else
1805 #endif
1806 {
1807 if (0UL != (reset_cause_reg & PMC_AOREG1_WDTRESET_MASK))
1808 { /* Watchdog Timer Reset */
1809 *p_reset_cause = kRESET_CAUSE_WDTRESET;
1810 *p_boot_mode = kBOOT_MODE_POWER_UP;
1811 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1812 }
1813 else
1814 {
1815 if (0UL != (reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK))
1816 { /* ARM System Reset */
1817 *p_reset_cause = kRESET_CAUSE_ARMSYSTEMRESET;
1818 *p_boot_mode = kBOOT_MODE_POWER_UP;
1819 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1820 }
1821 else
1822 {
1823 boot_mode_reg = (PMC->STATUS & PMC_STATUS_BOOTMODE_MASK) >> PMC_STATUS_BOOTMODE_SHIFT;
1824
1825 if (boot_mode_reg == 0UL) /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset */
1826 {
1827 *p_boot_mode = kBOOT_MODE_POWER_UP; /* All non wake-up from a Low Power mode */
1828 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1829
1830 /*
1831 * Prioritise Reset causes, starting from the strongest (Power On Reset)
1832 */
1833 if (0UL != (reset_cause_reg & PMC_AOREG1_POR_MASK))
1834 { /* Power On Reset */
1835 *p_reset_cause = kRESET_CAUSE_POR;
1836 }
1837 else
1838 {
1839 if (0UL != (reset_cause_reg & PMC_AOREG1_BODRESET_MASK))
1840 { /* Brown-out Detector reset (either BODVBAT or BODCORE) */
1841 *p_reset_cause = kRESET_CAUSE_BODRESET;
1842 }
1843 else
1844 {
1845 if (0UL != (reset_cause_reg & PMC_AOREG1_PADRESET_MASK))
1846 { /* Hardware Pin Reset */
1847 *p_reset_cause = kRESET_CAUSE_PADRESET;
1848 }
1849 else
1850 {
1851 if (0UL != (reset_cause_reg & PMC_AOREG1_SWRRESET_MASK))
1852 { /* Software triggered Reset */
1853 *p_reset_cause = kRESET_CAUSE_SWRRESET;
1854 }
1855 else
1856 { /* Unknown Reset Cause */
1857 *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1858 }
1859 }
1860 }
1861 }
1862
1863 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1864 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1865 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1866 /* Transfer the control of the 4 wake-up pins to IOCON (instead of the Power Management Controller
1867 */
1868 PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1869 #endif
1870 }
1871 else /* DEEP-SLEEP, POWER-DOWN and DEEP-POWER-DOWN */
1872 {
1873 /*
1874 * 1- First, save wakeup_io_cause register ...
1875 */
1876 *p_wakeupio_cause = PMC->WAKEIOCAUSE;
1877
1878 if (boot_mode_reg == 3UL) /* DEEP-POWER-DOWN */
1879 {
1880 *p_boot_mode = kBOOT_MODE_LP_DEEP_POWER_DOWN;
1881
1882 switch (((reset_cause_reg >> PMC_AOREG1_DPDRESET_WAKEUPIO_SHIFT) & 0x7UL))
1883 {
1884 case 1:
1885 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO;
1886 break;
1887 case 2:
1888 *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC;
1889 break;
1890 case 3:
1891 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC;
1892 break;
1893 case 4:
1894 *p_reset_cause = kRESET_CAUSE_DPDRESET_OSTIMER;
1895 break;
1896 case 5:
1897 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER;
1898 break;
1899 case 6:
1900 *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC_OSTIMER;
1901 break;
1902 case 7:
1903 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER;
1904 break;
1905 default:
1906 /* Unknown Reset Cause */
1907 *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1908 break;
1909 }
1910
1911 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1912 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1913 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1914 /*
1915 * 2- Next, transfer the control of the 4 wake-up pins
1916 * to IOCON (instead of the Power Management Controller)
1917 */
1918 PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1919 #endif
1920 }
1921 else /* DEEP-SLEEP and POWER-DOWN */
1922 {
1923 *p_reset_cause = kRESET_CAUSE_NOT_RELEVANT;
1924
1925 /*
1926 * The control of the 4 wake-up pins is already in IOCON,
1927 * so there is nothing special to do.
1928 */
1929
1930 if (boot_mode_reg == 1UL) /* DEEP-SLEEP */
1931 {
1932 *p_boot_mode = kBOOT_MODE_LP_DEEP_SLEEP;
1933 }
1934 else /* POWER-DOWN */
1935 {
1936 *p_boot_mode = kBOOT_MODE_LP_POWER_DOWN;
1937
1938 } /* if ( boot_mode_reg == 1 ) DEEP-SLEEP */
1939
1940 } /* if ( boot_mode == 3 ) DEEP-POWER-DOWN */
1941
1942 } /* if ( boot_mode == 0 ) POWER-UP */
1943
1944 } /* if ( reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK ) */
1945
1946 } /* if ( reset_cause_reg & PMC_AOREG1_WDTRESET_MASK ) */
1947
1948 } /* if ( reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK ) */
1949 }
1950