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