1 /*
2  * Copyright 2020, NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #include <string.h>
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 /* NOTE: These registers are handled by the SDK. The user should not modify the source code. Changes to the source code
17  * can cause application failure. NXP is not responsible for any change to the code and is not obligated to provide
18  * support. */
19 
20 /*******************************************************************************
21  * Variables
22  ******************************************************************************/
23 
24 /*******************************************************************************
25  * Definitions
26  ******************************************************************************/
27 /**
28  * @brief LDO_FLASH_NV & LDO_EFUSE_PROG voltage settings
29  */
30 typedef enum _v_ldo_flashnv_ldo_efuse
31 {
32     V_LDO_1P650 = 0, /*!< 1.65  V */
33     V_LDO_1P700 = 1, /*!< 1.7   V */
34     V_LDO_1P750 = 2, /*!< 1.75  V */
35     V_LDO_1P800 = 3, /*!< 1.8   V */
36     V_LDO_1P850 = 4, /*!< 1.85  V */
37     V_LDO_1P900 = 5, /*!< 1.9   V */
38     V_LDO_1P950 = 6, /*!< 1.95  V */
39     V_LDO_2P000 = 7  /*!< 2.0   V */
40 } v_ldo_flashnv_ldo_efuse_t;
41 
42 /**
43  * @brief Always On and Memories LDO voltage settings
44  */
45 typedef enum _v_ao
46 {
47     // V_AO_1P220 1.22  = 0,  /*!< 1.22  V */
48     V_AO_0P700 = 1,  /*!< 0.7   V */
49     V_AO_0P725 = 2,  /*!< 0.725 V */
50     V_AO_0P750 = 3,  /*!< 0.75  V */
51     V_AO_0P775 = 4,  /*!< 0.775 V */
52     V_AO_0P800 = 5,  /*!< 0.8   V */
53     V_AO_0P825 = 6,  /*!< 0.825 V */
54     V_AO_0P850 = 7,  /*!< 0.85  V */
55     V_AO_0P875 = 8,  /*!< 0.875 V */
56     V_AO_0P900 = 9,  /*!< 0.9   V */
57     V_AO_0P960 = 10, /*!< 0.96  V */
58     V_AO_0P970 = 11, /*!< 0.97  V */
59     V_AO_0P980 = 12, /*!< 0.98  V */
60     V_AO_0P990 = 13, /*!< 0.99  V */
61     V_AO_1P000 = 14, /*!< 1     V */
62     V_AO_1P010 = 15, /*!< 1.01  V */
63     V_AO_1P020 = 16, /*!< 1.02  V */
64     V_AO_1P030 = 17, /*!< 1.03  V */
65     V_AO_1P040 = 18, /*!< 1.04  V */
66     V_AO_1P050 = 19, /*!< 1.05  V */
67     V_AO_1P060 = 20, /*!< 1.06  V */
68     V_AO_1P070 = 21, /*!< 1.07  V */
69     V_AO_1P080 = 22, /*!< 1.08  V */
70     V_AO_1P090 = 23, /*!< 1.09  V */
71     V_AO_1P100 = 24, /*!< 1.1   V */
72     V_AO_1P110 = 25, /*!< 1.11  V */
73     V_AO_1P120 = 26, /*!< 1.12  V */
74     V_AO_1P130 = 27, /*!< 1.13  V */
75     V_AO_1P140 = 28, /*!< 1.14  V */
76     V_AO_1P150 = 29, /*!< 1.15  V */
77     V_AO_1P160 = 30, /*!< 1.16  V */
78     V_AO_1P220 = 31  /*!< 1.22  V */
79 } v_ao_t;
80 
81 /**
82  * @brief DCDC voltage settings
83  */
84 typedef enum _v_dcdc
85 {
86     V_DCDC_0P950 = 0, /*!< 0.95  V */
87     V_DCDC_0P975 = 1, /*!< 0.975 V */
88     V_DCDC_1P000 = 2, /*!< 1     V */
89     V_DCDC_1P025 = 3, /*!< 1.025 V */
90     V_DCDC_1P050 = 4, /*!< 1.050 V */
91     V_DCDC_1P075 = 5, /*!< 1.075 V */
92     V_DCDC_1P100 = 6, /*!< 1.1   V */
93     V_DCDC_1P125 = 7, /*!< 1.125 V */
94     V_DCDC_1P150 = 8, /*!< 1.150 V */
95     V_DCDC_1P175 = 9, /*!< 1.175 V */
96     V_DCDC_1P200 = 10 /*!< 1.2   V */
97 } v_dcdc_t;
98 
99 /**
100  * @brief LDO_CORE High Power Mode voltage settings
101  */
102 typedef enum _v_ldocore_hp
103 {
104     V_LDOCORE_HP_1P373 = 0,  /*!< 1.373  V */
105     V_LDOCORE_HP_1P365 = 1,  /*!< 1.365  V */
106     V_LDOCORE_HP_1P359 = 2,  /*!< 1.359  V */
107     V_LDOCORE_HP_1P352 = 3,  /*!< 1.352  V */
108     V_LDOCORE_HP_1P345 = 4,  /*!< 1.345  V */
109     V_LDOCORE_HP_1P339 = 5,  /*!< 1.339  V */
110     V_LDOCORE_HP_1P332 = 6,  /*!< 1.332  V */
111     V_LDOCORE_HP_1P325 = 7,  /*!< 1.325  V */
112     V_LDOCORE_HP_1P318 = 8,  /*!< 1.318  V */
113     V_LDOCORE_HP_1P311 = 9,  /*!< 1.311  V */
114     V_LDOCORE_HP_1P305 = 10, /*!< 1.305  V */
115     V_LDOCORE_HP_1P298 = 11, /*!< 1.298  V */
116     V_LDOCORE_HP_1P291 = 12, /*!< 1.291  V */
117     V_LDOCORE_HP_1P285 = 13, /*!< 1.285  V */
118     V_LDOCORE_HP_1P278 = 14, /*!< 1.278  V */
119     V_LDOCORE_HP_1P271 = 15, /*!< 1.271  V */
120     V_LDOCORE_HP_1P264 = 16, /*!< 1.264  V */
121     V_LDOCORE_HP_1P258 = 17, /*!< 1.258  V */
122     V_LDOCORE_HP_1P251 = 18, /*!< 1.251  V */
123     V_LDOCORE_HP_1P244 = 19, /*!< 1.244  V */
124     V_LDOCORE_HP_1P237 = 20, /*!< 1.237  V */
125     V_LDOCORE_HP_1P231 = 21, /*!< 1.231  V */
126     V_LDOCORE_HP_1P224 = 22, /*!< 1.224  V */
127     V_LDOCORE_HP_1P217 = 23, /*!< 1.217  V */
128     V_LDOCORE_HP_1P210 = 24, /*!< 1.21   V */
129     V_LDOCORE_HP_1P204 = 25, /*!< 1.204  V */
130     V_LDOCORE_HP_1P197 = 26, /*!< 1.197  V */
131     V_LDOCORE_HP_1P190 = 27, /*!< 1.19   V */
132     V_LDOCORE_HP_1P183 = 28, /*!< 1.183  V */
133     V_LDOCORE_HP_1P177 = 29, /*!< 1.177  V */
134     V_LDOCORE_HP_1P169 = 30, /*!< 1.169  V */
135     V_LDOCORE_HP_1P163 = 31, /*!< 1.163  V */
136     V_LDOCORE_HP_1P156 = 32, /*!< 1.156  V */
137     V_LDOCORE_HP_1P149 = 33, /*!< 1.149  V */
138     V_LDOCORE_HP_1P143 = 34, /*!< 1.143  V */
139     V_LDOCORE_HP_1P136 = 35, /*!< 1.136  V */
140     V_LDOCORE_HP_1P129 = 36, /*!< 1.129  V */
141     V_LDOCORE_HP_1P122 = 37, /*!< 1.122  V */
142     V_LDOCORE_HP_1P116 = 38, /*!< 1.116  V */
143     V_LDOCORE_HP_1P109 = 39, /*!< 1.109  V */
144     V_LDOCORE_HP_1P102 = 40, /*!< 1.102  V */
145     V_LDOCORE_HP_1P095 = 41, /*!< 1.095  V */
146     V_LDOCORE_HP_1P088 = 42, /*!< 1.088  V */
147     V_LDOCORE_HP_1P082 = 43, /*!< 1.082  V */
148     V_LDOCORE_HP_1P075 = 44, /*!< 1.075  V */
149     V_LDOCORE_HP_1P068 = 45, /*!< 1.068  V */
150     V_LDOCORE_HP_1P062 = 46, /*!< 1.062  V */
151     V_LDOCORE_HP_1P055 = 47, /*!< 1.055  V */
152     V_LDOCORE_HP_1P048 = 48, /*!< 1.048  V */
153     V_LDOCORE_HP_1P041 = 49, /*!< 1.041  V */
154     V_LDOCORE_HP_1P034 = 50, /*!< 1.034  V */
155     V_LDOCORE_HP_1P027 = 51, /*!< 1.027  V */
156     V_LDOCORE_HP_1P021 = 52, /*!< 1.021  V */
157     V_LDOCORE_HP_1P014 = 53, /*!< 1.014  V */
158     V_LDOCORE_HP_1P007 = 54, /*!< 1.007  V */
159     V_LDOCORE_HP_1P001 = 55, /*!< 1.001  V */
160     V_LDOCORE_HP_0P993 = 56, /*!< 0.9937 V */
161     V_LDOCORE_HP_0P987 = 57, /*!< 0.987  V */
162     V_LDOCORE_HP_0P980 = 58, /*!< 0.9802 V */
163     V_LDOCORE_HP_0P973 = 59, /*!< 0.9731 V */
164     V_LDOCORE_HP_0P966 = 60, /*!< 0.9666 V */
165     V_LDOCORE_HP_0P959 = 61, /*!< 0.9598 V */
166     V_LDOCORE_HP_0P953 = 62, /*!< 0.9532 V */
167     V_LDOCORE_HP_0P946 = 63, /*!< 0.946  V */
168     V_LDOCORE_HP_0P939 = 64, /*!< 0.9398 V */
169     V_LDOCORE_HP_0P932 = 65, /*!< 0.9327 V */
170     V_LDOCORE_HP_0P926 = 66, /*!< 0.9262 V */
171     V_LDOCORE_HP_0P919 = 67, /*!< 0.9199 V */
172     V_LDOCORE_HP_0P913 = 68, /*!< 0.9135 V */
173     V_LDOCORE_HP_0P907 = 69, /*!< 0.9071 V */
174     V_LDOCORE_HP_0P901 = 70, /*!< 0.9012 V */
175     V_LDOCORE_HP_0P895 = 71, /*!< 0.8953 V */
176     V_LDOCORE_HP_0P889 = 72, /*!< 0.8895 V */
177     V_LDOCORE_HP_0P883 = 73, /*!< 0.8837 V */
178     V_LDOCORE_HP_0P877 = 74, /*!< 0.8779 V */
179     V_LDOCORE_HP_0P871 = 75, /*!< 0.8719 V */
180     V_LDOCORE_HP_0P865 = 76, /*!< 0.8658 V */
181     V_LDOCORE_HP_0P859 = 77, /*!< 0.8596 V */
182     V_LDOCORE_HP_0P853 = 78, /*!< 0.8537 V */
183     V_LDOCORE_HP_0P847 = 79, /*!< 0.8474 V */
184     V_LDOCORE_HP_0P841 = 80, /*!< 0.8413 V */
185     V_LDOCORE_HP_0P835 = 81, /*!< 0.835  V */
186     V_LDOCORE_HP_0P828 = 82, /*!< 0.8288 V */
187     V_LDOCORE_HP_0P822 = 83, /*!< 0.8221 V */
188     V_LDOCORE_HP_0P815 = 84, /*!< 0.8158 V */
189     V_LDOCORE_HP_0P809 = 85, /*!< 0.8094 V */
190     V_LDOCORE_HP_0P802 = 86, /*!< 0.8026 V */
191     V_LDOCORE_HP_0P795 = 87, /*!< 0.7959 V */
192     V_LDOCORE_HP_0P789 = 88, /*!< 0.7893 V */
193     V_LDOCORE_HP_0P782 = 89, /*!< 0.7823 V */
194     V_LDOCORE_HP_0P775 = 90, /*!< 0.7756 V */
195     V_LDOCORE_HP_0P768 = 91, /*!< 0.7688 V */
196     V_LDOCORE_HP_0P762 = 92, /*!< 0.7623 V */
197     V_LDOCORE_HP_0P755 = 93, /*!< 0.7558 V */
198     V_LDOCORE_HP_0P749 = 94, /*!< 0.749  V */
199     V_LDOCORE_HP_0P742 = 95, /*!< 0.7421 V */
200     V_LDOCORE_HP_0P735 = 96, /*!< 0.7354 V */
201     V_LDOCORE_HP_0P728 = 97, /*!< 0.7284 V */
202     V_LDOCORE_HP_0P722 = 98, /*!< 0.722  V */
203     V_LDOCORE_HP_0P715 = 99  /*!< 0.715  V */
204     //    V_LDOCORE_HP_0P715 = 100, /*!< 0.7148 V */
205     //    V_LDOCORE_HP_0P715 = 101, /*!< 0.7148 V */
206     //    V_LDOCORE_HP_0P715 = 102, /*!< 0.7151 V */
207     //    V_LDOCORE_HP_0P715 = 103, /*!< 0.7147 V */
208     //    V_LDOCORE_HP_0P715 = 104, /*!< 0.7147 V */
209     //    V_LDOCORE_HP_0P715 = 105, /*!< 0.715  V */
210     //    V_LDOCORE_HP_0P715 = 106, /*!< 0.7147 V */
211     //    V_LDOCORE_HP_0P715 = 107, /*!< 0.715  V */
212     //    V_LDOCORE_HP_0P715 = 108, /*!< 0.7152 V */
213     //    V_LDOCORE_HP_0P715 = 109, /*!< 0.7148 V */
214     //    V_LDOCORE_HP_0P715 = 110, /*!< 0.715  V */
215     //    V_LDOCORE_HP_0P715 = 111, /*!< 0.7151 V */
216     //    V_LDOCORE_HP_0P715 = 112, /*!< 0.7153 V */
217     //    V_LDOCORE_HP_0P715 = 113, /*!< 0.7152 V */
218     //    V_LDOCORE_HP_0P715 = 114, /*!< 0.7149 V */
219     //    V_LDOCORE_HP_0P715 = 115, /*!< 0.7154 V */
220     //    V_LDOCORE_HP_0P715 = 116, /*!< 0.7152 V */
221     //    V_LDOCORE_HP_0P715 = 117, /*!< 0.7154 V */
222     //    V_LDOCORE_HP_0P715 = 118, /*!< 0.7147 V */
223     //    V_LDOCORE_HP_0P715 = 119, /*!< 0.7152 V */
224     //    V_LDOCORE_HP_0P715 = 120, /*!< 0.7149 V */
225     //    V_LDOCORE_HP_0P715 = 121, /*!< 0.7151 V */
226     //    V_LDOCORE_HP_0P715 = 122, /*!< 0.7152 V */
227     //    V_LDOCORE_HP_0P715 = 123, /*!< 0.7153 V */
228     //    V_LDOCORE_HP_0P715 = 124, /*!< 0.7149 V */
229     //    V_LDOCORE_HP_0P715 = 125, /*!< 0.7154 V */
230     //    V_LDOCORE_HP_0P715 = 126, /*!< 0.7153 V */
231     //    V_LDOCORE_HP_0P715 = 127, /*!< 0.7154 V */
232 } v_ldocore_hp_t;
233 
234 /**
235  * @brief LDO_CORE Low Power Mode voltage settings
236  */
237 typedef enum _v_ldocore_lp
238 {
239     V_LDOCORE_LP_0P750 = 3, /*!< 0.75  V */
240     V_LDOCORE_LP_0P800 = 2, /*!< 0.8   V */
241     V_LDOCORE_LP_0P850 = 1, /*!< 0.85  V */
242     V_LDOCORE_LP_0P900 = 0  /*!< 0.9   V */
243 } v_ldocore_lp_t;
244 
245 /**
246  * @brief System Power Mode settings
247  */
248 typedef enum _v_system_power_profile
249 {
250     V_SYSTEM_POWER_PROFILE_LOW    = 0UL, /*!< For system below or equal to 100 MHz */
251     V_SYSTEM_POWER_PROFILE_MEDIUM = 1UL, /*!< For system frequencies in ]100 MHz - 150 MHz] */
252     V_SYSTEM_POWER_PROFILE_HIGH   = 2UL, /*!< For system above 150 MHz */
253 } v_system_power_profile_t;
254 
255 /**
256  * @brief Manufacturing Process Corners
257  */
258 typedef enum
259 {
260     PROCESS_CORNER_SSS,    /**< Slow Corner Process */
261     PROCESS_CORNER_NNN,    /**< Nominal Corner Process */
262     PROCESS_CORNER_FFF,    /**< Fast Corner Process */
263     PROCESS_CORNER_OTHERS, /**< SFN, SNF, NFS, Poly Res ... Corner Process */
264 } lowpower_process_corner_enum;
265 
266 /** @brief  Low Power main structure */
267 typedef struct
268 {
269     __IO uint32_t CFG;          /*!< Low Power Mode Configuration, and miscallenous options  */
270     __IO uint32_t PDCTRL[2];    /*!< Power Down control : controls power of various modules
271                                  in the different Low power modes, including ROM */
272     __IO uint32_t SRAMRETCTRL;  /*!< Power Down control : controls power SRAM instances
273                                  in the different Low power modes */
274     __IO uint32_t CPURETCTRL;   /*!< CPU0 retention control : controls CPU retention parameters in POWER DOWN modes */
275     __IO uint64_t VOLTAGE;      /*!< Voltage control in Low Power Modes */
276     __IO uint32_t WAKEUPSRC[4]; /*!< Wake up sources control for sleepcon */
277     __IO uint32_t WAKEUPINT[4]; /*!< Wake up sources control for ARM */
278     __IO uint32_t HWWAKE;       /*!< Interrupt that can postpone power down modes
279                                  in case an interrupt is pending when the processor request deepsleep */
280     __IO uint32_t WAKEUPIOSRC;  /*!< Wake up I/O sources in DEEP POWER-DOWN mode */
281 } LPC_LOWPOWER_T;
282 
283 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
284 /**
285  * @brief NMPA related Registers
286  */
287 #define FLASH_NMPA_BOD_LDOCORE                      (*((volatile unsigned int *)(0x3FC08)))
288 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_ARRAY0    (*((volatile unsigned int *)(0x3FC18)))
289 #define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_ARRAY1    (*((volatile unsigned int *)(0x3FC1C)))
290 #define FLASH_NMPA_LDO_AO                           (*((volatile unsigned int *)(0x3FC24)))
291 #define FLASH_NMPA_LDO_MEM                          (*((volatile unsigned int *)(0x3FD60)))
292 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_ARRAY0   (*((volatile unsigned int *)(0x3FCB0)))
293 #define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_ARRAY1   (*((volatile unsigned int *)(0x3FCB4)))
294 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_ARRAY0 (*((volatile unsigned int *)(0x3FCB8)))
295 #define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_ARRAY1 (*((volatile unsigned int *)(0x3FCBC)))
296 #define FLASH_NMPA_PVT_MONITOR_0_RINGO              (*((volatile unsigned int *)(0x3FCE0)))
297 #define FLASH_NMPA_PVT_MONITOR_1_RINGO              (*((volatile unsigned int *)(0x3FCF0)))
298 
299 /**
300  * @brief NMPA related masks
301  */
302 
303 #define FLASH_NMPA_BOD_LDOCORE_REGREF_1P8V_OFFSET_SHIFT (24U)
304 #define FLASH_NMPA_BOD_LDOCORE_REGREF_1P8V_OFFSET_MASK  (0xFF000000U)
305 #define FLASH_NMPA_LDO_AO_VADJ_ACTIVE_SHIFT             (0U)
306 #define FLASH_NMPA_LDO_AO_VADJ_ACTIVE_MASK              (0xFFU)
307 #endif
308 
309 /**
310  * @brief CSS related Registers
311  */
312 #define CSSV2_STATUS_REG            (*((volatile unsigned int *)(0x40030000)))
313 #define CSSV2_CTRL_REG              (*((volatile unsigned int *)(0x40030004)))
314 #define SYSCON_CSS_CLK_CTRL_REG     (*((volatile unsigned int *)(0x400009B0)))
315 #define SYSCON_CSS_CLK_CTRL_SET_REG (*((volatile unsigned int *)(0x400009B4)))
316 #define SYSCON_CSS_CLK_CTRL_CLR_REG (*((volatile unsigned int *)(0x400009B8)))
317 
318 /**
319  * @brief Wake-up I/O positions
320  */
321 /*!< wake-up 0 */
322 #define WAKEUPIO_0_PORT (1UL)
323 #define WAKEUPIO_0_PINS (1UL)
324 /*!< wake-up 1 */
325 #define WAKEUPIO_1_PORT (0UL)
326 #define WAKEUPIO_1_PINS (28UL)
327 /*!< wake-up 2 */
328 #define WAKEUPIO_2_PORT (1UL)
329 #define WAKEUPIO_2_PINS (18UL)
330 /*!< wake-up 3 */
331 #define WAKEUPIO_3_PORT (1UL)
332 #define WAKEUPIO_3_PINS (30UL)
333 /*!< wake-up 4 */
334 #define WAKEUPIO_4_PORT (0UL)
335 #define WAKEUPIO_4_PINS (26UL)
336 
337 /**
338  * @brief SRAM Low Power Modes
339  */
340 #define LOWPOWER_SRAM_LPMODE_MASK      (0xFUL)
341 #define LOWPOWER_SRAM_LPMODE_ACTIVE    (0x6UL) /*!< SRAM functional mode                                */
342 #define LOWPOWER_SRAM_LPMODE_SLEEP     (0xFUL) /*!< SRAM Sleep mode (Data retention, fast wake up)      */
343 #define LOWPOWER_SRAM_LPMODE_DEEPSLEEP (0x8UL) /*!< SRAM Deep Sleep mode (Data retention, slow wake up) */
344 #define LOWPOWER_SRAM_LPMODE_SHUTDOWN  (0x9UL) /*!< SRAM Shut Down mode (no data retention)             */
345 #define LOWPOWER_SRAM_LPMODE_POWERUP   (0xAUL) /*!< SRAM is powering up                                 */
346 
347 /**
348  * @brief SoC Low Power modes
349  */
350 #define LOWPOWER_CFG_LPMODE_INDEX          0
351 #define LOWPOWER_CFG_LPMODE_MASK           (0x3UL << LOWPOWER_CFG_LPMODE_INDEX)
352 #define LOWPOWER_CFG_SELCLOCK_INDEX        2
353 #define LOWPOWER_CFG_SELCLOCK_MASK         (0x1UL << LOWPOWER_CFG_SELCLOCK_INDEX)
354 #define LOWPOWER_CFG_SELMEMSUPPLY_INDEX    3
355 #define LOWPOWER_CFG_SELMEMSUPPLY_MASK     (0x1UL << LOWPOWER_CFG_SELMEMSUPPLY_INDEX)
356 #define LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX 4
357 #define LOWPOWER_CFG_MEMLOWPOWERMODE_MASK  (0x1UL << LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX)
358 #define LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX 5
359 #define LOWPOWER_CFG_LDODEEPSLEEPREF_MASK  (0x1UL << LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX)
360 
361 #define LOWPOWER_CFG_LPMODE_ACTIVE        0 /*!< ACTIVE mode */
362 #define LOWPOWER_CFG_LPMODE_DEEPSLEEP     1 /*!< DEEP-SLEEP mode */
363 #define LOWPOWER_CFG_LPMODE_POWERDOWN     2 /*!< POWER-DOWN mode */
364 #define LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN 3 /*!< DEEP POWER-DOWN mode */
365 #define LOWPOWER_CFG_LPMODE_SLEEP         4 /*!< SLEEP mode */
366 
367 #define LOWPOWER_CFG_SELCLOCK_1MHZ 0 /*!< The 1 MHz clock is used during the configuration of the PMC */
368 #define LOWPOWER_CFG_SELCLOCK_12MHZ \
369     1 /*!< The 12 MHz clock is used during the configuration of the PMC (to speed up PMC configuration process)*/
370 
371 #define LOWPOWER_CFG_SELMEMSUPPLY_LDOMEM 0 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_MEM */
372 #define LOWPOWER_CFG_SELMEMSUPPLY_LDODEEPSLEEP \
373     1 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_DEEP_SLEEP (or DCDC) */
374 
375 #define LOWPOWER_CFG_MEMLOWPOWERMODE_SOURCEBIASING                                                                     \
376     0 /*!< All SRAM instances use "Source Biasing" as low power mode technic (it is recommended to set LDO_MEM as high \
377          as possible -- 1.1V typical -- during low power mode) */
378 #define LOWPOWER_CFG_MEMLOWPOWERMODE_VOLTAGESCALING                                                                    \
379     1 /*!< All SRAM instances use "Voltage Scaling" as low power mode technic (it is recommended to set LDO_MEM as low \
380          as possible -- down to 0.7V -- during low power mode) */
381 
382 /**
383  * @brief LDO Voltage control in Low Power Modes
384  */
385 #define LOWPOWER_VOLTAGE_LDO_PMU_INDEX       0
386 #define LOWPOWER_VOLTAGE_LDO_PMU_MASK        (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_INDEX)
387 #define LOWPOWER_VOLTAGE_LDO_MEM_INDEX       5
388 #define LOWPOWER_VOLTAGE_LDO_MEM_MASK        (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_INDEX)
389 #define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX 10
390 #define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_MASK  (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX)
391 #define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX 15
392 #define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_MASK  (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX)
393 
394 /* CPU Retention Control*/
395 #define LOWPOWER_CPURETCTRL_ENA_INDEX           0
396 #define LOWPOWER_CPURETCTRL_ENA_MASK            (0x1UL << LOWPOWER_CPURETCTRL_ENA_INDEX)
397 #define LOWPOWER_CPURETCTRL_MEMBASE_INDEX       1
398 #define LOWPOWER_CPURETCTRL_MEMBASE_MASK        (0x1FFF << LOWPOWER_CPURETCTRL_MEMBASE_INDEX)
399 #define LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX 14
400 #define LOWPOWER_CPURETCTRL_RETDATALENGTH_MASK  (0x3FFUL << LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX)
401 
402 /**
403  * @brief SRAM Power Control Registers Code
404  */
405 //                                                         LSDEL   DSBDEL   DSB    LS
406 #define SRAM_PWR_MODE_ACT_CODE (0x6UL) // Active          |  0        1      1      0
407 #define SRAM_PWR_MODE_LS_CODE  (0xFUL) // Light Sleep     |  1        1      1      1
408 #define SRAM_PWR_MODE_DS_CODE  (0x8UL) // Deep Sleep      |  1        0      0      0
409 #define SRAM_PWR_MODE_SD_CODE  (0x9UL) // Shut Down       |  1        0      0      1
410 #define SRAM_PWR_MODE_MPU_CODE (0xEUL) // Matrix Power Up |  1        1      1      0
411 #define SRAM_PWR_MODE_FPU_CODE (0xAUL) // Full Power Up   |  1        0      1      0
412 
413 /**
414  * @brief System voltage setting
415  */
416 // All 3 DCDC_POWER_PROFILE_* constants below have been updated after chip characterization on ATE
417 #define DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ \
418     (100000000UL) /* Maximum System Frequency allowed with DCDC Power Profile LOW */
419 #define DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ \
420     (135000000UL) /* Maximum System Frequency allowed with DCDC Power Profile MEDIUM */
421 #define DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ \
422     (150000000UL) /* Maximum System Frequency allowed with DCDC Power Profile HIGH */
423 
424 /**
425  * @brief Manufacturing Process Parameters
426  */
427 // All 3 PROCESS_* constants below have been updated after chip characterization on ATE
428 #define PROCESS_NNN_AVG_HZ (14900000UL) /* Average Ring Oscillator value for Nominal (NNN) Manufacturing Process */
429 #define PROCESS_NNN_STD_HZ \
430     (515000UL) /* Standard Deviation Ring Oscillator value for Nominal (NNN) Manufacturing Process */
431 #define PROCESS_NNN_LIMITS \
432     (2UL) /* Nominal (NNN) Manufacturing Process Ring Oscillator values limit (with respect to the Average value) */
433 
434 #define PROCESS_NNN_MIN_HZ \
435     (PROCESS_NNN_AVG_HZ -  \
436      (PROCESS_NNN_LIMITS * \
437       PROCESS_NNN_STD_HZ)) /* Minimum Ring Oscillator value for Nominal (NNN) Manufacturing Process */
438 
439 #define PROCESS_NNN_MAX_HZ \
440     (PROCESS_NNN_AVG_HZ +  \
441      (PROCESS_NNN_LIMITS * \
442       PROCESS_NNN_STD_HZ)) /* Maximum Ring OScillator value for Nominal (NNN) Manufacturing Process */
443 
444 // All 9 VOLTAGE_* constants below have been updated after chip characterization on ATE
445 #define VOLTAGE_SSS_LOW_MV (1075UL) /* Voltage Settings for : Process=SSS, DCDC Power Profile=LOW */
446 #define VOLTAGE_SSS_MED_MV (1175UL) /* Voltage Settings for : Process=SSS, DCDC Power Profile=MEDIUM */
447 #define VOLTAGE_SSS_HIG_MV (1200UL) /* Voltage Settings for : Process=SSS, DCDC Power Profile=HIGH */
448 
449 #define VOLTAGE_NNN_LOW_MV (1025UL) /* Voltage Settings for : Process=NNN, DCDC Power Profile=LOW */
450 #define VOLTAGE_NNN_MED_MV (1100UL) /* Voltage Settings for : Process=NNN, DCDC Power Profile=MEDIUM */
451 #define VOLTAGE_NNN_HIG_MV (1150UL) /* Voltage Settings for : Process=NNN, DCDC Power Profile=HIGH */
452 
453 #define VOLTAGE_FFF_LOW_MV (1025UL) /* Voltage Settings for : Process=FFF, DCDC Power Profile=LOW */
454 #define VOLTAGE_FFF_MED_MV (1100UL) /* Voltage Settings for : Process=FFF, DCDC Power Profile=MEDIUM */
455 #define VOLTAGE_FFF_HIG_MV (1150UL) /* Voltage Settings for : Process=FFF, DCDC Power Profile=HIGH */
456 
457 /*******************************************************************************
458  * Codes
459  ******************************************************************************/
460 
461 /*******************************************************************************
462  * LOCAL FUNCTIONS PROTOTYPES
463  ******************************************************************************/
464 static void POWER_WaitLDOCoreInit(void);
465 static void POWER_SRAMPowerUpDelay(void);
466 static void POWER_PowerCycleCpu(void);
467 static void POWER_SetLowPowerMode(LPC_LOWPOWER_T *p_lowpower_cfg);
468 static uint32_t POWER_WakeUpIOCtrl(uint32_t p_wakeup_io_ctrl);
469 static uint32_t POWER_SetLdoAoLdoMemVoltage(uint32_t p_lp_mode);
470 static void POWER_SetSystemPowerProfile(v_system_power_profile_t power_profile);
471 static void POWER_SetVoltageForProcess(v_system_power_profile_t power_profile);
472 static lowpower_process_corner_enum POWER_GetPartProcessCorner(void);
473 static void POWER_SetSystemVoltage(uint32_t system_voltage_mv);
474 static void POWER_SetSystemClock12MHZ(void);
475 static void POWER_SRAMSetRegister(power_sram_index_t sram_index, uint32_t power_mode);
476 static void POWER_SRAMActiveToLightSleep(power_sram_index_t sram_index);
477 static void POWER_SRAMActiveToDeepSleep(power_sram_index_t sram_index);
478 static void POWER_SRAMActiveToShutDown(power_sram_index_t sram_index);
479 static void POWER_SRAMLightSleepToActive(power_sram_index_t sram_index);
480 static void POWER_SRAMDeepSleepToActive(power_sram_index_t sram_index);
481 static void POWER_SRAMShutDownToActive(power_sram_index_t sram_index);
482 
483 /**
484  * brief    SoC Power Management Controller initialization
485  * return   power_status_t
486  */
POWER_PowerInit(void)487 power_status_t POWER_PowerInit(void)
488 {
489     // To speed up PMC configuration, change PMC clock from 1 MHz to 12 MHz.
490     // Set Power Mode to "ACTIVE" (required specially when waking up from DEEP POWER-DOWN)
491     PMC->CTRL = (PMC->CTRL | PMC_CTRL_SELCLOCK_MASK) & (~PMC_CTRL_LPMODE_MASK);
492 
493     // Check that no time out occured during the hardware wake-up process
494     if (PMC->TIMEOUTEVENTS != 0)
495     {
496         // A least 1 time-out error occured.
497         return kPOWER_Status_Fail;
498     }
499 
500     // Set up wake-up IO pad control source : IOCON ((WAKEUPIO_ENABLE = 0)
501     PMC->WAKEUPIOCTRL &= ~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK;
502 
503     // Set LDO_FLASHNV output voltage
504     PMC->LDOFLASHNV = (PMC->LDOFLASHNV & (~PMC_LDOFLASHNV_VADJ_MASK)) | PMC_LDOFLASHNV_VADJ(V_LDO_1P850);
505 
506     // Set LDO_EFUSE_PROG output voltage
507     PMC->LDOEFUSEPROG = (PMC->LDOEFUSEPROG & (~PMC_LDOEFUSEPROG_VADJ_MASK)) | PMC_LDOEFUSEPROG_VADJ(V_LDO_1P850);
508 
509     // Configure the voltage level of LDO CORE Low Power mode (TODO :: :: Temporarily set to 0.9V; target is 0.8 V)*/
510     PMC->LDOCORE0 = (PMC->LDOCORE0 & (~PMC_LDOCORE0_LPREGREFSEL_MASK)) | PMC_LDOCORE0_LPREGREFSEL(V_LDOCORE_LP_0P900);
511 
512     // SRAM uses Voltage Scaling in all Low Power modes
513     PMC->SRAMCTRL = (PMC->SRAMCTRL & (~PMC_SRAMCTRL_SMB_MASK)) | PMC_SRAMCTRL_SMB(3);
514 
515     // Enable Analog References fast wake-up in case of wake-up from all low power modes and Hardware Pin reset
516     PMC->REFFASTWKUP = PMC->REFFASTWKUP | PMC_REFFASTWKUP_LPWKUP_MASK | PMC_REFFASTWKUP_HWWKUP_MASK;
517 
518     // Enable FRO192MHz shut-off glitch suppression.
519     // TODO ::  :: Check the Power Consumption Impact of this setting during DEEP-SLEEP and POWER-DOWN.
520     //             (Supposed to be 1 to 2uA in typical conditions). If the impe
521     //
522     ANACTRL->OSC_TESTBUS = 0x1;
523 
524     return kPOWER_Status_Success;
525 }
526 
527 /**
528  * brief
529  * return   power_status_t
530  */
POWER_SetCorePowerSource(power_core_pwr_source_t pwr_source)531 power_status_t POWER_SetCorePowerSource(power_core_pwr_source_t pwr_source)
532 {
533     uint32_t pmc_reg_data;
534 
535     switch (pwr_source)
536     {
537         case kPOWER_CoreSrcDCDC:
538         {
539             // Enable DCDC (1st step)
540             PMC->CMD = PMC_CMD_DCDCENABLE_MASK;
541 
542             // Wait until DCDC is enabled
543             while ((PMC->STATUSPWR & PMC_STATUSPWR_DCDCPWROK_MASK) == 0)
544                 ;
545 
546             // Disable LDO Core Low Power Mode (2nd step)
547             PMC->CMD = PMC_CMD_LDOCORELOWPWRDISABLE_MASK;
548 
549             // Disable LDO Core High Power Mode (3rd step)
550             PMC->CMD = PMC_CMD_LDOCOREHIGHPWRDISABLE_MASK;
551 
552             // Check PMC Finite State Machines status
553             pmc_reg_data = PMC->STATUS & (PMC_STATUS_FSMDCDCENABLE_MASK | PMC_STATUS_FSMLDOCOREHPENABLE_MASK |
554                                           PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK);
555             if (pmc_reg_data != (PMC_STATUS_FSMDCDCENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK))
556             {
557                 // Error : only DCDC and LDO CORE Exponential Timer must both be enabled.
558                 return (kPOWER_Status_Fail);
559             }
560         }
561         break;
562 
563         case kPOWER_CoreSrcLDOCoreHP:
564         {
565             // Enable LDO Core High Power Mode (1st step)
566             PMC->CMD = PMC_CMD_LDOCOREHIGHPWRENABLE_MASK;
567 
568             // Note: Once LDO_CORE High Power Mode has been enabled,
569             // at least 2us are required before one can reliabily sample
570             // the LDO Low Voltage Detectore Output.
571             POWER_WaitLDOCoreInit();
572 
573             // Wait until LDO CORE High Power is enabled
574             while ((PMC->STATUSPWR & PMC_STATUSPWR_LDOCOREPWROK_MASK) == 0)
575                 ;
576 
577             // Disable DCDC (2nd step)
578             PMC->CMD = PMC_CMD_DCDCDISABLE_MASK;
579 
580             // Disable LDO Core Low Power Mode (3rd step)
581             PMC->CMD = PMC_CMD_LDOCORELOWPWRDISABLE_MASK;
582 
583             // Check PMC Finite State Machines status
584             pmc_reg_data = PMC->STATUS & (PMC_STATUS_FSMDCDCENABLE_MASK | PMC_STATUS_FSMLDOCOREHPENABLE_MASK |
585                                           PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK);
586             if (pmc_reg_data != PMC_STATUS_FSMLDOCOREHPENABLE_MASK)
587             {
588                 // Error : only LDO CORE High Power mode must both be enabled.
589                 return (kPOWER_Status_Fail);
590             }
591         }
592         break;
593 
594         case kPOWER_CoreSrcLDOCoreLP:
595         {
596             // Enable LDO Core Low Power Mode (1st step)
597             PMC->CMD = PMC_CMD_LDOCORELOWPWRENABLE_MASK;
598 
599             // Disable LDO Core High Power Mode (2nd step)
600             PMC->CMD = PMC_CMD_LDOCOREHIGHPWRDISABLE_MASK;
601 
602             // Disable DCDC (3rd step)
603             PMC->CMD = PMC_CMD_DCDCDISABLE_MASK;
604 
605             // Check PMC Finite State Machines status
606             pmc_reg_data = PMC->STATUS & (PMC_STATUS_FSMDCDCENABLE_MASK | PMC_STATUS_FSMLDOCOREHPENABLE_MASK |
607                                           PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK);
608             if (pmc_reg_data != (PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK))
609             {
610                 // Error : only LDO CORE Low Power mode and LDO CORE Exponential Timer must both be enabled.
611                 return (kPOWER_Status_Fail);
612             }
613         }
614         break;
615 
616         case kPOWER_CoreSrcExternal:
617         {
618             // Disable LDO Core Low Power Mode (1st step)
619             PMC->CMD = PMC_CMD_LDOCORELOWPWRDISABLE_MASK;
620 
621             // Disable LDO Core High Power Mode (2nd step)
622             PMC->CMD = PMC_CMD_LDOCOREHIGHPWRDISABLE_MASK;
623 
624             // Disable DCDC (3rd step)
625             PMC->CMD = PMC_CMD_DCDCDISABLE_MASK;
626 
627             // Check PMC Finite State Machines status
628             pmc_reg_data = PMC->STATUS & (PMC_STATUS_FSMDCDCENABLE_MASK | PMC_STATUS_FSMLDOCOREHPENABLE_MASK |
629                                           PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK);
630             if (pmc_reg_data != 0)
631             {
632                 // Error :  All power sources must be disabled.
633                 return (kPOWER_Status_Fail);
634             }
635         }
636         break;
637 
638         default: // Not supported
639             return (kPOWER_Status_Fail);
640 
641     } // End switch (pwr_source)
642 
643     return (kPOWER_Status_Success);
644 }
645 
646 /**
647  * brief
648  * @param   :
649  * return   power_core_pwr_source_t
650  */
POWER_GetCorePowerSource(void)651 power_core_pwr_source_t POWER_GetCorePowerSource(void)
652 {
653     uint32_t reg_status, reg_statuspwr;
654 
655     reg_status    = PMC->STATUS;
656     reg_statuspwr = PMC->STATUSPWR;
657 
658     if ((reg_statuspwr & PMC_STATUSPWR_DCDCPWROK_MASK) && (reg_status & PMC_STATUS_FSMDCDCENABLE_MASK))
659     {
660         /* DCDC */
661         return (kPOWER_CoreSrcDCDC);
662     }
663     else
664     {
665         if ((reg_statuspwr & PMC_STATUSPWR_LDOCOREPWROK_MASK) && (reg_status & PMC_STATUS_FSMLDOCOREHPENABLE_MASK))
666         {
667             /* LDO_CORE High Power Mode */
668             return (kPOWER_CoreSrcLDOCoreHP);
669         }
670         else
671         {
672             if (reg_status & PMC_STATUS_FSMLDOCORELPENABLE_MASK)
673             {
674                 /* LDO_CORE Low Power Mode */
675                 return (kPOWER_CoreSrcLDOCoreLP);
676             }
677             else
678             {
679                 /* External */
680                 return (kPOWER_CoreSrcExternal);
681             }
682         }
683     }
684 }
685 
686 /**
687  * brief
688  * return   nothing
689  */
POWER_CorePowerSourceControl(power_core_pwr_source_t pwr_source,power_core_pwr_state_t pwr_state)690 power_status_t POWER_CorePowerSourceControl(power_core_pwr_source_t pwr_source, power_core_pwr_state_t pwr_state)
691 {
692     switch (pwr_source)
693     {
694         case kPOWER_CoreSrcDCDC:
695         {
696             if (pwr_state == kPOWER_CorePwrEnable)
697             {
698                 // Enable DCDC
699                 PMC->CMD = PMC_CMD_DCDCENABLE_MASK;
700 
701                 // Wait until DCDC is enabled
702                 while ((PMC->STATUSPWR & PMC_STATUSPWR_DCDCPWROK_MASK) == 0)
703                     ;
704 
705                 // Check PMC Finite State Machines status
706                 if ((PMC->STATUS & PMC_STATUS_FSMDCDCENABLE_MASK) == 0)
707                 {
708                     // Error : DCDC not enabled.
709                     return (kPOWER_Status_Fail);
710                 }
711             }
712             else
713             {
714                 // Disable DCDC
715                 PMC->CMD = PMC_CMD_DCDCDISABLE_MASK;
716 
717                 // Check PMC Finite State Machines status
718                 if ((PMC->STATUS & PMC_STATUS_FSMDCDCENABLE_MASK) != 0)
719                 {
720                     // Error : DCDC is enabled.
721                     return (kPOWER_Status_Fail);
722                 }
723             }
724         }
725         break;
726 
727         case kPOWER_CoreSrcLDOCoreHP:
728         {
729             if (pwr_state == kPOWER_CorePwrEnable)
730             {
731                 // Enable LDO Core High Power Mode
732                 PMC->CMD = PMC_CMD_LDOCOREHIGHPWRENABLE_MASK;
733 
734                 // Note: Once LDO_CORE High Power Mode has been enabled,
735                 // at least 2us are required before one can reliabily sample
736                 // the LDO Low Voltage Detector Output.
737                 POWER_WaitLDOCoreInit();
738 
739                 // Wait until LDO CORE High Power is enabled
740                 while ((PMC->STATUSPWR & PMC_STATUSPWR_LDOCOREPWROK_MASK) == 0)
741                     ;
742 
743                 // Check PMC Finite State Machines status
744                 if ((PMC->STATUS & PMC_STATUS_FSMLDOCOREHPENABLE_MASK) == 0)
745                 {
746                     // Error : LDO CORE High Power mode is not enabled.
747                     return (kPOWER_Status_Fail);
748                 }
749             }
750             else
751             {
752                 // Disable LDO Core High Power Mode
753                 PMC->CMD = PMC_CMD_LDOCOREHIGHPWRDISABLE_MASK;
754 
755                 // Check PMC Finite State Machines status
756                 if ((PMC->STATUS & PMC_STATUS_FSMLDOCOREHPENABLE_MASK) != 0)
757                 {
758                     // Error : LDO CORE High Power mode is enabled.
759                     return (kPOWER_Status_Fail);
760                 }
761             }
762         }
763         break;
764 
765         case kPOWER_CoreSrcLDOCoreLP:
766         {
767             if (pwr_state == kPOWER_CorePwrEnable)
768             {
769                 // Enable LDO Core Low Power Mode (1st step)
770                 PMC->CMD = PMC_CMD_LDOCORELOWPWRENABLE_MASK;
771 
772                 // Check PMC Finite State Machines status
773                 if ((PMC->STATUS & (PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK)) !=
774                     (PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK))
775                 {
776                     // Error : LDO CORE Low Power mode is not enabled.
777                     return (kPOWER_Status_Fail);
778                 }
779             }
780             else
781             {
782                 // Disable LDO Core Low Power Mode
783                 PMC->CMD = PMC_CMD_LDOCORELOWPWRDISABLE_MASK;
784 
785                 // Check PMC Finite State Machines status
786                 if ((PMC->STATUS & (PMC_STATUS_FSMLDOCORELPENABLE_MASK | PMC_STATUS_FSMLDOCOREEXPTMRENABLE_MASK)) != 0)
787                 {
788                     // Error : LDO CORE Low Power mode is enabled.
789                     return (kPOWER_Status_Fail);
790                 }
791             }
792         }
793         break;
794 
795         default: // Not supported
796             return (kPOWER_Status_Fail);
797 
798     } // End switch (pwr_source)
799 
800     return (kPOWER_Status_Success);
801 }
802 
803 /**
804  * brief
805  * return
806  */
POWER_GetSRAMPowerMode(power_sram_index_t sram_index)807 power_sram_pwr_mode_t POWER_GetSRAMPowerMode(power_sram_index_t sram_index)
808 {
809     power_sram_pwr_mode_t pwr_mode;
810     uint32_t state;
811     uint32_t sram_ctrl_0 = PMC->SRAMCTRL0;
812     uint32_t sram_ctrl_1 = PMC->SRAMCTRL1;
813 
814     switch (sram_index)
815     {
816         case kPOWER_SRAM_IDX_RAM_X0:
817         {
818             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_X0_LS_SHIFT) & 0xF;
819             break;
820         }
821 
822         case kPOWER_SRAM_IDX_RAM_00:
823         {
824             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_00_LS_SHIFT) & 0xF;
825             break;
826         }
827 
828         case kPOWER_SRAM_IDX_RAM_01:
829         {
830             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_01_LS_SHIFT) & 0xF;
831             break;
832         }
833 
834         case kPOWER_SRAM_IDX_RAM_02:
835         {
836             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_02_LS_SHIFT) & 0xF;
837             break;
838         }
839 
840         case kPOWER_SRAM_IDX_RAM_03:
841         {
842             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_03_LS_SHIFT) & 0xF;
843             break;
844         }
845 
846         case kPOWER_SRAM_IDX_RAM_10:
847         {
848             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_10_LS_SHIFT) & 0xF;
849             break;
850         }
851 
852         case kPOWER_SRAM_IDX_RAM_20:
853         {
854             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_20_LS_SHIFT) & 0xF;
855             break;
856         }
857 
858         case kPOWER_SRAM_IDX_RAM_30:
859         {
860             state = (sram_ctrl_0 >> PMC_SRAMCTRL0_RAM_30_LS_SHIFT) & 0xF;
861             break;
862         }
863 
864         case kPOWER_SRAM_IDX_RAM_40:
865         {
866             state = (sram_ctrl_1 >> PMC_SRAMCTRL1_RAM_40_LS_SHIFT) & 0xF;
867             break;
868         }
869 
870         case kPOWER_SRAM_IDX_RAM_41:
871         {
872             state = (sram_ctrl_1 >> PMC_SRAMCTRL1_RAM_41_LS_SHIFT) & 0xF;
873             break;
874         }
875 
876         case kPOWER_SRAM_IDX_RAM_42:
877         {
878             state = (sram_ctrl_1 >> PMC_SRAMCTRL1_RAM_42_LS_SHIFT) & 0xF;
879             break;
880         }
881 
882         case kPOWER_SRAM_IDX_RAM_43:
883         {
884             state = (sram_ctrl_1 >> PMC_SRAMCTRL1_RAM_43_LS_SHIFT) & 0xF;
885             break;
886         }
887 
888         default:
889             // Error
890             state = 0x6; // Active.
891     }
892 
893     switch (state)
894     {
895         case 0x6:
896             pwr_mode = kPOWER_SRAMPwrActive;
897             break;
898 
899         case 0xF:
900             pwr_mode = kPOWER_SRAMPwrLightSleep;
901             break;
902 
903         case 0x8:
904             pwr_mode = kPOWER_SRAMPwrDeepSleep;
905             break;
906 
907         case 0x9:
908             pwr_mode = kPOWER_SRAMPwrShutDown;
909             break;
910 
911         default:
912             pwr_mode = kPOWER_SRAMPwrActive;
913     }
914 
915     return (pwr_mode);
916 }
917 
918 /**
919  * brief
920  * return
921  */
POWER_SRAMPowerModeControl(power_sram_bit_t sram_inst,power_sram_pwr_mode_t pwr_mode)922 power_status_t POWER_SRAMPowerModeControl(power_sram_bit_t sram_inst, power_sram_pwr_mode_t pwr_mode)
923 {
924     power_sram_pwr_mode_t current_pwr_mode;
925     power_sram_index_t sram_index = kPOWER_SRAM_IDX_RAM_X0;
926 
927     sram_inst = (power_sram_bit_t)((uint32_t)sram_inst & 0x3FFF); /* Only SRAM from RAM_X0 to RAM_F3 */
928     while ((uint32_t)sram_inst != 0)
929     {
930         // There is a least 1 SRAM instance to be processed
931         if ((uint32_t)sram_inst & 0x1)
932         {
933             // Get current SRAM state
934             current_pwr_mode = POWER_GetSRAMPowerMode(sram_index);
935 
936             // The SRAM instance Power state must be updated
937             switch (current_pwr_mode)
938             {
939                 case kPOWER_SRAMPwrActive:
940                 { // Active
941                     switch (pwr_mode)
942                     {
943                         case kPOWER_SRAMPwrActive:
944                         { // Active ---> Active : there is nothing to do.
945                             break;
946                         }
947 
948                         case kPOWER_SRAMPwrLightSleep:
949                         { // Active ---> Light Sleep
950                             POWER_SRAMActiveToLightSleep(sram_index);
951                             break;
952                         }
953 
954                         case kPOWER_SRAMPwrDeepSleep:
955                         { // Active ---> Deep Sleep
956                             POWER_SRAMActiveToDeepSleep(sram_index);
957                             break;
958                         }
959 
960                         case kPOWER_SRAMPwrShutDown:
961                         { // Active ---> Shut Down
962                             POWER_SRAMActiveToShutDown(sram_index);
963                             break;
964                         }
965 
966                         default:
967                             // Do nothing.
968                             ;
969                     } // switch( pwr_mode )
970 
971                     break;
972                 }
973 
974                 case kPOWER_SRAMPwrLightSleep:
975                 { // Light Sleep
976                     switch (pwr_mode)
977                     {
978                         case kPOWER_SRAMPwrActive:
979                         { // Light Sleep ---> Active
980                             POWER_SRAMLightSleepToActive(sram_index);
981                             break;
982                         }
983 
984                         case kPOWER_SRAMPwrLightSleep:
985                         { // Light Sleep ---> Light Sleep : there is nothing to do.
986                             break;
987                         }
988 
989                         default:
990                             // Light Sleep ---> Shut Down : FORBIDDEN (error)
991                             // Light Sleep ---> Deep Sleep : FORBIDDEN (error)
992                             return (kPOWER_Status_Fail);
993                     } // switch( pwr_mode )
994 
995                     break;
996                 }
997 
998                 case kPOWER_SRAMPwrDeepSleep:
999                 { // Deep Sleep
1000                     switch (pwr_mode)
1001                     {
1002                         case kPOWER_SRAMPwrActive:
1003                         { // Deep Sleep ---> Active
1004                             POWER_SRAMDeepSleepToActive(sram_index);
1005                             break;
1006                         }
1007 
1008                         case kPOWER_SRAMPwrDeepSleep:
1009                         { // Deep Sleep ---> Deep Sleep : there is nothing to do.
1010                             break;
1011                         }
1012 
1013                         default:
1014                             // Deep Sleep ---> Shut Down : FORBIDDEN (error)
1015                             // Deep Sleep ---> Light Sleep : FORBIDDEN (error)
1016                             return (kPOWER_Status_Fail);
1017                     } // switch( pwr_mode )
1018 
1019                     break;
1020                 }
1021 
1022                 case kPOWER_SRAMPwrShutDown:
1023                 { // Shutdown
1024                     switch (pwr_mode)
1025                     {
1026                         case kPOWER_SRAMPwrActive:
1027                         { // Shutdown ---> Active
1028                             POWER_SRAMShutDownToActive(sram_index);
1029                             break;
1030                         }
1031 
1032                         case kPOWER_SRAMPwrShutDown:
1033                         { // Shutdown ---> Shut Down : there is nothing to do.
1034                             break;
1035                         }
1036 
1037                         default:
1038                             // Shutdown ---> Deep Sleep : FORBIDDEN (error)
1039                             // Shutdown ---> Light Sleep : FORBIDDEN (error)
1040                             return (kPOWER_Status_Fail);
1041                     } // switch( pwr_mode )
1042 
1043                     break;
1044                 }
1045 
1046                 default:
1047                     // Do nothing
1048                     ;
1049             } // switch( current_pwr_mode )
1050         }     // if ( (uint32_t)sram_inst & 0x1 )
1051 
1052         // Move to next SRAM index
1053         sram_inst  = (power_sram_bit_t)((uint32_t)sram_inst >> 1);
1054         sram_index = (power_sram_index_t)((uint32_t)sram_index + 1);
1055     } // while ((uint32_t)sram_inst != 0 )
1056 
1057     return (kPOWER_Status_Success);
1058 }
1059 
1060 /**
1061  * @brief   Configures and enters in SLEEP low power mode
1062  * @return  Nothing
1063  */
POWER_EnterSleep(void)1064 void POWER_EnterSleep(void)
1065 {
1066     uint32_t pmsk;
1067     pmsk = __get_PRIMASK();             /* Save CORTEX-M33 interrupt configuration */
1068     __disable_irq();                    /* Disable all interrupts */
1069     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; /* CORTEX-M33 uses "Sleep" mode */
1070     __WFI();                            /* CORTEX-M33 enters "Sleep" mode */
1071     __set_PRIMASK(pmsk);                /* Restore CORTEX-M33 interrupt configuration (after wake up) */
1072 }
1073 
1074 /**
1075  * brief    PMC Deep Sleep function call
1076  * return   nothing
1077  */
POWER_EnterDeepSleep(uint32_t exclude_from_pd[2],uint32_t sram_retention_ctrl,uint32_t wakeup_interrupts[4],uint32_t hardware_wake_ctrl)1078 void POWER_EnterDeepSleep(uint32_t exclude_from_pd[2],
1079                           uint32_t sram_retention_ctrl,
1080                           uint32_t wakeup_interrupts[4],
1081                           uint32_t hardware_wake_ctrl)
1082 {
1083     LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
1084     uint32_t pmc_reset_ctrl;
1085 
1086     /* Clear Low Power Mode configuration variable */
1087     memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
1088 
1089     /* Configure Low Power Mode configuration variable */
1090     lv_low_power_mode_cfg.CFG = LOWPOWER_CFG_LPMODE_DEEPSLEEP << LOWPOWER_CFG_LPMODE_INDEX; /* DEEPSLEEP mode */
1091 
1092     /* Make sure LDO MEM & Analog references will stay powered, Shut down ROM & LDO Flash NV */
1093     lv_low_power_mode_cfg.PDCTRL[0] =
1094         (~exclude_from_pd[0] & ~kPDRUNCFG_PD_LDOMEM & ~kPDRUNCFG_PD_BIAS) | kPDRUNCFG_PD_ROM | kPDRUNCFG_PD_LDOFLASHNV;
1095     lv_low_power_mode_cfg.PDCTRL[1] = ~exclude_from_pd[1];
1096 
1097     // Voltage control in DeepSleep Low Power Modes
1098     lv_low_power_mode_cfg.VOLTAGE = POWER_SetLdoAoLdoMemVoltage(LOWPOWER_CFG_LPMODE_DEEPSLEEP);
1099 
1100     // SRAM retention control during DEEP-SLEEP
1101     lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl & kPOWER_SRAM_DSLP_MASK;
1102 
1103     /* Interrupts that allow DMA transfers with Flexcomm without waking up the Processor */
1104     if (hardware_wake_ctrl & (LOWPOWER_HWWAKE_PERIPHERALS | LOWPOWER_HWWAKE_DMIC | LOWPOWER_HWWAKE_SDMA0 |
1105                               LOWPOWER_HWWAKE_SDMA1 | LOWPOWER_HWWAKE_DAC))
1106     {
1107         lv_low_power_mode_cfg.HWWAKE = (hardware_wake_ctrl & ~LOWPOWER_HWWAKE_FORCED) | LOWPOWER_HWWAKE_ENABLE_FRO192M;
1108     }
1109 
1110     // @NOTE Niobe4mini: update with new BOD reset enable management
1111     pmc_reset_ctrl = PMC->RESETCTRL;
1112     if ((pmc_reset_ctrl & (PMC_RESETCTRL_BODCORERESETENA_SECURE_MASK | PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_MASK)) ==
1113         ((0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_SHIFT) | (0x1 << PMC_RESETCTRL_BODCORERESETENA_SECURE_DP_SHIFT)))
1114     {
1115         /* BoD CORE reset is activated, so make sure BoD Core and Biasing won't be shutdown */
1116         lv_low_power_mode_cfg.PDCTRL[0] &= ~kPDRUNCFG_PD_BODCORE & ~kPDRUNCFG_PD_BIAS;
1117     }
1118 
1119     if ((pmc_reset_ctrl &
1120          (PMC_RESETCTRL_BODVDDMAINRESETENA_SECURE_MASK | PMC_RESETCTRL_BODVDDMAINRESETENA_SECURE_DP_MASK)) ==
1121         ((0x1 << PMC_RESETCTRL_BODVDDMAINRESETENA_SECURE_SHIFT) |
1122          (0x1 << PMC_RESETCTRL_BODVDDMAINRESETENA_SECURE_DP_SHIFT)))
1123     {
1124         /* BoD VDDMAIN reset is activated, so make sure BoD VDDMAIN and Biasing won't be shutdown */
1125         lv_low_power_mode_cfg.PDCTRL[0] &= ~kPDRUNCFG_PD_BODVDDMAIN & ~kPDRUNCFG_PD_BIAS;
1126     }
1127 
1128     /* CPU Wake up & Interrupt sources control */
1129     lv_low_power_mode_cfg.WAKEUPSRC[0] = lv_low_power_mode_cfg.WAKEUPINT[0] = wakeup_interrupts[0];
1130     lv_low_power_mode_cfg.WAKEUPSRC[1] = lv_low_power_mode_cfg.WAKEUPINT[1] = wakeup_interrupts[1];
1131     lv_low_power_mode_cfg.WAKEUPSRC[2] = lv_low_power_mode_cfg.WAKEUPINT[2] = wakeup_interrupts[2];
1132     lv_low_power_mode_cfg.WAKEUPSRC[3] = lv_low_power_mode_cfg.WAKEUPINT[3] = wakeup_interrupts[3];
1133 
1134     /* Enter low power mode */
1135     POWER_SetLowPowerMode(&lv_low_power_mode_cfg);
1136 }
1137 
1138 /**
1139  * brief    PMC power Down function call
1140  * return   nothing
1141  */
POWER_EnterPowerDown(uint32_t exclude_from_pd[1],uint32_t sram_retention_ctrl,uint32_t wakeup_interrupts[4],uint32_t cpu_retention_addr)1142 void POWER_EnterPowerDown(uint32_t exclude_from_pd[1],
1143                           uint32_t sram_retention_ctrl,
1144                           uint32_t wakeup_interrupts[4],
1145                           uint32_t cpu_retention_addr)
1146 {
1147     LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
1148 
1149     // Clear Low Power Mode configuration variable
1150     memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
1151 
1152     // Configure Low Power Mode configuration variable : POWER DOWN mode
1153     lv_low_power_mode_cfg.CFG = LOWPOWER_CFG_LPMODE_POWERDOWN << LOWPOWER_CFG_LPMODE_INDEX;
1154 
1155     // Only FRO32K, XTAL32K, FRO1M, COMP, BIAS and VREF can stay powered during POWERDOWN.
1156     // LDO_MEM is enabled (because at least 1 SRAM instance will be required - for CPU state retention -)
1157     lv_low_power_mode_cfg.PDCTRL[0] = ~(exclude_from_pd[0] | kPDRUNCFG_PD_LDOMEM);
1158     lv_low_power_mode_cfg.PDCTRL[1] = 0xFFFFFFFF;
1159 
1160     // Force Bias activation if Analog Comparator is required, otherwise, disable it.
1161     if ((lv_low_power_mode_cfg.PDCTRL[0] & kPDRUNCFG_PD_COMP) == 0)
1162     {
1163         // Analog Comparator is required du ring power-down: Enable Biasing
1164         lv_low_power_mode_cfg.PDCTRL[0] = lv_low_power_mode_cfg.PDCTRL[0] & (~kPDRUNCFG_PD_BIAS);
1165     }
1166     else
1167     {
1168         // Analog Comparator is not required du ring power-down: Disable Biasing
1169         lv_low_power_mode_cfg.PDCTRL[0] = lv_low_power_mode_cfg.PDCTRL[0] | kPDRUNCFG_PD_BIAS;
1170     }
1171 
1172 // SRAM retention control during POWER-DOWN
1173 
1174 // Depending on where the user wants to locate the CPU state retention data,
1175 // the associated SRAM instance will be automatically put in retention mode.
1176 // The boundaries are defined in such a way that the area where the CPU state
1177 // will be retained does not cross any SRAM instance boundary.
1178 // Per hardware design, 1540 bytes are necessary to store the whole CPU state
1179 #define RAM_00_CPU_RET_ADDR_MIN 0x20000000UL // RAM_00 start address
1180 #define RAM_00_CPU_RET_ADDR_MAX 0x200009FCUL // RAM_00 start address + 1540 - 1
1181 #define RAM_01_CPU_RET_ADDR_MIN 0x20001000UL // RAM_01 start address
1182 #define RAM_01_CPU_RET_ADDR_MAX 0x200019FCUL // RAM_01 start address + 1540 - 1
1183 #define RAM_02_CPU_RET_ADDR_MIN 0x20002000UL // RAM_02 start address
1184 #define RAM_02_CPU_RET_ADDR_MAX 0x200029FCUL // RAM_02 start address + 1540 - 1
1185 #define RAM_03_CPU_RET_ADDR_MIN 0x20003000UL // RAM_03 start address
1186 #define RAM_03_CPU_RET_ADDR_MAX 0x200039FCUL // RAM_03 start address + 1540 - 1
1187 
1188     if ((cpu_retention_addr >= RAM_00_CPU_RET_ADDR_MIN) && (cpu_retention_addr <= RAM_00_CPU_RET_ADDR_MAX))
1189     {
1190         // Inside RAM_00
1191         sram_retention_ctrl |= kPOWER_SRAM_RAM_00;
1192     }
1193     else
1194     {
1195         if ((cpu_retention_addr >= RAM_01_CPU_RET_ADDR_MIN) && (cpu_retention_addr <= RAM_01_CPU_RET_ADDR_MAX))
1196         {
1197             // Inside RAM_01
1198             sram_retention_ctrl |= kPOWER_SRAM_RAM_01;
1199         }
1200         else
1201         {
1202             if ((cpu_retention_addr >= RAM_02_CPU_RET_ADDR_MIN) && (cpu_retention_addr <= RAM_02_CPU_RET_ADDR_MAX))
1203             {
1204                 // Inside RAM_02
1205                 sram_retention_ctrl |= kPOWER_SRAM_RAM_02;
1206             }
1207             else
1208             {
1209                 if ((cpu_retention_addr >= RAM_03_CPU_RET_ADDR_MIN) && (cpu_retention_addr <= RAM_03_CPU_RET_ADDR_MAX))
1210                 {
1211                     // Inside RAM_03
1212                     sram_retention_ctrl |= kPOWER_SRAM_RAM_03;
1213                 }
1214                 else
1215                 {
1216                     // Error! Therefore, we locate the retention area in RAM_00
1217                     cpu_retention_addr = 0x20000000UL;
1218                     sram_retention_ctrl |= kPOWER_SRAM_RAM_00;
1219                 }
1220             }
1221         }
1222     }
1223 
1224     lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl & kPOWER_SRAM_PDWN_MASK;
1225 
1226     // Voltage control in Low Power Modes
1227     // The Memories Voltage settings below are for voltage scaling
1228     lv_low_power_mode_cfg.VOLTAGE = POWER_SetLdoAoLdoMemVoltage(LOWPOWER_CFG_LPMODE_POWERDOWN);
1229 
1230     /* CPU0 retention Address */
1231     lv_low_power_mode_cfg.CPURETCTRL = ((cpu_retention_addr >> 1) | LOWPOWER_CPURETCTRL_ENA_MASK) &
1232                                        (LOWPOWER_CPURETCTRL_MEMBASE_MASK | LOWPOWER_CPURETCTRL_ENA_MASK);
1233 
1234     /* CPU Wake up & Interrupt sources control */
1235     lv_low_power_mode_cfg.WAKEUPSRC[0] = lv_low_power_mode_cfg.WAKEUPINT[0] =
1236         wakeup_interrupts[0] & (WAKEUP_GPIO_GLOBALINT0 | WAKEUP_GPIO_GLOBALINT1 | WAKEUP_FLEXCOMM3 | WAKEUP_ACMP |
1237                                 WAKEUP_RTC_ALARM_WAKEUP | WAKEUP_WAKEUP_MAILBOX);
1238     lv_low_power_mode_cfg.WAKEUPSRC[1] = lv_low_power_mode_cfg.WAKEUPINT[1] =
1239         wakeup_interrupts[1] & WAKEUP_OS_EVENT_TIMER;
1240     lv_low_power_mode_cfg.WAKEUPSRC[2] = lv_low_power_mode_cfg.WAKEUPINT[2] = 0UL;
1241     lv_low_power_mode_cfg.WAKEUPSRC[3] = lv_low_power_mode_cfg.WAKEUPINT[3] = wakeup_interrupts[3] & WAKEUP_ITRC;
1242 
1243     /* Enter low power mode */
1244     POWER_SetLowPowerMode(&lv_low_power_mode_cfg);
1245 }
1246 
1247 /**
1248  * brief    PMC Deep Power-Down function call
1249  * return   nothing
1250  */
POWER_EnterDeepPowerDown(uint32_t exclude_from_pd[1],uint32_t sram_retention_ctrl,uint32_t wakeup_interrupts[2],uint32_t wakeup_io_ctrl)1251 void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd[1],
1252                               uint32_t sram_retention_ctrl,
1253                               uint32_t wakeup_interrupts[2],
1254                               uint32_t wakeup_io_ctrl)
1255 {
1256     LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
1257 
1258     // Clear Low Power Mode configuration variable
1259     memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
1260 
1261     // Configure Low Power Mode configuration variable : DEEP POWER-DOWN mode
1262     lv_low_power_mode_cfg.CFG = LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN << LOWPOWER_CFG_LPMODE_INDEX;
1263 
1264     // Note: only FRO32K, XTAL32K, FRO1M and LDO_MEM can stay powered during DEEP POWER-DOWN
1265     lv_low_power_mode_cfg.PDCTRL[0] = ~exclude_from_pd[0];
1266     lv_low_power_mode_cfg.PDCTRL[1] = 0xFFFFFFFF;
1267 
1268     // SRAM retention control during DEEP POWER-DOWN
1269     // RAM_X0, RAM_02 and RAM_03 excluded: they are used by ROM Boot code
1270     sram_retention_ctrl               = sram_retention_ctrl & kPOWER_SRAM_DPWD_MASK;
1271     lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
1272 
1273     // Sanity check: if retention is required for any SRAM instance other than RAM_00, make sure LDO MEM will stay
1274     // powered */
1275     if ((sram_retention_ctrl & (~kPOWER_SRAM_RAM_00)) != 0)
1276     {
1277         // SRAM retention is required : enable LDO_MEM
1278         lv_low_power_mode_cfg.PDCTRL[0] &= ~kPDRUNCFG_PD_LDOMEM;
1279     }
1280     else
1281     {
1282         // No SRAM retention required : disable LDO_MEM
1283         lv_low_power_mode_cfg.PDCTRL[0] |= kPDRUNCFG_PD_LDOMEM;
1284     }
1285 
1286     // Voltage control in Low Power Modes
1287     // The Memories Voltage settings below are for voltage scaling
1288     lv_low_power_mode_cfg.VOLTAGE = POWER_SetLdoAoLdoMemVoltage(LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN);
1289 
1290     // Wake up sources control
1291     lv_low_power_mode_cfg.WAKEUPSRC[0] = lv_low_power_mode_cfg.WAKEUPINT[0] =
1292         wakeup_interrupts[0] &
1293         WAKEUP_RTC_ALARM_WAKEUP; /* CPU Wake up sources control : only WAKEUP_RTC_LITE_ALARM_WAKEUP */
1294     lv_low_power_mode_cfg.WAKEUPSRC[1] = lv_low_power_mode_cfg.WAKEUPINT[1] =
1295         wakeup_interrupts[1] & WAKEUP_OS_EVENT_TIMER; /* CPU Wake up sources control : only WAKEUP_OS_EVENT_TIMER */
1296     lv_low_power_mode_cfg.WAKEUPSRC[2] = lv_low_power_mode_cfg.WAKEUPINT[2] = 0UL;
1297     lv_low_power_mode_cfg.WAKEUPSRC[3] = lv_low_power_mode_cfg.WAKEUPINT[3] = 0UL;
1298 
1299     /* Wake up I/O sources */
1300     lv_low_power_mode_cfg.WAKEUPIOSRC = POWER_WakeUpIOCtrl(wakeup_io_ctrl);
1301 
1302     /* Enter low power mode */
1303     POWER_SetLowPowerMode(&lv_low_power_mode_cfg);
1304 
1305     /*** We'll reach this point ONLY and ONLY if the DEEPPOWERDOWN has not been taken (for instance because an RTC or
1306      * OSTIMER interrupt is pending) ***/
1307 }
1308 
1309 /**
1310  * @brief   Configures the 5 wake-up pins to wake up the part in DEEP-SLEEP and POWER-DOWN low power modes.
1311  * @param   wakeup_io_cfg_src : for all wake-up pins : indicates if the config is from IOCON or from PMC.
1312  * @param   wakeup_io_ctrl: the 5 wake-up pins configurations (see "LOWPOWER_WAKEUPIOSRC_*" #defines)
1313 
1314  * @return  Nothing
1315  *
1316  *          !!! IMPORTANT NOTES :
1317  *           1 - To be called just before POWER_EnterDeepSleep() or POWER_EnterPowerDown().
1318  */
1319 /**
1320  * brief    PMC Deep Power-Down function call
1321  * return   nothing
1322  */
POWER_SetWakeUpPins(uint32_t wakeup_io_cfg_src,uint32_t wakeup_io_ctrl)1323 void POWER_SetWakeUpPins(uint32_t wakeup_io_cfg_src, uint32_t wakeup_io_ctrl)
1324 {
1325     if (wakeup_io_cfg_src == LOWPOWER_WAKEUPIO_CFG_SRC_IOCON)
1326     {
1327         /* All wake-up pins controls are coming from IOCON */
1328 
1329         wakeup_io_ctrl = wakeup_io_ctrl | LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK |
1330                          LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK | LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK |
1331                          LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK |
1332                          LOWPOWER_WAKEUPIO_PIO4_DISABLEPULLUPDOWN_MASK; /* Make sure IOCON is not modified inside
1333                                                                            POWER_WakeUpIOCtrl */
1334 
1335         PMC->WAKEUPIOCTRL = POWER_WakeUpIOCtrl(wakeup_io_ctrl) & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
1336     }
1337     else
1338     {
1339         /* All wake-up pins controls are coming from PMC */
1340         PMC->WAKEUPIOCTRL = POWER_WakeUpIOCtrl(wakeup_io_ctrl) | PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK;
1341     }
1342 
1343     /* Release Wake up I/O reset (WAKEUPIO_RSTN = 1)*/
1344     PMC->WAKEUPIOCTRL |= PMC_WAKEUPIOCTRL_WAKEUPIO_RSTN_MASK;
1345 }
1346 
POWER_GetWakeUpCause(power_reset_cause_t * reset_cause,power_boot_mode_t * boot_mode,power_wakeup_pin_t * wakeup_pin_cause)1347 void POWER_GetWakeUpCause(power_reset_cause_t *reset_cause,
1348                           power_boot_mode_t *boot_mode,
1349                           power_wakeup_pin_t *wakeup_pin_cause)
1350 {
1351     uint32_t reset_cause_reg;
1352     uint32_t boot_mode_reg;
1353     uint32_t wakeupio_cause_reg;
1354 
1355     boot_mode_reg = (PMC->STATUS & PMC_STATUS_BOOTMODE_MASK) >> PMC_STATUS_BOOTMODE_SHIFT;
1356 
1357     switch (boot_mode_reg)
1358     {
1359         case 1:
1360             /* DEEP-SLEEP */
1361             *boot_mode = kBOOT_MODE_LP_DEEP_SLEEP;
1362             break;
1363         case 2:
1364             /* POWER-DOWN */
1365             *boot_mode = kBOOT_MODE_LP_POWER_DOWN;
1366             break;
1367         case 3:
1368             /* DEEP-POWER-DOWN */
1369             *boot_mode = kBOOT_MODE_LP_DEEP_POWER_DOWN;
1370             break;
1371         default:
1372             /* All non Low Power Mode wake-up */
1373             *boot_mode = kBOOT_MODE_POWER_UP;
1374     }
1375 
1376     wakeupio_cause_reg = PMC->WAKEIOCAUSE;
1377 
1378     if (boot_mode_reg == 0)
1379     {
1380         /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset:
1381          * PMC has been reset, so wake up pin event not expected to have happened. */
1382         *wakeup_pin_cause = kWAKEUP_PIN_NONE;
1383     }
1384     else
1385     {
1386         switch (((wakeupio_cause_reg & PMC_WAKEIOCAUSE_WAKEUPIO_EVENTS_ORDER_MASK) >>
1387                  PMC_WAKEIOCAUSE_WAKEUPIO_EVENTS_ORDER_SHIFT))
1388         {
1389             case 0x0:
1390                 *wakeup_pin_cause = kWAKEUP_PIN_NONE;
1391                 break;
1392             case 0x1:
1393                 *wakeup_pin_cause = kWAKEUP_PIN_0;
1394                 break;
1395             case 0x2:
1396                 *wakeup_pin_cause = kWAKEUP_PIN_1;
1397                 break;
1398             case 0x4:
1399                 *wakeup_pin_cause = kWAKEUP_PIN_2;
1400                 break;
1401             case 0x8:
1402                 *wakeup_pin_cause = kWAKEUP_PIN_3;
1403                 break;
1404             case 0x10:
1405                 *wakeup_pin_cause = kWAKEUP_PIN_4;
1406                 break;
1407             default:
1408                 /* Mutiple */
1409                 *wakeup_pin_cause = kWAKEUP_PIN_MULTIPLE;
1410                 break;
1411         }
1412     }
1413 
1414     reset_cause_reg = PMC->AOREG1;
1415 
1416     /*
1417      * Prioritize interrupts source with respect to how critical they are.
1418      */
1419     if (reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK)
1420     { /* Code Watchdog Reset */
1421         *reset_cause = kRESET_CAUSE_CDOGRESET;
1422     }
1423     else
1424     {
1425         if (reset_cause_reg & PMC_AOREG1_WDTRESET_MASK)
1426         { /* Watchdog Timer Reset */
1427             *reset_cause = kRESET_CAUSE_WDTRESET;
1428         }
1429         else
1430         {
1431             if (reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK)
1432             { /* ARM System Reset */
1433                 *reset_cause = kRESET_CAUSE_ARMSYSTEMRESET;
1434             }
1435             else
1436             {
1437                 if (boot_mode_reg != 3) /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset,
1438                                            DEEP-SLEEP and POWER-DOWN */
1439                 {
1440                     /*
1441                      * Prioritise Reset causes, starting from the strongest (Power On Reset)
1442                      */
1443                     if (reset_cause_reg & PMC_AOREG1_POR_MASK)
1444                     { /* Power On Reset */
1445                         *reset_cause = kRESET_CAUSE_POR;
1446                     }
1447                     else
1448                     {
1449                         if (reset_cause_reg & PMC_AOREG1_BODRESET_MASK)
1450                         { /* Brown-out Detector reset (either BODVBAT or BODCORE) */
1451                             *reset_cause = kRESET_CAUSE_BODRESET;
1452                         }
1453                         else
1454                         {
1455                             if (reset_cause_reg & PMC_AOREG1_PADRESET_MASK)
1456                             { /* Hardware Pin Reset */
1457                                 *reset_cause = kRESET_CAUSE_PADRESET;
1458                             }
1459                             else
1460                             {
1461                                 if (reset_cause_reg & PMC_AOREG1_SWRRESET_MASK)
1462                                 { /* Software triggered Reset */
1463                                     *reset_cause = kRESET_CAUSE_SWRRESET;
1464                                 }
1465                                 else
1466                                 { /* Unknown Reset Cause (shall never occur) */
1467                                     *reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1468                                 }
1469                             }
1470                         }
1471                     }
1472                 }
1473                 else /* boot_mode_reg == 3 : DEEP-POWER-DOWN */
1474                 {
1475                     switch (((reset_cause_reg & PMC_AOREG1_DPD_EVENTS_ORDER_MASK) >> PMC_AOREG1_DPD_EVENTS_ORDER_SHIFT))
1476                     {
1477                         case 1:
1478                             *reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO;
1479                             break;
1480                         case 2:
1481                             *reset_cause = kRESET_CAUSE_DPDRESET_RTC;
1482                             break;
1483                         case 3:
1484                             *reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC;
1485                             break;
1486                         case 4:
1487                             *reset_cause = kRESET_CAUSE_DPDRESET_OSTIMER;
1488                             break;
1489                         case 5:
1490                             *reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER;
1491                             break;
1492                         case 6:
1493                             *reset_cause = kRESET_CAUSE_DPDRESET_RTC_OSTIMER;
1494                             break;
1495                         case 7:
1496                             *reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER;
1497                             break;
1498                         default:
1499                             /* Unknown Reset Cause (shall not occur) */
1500                             *reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
1501                             break;
1502                     }
1503                 } // if ( boot_mode != 3 )
1504 
1505             } // if ( reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK )
1506 
1507         } // if ( reset_cause_reg & PMC_AOREG1_WDTRESET_MASK )
1508 
1509     } // if ( reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK )
1510 }
1511 
1512 /**
1513  * @brief             Described in fsl_common.h
1514  * @param
1515  * @return
1516  */
POWER_SetVoltageForFreq(uint32_t system_freq_hz)1517 void POWER_SetVoltageForFreq(uint32_t system_freq_hz)
1518 {
1519     if (system_freq_hz <= DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ)
1520     {
1521         /* [0 Hz - DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz] */
1522         POWER_SetSystemPowerProfile(V_SYSTEM_POWER_PROFILE_LOW);
1523         POWER_SetVoltageForProcess(V_SYSTEM_POWER_PROFILE_LOW);
1524     }
1525     else
1526     {
1527         if (system_freq_hz <= DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ)
1528         {
1529             /* ]DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz - DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz] */
1530             POWER_SetSystemPowerProfile(V_SYSTEM_POWER_PROFILE_MEDIUM);
1531             POWER_SetVoltageForProcess(V_SYSTEM_POWER_PROFILE_MEDIUM);
1532         }
1533         else
1534         {
1535             /* > DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz */
1536             POWER_SetSystemPowerProfile(V_SYSTEM_POWER_PROFILE_HIGH);
1537             POWER_SetVoltageForProcess(V_SYSTEM_POWER_PROFILE_HIGH);
1538         }
1539     }
1540 }
1541 
1542 /**
1543  * @brief	Wait at least 2us.
1544  * @param	None
1545  * @return	Nothing
1546  */
1547 
POWER_WaitLDOCoreInit(void)1548 static void POWER_WaitLDOCoreInit(void)
1549 {
1550     /*
1551      * Note: Once LDO_CORE High Power Mode has been enabled,
1552      * at least 2us are required before one can reliabily sample
1553      * the LDO Low Voltage Detectore Output.
1554      * The PMC clock being 12 MHz, with at least 5 dummy read
1555      * operations, it is guaranteed by design that, whatever the
1556      * System/CPU clock frequency (up to 200 MHz).
1557      */
1558 
1559     volatile uint32_t reg_data;
1560     for (uint32_t i = 0; i < 5; i++)
1561         reg_data = PMC->STATUSPWR; /* Dummy Read */
1562     (void)reg_data;
1563 }
1564 
1565 /**
1566  * @brief	Wait at least 2us.
1567  * @param	None
1568  * @return	Nothing
1569  */
1570 
POWER_SRAMPowerUpDelay(void)1571 static void POWER_SRAMPowerUpDelay(void)
1572 {
1573     /*
1574      * Note: Wait about 1 us
1575      * The PMC clock being 12 MHz, with at least 3 dummy read
1576      * operations, it is guaranteed by design that when this ,
1577      * function is called, at least 1 us will elapse,
1578      * whatever the System/CPU clock frequency (up to 200 MHz).
1579      */
1580 
1581     volatile uint32_t reg_data;
1582     for (uint32_t i = 0; i < 3; i++)
1583         reg_data = PMC->STATUSPWR; /* Dummy Read */
1584     (void)reg_data;
1585 }
1586 
1587 /**
1588  * @brief	Shut off the Flash and execute the _WFI(), then power up the Flash after wake-up event
1589  * @param	None
1590  * @return	Nothing
1591  */
1592 
POWER_PowerCycleCpu(void)1593 static void POWER_PowerCycleCpu(void)
1594 {
1595     /* Switch System Clock to FRO12Mhz (the configuration before calling this function will not be restored back) */
1596     POWER_SetSystemClock12MHZ();
1597 
1598     /* Configure the Cortex-M33 in Deep Sleep mode */
1599     SCB->SCR = SCB->SCR | SCB_SCR_SLEEPDEEP_Msk;
1600 
1601     /* Enter in low power mode */
1602     __WFI();
1603 
1604     /* Configure the Cortex-M33 in Active mode */
1605     SCB->SCR = SCB->SCR & (~SCB_SCR_SLEEPDEEP_Msk);
1606 };
1607 
1608 /**
1609  * @brief	Configures and enters in low power mode
1610  * @param	: p_lowpower_cfg
1611  * @return	Nothing
1612  */
POWER_SetLowPowerMode(LPC_LOWPOWER_T * p_lowpower_cfg)1613 static void POWER_SetLowPowerMode(LPC_LOWPOWER_T *p_lowpower_cfg)
1614 {
1615     uint32_t i, primask, reg_data;
1616     uint32_t cpu0_nmi_enable;
1617     uint32_t cpu0_int_enable[4];
1618     uint32_t analog_ctrl_regs[7]; /* To store Analog Controller Registers */
1619     uint32_t vref_regs[4];        /* To store VREF Registers */
1620     uint32_t fmccr_reg;           /* FMC Configuration Register */
1621 
1622     /* Save FMC configuration */
1623     fmccr_reg = SYSCON->FMCCR;
1624 
1625     cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
1626     SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK;                 /* Disable NMI of CPU0 */
1627 
1628     // Save the configuration of the CPU interrupt enable Registers (because they are overwritten in
1629     // POWER_SetLowPowerMode)
1630     for (i = 0; i < 4; i++)
1631     {
1632         cpu0_int_enable[i] = NVIC->ISER[i];
1633     }
1634 
1635     uint32_t low_power_mode = (p_lowpower_cfg->CFG & LOWPOWER_CFG_LPMODE_MASK) >> LOWPOWER_CFG_LPMODE_INDEX;
1636 
1637     /* Set the Low power mode.*/
1638     PMC->CTRL = (PMC->CTRL & (~PMC_CTRL_LPMODE_MASK)) | PMC_CTRL_LPMODE(low_power_mode);
1639 
1640     /* SRAM in Retention modes */
1641     PMC->SRAMRETCTRL = p_lowpower_cfg->SRAMRETCTRL;
1642 
1643     /* Configure the voltage level of the Always On domain, Memories LDO */
1644     PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_PWD_MASK) & (~PMC_LDOPMU_VADJ_BOOST_PWD_MASK)) |
1645                   PMC_LDOPMU_VADJ_PWD((p_lowpower_cfg->VOLTAGE & LOWPOWER_VOLTAGE_LDO_PMU_MASK) >>
1646                                       LOWPOWER_VOLTAGE_LDO_PMU_INDEX) |
1647                   PMC_LDOPMU_VADJ_BOOST_PWD((p_lowpower_cfg->VOLTAGE & LOWPOWER_VOLTAGE_LDO_PMU_BOOST_MASK) >>
1648                                             LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX);
1649 
1650     PMC->LDOMEM = (PMC->LDOMEM & (~PMC_LDOMEM_VADJ_PWD_MASK) & (~PMC_LDOMEM_VADJ_BOOST_PWD_MASK)) |
1651                   PMC_LDOMEM_VADJ_PWD((p_lowpower_cfg->VOLTAGE & LOWPOWER_VOLTAGE_LDO_MEM_MASK) >>
1652                                       LOWPOWER_VOLTAGE_LDO_MEM_INDEX) |
1653                   PMC_LDOMEM_VADJ_BOOST_PWD((p_lowpower_cfg->VOLTAGE & LOWPOWER_VOLTAGE_LDO_MEM_BOOST_MASK) >>
1654                                             LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX);
1655 
1656     /*
1657      * Enable wake up interrupt.
1658      * Rational : we enable each interrupt (NVIC->ISER) that can wake up the CPU here (before the __disable_irq()
1659      * below): Hence, if an interrupt was pending and not treated before (for any reason), the CPU will jump to that
1660      *            interrupt handler before trying to enter the low power mode.
1661      *            VERY IMPORTANT : Also, any interrupt set in NVIC->ISER, even though __disable_irq(), will make the CPU
1662      *                             go out of the Deep Sleep mode.
1663      */
1664     for (i = 0; i < 4; i++)
1665     {
1666         NVIC->ISER[i]      = p_lowpower_cfg->WAKEUPINT[i]; /* Enable wake-up interrupt */
1667         SYSCON->STARTER[i] = p_lowpower_cfg->WAKEUPSRC[i]; /* Enable wake-up sources */
1668     }
1669 
1670     /* Save the configuration of the Priority Mask Register */
1671     primask = __get_PRIMASK();
1672 
1673     switch (low_power_mode)
1674     {
1675         case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
1676         {
1677             /* DEEP SLEEP power mode */
1678 
1679             uint32_t bod_core_trglvl; /* BoD Core trigger level */
1680             uint32_t css_ctrl, syscon_css_clk_ctrl, syscon_css_clk_pclk_hclk;
1681             uint32_t syscon_autoclkgateoverride_reg; /* AUTOCLKGATEOVERRIDE Configuration Register */
1682 
1683             /* Analog Modules to be shut off */
1684             PMC->PDSLEEPCFG0 = p_lowpower_cfg->PDCTRL[0];
1685             PMC->PDSLEEPCFG1 = p_lowpower_cfg->PDCTRL[1];
1686 
1687             /* Saving AUTOCLKGATEOVERRIDE register*/
1688             syscon_autoclkgateoverride_reg = SYSCON->AUTOCLKGATEOVERRIDE;
1689 
1690             /* DMA transactions with Flexcomm during DEEP SLEEP */
1691             SYSCON->HARDWARESLEEP = p_lowpower_cfg->HWWAKE;
1692             /* Enable autoclockgating on SDMA0 and SDMA1 during DeepSleep*/
1693             SYSCON->AUTOCLKGATEOVERRIDE =
1694                 0xC0DE0000 | (syscon_autoclkgateoverride_reg &
1695                               (~(SYSCON_AUTOCLKGATEOVERRIDE_SDMA1_MASK | SYSCON_AUTOCLKGATEOVERRIDE_SDMA0_MASK)));
1696 
1697             /* Make sure DEEP POWER DOWN reset is disabled */
1698             PMC->RESETCTRL = PMC->RESETCTRL & (~PMC_RESETCTRL_DPDWAKEUPRESETENABLE_MASK);
1699 
1700             /* Adjust BoD Core Trip point . Currently set to 700 mV. TODO :: :: Check this value. */
1701             reg_data        = PMC->BODCORE;
1702             bod_core_trglvl = (reg_data & PMC_BODCORE_TRIGLVL_MASK) >> PMC_BODCORE_TRIGLVL_SHIFT;
1703             PMC->BODCORE    = (reg_data & (~PMC_BODCORE_TRIGLVL_MASK)) | PMC_BODCORE_TRIGLVL(kPOWER_BodCoreLevel700mv);
1704 
1705             // CSSV2
1706             {
1707                 syscon_css_clk_ctrl = SYSCON_CSS_CLK_CTRL_REG & (1U << 1);
1708 
1709                 css_ctrl = 0U;
1710 
1711 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1712                 syscon_css_clk_pclk_hclk = SYSCON->AHBCLKCTRL2 & (1U << 18);
1713                 /* Check if CSS is NOT in reset AND is clocked and enable, to avoid deadlock situations or a hardfault
1714                  */
1715                 if (((SYSCON->PRESETCTRL2 & 0x40000U) == 0) && syscon_css_clk_pclk_hclk && (CSSV2_CTRL_REG & 0x1))
1716 #else
1717                 syscon_css_clk_pclk_hclk = SYSCON->AHBCLKCTRL[2] & (1U << 18);
1718                 /* Check if CSS is NOT in reset AND is clocked and enable, to avoid deadlock situations or a hardfault
1719                  */
1720                 if (((SYSCON->PRESETCTRL[2] & 0x40000U) == 0) && syscon_css_clk_pclk_hclk && (CSSV2_CTRL_REG & 0x1))
1721 #endif
1722                 {
1723                     css_ctrl = CSSV2_CTRL_REG;
1724 
1725                     /* Wait until CSS is in idle state (CSS_STATUS_BUSY_MASK) */
1726                     while (CSSV2_STATUS_REG & 0x1)
1727                         ;
1728 
1729                     /* Disable CSS */
1730                     CSSV2_CTRL_REG = CSSV2_CTRL_REG & 0xFFFFFFFE;
1731 
1732                     /* Swicth off i_css_clk/pclk/hclk */
1733                     SYSCON->AHBCLKCTRLCLR[2] = (1U << 18);
1734                 }
1735 
1736                 /* Switch off DTRNG clocks */
1737                 SYSCON_CSS_CLK_CTRL_CLR_REG = (1U << 1);
1738             }
1739 
1740             /* Disable all IRQs */
1741             __disable_irq();
1742 
1743             /*
1744              * - Switch PMC clock to 1 MHz,
1745              * - Set LDO_MEM as SRAM supply source during DEEP-SLEEP,
1746              * - Set LDO_CORE Low Power mode as Core supply source during DEEP-SLEEP,
1747              * - Select Core Logic supply source when waking up from DEEP-SLEEP.
1748              */
1749             reg_data = PMC->CTRL & (~PMC_CTRL_SELCLOCK_MASK) & (~PMC_CTRL_DEEPSLEEPCORESUPPLY_MASK) &
1750                        (~PMC_CTRL_SELMEMSUPPLY_MASK);
1751             if (POWER_GetCorePowerSource() == kPOWER_CoreSrcDCDC)
1752             {
1753                 /* Core Logic is supplied by DCDC Converter when waking up from DEEP-SLEEP */
1754                 PMC->CTRL = reg_data & (~PMC_CTRL_SELCORESUPPLYWK_MASK);
1755             }
1756             else
1757             {
1758                 /* Core Logic is supplied by LDO CORE (configured in High Power mode) when waking up from DEEP-SLEEP */
1759                 PMC->CTRL = reg_data | PMC_CTRL_SELCORESUPPLYWK_MASK;
1760             }
1761 
1762             /* _WFI() */
1763             POWER_PowerCycleCpu();
1764 
1765             /* Switch PMC clock to 12 MHz and Configure the PMC in ACTIVE mode */
1766             PMC->CTRL = (PMC->CTRL & (~PMC_CTRL_LPMODE_MASK)) | PMC_CTRL_SELCLOCK_MASK |
1767                         PMC_CTRL_LPMODE(LOWPOWER_CFG_LPMODE_ACTIVE);
1768 
1769             /* Restore BoD Core Trip point. */
1770             PMC->BODCORE = (PMC->BODCORE & (~PMC_BODCORE_TRIGLVL_MASK)) | PMC_BODCORE_TRIGLVL(bod_core_trglvl);
1771 
1772             // CSSV2
1773             {
1774                 /* Restore i_css_clk/pclk/hclk */
1775                 SYSCON->AHBCLKCTRLSET[2] = syscon_css_clk_pclk_hclk;
1776 
1777                 /* Restore DTRNG clocks */
1778                 SYSCON_CSS_CLK_CTRL_SET_REG = syscon_css_clk_ctrl;
1779 
1780 /* Check if CSS is NOT in reset AND is clocked, to avoid deadlock situations */
1781 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1782                 if (((SYSCON->PRESETCTRL2 & 0x40000U) == 0) && syscon_css_clk_pclk_hclk && (css_ctrl & 0x1))
1783 #else
1784                 if (((SYSCON->PRESETCTRL[2] & 0x40000U) == 0) && syscon_css_clk_pclk_hclk && (css_ctrl & 0x1))
1785 #endif
1786                 {
1787                     /* Restore CSS */
1788                     CSSV2_CTRL_REG = css_ctrl;
1789 
1790                     /* Wait until CSS is in idle state */
1791                     while (CSSV2_STATUS_REG & 0x1)
1792                         ;
1793                 }
1794             }
1795 
1796             /* Restore AUTOCLKGATEOVERRIDE register*/
1797             SYSCON->AUTOCLKGATEOVERRIDE = 0xC0DE0000 | syscon_autoclkgateoverride_reg;
1798 
1799             /* Reset Sleep Postpone configuration */
1800             SYSCON->HARDWARESLEEP = 0;
1801 
1802             break;
1803         }
1804 
1805         case LOWPOWER_CFG_LPMODE_POWERDOWN:
1806         {
1807             uint32_t lpcac_ctrl_reg;
1808             uint32_t vref_rst_state;
1809             uint32_t vref_clk_state;
1810             uint32_t syscon_ahbclk_reg_0;
1811             uint32_t syscon_css_clk_ctrl, syscon_css_clk_pclk_hclk;
1812 
1813             /* POWER DOWN power mode */
1814             power_core_pwr_source_t core_supply_source;
1815 
1816             /* Only FRO32K, XTAL32K, FRO1M, COMP, BIAS, LDO_MEM and can VREF stay powered during POWERDOWN */
1817             PMC->PDSLEEPCFG0 =
1818                 p_lowpower_cfg->PDCTRL[0] |
1819                 (0xFFFFFFFF & (~(kPDRUNCFG_PD_FRO1M | kPDRUNCFG_PD_FRO32K | kPDRUNCFG_PD_XTAL32K | kPDRUNCFG_PD_COMP |
1820                                  kPDRUNCFG_PD_BIAS | kPDRUNCFG_PD_LDOMEM | kPDRUNCFG_PD_VREF)));
1821             PMC->PDSLEEPCFG1 = p_lowpower_cfg->PDCTRL[1];
1822 
1823             /* Make sure DEEP POWER DOWN reset is disabled */
1824             PMC->RESETCTRL = PMC->RESETCTRL & (~PMC_RESETCTRL_DPDWAKEUPRESETENABLE_MASK);
1825 
1826 /* Enable VREF Module (reset & clock) */
1827 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1828             vref_rst_state           = (SYSCON->PRESETCTRL3) & SYSCON_PRESETCTRL3_VREF_RST_MASK;
1829             vref_clk_state           = (SYSCON->AHBCLKCTRL3) & SYSCON_AHBCLKCTRL3_VREF_MASK;
1830             SYSCON->PRESETCTRLCLR[3] = SYSCON_PRESETCTRL3_VREF_RST_MASK;
1831             SYSCON->AHBCLKCTRLSET[3] = SYSCON_AHBCLKCTRL3_VREF_MASK;
1832 #else
1833             vref_rst_state = (*(uint32_t *)(((uint32_t *)SYSCON->RESERVED_5))) & 0x40000UL;
1834             vref_clk_state = (*(uint32_t *)(((uint32_t *)SYSCON->RESERVED_9))) & 0x40000UL;
1835             *(uint32_t *)(((uint32_t *)SYSCON->RESERVED_7)) = 0x40000UL;
1836             *(uint32_t *)(((uint32_t *)SYSCON->RESERVED_10)) = 0x40000UL;
1837 #endif
1838 
1839             /* Save VREF Module User Configuration ... */
1840             vref_regs[0] = VREF->CSR;
1841             vref_regs[1] = VREF->UTRIM;
1842             /* Save VREF Module Factory Trimmings ... */
1843             VREF->TEST_UNLOCK = 0x5AA5UL << 1; /* TEST_UNLOCK. Required before writting TRIM0 & TRIM1 */
1844             vref_regs[2]      = VREF->TRIM0;
1845             vref_regs[3]      = VREF->TRIM1;
1846 
1847             /* ... then enable VREF Module isolation */
1848             PMC->MISCCTRL = PMC->MISCCTRL | PMC_MISCCTRL_VREF_ISO_MASK;
1849 
1850             // CSSV2
1851             {
1852                 syscon_css_clk_ctrl = SYSCON_CSS_CLK_CTRL_REG & (1U << 1);
1853 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1854                 syscon_css_clk_pclk_hclk = SYSCON->AHBCLKCTRL2 & (1U << 18);
1855 #else
1856                 syscon_css_clk_pclk_hclk = SYSCON->AHBCLKCTRL[2] & (1U << 18);
1857 #endif
1858 
1859                 /* Switch off DTRNG clocks */
1860                 SYSCON_CSS_CLK_CTRL_CLR_REG = (1U << 1);
1861 
1862                 /* Swicth off i_css_clk/pclk/hclk */
1863                 SYSCON->AHBCLKCTRLCLR[2] = (1U << 18);
1864             }
1865 
1866             /* CPU0 Retention */
1867             SYSCON->FUNCRETENTIONCTRL =
1868                 (SYSCON->FUNCRETENTIONCTRL & SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK) | p_lowpower_cfg->CPURETCTRL;
1869 
1870             /* Disable all IRQs */
1871             __disable_irq();
1872 
1873             /*
1874              * From here :
1875              *  1 - If an interrupt that is enable occurs, the _WFI instruction will not be executed and we won't enter
1876              * in POWER DOWN. 2 - If an interrupt that is not enable occurs, there is no consequence neither on the
1877              * execution of the low power mode nor on the behaviour of the CPU.
1878              */
1879 
1880             /* Switch PMC clock to 1 MHz and select LDO CORE (configured in High Power mode) as Core Logic supply source
1881              * when waking up from POWER-DOWN */
1882             PMC->CTRL = (PMC->CTRL & (~PMC_CTRL_SELCLOCK_MASK)) | PMC_CTRL_SELCORESUPPLYWK_MASK;
1883 
1884             /* Save user Core Supply Source configuration */
1885             core_supply_source = POWER_GetCorePowerSource();
1886 
1887             /* Store Analog Controller Registers */
1888             analog_ctrl_regs[0] = ANACTRL->FRO192M_CTRL;
1889             analog_ctrl_regs[1] = ANACTRL->ANALOG_CTRL_CFG;
1890             analog_ctrl_regs[2] = ANACTRL->ADC_CTRL;
1891             analog_ctrl_regs[3] = ANACTRL->XO32M_CTRL;
1892             analog_ctrl_regs[4] = ANACTRL->BOD_DCDC_INT_CTRL;
1893             analog_ctrl_regs[5] = ANACTRL->LDO_XO32M;
1894             analog_ctrl_regs[6] = ANACTRL->OSC_TESTBUS;
1895 
1896             /* Save Flash Cache settings, then disable and clear it */
1897             lpcac_ctrl_reg     = SYSCON->LPCAC_CTRL;
1898             SYSCON->LPCAC_CTRL = 0x3; /* dis_lpcac = '1', clr_lpcac = '1' */
1899 
1900 /* Save ROM clock setting, then enable it.
1901  * It is important to have the ROM clock running before entering
1902  * POWER-DOWN for the following two reasons:
1903  * 1 - In case of POWER-DOWN with CPU state retention (which is the only
1904  *     option currently offered to the user), some flip-flops that depend
1905        on this clock need to be saved.
1906  * 2 - In case of POWER-DOWN without CPU state retention (which is a
1907  *     hardware feature that is NOT offered to the user for the time being)
1908  *     CPU reboot cannot occur if ROM clock has been shut down.
1909  */
1910 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1911             syscon_ahbclk_reg_0      = SYSCON->AHBCLKCTRL0;
1912             SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL0_ROM_MASK; /* Enable the clock for ROM */
1913 #else
1914             syscon_ahbclk_reg_0 = SYSCON->AHBCLKCTRL[0];
1915             SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL_ROM_MASK; /* Enable the clock for ROM */
1916 #endif
1917 
1918             /* _WFI() */
1919             POWER_PowerCycleCpu();
1920 
1921 /* Restore ROM clock setting */
1922 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1923             SYSCON->AHBCLKCTRL0 = syscon_ahbclk_reg_0;
1924 #else
1925             SYSCON->AHBCLKCTRL[0] = syscon_ahbclk_reg_0;
1926 #endif
1927             /* Restore Flash Cache settings */
1928             SYSCON->LPCAC_CTRL = lpcac_ctrl_reg;
1929 
1930             /* Switch PMC clock to 12 MHz and Configure the PMC in ACTIVE mode */
1931             PMC->CTRL = (PMC->CTRL & (~PMC_CTRL_LPMODE_MASK)) | PMC_CTRL_SELCLOCK_MASK |
1932                         PMC_CTRL_LPMODE(LOWPOWER_CFG_LPMODE_ACTIVE);
1933 
1934 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1935             {
1936                 /* Restore i_css_clk/pclk/hclk */
1937                 SYSCON->AHBCLKCTRLSET[2] = syscon_css_clk_pclk_hclk;
1938 
1939                 /* Restore DTRNG clocks */
1940                 SYSCON_CSS_CLK_CTRL_SET_REG = syscon_css_clk_ctrl;
1941             }
1942 #endif
1943 
1944             /* Restore Analog Controller Registers */
1945             ANACTRL->FRO192M_CTRL      = analog_ctrl_regs[0] | ANACTRL_FRO192M_CTRL_WRTRIM_MASK;
1946             ANACTRL->ANALOG_CTRL_CFG   = analog_ctrl_regs[1];
1947             ANACTRL->ADC_CTRL          = analog_ctrl_regs[2];
1948             ANACTRL->XO32M_CTRL        = analog_ctrl_regs[3];
1949             ANACTRL->BOD_DCDC_INT_CTRL = analog_ctrl_regs[4];
1950             ANACTRL->LDO_XO32M         = analog_ctrl_regs[5];
1951             ANACTRL->OSC_TESTBUS       = analog_ctrl_regs[6];
1952 
1953             /* Restore VREF Module Factory Trimmings ... */
1954             VREF->TEST_UNLOCK = 0x5AA5UL << 1; /* TEST_UNLOCK. Required before writting TRIM0 & TRIM1 */
1955             VREF->TRIM0       = vref_regs[2];
1956             VREF->TRIM1       = vref_regs[3];
1957             /* ... then restore VREF Module User Configuration */
1958             VREF->CSR   = vref_regs[0];
1959             VREF->UTRIM = vref_regs[1];
1960 
1961 /* Restore VREF module reset and clock state */
1962 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
1963             SYSCON->PRESETCTRL3 = (SYSCON->PRESETCTRL3 & (~SYSCON_PRESETCTRL3_VREF_RST_MASK)) | vref_rst_state;
1964             SYSCON->AHBCLKCTRL3 = (SYSCON->AHBCLKCTRL3 & (~SYSCON_AHBCLKCTRL3_VREF_MASK)) | vref_clk_state;
1965 #else
1966             *(uint32_t *)(((uint32_t *)SYSCON->RESERVED_5)) =
1967                 ((*(uint32_t *)(((uint32_t *)SYSCON->RESERVED_5))) & (~0x40000UL)) | vref_rst_state;
1968             *(uint32_t *)(((uint32_t *)SYSCON->RESERVED_9)) =
1969                 ((*(uint32_t *)(((uint32_t *)SYSCON->RESERVED_9))) & (~0x40000UL)) | vref_clk_state;
1970 #endif
1971 
1972             /* Disable VREF Module isolation ... */
1973             PMC->MISCCTRL = PMC->MISCCTRL & (~PMC_MISCCTRL_VREF_ISO_MASK);
1974 
1975             /* After wake up from Power-down, the Core supply source is LDO CORE */
1976             /* So restore the user configuration if necessary */
1977             if (core_supply_source == kPOWER_CoreSrcDCDC)
1978             {
1979                 /* Restore DCDC Converter as Core Logic supply source */
1980                 /* NOTE: PMC must be set in ACTIVE mode first before doing this switching to DCDC */
1981                 (void)POWER_SetCorePowerSource(kPOWER_CoreSrcDCDC);
1982             }
1983 
1984             break;
1985         }
1986 
1987         case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
1988         {
1989             /* DEEP-POWER-DOWN power mode */
1990 
1991             /* Configure wake-up by I/O :
1992              * - Set up wake-up IO pad control source : PMC WAKEUPIOCTRL (WAKEUPIO_ENABLE = 1)
1993              * - Reset Wake-up I/O Edge Detectors & Cause (WAKEUPIO_RSTN = 0)
1994              */
1995             PMC->WAKEUPIOCTRL = p_lowpower_cfg->WAKEUPIOSRC | PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK;
1996 
1997             /* Release Wake up I/O reset (WAKEUPIO_RSTN = 1)*/
1998             PMC->WAKEUPIOCTRL |= PMC_WAKEUPIOCTRL_WAKEUPIO_RSTN_MASK;
1999 
2000             /* Only FRO1M, FRO32K, XTAL32K and LDOMEM can stay powered during DEEP POWER-DOWN */
2001             PMC->PDSLEEPCFG0 =
2002                 p_lowpower_cfg->PDCTRL[0] | (0xFFFFFFFF & (~(kPDRUNCFG_PD_FRO1M | kPDRUNCFG_PD_FRO32K |
2003                                                              kPDRUNCFG_PD_XTAL32K | kPDRUNCFG_PD_LDOMEM)));
2004             PMC->PDSLEEPCFG1 = p_lowpower_cfg->PDCTRL[1];
2005 
2006             /* Disable all IRQs */
2007             __disable_irq();
2008 
2009             /*
2010              * From here :
2011              *  1 - If an interrupt that is enabled occurs, the _WFI instruction will not be executed and we won't enter
2012              * in POWER DOWN. 2 - If an interrupt that is not enabled occurs, there is no consequence neither on the
2013              * execution of the low power mode nor on the behaviour of the CPU.
2014              */
2015 
2016             /* clear all Reset causes */
2017             PMC->RESETCAUSE = 0xFFFFFFFF;
2018 
2019             /* Enable DEEP POWER-DOWN reset */
2020             PMC->RESETCTRL |= PMC_RESETCTRL_DPDWAKEUPRESETENABLE_MASK;
2021 
2022             /* Switch PMC clock to 1 MHz */
2023             PMC->CTRL = PMC->CTRL & (~PMC_CTRL_SELCLOCK_MASK);
2024 
2025             /* _WFI() */
2026             POWER_PowerCycleCpu();
2027 
2028             /*** We should never reach this point, unless the Low Power cycle has been cancelled somehow. ***/
2029             /* Switch PMC clock to 12 MHz and Configure the PMC in ACTIVE mode */
2030             PMC->CTRL = (PMC->CTRL & (~PMC_CTRL_LPMODE_MASK)) | PMC_CTRL_SELCLOCK_MASK |
2031                         PMC_CTRL_LPMODE(LOWPOWER_CFG_LPMODE_ACTIVE);
2032 
2033             break;
2034         }
2035 
2036         default:
2037         {
2038             /* Error */
2039         }
2040     } // End switch( low_power_mode )
2041 
2042     /* Restore FMC Configuration */
2043     SYSCON->FMCCR = SYSCON->FMCCR | (fmccr_reg & SYSCON_FMCCR_PREFEN_MASK);
2044 
2045     /*
2046      * Restore the configuration of the Priority Mask Register.
2047      * Rational : if the interrupts were enable before entering the Low power mode, they will be re-enabled,
2048      *            if they were disabled, they will stay disabled.
2049      */
2050     __set_PRIMASK(primask);
2051 
2052     /* Restore the configuration of the NMI Register */
2053     SYSCON->NMISRC |= cpu0_nmi_enable;
2054 
2055     /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
2056      * low power API */
2057     for (i = 0; i < 4; i++)
2058     {
2059         NVIC->ISER[i] = cpu0_int_enable[i];
2060     }
2061 }
2062 
2063 /**
2064  * @brief	Configures and enters in low power mode
2065  * @param	: p_lowpower_cfg
2066  * @return	Nothing
2067  */
POWER_WakeUpIOCtrl(uint32_t p_wakeup_io_ctrl)2068 static uint32_t POWER_WakeUpIOCtrl(uint32_t p_wakeup_io_ctrl)
2069 {
2070     uint32_t wake_up_type;
2071     uint32_t wakeup_io_ctrl_reg = 0;
2072 
2073 // Enable IOCON
2074 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2075     SYSCON->PRESETCTRLCLR[0] = SYSCON_PRESETCTRL0_IOCON_RST_MASK;
2076     SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL0_IOCON_MASK;
2077 #else
2078     SYSCON->PRESETCTRLCLR[0] = SYSCON_PRESETCTRL_IOCON_RST_MASK;
2079     SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL_IOCON_MASK;
2080 #endif
2081 
2082     /* Configure Pull up & Pull down based on the required wake-up edge */
2083 
2084     /* Wake-up I/O 0 */
2085     wake_up_type =
2086         (p_wakeup_io_ctrl & (PMC_WAKEUPIOCTRL_RISINGEDGEWAKEUP0_MASK | PMC_WAKEUPIOCTRL_FALLINGEDGEWAKEUP0_MASK)) >>
2087         LOWPOWER_WAKEUPIOSRC_PIO0_INDEX;
2088     wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO0_INDEX);
2089     if ((wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING) || (wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING_FALLING))
2090     {
2091         /* Rising edge and both rising and falling edges */
2092         if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) == 0)
2093         {
2094             /* Internal pull up / pull down are not disabled by the user, so use them */
2095             IOCON->PIO[WAKEUPIO_0_PORT][WAKEUPIO_0_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
2096             wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
2097         }
2098     }
2099     else
2100     {
2101         if (wake_up_type == LOWPOWER_WAKEUPIOSRC_FALLING)
2102         {
2103             /* Falling edge only */
2104             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) == 0)
2105             {
2106                 /* Internal pull up / pull down are not disabled by the user, so use them */
2107                 IOCON->PIO[WAKEUPIO_0_PORT][WAKEUPIO_0_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
2108                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
2109             }
2110         }
2111         else
2112         {
2113             /* Wake-up I/O is disabled : set pull-up/pull-down as required by the user */
2114             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) != 0)
2115             {
2116                 /* Wake-up I/O is configured as Plain Input */
2117                 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
2118                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
2119             }
2120             else
2121             {
2122                 /* Wake-up I/O is configured as pull-up or pull-down */
2123                 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK) != 0)
2124                 {
2125                     /* Wake-up I/O is configured as pull-up */
2126                     wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
2127                 }
2128                 else
2129                 {
2130                     /* Wake-up I/O is configured as pull-down */
2131                     wakeup_io_ctrl_reg |=
2132                         (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO0MODE_INDEX);
2133                 }
2134             }
2135         }
2136     }
2137 
2138     /* Wake-up I/O 1 */
2139     wake_up_type =
2140         (p_wakeup_io_ctrl & (PMC_WAKEUPIOCTRL_RISINGEDGEWAKEUP1_MASK | PMC_WAKEUPIOCTRL_FALLINGEDGEWAKEUP1_MASK)) >>
2141         LOWPOWER_WAKEUPIOSRC_PIO1_INDEX;
2142     wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO1_INDEX);
2143     if ((wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING) || (wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING_FALLING))
2144     {
2145         /* Rising edge  and both rising and falling edges */
2146         if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) == 0)
2147         {
2148             /* Internal pull up / pull down are not disabled by the user, so use them */
2149             IOCON->PIO[WAKEUPIO_1_PORT][WAKEUPIO_1_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
2150             wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
2151         }
2152     }
2153     else
2154     {
2155         if (wake_up_type == LOWPOWER_WAKEUPIOSRC_FALLING)
2156         {
2157             /* Falling edge only */
2158             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) == 0)
2159             {
2160                 /* Internal pull up / pull down are not disabled by the user, so use them */
2161                 IOCON->PIO[WAKEUPIO_1_PORT][WAKEUPIO_1_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
2162                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
2163             }
2164         }
2165         else
2166         {
2167             /* Wake-up I/O is disabled : set it as required by the user */
2168             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) != 0)
2169             {
2170                 /* Wake-up I/O is configured as Plain Input */
2171                 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
2172                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
2173             }
2174             else
2175             {
2176                 /* Wake-up I/O is configured as pull-up or pull-down */
2177                 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK) != 0)
2178                 {
2179                     /* Wake-up I/O is configured as pull-up */
2180                     wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
2181                 }
2182                 else
2183                 {
2184                     /* Wake-up I/O is configured as pull-down */
2185                     wakeup_io_ctrl_reg |=
2186                         (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO1MODE_INDEX);
2187                 }
2188             }
2189         }
2190     }
2191 
2192     /* Wake-up I/O 2 */
2193     wake_up_type =
2194         (p_wakeup_io_ctrl & (PMC_WAKEUPIOCTRL_RISINGEDGEWAKEUP2_MASK | PMC_WAKEUPIOCTRL_FALLINGEDGEWAKEUP2_MASK)) >>
2195         LOWPOWER_WAKEUPIOSRC_PIO2_INDEX;
2196     wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO2_INDEX);
2197     if ((wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING) || (wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING_FALLING))
2198     {
2199         /* Rising edge  and both rising and falling edges */
2200         if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) == 0)
2201         {
2202             /* Internal pull up / pull down are not disabled by the user, so use them */
2203             IOCON->PIO[WAKEUPIO_2_PORT][WAKEUPIO_2_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
2204             wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
2205         }
2206     }
2207     else
2208     {
2209         if (wake_up_type == LOWPOWER_WAKEUPIOSRC_FALLING)
2210         {
2211             /* Falling edge only */
2212             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) == 0)
2213             {
2214                 /* Internal pull up / pull down are not disabled by the user, so use them */
2215                 IOCON->PIO[WAKEUPIO_2_PORT][WAKEUPIO_2_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
2216                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
2217             }
2218         }
2219         else
2220         {
2221             /* Wake-up I/O is disabled : set it as required by the user */
2222             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) != 0)
2223             {
2224                 /* Wake-up I/O is configured as Plain Input */
2225                 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
2226                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
2227             }
2228             else
2229             {
2230                 /* Wake-up I/O is configured as pull-up or pull-down */
2231                 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK) != 0)
2232                 {
2233                     /* Wake-up I/O is configured as pull-up */
2234                     wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
2235                 }
2236                 else
2237                 {
2238                     /* Wake-up I/O is configured as pull-down */
2239                     wakeup_io_ctrl_reg |=
2240                         (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO2MODE_INDEX);
2241                 }
2242             }
2243         }
2244     }
2245 
2246     /* Wake-up I/O 3 */
2247     wake_up_type =
2248         (p_wakeup_io_ctrl & (PMC_WAKEUPIOCTRL_RISINGEDGEWAKEUP3_MASK | PMC_WAKEUPIOCTRL_FALLINGEDGEWAKEUP3_MASK)) >>
2249         LOWPOWER_WAKEUPIOSRC_PIO3_INDEX;
2250     wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO3_INDEX);
2251     if ((wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING) || (wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING_FALLING))
2252     {
2253         /* Rising edge  and both rising and falling edges */
2254         if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) == 0)
2255         {
2256             /* Internal pull up / pull down are not disabled by the user, so use them */
2257             IOCON->PIO[WAKEUPIO_3_PORT][WAKEUPIO_3_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
2258             wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
2259         }
2260     }
2261     else
2262     {
2263         if (wake_up_type == LOWPOWER_WAKEUPIOSRC_FALLING)
2264         {
2265             /* Falling edge only */
2266             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) == 0)
2267             {
2268                 /* Internal pull up / pull down are not disabled by the user, so use them */
2269                 IOCON->PIO[WAKEUPIO_3_PORT][WAKEUPIO_3_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
2270                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
2271             }
2272         }
2273         else
2274         {
2275             /* Wake-up I/O is disabled : set it as required by the user */
2276             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) != 0)
2277             {
2278                 /* Wake-up I/O is configured as Plain Input */
2279                 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
2280                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
2281             }
2282             else
2283             {
2284                 /* Wake-up I/O is configured as pull-up or pull-down */
2285                 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK) != 0)
2286                 {
2287                     /* Wake-up I/O is configured as pull-up */
2288                     wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
2289                 }
2290                 else
2291                 {
2292                     /* Wake-up I/O is configured as pull-down */
2293                     wakeup_io_ctrl_reg |=
2294                         (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO3MODE_INDEX);
2295                 }
2296             }
2297         }
2298     }
2299 
2300     /* Wake-up I/O 4 */
2301     wake_up_type =
2302         (p_wakeup_io_ctrl & (PMC_WAKEUPIOCTRL_RISINGEDGEWAKEUP4_MASK | PMC_WAKEUPIOCTRL_FALLINGEDGEWAKEUP4_MASK)) >>
2303         LOWPOWER_WAKEUPIOSRC_PIO4_INDEX;
2304     wakeup_io_ctrl_reg |= (wake_up_type << LOWPOWER_WAKEUPIOSRC_PIO4_INDEX);
2305     if ((wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING) || (wake_up_type == LOWPOWER_WAKEUPIOSRC_RISING_FALLING))
2306     {
2307         /* Rising edge  and both rising and falling edges */
2308         if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO4_DISABLEPULLUPDOWN_MASK) == 0)
2309         {
2310             /* Internal pull up / pull down are not disabled by the user, so use them */
2311             IOCON->PIO[WAKEUPIO_4_PORT][WAKEUPIO_4_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
2312             wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO4MODE_INDEX);
2313         }
2314     }
2315     else
2316     {
2317         if (wake_up_type == LOWPOWER_WAKEUPIOSRC_FALLING)
2318         {
2319             /* Falling edge only */
2320             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO4_DISABLEPULLUPDOWN_MASK) == 0)
2321             {
2322                 /* Internal pull up / pull down are not disabled by the user, so use them */
2323                 IOCON->PIO[WAKEUPIO_4_PORT][WAKEUPIO_4_PINS] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
2324                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO4MODE_INDEX);
2325             }
2326         }
2327         else
2328         {
2329             /* Wake-up I/O is disabled : set it as required by the user */
2330             if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO4_DISABLEPULLUPDOWN_MASK) != 0)
2331             {
2332                 /* Wake-up I/O is configured as Plain Input */
2333                 p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO4_PULLUPDOWN_MASK;
2334                 wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PLAIN << LOWPOWER_WAKEUPIOSRC_PIO4MODE_INDEX);
2335             }
2336             else
2337             {
2338                 /* Wake-up I/O is configured as pull-up or pull-down */
2339                 if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO4_PULLUPDOWN_MASK) != 0)
2340                 {
2341                     /* Wake-up I/O is configured as pull-up */
2342                     wakeup_io_ctrl_reg |= (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLUP << LOWPOWER_WAKEUPIOSRC_PIO4MODE_INDEX);
2343                 }
2344                 else
2345                 {
2346                     /* Wake-up I/O is configured as pull-down */
2347                     wakeup_io_ctrl_reg |=
2348                         (LOWPOWER_WAKEUPIOSRC_IO_MODE_PULLDOWN << LOWPOWER_WAKEUPIOSRC_PIO4MODE_INDEX);
2349                 }
2350             }
2351         }
2352     }
2353 
2354     return (wakeup_io_ctrl_reg);
2355 }
2356 
POWER_SetLdoAoLdoMemVoltage(uint32_t p_lp_mode)2357 static uint32_t POWER_SetLdoAoLdoMemVoltage(uint32_t p_lp_mode)
2358 {
2359     uint32_t voltage      = 0;
2360     uint32_t ldo_ao_trim  = 0;
2361     uint32_t ldo_mem_trim = 0;
2362     uint32_t lv_v_ldo_pmu, lv_v_ldo_pmu_boost;
2363     uint32_t lv_v_ldo_mem, lv_v_ldo_mem_boost;
2364 
2365 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2366     ldo_ao_trim  = FLASH_NMPA_LDO_AO;
2367     ldo_mem_trim = FLASH_NMPA_LDO_MEM;
2368 #endif
2369 
2370     switch (p_lp_mode)
2371     {
2372         case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
2373         {
2374             if ((ldo_ao_trim & 0x80000000) != 0)
2375             {
2376                 /* Apply settings coming from Flash */
2377                 lv_v_ldo_pmu       = (ldo_ao_trim >> 8) & 0x1F;
2378                 lv_v_ldo_pmu_boost = (ldo_ao_trim >> 13) & 0x1F;
2379             }
2380             else
2381             {
2382                 /* Apply default settings */
2383                 lv_v_ldo_pmu       = V_AO_0P900;
2384                 lv_v_ldo_pmu_boost = V_AO_0P850;
2385             }
2386         }
2387         break;
2388 
2389         case LOWPOWER_CFG_LPMODE_POWERDOWN:
2390         {
2391             if ((ldo_ao_trim & 0x80000000) != 0)
2392             {
2393                 /* Apply settings coming from Flash */
2394                 lv_v_ldo_pmu       = (ldo_ao_trim >> 18) & 0x1F;
2395                 lv_v_ldo_pmu_boost = (ldo_ao_trim >> 23) & 0x1F;
2396             }
2397             else
2398             {
2399                 /* Apply default settings */
2400                 lv_v_ldo_pmu       = V_AO_0P800;
2401                 lv_v_ldo_pmu_boost = V_AO_0P750;
2402             }
2403         }
2404         break;
2405 
2406         case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
2407         {
2408             if ((ldo_ao_trim & 0x80000000) != 0)
2409             {
2410                 /* Apply settings coming from Flash */
2411                 lv_v_ldo_pmu       = (ldo_ao_trim >> 18) & 0x1F;
2412                 lv_v_ldo_pmu_boost = (ldo_ao_trim >> 23) & 0x1F;
2413             }
2414             else
2415             {
2416                 /* Apply default settings */
2417                 lv_v_ldo_pmu       = V_AO_0P800;
2418                 lv_v_ldo_pmu_boost = V_AO_0P750;
2419             }
2420         }
2421         break;
2422 
2423         default:
2424             /* We should never reach this point */
2425             lv_v_ldo_pmu       = V_AO_1P100;
2426             lv_v_ldo_pmu_boost = V_AO_1P050;
2427     }
2428 
2429     if ((ldo_mem_trim & 0x80000000) != 0)
2430     {
2431         /* Apply settings coming from Flash */
2432         lv_v_ldo_mem       = ldo_mem_trim & 0x1F;
2433         lv_v_ldo_mem_boost = (ldo_mem_trim >> 8) & 0x1F;
2434     }
2435     else
2436     {
2437         /* Apply default settings */
2438         lv_v_ldo_mem       = V_AO_0P750; /* Set to 0.75V (voltage Scaling) */
2439         lv_v_ldo_mem_boost = V_AO_0P700; /* Set to 0.7V  (voltage Scaling) */
2440     }
2441 
2442     /* The Memories Voltage settings below are for voltage scaling */
2443     voltage = (lv_v_ldo_pmu << LOWPOWER_VOLTAGE_LDO_PMU_INDEX) |
2444               (lv_v_ldo_pmu_boost << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX) |
2445               (lv_v_ldo_mem << LOWPOWER_VOLTAGE_LDO_MEM_INDEX) |
2446               (lv_v_ldo_mem_boost << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX);
2447 
2448     return (voltage);
2449 }
2450 
2451 /**
2452  * @brief	Configures System Power Profile
2453  * @param	power_profile : Low/Medium/High
2454  * @return	Nothing
2455  */
POWER_SetSystemPowerProfile(v_system_power_profile_t power_profile)2456 static void POWER_SetSystemPowerProfile(v_system_power_profile_t power_profile)
2457 {
2458     uint32_t dcdcTrimValue0 = 0;
2459     uint32_t dcdcTrimValue1 = 0;
2460 
2461     switch (power_profile)
2462     {
2463         case V_SYSTEM_POWER_PROFILE_MEDIUM:
2464             /* Medium */
2465 
2466 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2467             dcdcTrimValue0 = FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_ARRAY0;
2468             dcdcTrimValue1 = FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_ARRAY1;
2469 #endif
2470 
2471             if (dcdcTrimValue0 & 0x1)
2472             {
2473                 /* DCDC Trimmings in Flash are valid */
2474                 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
2475                 PMC->DCDC0     = dcdcTrimValue0;
2476                 PMC->DCDC1     = dcdcTrimValue1;
2477             }
2478             else
2479             {
2480                 /* DCDC Trimmings in Flash are not valid.
2481                  * Set a default value */
2482                 PMC->DCDC0 = 0x0220ACF1 >> 1;
2483                 PMC->DCDC1 = 0x01D05C78;
2484             }
2485 
2486             break;
2487 
2488         case V_SYSTEM_POWER_PROFILE_HIGH:
2489 /* High */
2490 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2491             dcdcTrimValue0 = FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_ARRAY0;
2492             dcdcTrimValue1 = FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_ARRAY1;
2493 #endif
2494 
2495             if (dcdcTrimValue0 & 0x1)
2496             {
2497                 /* DCDC Trimmings in Flash are valid */
2498                 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
2499                 PMC->DCDC0     = dcdcTrimValue0;
2500                 PMC->DCDC1     = dcdcTrimValue1;
2501             }
2502             else
2503             {
2504                 /* DCDC Trimmings in Flash are not valid.
2505                  * Set a default value */
2506                 PMC->DCDC0 = 0x0228ACF9 >> 1;
2507                 PMC->DCDC1 = 0x01E05C68;
2508             }
2509 
2510             break;
2511 
2512         default:
2513 /* Low */
2514 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2515             dcdcTrimValue0 = FLASH_NMPA_DCDC_POWER_PROFILE_LOW_ARRAY0;
2516             dcdcTrimValue1 = FLASH_NMPA_DCDC_POWER_PROFILE_LOW_ARRAY1;
2517 #endif
2518 
2519             if (dcdcTrimValue0 & 0x1)
2520             {
2521                 /* DCDC Trimmings in Flash are valid */
2522                 dcdcTrimValue0 = dcdcTrimValue0 >> 1;
2523                 PMC->DCDC0     = dcdcTrimValue0;
2524                 PMC->DCDC1     = dcdcTrimValue1;
2525             }
2526             else
2527             {
2528                 /* DCDC Trimmings in Flash are not valid.
2529                  * Set a default value */
2530                 PMC->DCDC0 = 0x0210CCFD >> 1;
2531                 PMC->DCDC1 = 0x01C05C98;
2532             }
2533     }
2534 }
2535 
2536 /**
2537  * @brief	Configures System Power Profile
2538  * @param	power_profile : Low/Medium/High
2539  * @return	Nothing
2540  */
POWER_SetVoltageForProcess(v_system_power_profile_t power_profile)2541 static void POWER_SetVoltageForProcess(v_system_power_profile_t power_profile)
2542 {
2543     /* Get Sample Process Corner */
2544     lowpower_process_corner_enum part_process_corner = POWER_GetPartProcessCorner();
2545 
2546     switch (part_process_corner)
2547     {
2548         case PROCESS_CORNER_SSS:
2549             /* Slow Corner */
2550             {
2551                 switch (power_profile)
2552                 {
2553                     case V_SYSTEM_POWER_PROFILE_MEDIUM:
2554                         /* Medium */
2555                         POWER_SetSystemVoltage(VOLTAGE_SSS_MED_MV);
2556                         break;
2557 
2558                     case V_SYSTEM_POWER_PROFILE_HIGH:
2559                         /* High */
2560                         POWER_SetSystemVoltage(VOLTAGE_SSS_HIG_MV);
2561                         break;
2562 
2563                     default:
2564                         /* V_SYSTEM_POWER_PROFILE_LOW */
2565                         POWER_SetSystemVoltage(VOLTAGE_SSS_LOW_MV);
2566                 } // switch(power_profile)
2567             }
2568             break;
2569 
2570         case PROCESS_CORNER_FFF:
2571             /* Fast Corner */
2572             {
2573                 switch (power_profile)
2574                 {
2575                     case V_SYSTEM_POWER_PROFILE_MEDIUM:
2576                         /* Medium */
2577                         POWER_SetSystemVoltage(VOLTAGE_FFF_MED_MV);
2578                         break;
2579 
2580                     case V_SYSTEM_POWER_PROFILE_HIGH:
2581                         /* High */
2582                         POWER_SetSystemVoltage(VOLTAGE_FFF_HIG_MV);
2583                         break;
2584 
2585                     default:
2586                         /* V_SYSTEM_POWER_PROFILE_LOW */
2587                         POWER_SetSystemVoltage(VOLTAGE_FFF_LOW_MV);
2588                 } // switch(power_profile)
2589             }
2590             break;
2591 
2592         default:
2593             /* Nominal (NNN) and all others Process Corners : assume Nominal Corner */
2594             {
2595                 switch (power_profile)
2596                 {
2597                     case V_SYSTEM_POWER_PROFILE_MEDIUM:
2598                         /* Medium */
2599                         POWER_SetSystemVoltage(VOLTAGE_NNN_MED_MV);
2600                         break;
2601 
2602                     case V_SYSTEM_POWER_PROFILE_HIGH:
2603                         /* High */
2604                         POWER_SetSystemVoltage(VOLTAGE_NNN_HIG_MV);
2605                         break;
2606 
2607                     default:
2608                         /* V_SYSTEM_POWER_PROFILE_LOW */
2609                         POWER_SetSystemVoltage(VOLTAGE_NNN_LOW_MV);
2610                 } // switch(power_profile)
2611             }
2612     } // switch(part_process_corner)
2613 }
2614 
2615 /**
2616  * @brief
2617  * @param
2618  * @return
2619  */
POWER_GetPartProcessCorner(void)2620 static lowpower_process_corner_enum POWER_GetPartProcessCorner(void)
2621 {
2622     lowpower_process_corner_enum part_process_corner;
2623     uint32_t pvt_ringo_hz;
2624     uint32_t pvt_ringo_0 = 0;
2625     uint32_t pvt_ringo_1 = 0;
2626 
2627 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2628     pvt_ringo_0 = FLASH_NMPA_PVT_MONITOR_0_RINGO;
2629     pvt_ringo_1 = FLASH_NMPA_PVT_MONITOR_1_RINGO;
2630 #endif
2631 
2632     /*
2633      * Check that the PVT Monitors Trimmings in flash are valid.
2634      * Note : On Customer Samples, PVT Trimmings in flash will ALWAYS be valid,
2635      *      so that in the SDK, the check below could be skipped (but NOT the right shift operation)
2636      */
2637     if (pvt_ringo_0 & 0x1)
2638     {
2639         /* PVT Trimmings in Flash are valid */
2640         pvt_ringo_0 = pvt_ringo_0 >> 1;
2641     }
2642     else
2643     {
2644         /* PVT Trimmings in Flash are NOT valid (average value assumed) */
2645         pvt_ringo_0 = PROCESS_NNN_AVG_HZ;
2646     }
2647 
2648     if (pvt_ringo_1 & 0x1)
2649     {
2650         /* PVT Trimmings in Flash are valid */
2651         pvt_ringo_1 = pvt_ringo_1 >> 1;
2652     }
2653     else
2654     {
2655         /* PVT Trimmings in Flash are NOT valid (average value assumed) */
2656         pvt_ringo_1 = PROCESS_NNN_AVG_HZ;
2657     }
2658 
2659     /*
2660      * There are 2 Ring Oscillators in the System.
2661      * We consider the worst case scenario by choosing
2662      * the minimum of the 2 Ring Oscillators values
2663      * as the final value to determine the Process Corner.
2664      */
2665     if (pvt_ringo_1 <= pvt_ringo_0)
2666     {
2667         pvt_ringo_hz = pvt_ringo_1;
2668     }
2669     else
2670     {
2671         pvt_ringo_hz = pvt_ringo_0;
2672     }
2673 
2674     /*
2675      * Determine the process corner based on the value of the Ring Oscillator frequency
2676      */
2677     if (pvt_ringo_hz <= PROCESS_NNN_MIN_HZ)
2678     {
2679         /* SSS Process Corner */
2680         part_process_corner = PROCESS_CORNER_SSS;
2681     }
2682     else
2683     {
2684         if (pvt_ringo_hz <= PROCESS_NNN_MAX_HZ)
2685         {
2686             /* NNN Process Corner */
2687             part_process_corner = PROCESS_CORNER_NNN;
2688         }
2689         else
2690         {
2691             /* FFF Process Corner */
2692             part_process_corner = PROCESS_CORNER_FFF;
2693         }
2694     }
2695 
2696     return (part_process_corner);
2697 }
2698 
2699 /**
2700  * @brief
2701  * @param
2702  * @return
2703  */
POWER_SetSystemVoltage(uint32_t system_voltage_mv)2704 static void POWER_SetSystemVoltage(uint32_t system_voltage_mv)
2705 {
2706     /*
2707      * Set system voltage
2708      */
2709     uint32_t lv_ldo_ao       = V_AO_1P100;         /* <ldo_ao> */
2710     uint32_t lv_ldo_ao_boost = V_AO_1P150;         /* <ldo_ao_boost> */
2711     uint32_t lv_dcdc         = V_DCDC_1P100;       /* <dcdc> */
2712     uint32_t lv_ldo_core     = V_LDOCORE_HP_1P102; /* <ldo_core> */
2713 
2714     /*
2715      * Because DCDC has less code than LD_AO, we first determine the
2716      * optimum DCDC settings, then we find the closest possible settings
2717      * for LDO_AO, knowing that we want both settings to be as close as possible
2718      * (ideally, they shall be equal).
2719      */
2720 
2721     if (system_voltage_mv <= 950)
2722     {
2723         lv_dcdc         = V_DCDC_0P950;
2724         lv_ldo_ao       = V_AO_0P960;
2725         lv_ldo_ao_boost = V_AO_1P010;
2726         lv_ldo_core     = V_LDOCORE_HP_0P953;
2727     }
2728     else if (system_voltage_mv <= 975)
2729     {
2730         lv_dcdc         = V_DCDC_0P975;
2731         lv_ldo_ao       = V_AO_0P980;
2732         lv_ldo_ao_boost = V_AO_1P030;
2733         lv_ldo_core     = V_LDOCORE_HP_0P980;
2734     }
2735     else if (system_voltage_mv <= 1000)
2736     {
2737         lv_dcdc         = V_DCDC_1P000;
2738         lv_ldo_ao       = V_AO_1P000;
2739         lv_ldo_ao_boost = V_AO_1P050;
2740         lv_ldo_core     = V_LDOCORE_HP_1P001;
2741     }
2742     else if (system_voltage_mv <= 1025)
2743     {
2744         lv_dcdc         = V_DCDC_1P025;
2745         lv_ldo_ao       = V_AO_1P030;
2746         lv_ldo_ao_boost = V_AO_1P080;
2747         lv_ldo_core     = V_LDOCORE_HP_1P027;
2748     }
2749     else if (system_voltage_mv <= 1050)
2750     {
2751         lv_dcdc         = V_DCDC_1P050;
2752         lv_ldo_ao       = V_AO_1P060;
2753         lv_ldo_ao_boost = V_AO_1P110;
2754         lv_ldo_core     = V_LDOCORE_HP_1P055;
2755     }
2756     else if (system_voltage_mv <= 1075)
2757     {
2758         lv_dcdc         = V_DCDC_1P075;
2759         lv_ldo_ao       = V_AO_1P080;
2760         lv_ldo_ao_boost = V_AO_1P130;
2761         lv_ldo_core     = V_LDOCORE_HP_1P075;
2762     }
2763     else if (system_voltage_mv <= 1100)
2764     {
2765         lv_dcdc         = V_DCDC_1P100;
2766         lv_ldo_ao       = V_AO_1P100;
2767         lv_ldo_ao_boost = V_AO_1P150;
2768         lv_ldo_core     = V_LDOCORE_HP_1P102;
2769     }
2770     else if (system_voltage_mv <= 1125)
2771     {
2772         lv_dcdc         = V_DCDC_1P125;
2773         lv_ldo_ao       = V_AO_1P130;
2774         lv_ldo_ao_boost = V_AO_1P160;
2775         lv_ldo_core     = V_LDOCORE_HP_1P027;
2776     }
2777     else if (system_voltage_mv <= 1150)
2778     {
2779         lv_dcdc         = V_DCDC_1P150;
2780         lv_ldo_ao       = V_AO_1P160;
2781         lv_ldo_ao_boost = V_AO_1P220;
2782         lv_ldo_core     = V_LDOCORE_HP_1P156;
2783     }
2784     else if (system_voltage_mv <= 1175)
2785     {
2786         lv_dcdc         = V_DCDC_1P175;
2787         lv_ldo_ao       = V_AO_1P160;
2788         lv_ldo_ao_boost = V_AO_1P220;
2789         lv_ldo_core     = V_LDOCORE_HP_1P177;
2790     }
2791     else
2792     {
2793         lv_dcdc         = V_DCDC_1P200;
2794         lv_ldo_ao       = V_AO_1P220;
2795         lv_ldo_ao_boost = V_AO_1P220;
2796         lv_ldo_core     = V_LDOCORE_HP_1P204;
2797     }
2798 
2799 /* Set up LDO Always-On voltages */
2800 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2801     /* Apply LDO_AO Trimmings */
2802     {
2803         int8_t ldo_ao_offset;
2804         int32_t lv_ldo_ao_signed;
2805 
2806         ldo_ao_offset =
2807             (int8_t)((FLASH_NMPA_LDO_AO & FLASH_NMPA_LDO_AO_VADJ_ACTIVE_MASK) >> FLASH_NMPA_LDO_AO_VADJ_ACTIVE_SHIFT);
2808         lv_ldo_ao_signed = (int32_t)((int32_t)lv_ldo_ao + (int32_t)ldo_ao_offset);
2809 
2810         if (lv_ldo_ao_signed < (int32_t)V_AO_0P960)
2811         {
2812             lv_ldo_ao = V_AO_0P960;
2813         }
2814         else
2815         {
2816             if (lv_ldo_ao_signed > (int32_t)V_AO_1P220)
2817             {
2818                 lv_ldo_ao = V_AO_1P220;
2819             }
2820             else
2821             {
2822                 lv_ldo_ao = (uint32_t)lv_ldo_ao_signed;
2823             }
2824         }
2825     }
2826 // Note: In ACTIVE mode, the LDO BOOST mode is always enabled.
2827 // Therefore, the value of the "lv_ldo_ao_boost" does not really matter.
2828 // For that reason, we do not recompuete it here.
2829 #endif
2830     PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_MASK) & (~PMC_LDOPMU_VADJ_BOOST_MASK)) | PMC_LDOPMU_VADJ(lv_ldo_ao) |
2831                   PMC_LDOPMU_VADJ_BOOST(lv_ldo_ao_boost);
2832 
2833     /* Set up DCDC voltage */
2834     PMC->DCDC0 = (PMC->DCDC0 & (~PMC_DCDC0_VOUT_MASK)) | PMC_DCDC0_VOUT(lv_dcdc);
2835 
2836 /* Set up LDO_CORE voltage */
2837 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
2838     /* Apply LDO_CORE Trimmings */
2839     {
2840         int8_t ldo_core_regref_offset;
2841         int32_t lv_ldo_core_signed;
2842 
2843         ldo_core_regref_offset = (int8_t)((FLASH_NMPA_BOD_LDOCORE & FLASH_NMPA_BOD_LDOCORE_REGREF_1P8V_OFFSET_MASK) >>
2844                                           FLASH_NMPA_BOD_LDOCORE_REGREF_1P8V_OFFSET_SHIFT);
2845         lv_ldo_core_signed     = (int32_t)((int32_t)lv_ldo_core + (int32_t)ldo_core_regref_offset);
2846 
2847         if (lv_ldo_core_signed < (int32_t)V_LDOCORE_HP_1P204)
2848         {
2849             lv_ldo_core = V_LDOCORE_HP_1P204;
2850         }
2851         else
2852         {
2853             if (lv_ldo_core_signed > (int32_t)V_LDOCORE_HP_0P953)
2854             {
2855                 lv_ldo_core = V_LDOCORE_HP_0P953;
2856             }
2857             else
2858             {
2859                 lv_ldo_core = (uint32_t)lv_ldo_core_signed;
2860             }
2861         }
2862     }
2863 #endif
2864     PMC->LDOCORE0 = (PMC->LDOCORE0 & (~PMC_LDOCORE0_REGREFTRIM_MASK)) | PMC_LDOCORE0_REGREFTRIM(lv_ldo_core);
2865 }
2866 
2867 /**
2868  * brief
2869  * return
2870  */
POWER_SRAMSetRegister(power_sram_index_t sram_index,uint32_t power_mode)2871 static void POWER_SRAMSetRegister(power_sram_index_t sram_index, uint32_t power_mode)
2872 {
2873     switch (sram_index)
2874     {
2875         case kPOWER_SRAM_IDX_RAM_X0:
2876         {
2877             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_X0_LS_SHIFT))) |
2878                              (power_mode << PMC_SRAMCTRL0_RAM_X0_LS_SHIFT);
2879             break;
2880         }
2881 
2882         case kPOWER_SRAM_IDX_RAM_00:
2883         {
2884             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_00_LS_SHIFT))) |
2885                              (power_mode << PMC_SRAMCTRL0_RAM_00_LS_SHIFT);
2886             break;
2887         }
2888 
2889         case kPOWER_SRAM_IDX_RAM_01:
2890         {
2891             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_01_LS_SHIFT))) |
2892                              (power_mode << PMC_SRAMCTRL0_RAM_01_LS_SHIFT);
2893             break;
2894         }
2895 
2896         case kPOWER_SRAM_IDX_RAM_02:
2897         {
2898             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_02_LS_SHIFT))) |
2899                              (power_mode << PMC_SRAMCTRL0_RAM_02_LS_SHIFT);
2900             break;
2901         }
2902 
2903         case kPOWER_SRAM_IDX_RAM_03:
2904         {
2905             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_03_LS_SHIFT))) |
2906                              (power_mode << PMC_SRAMCTRL0_RAM_03_LS_SHIFT);
2907             break;
2908         }
2909 
2910         case kPOWER_SRAM_IDX_RAM_10:
2911         {
2912             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_10_LS_SHIFT))) |
2913                              (power_mode << PMC_SRAMCTRL0_RAM_10_LS_SHIFT);
2914             break;
2915         }
2916 
2917         case kPOWER_SRAM_IDX_RAM_20:
2918         {
2919             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_20_LS_SHIFT))) |
2920                              (power_mode << PMC_SRAMCTRL0_RAM_20_LS_SHIFT);
2921             break;
2922         }
2923 
2924         case kPOWER_SRAM_IDX_RAM_30:
2925         {
2926             PMC->SRAMCTRL0 = (PMC->SRAMCTRL0 & (~(0xFUL << PMC_SRAMCTRL0_RAM_30_LS_SHIFT))) |
2927                              (power_mode << PMC_SRAMCTRL0_RAM_30_LS_SHIFT);
2928             break;
2929         }
2930 
2931         case kPOWER_SRAM_IDX_RAM_40:
2932         {
2933             PMC->SRAMCTRL1 = (PMC->SRAMCTRL1 & (~(0xFUL << PMC_SRAMCTRL1_RAM_40_LS_SHIFT))) |
2934                              (power_mode << PMC_SRAMCTRL1_RAM_40_LS_SHIFT);
2935             break;
2936         }
2937 
2938         case kPOWER_SRAM_IDX_RAM_41:
2939         {
2940             PMC->SRAMCTRL1 = (PMC->SRAMCTRL1 & (~(0xFUL << PMC_SRAMCTRL1_RAM_41_LS_SHIFT))) |
2941                              (power_mode << PMC_SRAMCTRL1_RAM_41_LS_SHIFT);
2942             break;
2943         }
2944 
2945         case kPOWER_SRAM_IDX_RAM_42:
2946         {
2947             PMC->SRAMCTRL1 = (PMC->SRAMCTRL1 & (~(0xFUL << PMC_SRAMCTRL1_RAM_42_LS_SHIFT))) |
2948                              (power_mode << PMC_SRAMCTRL1_RAM_42_LS_SHIFT);
2949             break;
2950         }
2951 
2952         case kPOWER_SRAM_IDX_RAM_43:
2953         {
2954             PMC->SRAMCTRL1 = (PMC->SRAMCTRL1 & (~(0xFUL << PMC_SRAMCTRL1_RAM_43_LS_SHIFT))) |
2955                              (power_mode << PMC_SRAMCTRL1_RAM_43_LS_SHIFT);
2956             break;
2957         }
2958 
2959         case kPOWER_SRAM_IDX_FLASHCACHE:
2960         {
2961             PMC->SRAMCTRL1 = (PMC->SRAMCTRL1 & (~(0xFUL << PMC_SRAMCTRL1_RAM_FLASHLPCACHE_LS_SHIFT))) |
2962                              (power_mode << PMC_SRAMCTRL1_RAM_FLASHLPCACHE_LS_SHIFT);
2963             break;
2964         }
2965 
2966         case kPOWER_SRAM_IDX_FLEXSPICACHE:
2967         {
2968             PMC->SRAMCTRL1 = (PMC->SRAMCTRL1 & (~(0xFUL << PMC_SRAMCTRL1_RAM_FLEXSPILPCACHE_LS_SHIFT))) |
2969                              (power_mode << PMC_SRAMCTRL1_RAM_FLEXSPILPCACHE_LS_SHIFT);
2970             break;
2971         }
2972 
2973         default:
2974             // Error
2975             ;
2976     }
2977 }
2978 
2979 /**
2980  * brief
2981  * return
2982  */
POWER_SRAMActiveToLightSleep(power_sram_index_t sram_index)2983 static void POWER_SRAMActiveToLightSleep(power_sram_index_t sram_index)
2984 {
2985     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_LS_CODE);
2986 }
2987 
2988 /**
2989  * brief
2990  * return
2991  */
POWER_SRAMActiveToDeepSleep(power_sram_index_t sram_index)2992 static void POWER_SRAMActiveToDeepSleep(power_sram_index_t sram_index)
2993 {
2994     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_DS_CODE);
2995 }
2996 
2997 /**
2998  * brief
2999  * return
3000  */
POWER_SRAMActiveToShutDown(power_sram_index_t sram_index)3001 static void POWER_SRAMActiveToShutDown(power_sram_index_t sram_index)
3002 {
3003     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_SD_CODE);
3004 }
3005 
3006 /**
3007  * brief
3008  * return
3009  */
POWER_SRAMLightSleepToActive(power_sram_index_t sram_index)3010 static void POWER_SRAMLightSleepToActive(power_sram_index_t sram_index)
3011 {
3012     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_MPU_CODE);
3013     // Wait at least 944.90 ns (worst case, from gf40rfnv_nxp_ehlvsram_008192x032bw4c04_mh_pt_m7)
3014     POWER_SRAMPowerUpDelay(); // wait about 1 us
3015     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_ACT_CODE);
3016 }
3017 
3018 /**
3019  * brief
3020  * return
3021  */
POWER_SRAMDeepSleepToActive(power_sram_index_t sram_index)3022 static void POWER_SRAMDeepSleepToActive(power_sram_index_t sram_index)
3023 {
3024     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_FPU_CODE);
3025     // Wait at least 707.30 ns (worst case, from gf40rfnv_nxp_ehlvsram_008192x032bw4c04_mh_pt_m7)
3026     POWER_SRAMPowerUpDelay(); // wait about 1 us
3027     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_ACT_CODE);
3028 }
3029 
3030 /**
3031  * brief
3032  * return
3033  */
POWER_SRAMShutDownToActive(power_sram_index_t sram_index)3034 static void POWER_SRAMShutDownToActive(power_sram_index_t sram_index)
3035 {
3036     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_FPU_CODE);
3037     // Wait at least 382.80 ns (worst case, from gf40rfnv_nxp_ehlvsram_008192x032bw4c04_mh_pt_m7)
3038     POWER_SRAMPowerUpDelay(); // wait about 1 us
3039     POWER_SRAMSetRegister(sram_index, SRAM_PWR_MODE_ACT_CODE);
3040 }
3041 
3042 /**
3043  * brief
3044  * return
3045  */
POWER_SetSystemClock12MHZ(void)3046 static void POWER_SetSystemClock12MHZ(void)
3047 {
3048     if ((SYSCON->MAINCLKSELA != 0) || (SYSCON->MAINCLKSELB != 0) ||
3049         ((SYSCON->AHBCLKDIV & SYSCON_AHBCLKDIV_DIV_MASK) != 0))
3050     {
3051         /* The System is NOT running at 12 MHz: so switch the system on 12 MHz clock */
3052         /* IMPORTANT NOTE : The assumption here is that before calling any Low Power API
3053          * the system will be running at a frequency higher or equal to 12 MHz.
3054          */
3055         uint32_t flash_int_enable_reg;
3056         uint32_t num_wait_states = 1; /* Default to the maximum number of wait states */
3057 
3058         /* Switch main clock to FRO12MHz ( the order of the 5 settings below is critical) */
3059         SYSCON->MAINCLKSELA = SYSCON_MAINCLKSELA_SEL(0); /* Main clock A source select : FRO 12 MHz clock */
3060         SYSCON->MAINCLKSELB = SYSCON_MAINCLKSELB_SEL(0); /* Main clock B source select : Main Clock A */
3061         SYSCON->AHBCLKDIV   = SYSCON_AHBCLKDIV_DIV(0);   /* Main clock divided by 1 */
3062 
3063 /* Adjust FMC waiting time cycles (num_wait_states) and disable PREFETCH
3064  * NOTE : PREFETCH disable MUST BE DONE BEFORE the flash command below.
3065  */
3066 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
3067         SYSCON->FMCCR = (SYSCON->FMCCR & (~SYSCON_FMCCR_FLASHTIM_MASK) & (~SYSCON_FMCCR_PREFEN_MASK)) |
3068                         SYSCON_FMCCR_FLASHTIM(num_wait_states);
3069         /* Adjust Flash Controller waiting time */
3070         flash_int_enable_reg = FLASH->INTEN; /* Save INT_ENABLE register. */
3071         FLASH->INTEN_CLR     = 0x1F;         /* Disable all interrupt */
3072         FLASH->INTSTAT_CLR   = 0x1F;         /* Clear all status flags */
3073 #else
3074         SYSCON->FMCCR = (SYSCON->FMCCR & (~SYSCON_FMCCR_FMCTIM_MASK) & (~SYSCON_FMCCR_PREFEN_MASK)) |
3075                         SYSCON_FMCCR_FMCTIM(num_wait_states);
3076         /* Adjust Flash Controller waiting time */
3077         flash_int_enable_reg = FLASH->INT_ENABLE; /* Save INT_ENABLE register. */
3078         FLASH->INT_CLR_ENABLE = 0x1F;             /* Disable all interrupt */
3079         FLASH->INT_CLR_STATUS = 0x1F;             /* Clear all status flags */
3080 #endif
3081 
3082         FLASH->DATAW[0] = num_wait_states;
3083         FLASH->CMD      = 0x2; /* CMD_SET_READ_MODE */
3084 
3085 #if (defined(LPC55S36_SERIES) || defined(LPC5536_SERIES) || defined(LPC5534_SERIES))
3086         /* Wait until the cmd is completed (without error) */
3087         while (!(FLASH->INTSTAT & FLASH_INTSTAT_DONE_MASK))
3088             ;
3089         FLASH->INTSTAT_CLR = 0x1F;                 /* Clear all status flags, then ... */
3090         FLASH->INTEN_SET   = flash_int_enable_reg; /* ... restore INT_ENABLE register. */
3091 #else
3092         /* Wait until the cmd is completed (without error) */
3093         while (!(FLASH->INT_STATUS & FLASH_INT_STATUS_DONE_MASK))
3094             ;
3095         FLASH->INT_CLR_STATUS = 0x1F;                 /* Clear all status flags, then ... */
3096         FLASH->INT_SET_ENABLE = flash_int_enable_reg; /* ... restore INT_ENABLE register. */
3097 #endif
3098 
3099         POWER_SetSystemPowerProfile(
3100             V_SYSTEM_POWER_PROFILE_LOW); /* Align DCDC/LDO_CORE Power profile with the 12 MHz frequency */
3101     }
3102     else
3103     {
3104         /* The System is already running at 12 MHz: so disable FMC PREFETCH feature only */
3105         SYSCON->FMCCR = SYSCON->FMCCR & (~SYSCON_FMCCR_PREFEN_MASK);
3106     }
3107 }
3108