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