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 void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage);
306 static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage);
307 static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl);
308 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
309
310 static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile);
311 static lowpower_process_corner_enum lowpower_get_part_process_corner(void);
312 static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile);
313 static lowpower_driver_interface_t *s_lowpowerDriver = (lowpower_driver_interface_t *)(0x130050e4);
314
315 /**
316 * @brief Configures and enters in low power mode
317 * @param p_lowpower_cfg: pointer to a structure that contains all low power mode parameters
318 * @return Nothing
319 *
320 * !!! IMPORTANT NOTES :
321 * 1 - CPU Interrupt Enable registers are updated with p_lowpower_cfg->WAKEUPINT. They are NOT restored by the
322 * API.
323 * 2 - The Non Maskable Interrupt (NMI) should be disable before calling this API (otherwise, there is a risk
324 * of Dead Lock).
325 * 3 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
326 * reset)
327 */
328 static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg);
329
330 /**
331 * @brief
332 * @param
333 * @return
334 */
lf_set_dcdc_power_profile_low(void)335 static void lf_set_dcdc_power_profile_low(void)
336 {
337 #define DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U) // N4M (0x3FCE0U) / N4S (0x9FCE0U)
338 #define DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U) // N4M (0x3FCE4U) / N4S (0x9FCE4U)
339
340 uint32_t dcdcTrimValue0 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_0_ADDRS)));
341 uint32_t dcdcTrimValue1 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_1_ADDRS)));
342
343 if (0UL != (dcdcTrimValue0 & 0x1UL))
344 {
345 PMC->DCDC0 = dcdcTrimValue0 >> 1;
346 PMC->DCDC1 = dcdcTrimValue1;
347 }
348 }
349
350 /**
351 * @brief Configures and enters in low power mode
352 * @param : p_lowpower_cfg
353 * @return Nothing
354 */
POWER_EnterLowPower(LPC_LOWPOWER_T * p_lowpower_cfg)355 static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg)
356 {
357 /* PMC clk set to 12 MHZ */
358 p_lowpower_cfg->CFG |= (uint32_t)LOWPOWER_CFG_SELCLOCK_12MHZ << LOWPOWER_CFG_SELCLOCK_INDEX;
359
360 /* Enable Analog References fast wake-up in case of wake-up from a low power mode (DEEP SLEEP, POWER DOWN and DEEP
361 * POWER DOWN) and Hardware Pin reset */
362 PMC->REFFASTWKUP = (PMC->REFFASTWKUP & (~PMC_REFFASTWKUP_LPWKUP_MASK) & (~PMC_REFFASTWKUP_HWWKUP_MASK)) |
363 PMC_REFFASTWKUP_LPWKUP(1) | PMC_REFFASTWKUP_HWWKUP(1);
364
365 /* SRAM uses Voltage Scaling in all Low Power modes */
366 PMC->SRAMCTRL = (PMC->SRAMCTRL & (~PMC_SRAMCTRL_SMB_MASK)) | PMC_SRAMCTRL_SMB(3);
367
368 /* CPU Retention configuration : preserve the value of FUNCRETENTIONCTRL.RET_LENTH which is a Hardware defined
369 * parameter. */
370 p_lowpower_cfg->CPURETCTRL = (SYSCON->FUNCRETENTIONCTRL & SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK) |
371 (p_lowpower_cfg->CPURETCTRL & (~SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK));
372
373 /* Switch System Clock to FRO12Mhz (the configuration before calling this function will not be restored back) */
374 CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /* Switch main clock to FRO12MHz */
375 CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /* Main clock divided by 1 */
376 SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0000UL) | 0x201AUL; /* Adjust FMC waiting time cycles */
377 lf_set_dcdc_power_profile_low(); /* Align DCDC Power profile with the 12 MHz clock (DCDC Power Profile LOW) */
378
379 (*(s_lowpowerDriver->set_lowpower_mode))(p_lowpower_cfg);
380
381 /* Restore the configuration of the MISCCTRL Register : LOWPWR_FLASH_BUF = 0, LDOMEMBLEEDDSLP = 0, LDOMEMHIGHZMODE =
382 * 0 */
383 PMC->MISCCTRL &= (~PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK) & (~PMC_MISCCTRL_DISABLE_BLEED_MASK) &
384 (~PMC_MISCCTRL_LDOMEMHIGHZMODE_MASK);
385 }
386
387 /**
388 * @brief Shut off the Flash and execute the _WFI(), then power up the Flash after wake-up event
389 * @param None
390 * @return Nothing
391 */
POWER_CycleCpuAndFlash(void)392 void POWER_CycleCpuAndFlash(void)
393 {
394 (*(s_lowpowerDriver->power_cycle_cpu_and_flash))();
395 };
396
397 /**
398 * brief PMC Deep Sleep function call
399 * return nothing
400 */
POWER_EnterDeepSleep(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t hardware_wake_ctrl)401 void POWER_EnterDeepSleep(uint32_t exclude_from_pd,
402 uint32_t sram_retention_ctrl,
403 uint64_t wakeup_interrupts,
404 uint32_t hardware_wake_ctrl)
405 {
406 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
407 uint32_t cpu0_nmi_enable;
408 uint32_t cpu0_int_enable_0;
409 uint32_t cpu0_int_enable_1;
410 uint32_t dcdc_voltage;
411 uint32_t pmc_reset_ctrl;
412 /* Clear Low Power Mode configuration variable */
413 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
414
415 /* Configure Low Power Mode configuration variable */
416 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPSLEEP
417 << LOWPOWER_CFG_LPMODE_INDEX; /* DEEPSLEEP mode */
418
419 lf_get_deepsleep_core_supply_cfg(exclude_from_pd, &dcdc_voltage);
420
421 if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
422 ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
423 {
424 /* USB High Speed is required as wake-up source in Deep Sleep mode: make sure LDO FLASH NV stays powered during
425 * deep-sleep */
426 exclude_from_pd = exclude_from_pd | (uint32_t)kPDRUNCFG_PD_LDOFLASHNV;
427 }
428
429 /* DCDC will be always used during Deep Sleep (instead of LDO Deep Sleep); Make sure LDO MEM & Analog references
430 * will stay powered, Shut down ROM */
431 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd & ~(uint32_t)kPDRUNCFG_PD_DCDC & ~(uint32_t)kPDRUNCFG_PD_LDOMEM &
432 ~(uint32_t)kPDRUNCFG_PD_BIAS) |
433 (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP | (uint32_t)kPDRUNCFG_PD_ROM;
434
435 /* Voltage control in DeepSleep Low Power Modes */
436 /* The Memories Voltage settings below are for voltage scaling */
437 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, dcdc_voltage);
438
439 /* SRAM retention control during POWERDOWN */
440 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
441
442 /* CPU Wake up & Interrupt sources control */
443 lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts;
444 lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts;
445
446 /* Interrupts that allow DMA transfers with Flexcomm without waking up the Processor */
447 if (0UL != (hardware_wake_ctrl & (LOWPOWER_HWWAKE_PERIPHERALS | LOWPOWER_HWWAKE_SDMA0 | LOWPOWER_HWWAKE_SDMA1)))
448 {
449 lv_low_power_mode_cfg.HWWAKE = (hardware_wake_ctrl & ~LOWPOWER_HWWAKE_FORCED) | LOWPOWER_HWWAKE_ENABLE_FRO192M;
450 }
451
452 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
453 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
454
455 /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
456 * API */
457 cpu0_int_enable_0 = NVIC->ISER[0];
458 cpu0_int_enable_1 = NVIC->ISER[1];
459
460 pmc_reset_ctrl = PMC->RESETCTRL;
461
462 if ((pmc_reset_ctrl & (PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK)) ==
463 ((0x1UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
464 (0x1UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT)))
465 {
466 /* BoD CORE reset is activated, so make sure BoD Core and Biasing won't be shutdown */
467 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODCORE & ~(uint32_t)kPDRUNCFG_PD_BIAS;
468 }
469 if ((pmc_reset_ctrl & (PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK)) ==
470 ((0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
471 (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT)))
472 {
473 /* BoD VBAT reset is activated, so make sure BoD VBAT and Biasing won't be shutdown */
474 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODVBAT & ~(uint32_t)kPDRUNCFG_PD_BIAS;
475 }
476
477 /* Enter low power mode */
478 POWER_EnterLowPower(&lv_low_power_mode_cfg);
479
480 /* Restore the configuration of the NMI Register */
481 SYSCON->NMISRC |= cpu0_nmi_enable;
482
483 /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
484 * low power API */
485 NVIC->ISER[0] = cpu0_int_enable_0;
486 NVIC->ISER[1] = cpu0_int_enable_1;
487 }
488
489 /**
490 * brief PMC power Down function call
491 * return nothing
492 */
POWER_EnterPowerDown(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t cpu_retention_ctrl)493 void POWER_EnterPowerDown(uint32_t exclude_from_pd,
494 uint32_t sram_retention_ctrl,
495 uint64_t wakeup_interrupts,
496 uint32_t cpu_retention_ctrl)
497 {
498 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
499 uint32_t cpu0_nmi_enable;
500 uint32_t cpu0_int_enable_0;
501 uint32_t cpu0_int_enable_1;
502 uint64_t wakeup_src_int;
503 uint32_t pmc_reset_ctrl;
504 uint32_t rng_entropy_save[6];
505
506 uint32_t analog_ctrl_regs[12]; /* To store Analog Controller Regristers */
507
508 /* Clear Low Power Mode configuration variable */
509 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
510
511 /* Configure Low Power Mode configuration variable */
512 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_POWERDOWN
513 << LOWPOWER_CFG_LPMODE_INDEX; /* POWER DOWN mode */
514
515 /* Only FRO32K, XTAL32K, COMP, BIAS and LDO_MEM can be stay powered during POWERDOWN (valid from application point
516 * of view; Hardware allows BODVBAT, LDODEEPSLEEP and FRO1M to stay powered, that's why they are excluded below) */
517 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BODVBAT | (uint32_t)kPDRUNCFG_PD_FRO1M |
518 (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP;
519
520 /* @TODO Guillaume: add save/restore entropy during PowerDown */
521 /* Entropy for RNG need to saved */
522 if ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_RNG) != 0UL)
523 {
524 CLOCK_EnableClock(kCLOCK_Rng);
525 RESET_ClearPeripheralReset(kRNG_RST_SHIFT_RSTn);
526 for (int i = 0; i < 6; i++)
527 {
528 rng_entropy_save[i] = RNG->RANDOM_NUMBER;
529 }
530 }
531
532 /* CPU0 retention Ctrl.
533 * For the time being, we do not allow customer to relocate the CPU retention area in SRAMX, meaning that the
534 * retention area range is [0x0400_6000 - 0x0400_6600] (beginning of RAMX2 for N4S) If required by customer,
535 * retention area range is [0x0400_2000 - 0x0400_2600] (beginning of RAMX2 for N4M) If required by customer,
536 * cpu_retention_ctrl[13:1] will be used for that to modify the default retention area
537 */
538 lv_low_power_mode_cfg.CPURETCTRL =
539 (cpu_retention_ctrl & LOWPOWER_CPURETCTRL_ENA_MASK) |
540 ((((uint32_t)CPU_RETENTION_RAMX_STORAGE_START_ADDR >> 2UL) << LOWPOWER_CPURETCTRL_MEMBASE_INDEX) &
541 LOWPOWER_CPURETCTRL_MEMBASE_MASK);
542 if (0UL != (cpu_retention_ctrl & 0x1UL))
543 {
544 /* Add RAMX2 for retention */
545 sram_retention_ctrl |= LOWPOWER_SRAMRETCTRL_RETEN_RAMX2;
546 /* CPU retention is required: store Analog Controller Registers */
547 analog_ctrl_regs[0] = ANACTRL->FRO192M_CTRL;
548 analog_ctrl_regs[1] = ANACTRL->ANALOG_CTRL_CFG;
549 analog_ctrl_regs[2] = ANACTRL->ADC_CTRL;
550 analog_ctrl_regs[3] = ANACTRL->XO32M_CTRL;
551 analog_ctrl_regs[4] = ANACTRL->BOD_DCDC_INT_CTRL;
552 analog_ctrl_regs[5] = ANACTRL->RINGO0_CTRL;
553 analog_ctrl_regs[6] = ANACTRL->RINGO1_CTRL;
554 analog_ctrl_regs[7] = ANACTRL->RINGO2_CTRL;
555 analog_ctrl_regs[8] = ANACTRL->LDO_XO32M;
556 analog_ctrl_regs[9] = ANACTRL->AUX_BIAS;
557 analog_ctrl_regs[10] = ANACTRL->USBHS_PHY_CTRL;
558 analog_ctrl_regs[11] = ANACTRL->USBHS_PHY_TRIM;
559 }
560
561 /* SRAM retention control during POWERDOWN */
562 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
563
564 /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
565 if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
566 {
567 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
568 }
569
570 /* Voltage control in Low Power Modes */
571 /* The Memories Voltage settings below are for voltage scaling */
572 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, 0);
573
574 /* CPU Wake up & Interrupt sources control : only WAKEUP_GPIO_GLOBALINT0, WAKEUP_GPIO_GLOBALINT1, WAKEUP_FLEXCOMM3,
575 * WAKEUP_ACMP_CAPT, WAKEUP_RTC_LITE_ALARM_WAKEUP, WAKEUP_OS_EVENT_TIMER, WAKEUP_ALLWAKEUPIOS */
576 wakeup_src_int = (uint64_t)(WAKEUP_GPIO_GLOBALINT0 | WAKEUP_GPIO_GLOBALINT1 | WAKEUP_FLEXCOMM3 | WAKEUP_ACMP |
577 WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER | WAKEUP_ALLWAKEUPIOS);
578 lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts & wakeup_src_int;
579 lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts & wakeup_src_int;
580
581 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
582 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
583
584 /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
585 * API */
586 cpu0_int_enable_0 = NVIC->ISER[0];
587 cpu0_int_enable_1 = NVIC->ISER[1];
588
589 /* Save the configuration of the PMC RESETCTRL register */
590 pmc_reset_ctrl = PMC->RESETCTRL;
591
592 /* Disable BoD VBAT and BoD Core resets */
593 /* BOD VBAT disable reset */
594 PMC->RESETCTRL &= (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
595 PMC->RESETCTRL |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
596 (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
597
598 /* BOD CORE disable reset */
599 PMC->RESETCTRL &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
600 PMC->RESETCTRL |= (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
601 (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
602
603 /* Enter low power mode */
604 POWER_EnterLowPower(&lv_low_power_mode_cfg);
605
606 /*** We'll reach this point in case of POWERDOWN with CPU retention or if the POWERDOWN has not been taken (for
607 instance because an interrupt is pending). In case of CPU retention, assumption is that the SRAM containing the
608 stack used to call this function shall be preserved during low power ***/
609
610 #if defined(PUF_SRAM_CTRL_CFG_ENABLE_MASK)
611 /* Following code is to reset PUF to remove over consumption */
612 /* Enable PUF register clock to access register */
613 SYSCON->AHBCLKCTRLSET[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
614 /* Release PUF reset */
615 SYSCON->PRESETCTRLCLR[2] = SYSCON_PRESETCTRL2_PUF_RST_MASK;
616 /* Enable PUF SRAM */
617 PUF_SRAM_CTRL->CFG |= PUF_SRAM_CTRL_CFG_ENABLE_MASK | PUF_SRAM_CTRL_CFG_CKGATING_MASK;
618
619 /* Disable PUF register clock. */
620 // Delaying the line of code below until the PUF State Machine execution is completed:
621 // Shuting down the clock to early will prevent the state machine from reaching the end.
622 // => Wait for status bit in PUF Controller Registers before stop PUF clock.
623 while (0UL == (PUF_SRAM_CTRL->INT_STATUS & PUF_SRAM_CTRL_INT_STATUS_READY_MASK))
624 {
625 }
626
627 SYSCON->AHBCLKCTRLCLR[2] = SYSCON_AHBCLKCTRL2_PUF_MASK;
628 #endif
629 /* Restore the configuration of the NMI Register */
630 SYSCON->NMISRC |= cpu0_nmi_enable;
631
632 /* Restore PMC RESETCTRL register */
633 PMC->RESETCTRL = pmc_reset_ctrl;
634
635 /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
636 * low power API */
637 NVIC->ISER[0] = cpu0_int_enable_0;
638 NVIC->ISER[1] = cpu0_int_enable_1;
639
640 if ((cpu_retention_ctrl & 0x1UL) != 0UL)
641 {
642 /* Restore Analog Controller Registers */
643 ANACTRL->FRO192M_CTRL = analog_ctrl_regs[0] | ANACTRL_FRO192M_CTRL_WRTRIM_MASK;
644 ANACTRL->ANALOG_CTRL_CFG = analog_ctrl_regs[1];
645 ANACTRL->ADC_CTRL = analog_ctrl_regs[2];
646 ANACTRL->XO32M_CTRL = analog_ctrl_regs[3];
647 ANACTRL->BOD_DCDC_INT_CTRL = analog_ctrl_regs[4];
648 ANACTRL->RINGO0_CTRL = analog_ctrl_regs[5];
649 ANACTRL->RINGO1_CTRL = analog_ctrl_regs[6];
650 ANACTRL->RINGO2_CTRL = analog_ctrl_regs[7];
651 ANACTRL->LDO_XO32M = analog_ctrl_regs[8];
652 ANACTRL->AUX_BIAS = analog_ctrl_regs[9];
653 ANACTRL->USBHS_PHY_CTRL = analog_ctrl_regs[10];
654 ANACTRL->USBHS_PHY_TRIM = analog_ctrl_regs[11];
655 }
656
657 /* @TODO Guillaume: add save/restore entropy during PowerDown */
658 /* Restore Entropy for RNG */
659 if ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_RNG) != 0UL)
660 {
661 RNG->POWERDOWN &= ~RNG_POWERDOWN_POWERDOWN_MASK;
662 for (int i = 0; i < 6; i++)
663 {
664 RNG->ENTROPY_INJECT = rng_entropy_save[i];
665 }
666 }
667 }
668
669 /**
670 * brief PMC Deep Sleep Power Down function call
671 * return nothing
672 */
POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,uint32_t sram_retention_ctrl,uint64_t wakeup_interrupts,uint32_t wakeup_io_ctrl)673 void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,
674 uint32_t sram_retention_ctrl,
675 uint64_t wakeup_interrupts,
676 uint32_t wakeup_io_ctrl)
677 {
678 LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
679 uint32_t cpu0_nmi_enable;
680 uint32_t cpu0_int_enable_0;
681 uint32_t cpu0_int_enable_1;
682 uint32_t pmc_reset_ctrl;
683
684 /* Clear Low Power Mode configuration variable */
685 (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
686
687 /* Configure Low Power Mode configuration variable */
688 lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN
689 << LOWPOWER_CFG_LPMODE_INDEX; /* DEEP POWER DOWN mode */
690
691 /* Only FRO32K, XTAL32K and LDO_MEM can be stay powered during DEEPPOWERDOWN (valid from application point of view;
692 * Hardware allows BODVBAT, BIAS FRO1M and COMP to stay powered, that's why they are excluded below) */
693 lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BIAS | (uint32_t)kPDRUNCFG_PD_BODVBAT |
694 (uint32_t)kPDRUNCFG_PD_FRO1M | (uint32_t)kPDRUNCFG_PD_COMP;
695
696 /* SRAM retention control during DEEPPOWERDOWN */
697 /* RAM00 used by ROM code to restart. */
698 sram_retention_ctrl = sram_retention_ctrl & (~(LOWPOWER_SRAMRETCTRL_RETEN_RAM00));
699
700 /* SRAM retention control during DEEPPOWERDOWN */
701 lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
702
703 /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
704 if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
705 {
706 lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
707 }
708
709 /* Voltage control in Low Power Modes */
710 /* The Memories Voltage settings below are for voltage scaling */
711 lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN, 0);
712
713 lv_low_power_mode_cfg.WAKEUPINT =
714 wakeup_interrupts & (WAKEUP_RTC_LITE_ALARM_WAKEUP |
715 WAKEUP_OS_EVENT_TIMER); /* CPU Wake up sources control : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
716 WAKEUP_OS_EVENT_TIMER */
717 lv_low_power_mode_cfg.WAKEUPSRC =
718 wakeup_interrupts &
719 (WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER |
720 WAKEUP_ALLWAKEUPIOS); /*!< Hardware Wake up sources control: : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
721 WAKEUP_OS_EVENT_TIMER and WAKEUP_ALLWAKEUPIOS */
722
723 /* Wake up I/O sources */
724 lv_low_power_mode_cfg.WAKEUPIOSRC = lf_wakeup_io_ctrl(wakeup_io_ctrl);
725
726 cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
727 SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
728
729 /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
730 * API */
731 cpu0_int_enable_0 = NVIC->ISER[0];
732 cpu0_int_enable_1 = NVIC->ISER[1];
733
734 /* Save the configuration of the PMC RESETCTRL register */
735 pmc_reset_ctrl = PMC->RESETCTRL;
736
737 /* Disable BoD VBAT and BoD Core resets */
738 /* BOD VBAT disable reset */
739 PMC->RESETCTRL &= (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
740 PMC->RESETCTRL |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
741 (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
742
743 /* BOD CORE disable reset */
744 PMC->RESETCTRL &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
745 PMC->RESETCTRL |= (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
746 (0x2UL << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
747
748 /* Enter low power mode */
749 POWER_EnterLowPower(&lv_low_power_mode_cfg);
750
751 /*** We'll reach this point ONLY and ONLY if the DEEPPOWERDOWN has not been taken (for instance because an RTC or
752 * OSTIMER interrupt is pending) ***/
753
754 /* Restore the configuration of the NMI Register */
755 SYSCON->NMISRC |= cpu0_nmi_enable;
756
757 /* Restore PMC RESETCTRL register */
758 PMC->RESETCTRL = pmc_reset_ctrl;
759
760 /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
761 * low power API */
762 NVIC->ISER[0] = cpu0_int_enable_0;
763 NVIC->ISER[1] = cpu0_int_enable_1;
764 }
765
766 /**
767 * brief PMC Sleep function call
768 * return nothing
769 */
POWER_EnterSleep(void)770 void POWER_EnterSleep(void)
771 {
772 uint32_t pmsk;
773 pmsk = __get_PRIMASK();
774 __disable_irq();
775 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
776 __WFI();
777 __set_PRIMASK(pmsk);
778 }
779
780 /**
781 * @brief Get Digital Core logic supply source to be used during Deep Sleep.
782 * @param [in] exclude_from_pd: COmpoenents NOT to be powered down during Deep Sleep
783 * @param [out] core_supply: 0 = LDO DEEPSLEEP will be used / 1 = DCDC will be used
784 * @param [out] dcdc_voltage: as defined by V_DCDC_* in fsl_power.h
785
786 * @return Nothing
787 */
lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd,uint32_t * dcdc_voltage)788 static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage)
789 {
790 *dcdc_voltage = (uint32_t)V_DCDC_0P950; /* Default value */
791
792 if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
793 ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
794 {
795 /* USB High Speed is required as wake-up source in Deep Sleep mode */
796 PMC->MISCCTRL |= PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK; /* Force flash buffer in low power mode */
797 *dcdc_voltage =
798 (uint32_t)V_DCDC_1P000; /* Set DCDC voltage to be 1.000 V (USB HS IP cannot work below 0.990 V) */
799 }
800 }
801
802 /**
803 * @brief
804 * @param
805 * @return
806 */
lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode,uint32_t p_dcdc_voltage)807 static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage)
808 {
809 #define FLASH_NMPA_LDO_AO_ADDRS (FLASH_NMPA_BASE + 0x0F4U) // N4M (0x3FCF4U) / N4S (0x9FCF4U)
810 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK (0x100U)
811 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK (0x3E00U)
812 #define FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT (9U)
813 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK (0x10000U)
814 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK (0x3E0000U)
815 #define FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT (17U)
816 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK (0x1000000U)
817 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK (0x3E000000U)
818 #define FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT (25U)
819
820 uint32_t ldo_ao_trim, voltage;
821 uint32_t lv_v_ldo_pmu, lv_v_ldo_pmu_boost;
822
823 ldo_ao_trim = (*((volatile unsigned int *)(FLASH_NMPA_LDO_AO_ADDRS)));
824
825 switch (p_lp_mode)
826 {
827 case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
828 {
829 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK) != 0UL)
830 {
831 /* Apply settings coming from Flash */
832 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT;
833 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
834 }
835 else
836 {
837 /* Apply default settings */
838 lv_v_ldo_pmu = (uint32_t)V_AO_0P900;
839 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P850;
840 }
841 }
842 break;
843
844 case LOWPOWER_CFG_LPMODE_POWERDOWN:
845 {
846 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK) != 0UL)
847 {
848 /* Apply settings coming from Flash */
849 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK) >> FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT;
850 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
851 }
852 else
853 {
854 /* Apply default settings */
855 lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
856 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
857 }
858 }
859 break;
860
861 case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
862 {
863 if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK) != 0UL)
864 {
865 /* Apply settings coming from Flash */
866 lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT;
867 lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
868 }
869 else
870 {
871 /* Apply default settings */
872 lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
873 lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
874 }
875 }
876 break;
877
878 default:
879 /* Should never reach this point */
880 lv_v_ldo_pmu = (uint32_t)V_AO_1P100;
881 lv_v_ldo_pmu_boost = (uint32_t)V_AO_1P050;
882 break;
883 }
884
885 /* The Memories Voltage settings below are for voltage scaling */
886 voltage =
887 (lv_v_ldo_pmu << LOWPOWER_VOLTAGE_LDO_PMU_INDEX) | /* */
888 (lv_v_ldo_pmu_boost << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX) | /* */
889 ((uint32_t)V_AO_0P750 << LOWPOWER_VOLTAGE_LDO_MEM_INDEX) | /* Set to 0.75V (voltage Scaling) */
890 ((uint32_t)V_AO_0P700 << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX) | /* Set to 0.7V (voltage Scaling) */
891 ((uint32_t)V_DEEPSLEEP_0P900
892 << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX) | /* Set to 0.90 V (Not used because LDO_DEEP_SLEEP is disabled)*/
893 (p_dcdc_voltage << LOWPOWER_VOLTAGE_DCDC_INDEX) /* */
894 ;
895
896 return (voltage);
897 }
898
899 /**
900 * @brief
901 * @param
902 * @return
903 */
lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)904 static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)
905 {
906 uint32_t wake_up_type;
907 uint32_t wakeup_io_ctrl_reg;
908 uint8_t use_external_pullupdown = 0;
909
910 /* Configure Pull up & Pull down based on the required wake-up edge */
911 CLOCK_EnableClock(kCLOCK_Iocon);
912
913 wakeup_io_ctrl_reg = 0UL;
914
915 /* Wake-up I/O 0 */
916 wake_up_type = (p_wakeup_io_ctrl & 0x3UL) >> LOWPOWER_WAKEUPIOSRC_PIO0_INDEX;
917 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO0_INDEX);
918 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_MASK) >>
919 LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX);
920
921 if (use_external_pullupdown == 0UL)
922 {
923 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
924 {
925 /* Rising edge and both rising and falling edges */
926 IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
927 wakeup_io_ctrl_reg |=
928 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
929 }
930 else
931 {
932 if (wake_up_type == 2UL)
933 {
934 /* Falling edge only */
935 IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
936 wakeup_io_ctrl_reg |=
937 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
938 }
939 else
940 {
941 /* Wake-up I/O is disabled : set it as required by the user */
942 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) != 0UL)
943 {
944 /* Wake-up I/O is configured as Plain Input */
945 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
946 wakeup_io_ctrl_reg |=
947 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
948 }
949 else
950 {
951 /* Wake-up I/O is configured as pull-up or pull-down */
952 // @TODO update for mask name
953 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK) != 0UL)
954 {
955 /* Wake-up I/O is configured as pull-up */
956 wakeup_io_ctrl_reg |=
957 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
958 }
959 else
960 {
961 /* Wake-up I/O is configured as pull-down */
962 wakeup_io_ctrl_reg |=
963 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
964 }
965 }
966 }
967 }
968 }
969 else
970 {
971 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
972 }
973
974 /* Wake-up I/O 1 */
975 wake_up_type = (p_wakeup_io_ctrl & 0xCUL) >> LOWPOWER_WAKEUPIOSRC_PIO1_INDEX;
976 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO1_INDEX);
977 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_MASK) >>
978 LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX);
979
980 if (use_external_pullupdown == 0UL)
981 {
982 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
983 {
984 /* Rising edge and both rising and falling edges */
985 IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
986 wakeup_io_ctrl_reg |=
987 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
988 }
989 else
990 {
991 if (wake_up_type == 2UL)
992 {
993 /* Falling edge only */
994 IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
995 wakeup_io_ctrl_reg |=
996 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
997 }
998 else
999 {
1000 /* Wake-up I/O is disabled : set it as required by the user */
1001 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) != 0UL)
1002 {
1003 /* Wake-up I/O is configured as Plain Input */
1004 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
1005 wakeup_io_ctrl_reg |=
1006 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
1007 }
1008 else
1009 {
1010 /* Wake-up I/O is configured as pull-up or pull-down */
1011 // @TODO update for mask name
1012 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK) != 0UL)
1013 {
1014 /* Wake-up I/O is configured as pull-up */
1015 wakeup_io_ctrl_reg |=
1016 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
1017 }
1018 else
1019 {
1020 /* Wake-up I/O is configured as pull-down */
1021 wakeup_io_ctrl_reg |=
1022 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
1023 }
1024 }
1025 }
1026 }
1027 }
1028 else
1029 {
1030 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
1031 }
1032
1033 /* Wake-up I/O 2 */
1034 wake_up_type = (p_wakeup_io_ctrl & 0x30UL) >> LOWPOWER_WAKEUPIOSRC_PIO2_INDEX;
1035 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO2_INDEX);
1036 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_MASK) >>
1037 LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX);
1038
1039 if (use_external_pullupdown == 0UL)
1040 {
1041 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
1042 {
1043 /* Rising edge and both rising and falling edges */
1044 IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
1045 wakeup_io_ctrl_reg |=
1046 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1047 }
1048 else
1049 {
1050 if (wake_up_type == 2UL)
1051 {
1052 /* Falling edge only */
1053 IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
1054 wakeup_io_ctrl_reg |=
1055 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1056 }
1057 else
1058 {
1059 /* Wake-up I/O is disabled : set it as required by the user */
1060 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) != 0UL)
1061 {
1062 /* Wake-up I/O is configured as Plain Input */
1063 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
1064 wakeup_io_ctrl_reg |=
1065 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1066 }
1067 else
1068 {
1069 /* Wake-up I/O is configured as pull-up or pull-down */
1070 // @TODO update for mask name
1071 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK) != 0UL)
1072 {
1073 /* Wake-up I/O is configured as pull-up */
1074 wakeup_io_ctrl_reg |=
1075 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1076 }
1077 else
1078 {
1079 /* Wake-up I/O is configured as pull-down */
1080 wakeup_io_ctrl_reg |=
1081 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1082 }
1083 }
1084 }
1085 }
1086 }
1087 else
1088 {
1089 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
1090 }
1091
1092 /* Wake-up I/O 3 */
1093 wake_up_type = (p_wakeup_io_ctrl & 0xC0UL) >> LOWPOWER_WAKEUPIOSRC_PIO3_INDEX;
1094 wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO3_INDEX);
1095 use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_MASK) >>
1096 LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX);
1097
1098 if (use_external_pullupdown == 0UL)
1099 {
1100 if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
1101 {
1102 /* Rising edge and both rising and falling edges */
1103 IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
1104 wakeup_io_ctrl_reg |=
1105 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1106 }
1107 else
1108 {
1109 if (wake_up_type == 2UL)
1110 {
1111 /* Falling edge only */
1112 IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
1113 wakeup_io_ctrl_reg |=
1114 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1115 }
1116 else
1117 {
1118 /* Wake-up I/O is disabled : set it as required by the user */
1119 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) != 0UL)
1120 {
1121 /* Wake-up I/O is configured as Plain Input */
1122 // @TODO not used p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
1123 wakeup_io_ctrl_reg |=
1124 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1125 }
1126 else
1127 {
1128 /* Wake-up I/O is configured as pull-up or pull-down */
1129 // @TODO update for mask name
1130 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK) != 0UL)
1131 {
1132 /* Wake-up I/O is configured as pull-up */
1133 wakeup_io_ctrl_reg |=
1134 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1135 }
1136 else
1137 {
1138 /* Wake-up I/O is configured as pull-down */
1139 wakeup_io_ctrl_reg |=
1140 ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1141 }
1142 }
1143 }
1144 }
1145 }
1146 else
1147 {
1148 wakeup_io_ctrl_reg |= ((uint32_t)LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
1149 }
1150
1151 return (wakeup_io_ctrl_reg);
1152 }
1153
1154 /**
1155 * @brief
1156 * @param
1157 * @return
1158 */
CLOCK_u8OscCapConvert(uint8_t u8OscCap,uint8_t u8CapBankDiscontinuity)1159 static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
1160 {
1161 /* Compensate for discontinuity in the capacitor banks */
1162 if (u8OscCap < 64U)
1163 {
1164 if (u8OscCap >= u8CapBankDiscontinuity)
1165 {
1166 u8OscCap -= u8CapBankDiscontinuity;
1167 }
1168 else
1169 {
1170 u8OscCap = 0U;
1171 }
1172 }
1173 else
1174 {
1175 if (u8OscCap <= (127U - u8CapBankDiscontinuity))
1176 {
1177 u8OscCap += u8CapBankDiscontinuity;
1178 }
1179 else
1180 {
1181 u8OscCap = 127U;
1182 }
1183 }
1184 return u8OscCap;
1185 }
1186
1187 /**
1188 * @brief Described in fsl_common.h
1189 * @param
1190 * @return
1191 */
lowpower_set_system_voltage(uint32_t system_voltage_mv)1192 static void lowpower_set_system_voltage(uint32_t system_voltage_mv)
1193 {
1194 /*
1195 * Set system voltage
1196 */
1197 uint32_t lv_ldo_ao = (uint32_t)V_AO_1P100; /* <ldo_ao> */
1198 uint32_t lv_ldo_ao_boost = (uint32_t)V_AO_1P150; /* <ldo_ao_boost> */
1199 uint32_t lv_dcdc = (uint32_t)V_DCDC_1P100; /* <dcdc> */
1200
1201 if (system_voltage_mv <= 950UL)
1202 {
1203 lv_dcdc = (uint32_t)V_DCDC_0P950;
1204 lv_ldo_ao = (uint32_t)V_AO_0P960;
1205 lv_ldo_ao_boost = (uint32_t)V_AO_1P010;
1206 }
1207 else if (system_voltage_mv <= 975UL)
1208 {
1209 lv_dcdc = (uint32_t)V_DCDC_0P975;
1210 lv_ldo_ao = (uint32_t)V_AO_0P980;
1211 lv_ldo_ao_boost = (uint32_t)V_AO_1P030;
1212 }
1213 else if (system_voltage_mv <= 1000UL)
1214 {
1215 lv_dcdc = (uint32_t)V_DCDC_1P000;
1216 lv_ldo_ao = (uint32_t)V_AO_1P000;
1217 lv_ldo_ao_boost = (uint32_t)V_AO_1P050;
1218 }
1219 else if (system_voltage_mv <= 1025UL)
1220 {
1221 lv_dcdc = (uint32_t)V_DCDC_1P025;
1222 lv_ldo_ao = (uint32_t)V_AO_1P030;
1223 lv_ldo_ao_boost = (uint32_t)V_AO_1P080;
1224 }
1225 else if (system_voltage_mv <= 1050UL)
1226 {
1227 lv_dcdc = (uint32_t)V_DCDC_1P050;
1228 lv_ldo_ao = (uint32_t)V_AO_1P060;
1229 lv_ldo_ao_boost = (uint32_t)V_AO_1P110;
1230 }
1231 else if (system_voltage_mv <= 1075UL)
1232 {
1233 lv_dcdc = (uint32_t)V_DCDC_1P075;
1234 lv_ldo_ao = (uint32_t)V_AO_1P080;
1235 lv_ldo_ao_boost = (uint32_t)V_AO_1P130;
1236 }
1237 else if (system_voltage_mv <= 1100UL)
1238 {
1239 lv_dcdc = (uint32_t)V_DCDC_1P100;
1240 lv_ldo_ao = (uint32_t)V_AO_1P100;
1241 lv_ldo_ao_boost = (uint32_t)V_AO_1P150;
1242 }
1243 else if (system_voltage_mv <= 1125UL)
1244 {
1245 lv_dcdc = (uint32_t)V_DCDC_1P125;
1246 lv_ldo_ao = (uint32_t)V_AO_1P130;
1247 lv_ldo_ao_boost = (uint32_t)V_AO_1P160;
1248 }
1249 else if (system_voltage_mv <= 1150UL)
1250 {
1251 lv_dcdc = (uint32_t)V_DCDC_1P150;
1252 lv_ldo_ao = (uint32_t)V_AO_1P160;
1253 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1254 }
1255 else if (system_voltage_mv <= 1175UL)
1256 {
1257 lv_dcdc = (uint32_t)V_DCDC_1P175;
1258 lv_ldo_ao = (uint32_t)V_AO_1P160;
1259 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1260 }
1261 else
1262 {
1263 lv_dcdc = (uint32_t)V_DCDC_1P200;
1264 lv_ldo_ao = (uint32_t)V_AO_1P160;
1265 lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
1266 }
1267
1268 /* Set up LDO Always-On voltages */
1269 PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_MASK) & (~PMC_LDOPMU_VADJ_BOOST_MASK)) | PMC_LDOPMU_VADJ(lv_ldo_ao) |
1270 PMC_LDOPMU_VADJ_BOOST(lv_ldo_ao_boost);
1271
1272 /* Set up DCDC voltage */
1273 PMC->DCDC0 = (PMC->DCDC0 & (~PMC_DCDC0_VOUT_MASK)) | PMC_DCDC0_VOUT(lv_dcdc);
1274 }
1275
1276 /**
1277 * @brief Described in fsl_common.h
1278 * @param
1279 * @return
1280 */
lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)1281 static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)
1282 {
1283 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U)
1284 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U)
1285 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS (FLASH_NMPA_BASE + 0xE8U)
1286 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS (FLASH_NMPA_BASE + 0xECU)
1287 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS (FLASH_NMPA_BASE + 0xD8U)
1288 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS (FLASH_NMPA_BASE + 0xDCU)
1289
1290 const uint32_t PMC_DCDC0_DEFAULT = 0x010C4E68;
1291 const uint32_t PMC_DCDC1_DEFAULT = 0x01803A98;
1292
1293 uint32_t dcdcTrimValue0;
1294 uint32_t dcdcTrimValue1;
1295
1296 switch (dcdc_power_profile)
1297 {
1298 case DCDC_POWER_PROFILE_LOW:
1299 /* Low */
1300 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS)));
1301 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS)));
1302
1303 if (0UL != (dcdcTrimValue0 & 0x1UL))
1304 {
1305 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1306
1307 PMC->DCDC0 = dcdcTrimValue0;
1308 PMC->DCDC1 = dcdcTrimValue1;
1309 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1310 PRINTF(
1311 "\nINFO : DCDC Power Profile set to "
1312 "LOW"
1313 "\n");
1314 #endif
1315 }
1316 break;
1317
1318 case DCDC_POWER_PROFILE_MEDIUM:
1319 /* Medium */
1320 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS)));
1321 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS)));
1322
1323 if (0UL != (dcdcTrimValue0 & 0x1UL))
1324 {
1325 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1326
1327 PMC->DCDC0 = dcdcTrimValue0;
1328 PMC->DCDC1 = dcdcTrimValue1;
1329 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1330 PRINTF(
1331 "\nINFO : DCDC Power Profile set to "
1332 "MEDIUM"
1333 "\n");
1334 #endif
1335 }
1336 break;
1337
1338 case DCDC_POWER_PROFILE_HIGH:
1339 /* High */
1340 dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS)));
1341 dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS)));
1342
1343 if (0UL != (dcdcTrimValue0 & 0x1UL))
1344 {
1345 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
1346
1347 PMC->DCDC0 = dcdcTrimValue0;
1348 PMC->DCDC1 = dcdcTrimValue1;
1349 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1350 PRINTF(
1351 "\nINFO : DCDC Power Profile set to "
1352 "HIGH"
1353 "\n");
1354 #endif
1355 }
1356 break;
1357
1358 default:
1359 /* Low */
1360 PMC->DCDC0 = PMC_DCDC0_DEFAULT;
1361 PMC->DCDC1 = PMC_DCDC1_DEFAULT;
1362 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1363 PRINTF(
1364 "\nINFO : DCDC Power Profile set to "
1365 "LOW"
1366 "\n");
1367 #endif
1368 break;
1369 }
1370 }
1371
1372 /**
1373 * @brief
1374 * @param
1375 * @return
1376 */
lowpower_get_part_process_corner(void)1377 static lowpower_process_corner_enum lowpower_get_part_process_corner(void)
1378 {
1379 #define FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS (FLASH_NMPA_BASE + 0x130U)
1380 #define FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS (FLASH_NMPA_BASE + 0x140U)
1381
1382 lowpower_process_corner_enum part_process_corner;
1383 uint32_t pvt_ringo_hz;
1384 uint32_t pvt_ringo_0 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS)));
1385 uint32_t pvt_ringo_1 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS)));
1386
1387 /*
1388 * Check that the PVT Monitors Trimmings in flash are valid.
1389 */
1390 if (0UL != (pvt_ringo_0 & 0x1UL))
1391 {
1392 /* PVT Trimmings in Flash are valid */
1393 pvt_ringo_0 = pvt_ringo_0 >> 1;
1394 }
1395 else
1396 {
1397 /* PVT Trimmings in Flash are NOT valid (average value assumed) */
1398 pvt_ringo_0 = PROCESS_NNN_AVG_HZ;
1399 }
1400
1401 if (0UL != (pvt_ringo_1 & 0x1UL))
1402 {
1403 /* PVT Trimmings in Flash are valid */
1404 pvt_ringo_1 = pvt_ringo_1 >> 1;
1405 }
1406 else
1407 {
1408 /* PVT Trimmings in Flash are NOT valid (average value assumed) */
1409 pvt_ringo_1 = PROCESS_NNN_AVG_HZ;
1410 }
1411
1412 if (pvt_ringo_1 <= pvt_ringo_0)
1413 {
1414 pvt_ringo_hz = pvt_ringo_1;
1415 }
1416 else
1417 {
1418 pvt_ringo_hz = pvt_ringo_0;
1419 }
1420
1421 /*
1422 * Determine the process corner based on the value of the Ring Oscillator frequency
1423 */
1424 if (pvt_ringo_hz <= PROCESS_NNN_MIN_HZ)
1425 {
1426 /* SSS Process Corner */
1427 part_process_corner = PROCESS_CORNER_SSS;
1428 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1429 PRINTF(
1430 "\nINFO : Process Corner : "
1431 "SSS"
1432 "\n");
1433 #endif
1434 }
1435 else
1436 {
1437 if (pvt_ringo_hz <= PROCESS_NNN_MAX_HZ)
1438 {
1439 /* NNN Process Corner */
1440 part_process_corner = PROCESS_CORNER_NNN;
1441 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1442 PRINTF(
1443 "\nINFO : Process Corner : "
1444 "NNN"
1445 "\n");
1446 #endif
1447 }
1448 else
1449 {
1450 /* FFF Process Corner */
1451 part_process_corner = PROCESS_CORNER_FFF;
1452 #if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
1453 PRINTF(
1454 "\nINFO : Process Corner : "
1455 "FFF"
1456 "\n");
1457 #endif
1458 }
1459 }
1460
1461 return (part_process_corner);
1462 }
1463
1464 /**
1465 * @brief Described in fsl_common.h
1466 * @param
1467 * @return
1468 */
lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)1469 static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)
1470 {
1471 /* Get Sample Process Corner */
1472 lowpower_process_corner_enum part_process_corner = lowpower_get_part_process_corner();
1473
1474 switch (part_process_corner)
1475 {
1476 case PROCESS_CORNER_SSS:
1477 /* Slow Corner */
1478 {
1479 switch (dcdc_power_profile)
1480 {
1481 case DCDC_POWER_PROFILE_MEDIUM:
1482 /* Medium */
1483 lowpower_set_system_voltage(VOLTAGE_SSS_MED_MV);
1484 break;
1485
1486 case DCDC_POWER_PROFILE_HIGH:
1487 /* High */
1488 lowpower_set_system_voltage(VOLTAGE_SSS_HIG_MV);
1489 break;
1490
1491 default:
1492 /* DCDC_POWER_PROFILE_LOW */
1493 lowpower_set_system_voltage(VOLTAGE_SSS_LOW_MV);
1494 break;
1495 } // switch(dcdc_power_profile)
1496 }
1497 break;
1498
1499 case PROCESS_CORNER_FFF:
1500 /* Fast Corner */
1501 {
1502 switch (dcdc_power_profile)
1503 {
1504 case DCDC_POWER_PROFILE_MEDIUM:
1505 /* Medium */
1506 lowpower_set_system_voltage(VOLTAGE_FFF_MED_MV);
1507 break;
1508
1509 case DCDC_POWER_PROFILE_HIGH:
1510 /* High */
1511 lowpower_set_system_voltage(VOLTAGE_FFF_HIG_MV);
1512 break;
1513
1514 default:
1515 /* DCDC_POWER_PROFILE_LOW */
1516 lowpower_set_system_voltage(VOLTAGE_FFF_LOW_MV);
1517 break;
1518 } // switch(dcdc_power_profile)
1519 }
1520 break;
1521
1522 default:
1523 /* Nominal (NNN) and all others Process Corners : assume Nominal Corner */
1524 {
1525 switch (dcdc_power_profile)
1526 {
1527 case DCDC_POWER_PROFILE_MEDIUM:
1528 /* Medium */
1529 lowpower_set_system_voltage(VOLTAGE_NNN_MED_MV);
1530 break;
1531
1532 case DCDC_POWER_PROFILE_HIGH:
1533 /* High */
1534 lowpower_set_system_voltage(VOLTAGE_NNN_HIG_MV);
1535 break;
1536
1537 default:
1538 /* DCDC_POWER_PROFILE_LOW */
1539 lowpower_set_system_voltage(VOLTAGE_NNN_LOW_MV);
1540 break;
1541 } // switch(dcdc_power_profile)
1542 break;
1543 }
1544 } // switch(part_process_corner)
1545 }
1546
1547 /**
1548 * @brief Described in fsl_common.h
1549 * @param
1550 * @return
1551 */
POWER_SetVoltageForFreq(uint32_t system_freq_hz)1552 void POWER_SetVoltageForFreq(uint32_t system_freq_hz)
1553 {
1554 if (system_freq_hz <= DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ)
1555 {
1556 /* [0 Hz - DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz] */
1557 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_LOW); /* DCDC VOUT = 1.05 V by default */
1558 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_LOW);
1559 }
1560 else
1561 {
1562 if (system_freq_hz <= DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ)
1563 {
1564 /* ]DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz - DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz] */
1565 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_MEDIUM); /* DCDC VOUT = 1.15 V by default */
1566 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_MEDIUM);
1567 }
1568 else
1569 {
1570 /* > DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz */
1571 lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_HIGH); /* DCDC VOUT = 1.2 V by default */
1572 lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_HIGH);
1573 }
1574 }
1575 }
1576
POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,int32_t pi32_16MfXtalPPcbParCappF_x100,int32_t pi32_16MfXtalNPcbParCappF_x100)1577 void POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,
1578 int32_t pi32_16MfXtalPPcbParCappF_x100,
1579 int32_t pi32_16MfXtalNPcbParCappF_x100)
1580 {
1581 uint32_t u32XOTrimValue;
1582 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
1583 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
1584 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
1585 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
1586 uint32_t u32RegVal;
1587 int32_t i32Tmp;
1588
1589 /* Enable and set LDO, if not already done */
1590 POWER_SetXtal16mhzLdo();
1591 /* Get Cal values from Flash */
1592 u32XOTrimValue = GET_16MXO_TRIM();
1593 /* Check validity and apply */
1594 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
1595 {
1596 /* These fields are 7 bits, unsigned */
1597 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
1598 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
1599 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
1600 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
1601 /* This field is 1 bit */
1602 u8XOSlave = (uint8_t)((u32XOTrimValue >> 30UL) & 0x1UL);
1603 /* Linear fit coefficients calculation */
1604 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
1605 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
1606 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
1607 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
1608 }
1609 else
1610 {
1611 iaXin_x4 = 20; // gain in LSB/pF
1612 ibXin = -9; // offset in LSB
1613 iaXout_x4 = 20; // gain in LSB/pF
1614 ibXout = -13; // offset in LSB
1615 u8XOSlave = 0;
1616 }
1617 /* In & out load cap calculation with derating */
1618 iXOCapInpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalNPcbParCappF_x100 +
1619 39 * ((int32_t)XO_SLAVE_EN - (int32_t)u8XOSlave) - 15;
1620 iXOCapOutpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalPPcbParCappF_x100 - 21;
1621 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
1622 i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
1623 u8XOCapInCtrl = (uint8_t)i32Tmp;
1624 i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
1625 u8XOCapOutCtrl = (uint8_t)i32Tmp;
1626 /* Read register and clear fields to be written */
1627 u32RegVal = ANACTRL->XO32M_CTRL;
1628 u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
1629 /* Configuration of 32 MHz XO output buffers */
1630 #if (XO_SLAVE_EN == 0)
1631 u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
1632 #else
1633 u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
1634 #endif
1635 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
1636 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
1637 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
1638 /* Write back to register */
1639 ANACTRL->XO32M_CTRL = u32RegVal;
1640 }
1641
POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,int32_t pi32_32kfXtalPPcbParCappF_x100,int32_t pi32_32kfXtalNPcbParCappF_x100)1642 void POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
1643 int32_t pi32_32kfXtalPPcbParCappF_x100,
1644 int32_t pi32_32kfXtalNPcbParCappF_x100)
1645 {
1646 uint32_t u32XOTrimValue;
1647 uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
1648 int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
1649 int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
1650 uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
1651 uint32_t u32RegVal;
1652 int32_t i32Tmp;
1653 /* Get Cal values from Flash */
1654 u32XOTrimValue = GET_32KXO_TRIM();
1655 /* check validity and apply */
1656 if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
1657 {
1658 /* These fields are 7 bits, unsigned */
1659 u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
1660 u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
1661 u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
1662 u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
1663 /* Linear fit coefficients calculation */
1664 iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
1665 ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
1666 iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
1667 ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
1668 }
1669 else
1670 {
1671 iaXin_x4 = 16; // gain in LSB/pF
1672 ibXin = 12; // offset in LSB
1673 iaXout_x4 = 16; // gain in LSB/pF
1674 ibXout = 11; // offset in LSB
1675 }
1676
1677 /* In & out load cap calculation with derating */
1678 iXOCapInpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
1679 iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
1680
1681 /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
1682 i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
1683 u8XOCapInCtrl = (uint8_t)i32Tmp;
1684 i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
1685 u8XOCapOutCtrl = (uint8_t)i32Tmp;
1686
1687 /* Read register and clear fields to be written */
1688 u32RegVal = PMC->XTAL32K;
1689 u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
1690
1691 /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
1692 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23) << PMC_XTAL32K_CAPBANKIN_SHIFT;
1693 u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
1694
1695 /* Write back to register */
1696 PMC->XTAL32K = u32RegVal;
1697 }
1698
POWER_SetXtal16mhzLdo(void)1699 void POWER_SetXtal16mhzLdo(void)
1700 {
1701 uint32_t temp;
1702 const uint32_t u32Mask =
1703 (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
1704
1705 const uint32_t u32Value =
1706 (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
1707
1708 /* Enable & set-up XTAL 32 MHz clock LDO */
1709 temp = ANACTRL->LDO_XO32M;
1710
1711 if ((temp & u32Mask) != u32Value)
1712 {
1713 temp &= ~u32Mask;
1714
1715 /*
1716 * Enable the XTAL32M LDO
1717 * Adjust the output voltage level, 0x5 for 1.1V
1718 * Adjust the biasing current, 0x2 value
1719 * Stability configuration, 0x1 default mode
1720 */
1721 temp |= u32Value;
1722
1723 ANACTRL->LDO_XO32M = temp;
1724
1725 /* Delay for LDO to be up */
1726 // CLOCK_uDelay(20);
1727 }
1728
1729 /* Enable LDO XO32M */
1730 PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXO32M_MASK;
1731 }
1732
1733 /*!
1734 * @brief set BOD VBAT level.
1735 *
1736 * @param level BOD detect level
1737 * @param hyst BoD Hysteresis control
1738 * @param enBodVbatReset VBAT brown out detect reset
1739 */
POWER_SetBodVbatLevel(power_bod_vbat_level_t level,power_bod_hyst_t hyst,bool enBodVbatReset)1740 void POWER_SetBodVbatLevel(power_bod_vbat_level_t level, power_bod_hyst_t hyst, bool enBodVbatReset)
1741 {
1742 uint32_t pmc_reset_ctrl;
1743 /* BOD VBAT disable reset */
1744 pmc_reset_ctrl =
1745 PMC->RESETCTRL & (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
1746 pmc_reset_ctrl |= (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
1747 (0x2UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
1748
1749 PMC->RESETCTRL = pmc_reset_ctrl;
1750
1751 PMC->BODVBAT = (PMC->BODVBAT & (~(PMC_BODVBAT_TRIGLVL_MASK | PMC_BODVBAT_HYST_MASK))) | PMC_BODVBAT_TRIGLVL(level) |
1752 PMC_BODVBAT_HYST(hyst);
1753
1754 /* BOD VBAT enable reset */
1755 if ((uint32_t)enBodVbatReset == 1UL)
1756 {
1757 pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODVBATRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_MASK));
1758 pmc_reset_ctrl |= (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_SHIFT) |
1759 (0x1UL << PMC_RESETCTRL_BODVBATRESETENA_SECURE_DP_SHIFT);
1760 PMC->RESETCTRL = pmc_reset_ctrl;
1761 }
1762 }
1763
1764 #if defined(PMC_BODCORE_TRIGLVL_MASK)
1765 /*!
1766 * @brief set BOD core level.
1767 *
1768 * @param level BOD detect level
1769 * @param hyst BoD Hysteresis control
1770 * @param enBodCoreReset core brown out detect reset
1771 */
POWER_SetBodCoreLevel(power_bod_core_level_t level,power_bod_hyst_t hyst,bool enBodCoreReset)1772 void POWER_SetBodCoreLevel(power_bod_core_level_t level, power_bod_hyst_t hyst, bool enBodCoreReset)
1773 {
1774 uint32_t pmc_reset_ctrl;
1775 /* BOD CORE disable reset */
1776 pmc_reset_ctrl =
1777 PMC->RESETCTRL & (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
1778 pmc_reset_ctrl |=
1779 (0x2 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) | (0x2 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
1780
1781 PMC->RESETCTRL = pmc_reset_ctrl;
1782
1783 PMC->BODCORE = (PMC->BODCORE & (~(PMC_BODCORE_TRIGLVL_MASK | PMC_BODCORE_HYST_MASK))) | PMC_BODCORE_TRIGLVL(level) |
1784 PMC_BODCORE_HYST(hyst);
1785
1786 /* BOD CORE enable reset */
1787 if (enBodCoreReset == 1)
1788 {
1789 pmc_reset_ctrl &= (~(PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK));
1790 pmc_reset_ctrl |= (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) |
1791 (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT);
1792 PMC->RESETCTRL = pmc_reset_ctrl;
1793 }
1794 }
1795 #endif
1796
1797 /**
1798 * @brief Return some key information related to the device reset causes / wake-up sources, for all power modes.
1799 * @param p_reset_cause : the device reset cause, according to the definition of power_device_reset_cause_t type.
1800 * @param p_boot_mode : the device boot mode, according to the definition of power_device_boot_mode_t type.
1801 * @param p_wakeupio_cause: the wake-up pin sources, according to the definition of register PMC->WAKEIOCAUSE[3:0].
1802
1803 * @return Nothing
1804 *
1805 * !!! IMPORTANT ERRATA - IMPORTANT ERRATA - IMPORTANT ERRATA !!!
1806 * !!! valid ONLY for LPC55S69 (not for LPC55S16 and LPC55S06) !!!
1807 * !!! when FALLING EDGE DETECTION is enabled on wake-up pins: !!!
1808 * - 1. p_wakeupio_cause is NOT ACCURATE
1809 * - 2. Spurious kRESET_CAUSE_DPDRESET_WAKEUPIO* event is reported when
1810 * several wake-up sources are enabled during DEEP-POWER-DOWN
1811 * (like enabling wake-up on RTC and Falling edge wake-up pins)
1812 *
1813 */
POWER_GetWakeUpCause(power_device_reset_cause_t * p_reset_cause,power_device_boot_mode_t * p_boot_mode,uint32_t * p_wakeupio_cause)1814 void POWER_GetWakeUpCause(power_device_reset_cause_t *p_reset_cause,
1815 power_device_boot_mode_t *p_boot_mode,
1816 uint32_t *p_wakeupio_cause)
1817 {
1818 uint32_t reset_cause_reg;
1819 uint32_t boot_mode_reg;
1820
1821 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1822 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1823 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1824 reset_cause_reg = (PMC->AOREG1) & 0x3FF0UL;
1825 #else /* LPC55S69/28 */
1826 reset_cause_reg = (PMC->AOREG1) & 0x1FF0UL;
1827 #endif
1828
1829 /*
1830 * Prioritize interrupts source with respect to their critical level
1831 */
1832 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1833 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1834 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1835 if (0UL != (reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK))
1836 { /* Code Watchdog Reset */
1837 *p_reset_cause = kRESET_CAUSE_CDOGRESET;
1838 *p_boot_mode = kBOOT_MODE_POWER_UP;
1839 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1840 }
1841 else
1842 #endif
1843 {
1844 if (0UL != (reset_cause_reg & PMC_AOREG1_WDTRESET_MASK))
1845 { /* Watchdog Timer Reset */
1846 *p_reset_cause = kRESET_CAUSE_WDTRESET;
1847 *p_boot_mode = kBOOT_MODE_POWER_UP;
1848 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1849 }
1850 else
1851 {
1852 if (0UL != (reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK))
1853 { /* ARM System Reset */
1854 *p_reset_cause = kRESET_CAUSE_ARMSYSTEMRESET;
1855 *p_boot_mode = kBOOT_MODE_POWER_UP;
1856 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1857 }
1858 else
1859 {
1860 boot_mode_reg = (PMC->STATUS & PMC_STATUS_BOOTMODE_MASK) >> PMC_STATUS_BOOTMODE_SHIFT;
1861
1862 if (boot_mode_reg == 0UL) /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset */
1863 {
1864 *p_boot_mode = kBOOT_MODE_POWER_UP; /* All non wake-up from a Low Power mode */
1865 *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
1866
1867 /*
1868 * Prioritise Reset causes, starting from the strongest (Power On Reset)
1869 */
1870 if (0UL != (reset_cause_reg & PMC_AOREG1_POR_MASK))
1871 { /* Power On Reset */
1872 *p_reset_cause = kRESET_CAUSE_POR;
1873 }
1874 else
1875 {
1876 if (0UL != (reset_cause_reg & PMC_AOREG1_BODRESET_MASK))
1877 { /* Brown-out Detector reset (either BODVBAT or BODCORE) */
1878 *p_reset_cause = kRESET_CAUSE_BODRESET;
1879 }
1880 else
1881 {
1882 if (0UL != (reset_cause_reg & PMC_AOREG1_PADRESET_MASK))
1883 { /* Hardware Pin Reset */
1884 *p_reset_cause = kRESET_CAUSE_PADRESET;
1885 }
1886 else
1887 {
1888 if (0UL != (reset_cause_reg & PMC_AOREG1_SWRRESET_MASK))
1889 { /* Software triggered Reset */
1890 *p_reset_cause = kRESET_CAUSE_SWRRESET;
1891 }
1892 else
1893 { /* Unknown Reset Cause */
1894 *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1895 }
1896 }
1897 }
1898 }
1899
1900 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1901 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1902 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1903 /* Transfer the control of the 4 wake-up pins to IOCON (instead of the Power Management Controller
1904 */
1905 PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1906 #endif
1907 }
1908 else /* DEEP-SLEEP, POWER-DOWN and DEEP-POWER-DOWN */
1909 {
1910 /*
1911 * 1- First, save wakeup_io_cause register ...
1912 */
1913 *p_wakeupio_cause = PMC->WAKEIOCAUSE;
1914
1915 if (boot_mode_reg == 3UL) /* DEEP-POWER-DOWN */
1916 {
1917 *p_boot_mode = kBOOT_MODE_LP_DEEP_POWER_DOWN;
1918
1919 switch (((reset_cause_reg >> PMC_AOREG1_DPDRESET_WAKEUPIO_SHIFT) & 0x7UL))
1920 {
1921 case 1:
1922 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO;
1923 break;
1924 case 2:
1925 *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC;
1926 break;
1927 case 3:
1928 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC;
1929 break;
1930 case 4:
1931 *p_reset_cause = kRESET_CAUSE_DPDRESET_OSTIMER;
1932 break;
1933 case 5:
1934 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER;
1935 break;
1936 case 6:
1937 *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC_OSTIMER;
1938 break;
1939 case 7:
1940 *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER;
1941 break;
1942 default:
1943 /* Unknown Reset Cause */
1944 *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1945 break;
1946 }
1947
1948 #if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
1949 defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
1950 defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
1951 /*
1952 * 2- Next, transfer the control of the 4 wake-up pins
1953 * to IOCON (instead of the Power Management Controller)
1954 */
1955 PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1956 #endif
1957 }
1958 else /* DEEP-SLEEP and POWER-DOWN */
1959 {
1960 *p_reset_cause = kRESET_CAUSE_NOT_RELEVANT;
1961
1962 /*
1963 * The control of the 4 wake-up pins is already in IOCON,
1964 * so there is nothing special to do.
1965 */
1966
1967 if (boot_mode_reg == 1UL) /* DEEP-SLEEP */
1968 {
1969 *p_boot_mode = kBOOT_MODE_LP_DEEP_SLEEP;
1970 }
1971 else /* POWER-DOWN */
1972 {
1973 *p_boot_mode = kBOOT_MODE_LP_POWER_DOWN;
1974
1975 } /* if ( boot_mode_reg == 1 ) DEEP-SLEEP */
1976
1977 } /* if ( boot_mode == 3 ) DEEP-POWER-DOWN */
1978
1979 } /* if ( boot_mode == 0 ) POWER-UP */
1980
1981 } /* if ( reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK ) */
1982
1983 } /* if ( reset_cause_reg & PMC_AOREG1_WDTRESET_MASK ) */
1984
1985 } /* if ( reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK ) */
1986 }
1987