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