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