1 /**
2  * @file    lp.c
3  * @brief   Low power functions
4  */
5 
6 /******************************************************************************
7  *
8  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
9  * Analog Devices, Inc.),
10  * Copyright (C) 2023-2024 Analog Devices, Inc.
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *     http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  *
24  ******************************************************************************/
25 
26 /***** Includes *****/
27 #include "lp.h"
28 #include "pwrseq_regs.h"
29 #include "gcr_regs.h"
30 #include "mxc_device.h"
31 #include "mxc_errors.h"
32 #include "mxc_pins.h"
33 #include "mxc_sys.h"
34 #include "flc.h"
35 #include "mxc_delay.h"
36 
37 /***** Functions *****/
MXC_LP_ClearWakeStatus(void)38 void MXC_LP_ClearWakeStatus(void)
39 {
40     MXC_PWRSEQ->lp_wakefl = 0xFFFFFFFF;
41 
42     /* These flags are slow to clear, so block until they do */
43     while (MXC_PWRSEQ->lp_wakefl & (MXC_PWRSEQ->lpwk_en)) {}
44 }
45 
MXC_LP_EnableSRAM3(void)46 void MXC_LP_EnableSRAM3(void)
47 {
48     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF;
49 }
50 
MXC_LP_DisableSRAM3(void)51 void MXC_LP_DisableSRAM3(void)
52 {
53     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM3_OFF;
54 }
55 
MXC_LP_EnableSRAM2(void)56 void MXC_LP_EnableSRAM2(void)
57 {
58     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF;
59 }
60 
MXC_LP_DisableSRAM2(void)61 void MXC_LP_DisableSRAM2(void)
62 {
63     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM2_OFF;
64 }
65 
MXC_LP_EnableSRAM1(void)66 void MXC_LP_EnableSRAM1(void)
67 {
68     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF;
69 }
70 
MXC_LP_DisableSRAM1(void)71 void MXC_LP_DisableSRAM1(void)
72 {
73     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM1_OFF;
74 }
75 
MXC_LP_EnableSRAM0(void)76 void MXC_LP_EnableSRAM0(void)
77 {
78     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF;
79 }
80 
MXC_LP_DisableSRAM0(void)81 void MXC_LP_DisableSRAM0(void)
82 {
83     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM0_OFF;
84 }
85 
MXC_LP_EnableICacheLightSleep(void)86 void MXC_LP_EnableICacheLightSleep(void)
87 {
88     MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_ICACHE_RET);
89 }
90 
MXC_LP_DisableICacheLightSleep(void)91 void MXC_LP_DisableICacheLightSleep(void)
92 {
93     MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_ICACHE_RET);
94 }
95 
MXC_LP_EnableSysRAM3LightSleep(void)96 void MXC_LP_EnableSysRAM3LightSleep(void)
97 {
98     MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM3_LS);
99 }
100 
MXC_LP_DisableSysRAM3LightSleep(void)101 void MXC_LP_DisableSysRAM3LightSleep(void)
102 {
103     MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM3_LS);
104 }
105 
MXC_LP_EnableSysRAM2LightSleep(void)106 void MXC_LP_EnableSysRAM2LightSleep(void)
107 {
108     MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM2_LS);
109 }
110 
MXC_LP_DisableSysRAM2LightSleep(void)111 void MXC_LP_DisableSysRAM2LightSleep(void)
112 {
113     MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM2_LS);
114 }
115 
MXC_LP_EnableSysRAM1LightSleep(void)116 void MXC_LP_EnableSysRAM1LightSleep(void)
117 {
118     MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM1_LS);
119 }
120 
MXC_LP_DisableSysRAM1LightSleep(void)121 void MXC_LP_DisableSysRAM1LightSleep(void)
122 {
123     MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM1_LS);
124 }
125 
MXC_LP_EnableSysRAM0LightSleep(void)126 void MXC_LP_EnableSysRAM0LightSleep(void)
127 {
128     MXC_GCR->mem_ctrl |= (MXC_F_GCR_MEM_CTRL_RAM0_LS);
129 }
130 
MXC_LP_DisableSysRAM0LightSleep(void)131 void MXC_LP_DisableSysRAM0LightSleep(void)
132 {
133     MXC_GCR->mem_ctrl &= ~(MXC_F_GCR_MEM_CTRL_RAM0_LS);
134 }
135 
MXC_LP_EnableRTCAlarmWakeup(void)136 void MXC_LP_EnableRTCAlarmWakeup(void)
137 {
138     MXC_GCR->pm |= MXC_F_GCR_PM_RTCWK_EN;
139 }
140 
MXC_LP_DisableRTCAlarmWakeup(void)141 void MXC_LP_DisableRTCAlarmWakeup(void)
142 {
143     MXC_GCR->pm &= ~MXC_F_GCR_PM_RTCWK_EN;
144 }
145 
MXC_LP_EnableGPIOWakeup(const mxc_gpio_cfg_t * wu_pins)146 void MXC_LP_EnableGPIOWakeup(const mxc_gpio_cfg_t *wu_pins)
147 {
148     MXC_GCR->pm |= MXC_F_GCR_PM_GPIOWK_EN;
149     //switch(wu_pins->port)
150     //{
151     /*case 0:*/ MXC_PWRSEQ->lpwk_en |= wu_pins->mask; //break;
152     //}
153 }
154 
MXC_LP_DisableGPIOWakeup(const mxc_gpio_cfg_t * wu_pins)155 void MXC_LP_DisableGPIOWakeup(const mxc_gpio_cfg_t *wu_pins)
156 {
157     //switch(wu_pins->port)
158     //{
159     /*  case 0:*/ MXC_PWRSEQ->lpwk_en &= ~wu_pins->mask; //break;
160     //}
161 
162     if (MXC_PWRSEQ->lpwk_en == 0) {
163         MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIOWK_EN;
164     }
165 }
166 
MXC_LP_EnterSleepMode(void)167 void MXC_LP_EnterSleepMode(void)
168 {
169     // Clear SLEEPDEEP bit
170     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
171 
172     // Go into Sleep mode and wait for an interrupt to wake the processor
173     __WFI();
174 }
175 
MXC_LP_EnterDeepSleepMode(void)176 void MXC_LP_EnterDeepSleepMode(void)
177 {
178     // Set SLEEPDEEP bit
179     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
180 
181     // Auto-powerdown 96 MHz oscillator when in deep sleep
182     MXC_GCR->pm |= MXC_F_GCR_PM_HFIOPD;
183     // Go into Deepsleep mode and wait for an interrupt to wake the processor
184     __WFI();
185 }
186 
MXC_LP_EnterBackupMode(void)187 void MXC_LP_EnterBackupMode(void)
188 {
189     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
190     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
191     while (1) {}
192 }
193 
MXC_LP_EnterShutDownMode(void)194 void MXC_LP_EnterShutDownMode(void)
195 {
196     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
197     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_SHUTDOWN;
198     while (1) {}
199 }
200 
MXC_LP_SetOperatingVoltage(mxc_lp_ovr_t ovr)201 int MXC_LP_SetOperatingVoltage(mxc_lp_ovr_t ovr)
202 {
203     uint32_t current_clock, div;
204     int error;
205 
206     // Ensure part is operating from internal LDO for core power
207     if (MXC_PWRSEQ->lp_ctrl & MXC_F_PWRSEQ_LP_CTRL_LDO_DIS) {
208         return E_BAD_STATE;
209     }
210 
211     // Select the 8KHz nanoring (no guarantee 32KHz is attached) as system clock source
212     current_clock = MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_CLKSEL;
213     if (current_clock == MXC_SYS_CLOCK_HIRC) {
214         error = MXC_SYS_Clock_Select(MXC_SYS_CLOCK_NANORING);
215         if (error != E_NO_ERROR) {
216             return error;
217         }
218     }
219 
220     // Set flash wait state for any clock so its not to low after clock changes.
221     MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
222                         (0x5UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
223 
224     // Set the OVR bits
225     MXC_PWRSEQ->lp_ctrl &= ~(MXC_F_PWRSEQ_LP_CTRL_OVR);
226     MXC_PWRSEQ->lp_ctrl |= ovr;
227 
228     // Set LVE bit
229     if (ovr == MXC_LP_OVR_0_9) {
230         MXC_FLC->ctrl |= MXC_F_FLC_CTRL_LVE;
231 
232     } else {
233         MXC_FLC->ctrl &= ~(MXC_F_FLC_CTRL_LVE);
234     }
235 
236     // Revert the clock to original state if it was HIRC
237     if (current_clock == MXC_SYS_CLOCK_HIRC) {
238         error = MXC_SYS_Clock_Select(MXC_SYS_CLOCK_HIRC);
239         if (error != E_NO_ERROR) {
240             return error;
241         }
242     }
243 
244     // Update SystemCoreClock variable
245     SystemCoreClockUpdate();
246 
247     // Get the clock divider
248     div = (MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_PSC) >> MXC_F_GCR_CLK_CTRL_PSC_POS;
249 
250     // Set Flash Wait States
251     if (ovr == MXC_LP_OVR_0_9) {
252         if (div == 0) {
253             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
254                                 (0x2UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
255 
256         } else {
257             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
258                                 (0x1UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
259         }
260 
261     } else if (ovr == MXC_LP_OVR_1_0) {
262         if (div == 0) {
263             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
264                                 (0x2UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
265 
266         } else {
267             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
268                                 (0x1UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
269         }
270 
271     } else {
272         if (div == 0) {
273             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
274                                 (0x4UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
275 
276         } else if (div == 1) {
277             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
278                                 (0x2UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
279 
280         } else {
281             MXC_GCR->mem_ctrl = (MXC_GCR->mem_ctrl & ~(MXC_F_GCR_MEM_CTRL_FWS)) |
282                                 (0x1UL << MXC_F_GCR_MEM_CTRL_FWS_POS);
283         }
284     }
285 
286     // Caller must perform peripheral reset
287 
288     return E_NO_ERROR;
289 }
290 
MXC_LP_EnableSRamRet0(void)291 void MXC_LP_EnableSRamRet0(void)
292 {
293     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0;
294 }
295 
MXC_LP_DisableSRamRet0(void)296 void MXC_LP_DisableSRamRet0(void)
297 {
298     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL0;
299 }
300 
MXC_LP_EnableSRamRet1(void)301 void MXC_LP_EnableSRamRet1(void)
302 {
303     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1;
304 }
305 
MXC_LP_DisableSRamRet1(void)306 void MXC_LP_DisableSRamRet1(void)
307 {
308     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL1;
309 }
310 
MXC_LP_EnableSRamRet2(void)311 void MXC_LP_EnableSRamRet2(void)
312 {
313     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2;
314 }
315 
MXC_LP_DisableSRamRet2(void)316 void MXC_LP_DisableSRamRet2(void)
317 {
318     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL2;
319 }
320 
MXC_LP_EnableSRamRet3(void)321 void MXC_LP_EnableSRamRet3(void)
322 {
323     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3;
324 }
325 
MXC_LP_DisableSRamRet3(void)326 void MXC_LP_DisableSRamRet3(void)
327 {
328     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RAMRET_SEL3;
329 }
330 
MXC_LP_EnableBlockDetect(void)331 void MXC_LP_EnableBlockDetect(void)
332 {
333     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS;
334 }
335 
MXC_LP_DisableBlockDetect(void)336 void MXC_LP_DisableBlockDetect(void)
337 {
338     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VCORE_DET_BYPASS;
339 }
340 
MXC_LP_EnableRamRetReg(void)341 void MXC_LP_EnableRamRetReg(void)
342 {
343     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_RETREG_EN;
344 }
345 
MXC_LP_DisableRamRetReg(void)346 void MXC_LP_DisableRamRetReg(void)
347 {
348     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_RETREG_EN;
349 }
350 
MXC_LP_EnableFastWk(void)351 void MXC_LP_EnableFastWk(void)
352 {
353     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN;
354 }
355 
MXC_LP_DisableFastWk(void)356 void MXC_LP_DisableFastWk(void)
357 {
358     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_FAST_WK_EN;
359 }
360 
MXC_LP_EnableBandGap(void)361 void MXC_LP_EnableBandGap(void)
362 {
363     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_BG_OFF;
364 }
365 
MXC_LP_DisableBandGap(void)366 void MXC_LP_DisableBandGap(void)
367 {
368     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_BG_OFF;
369 }
370 
MXC_LP_EnableVCorePORSignal(void)371 void MXC_LP_EnableVCorePORSignal(void)
372 {
373     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS;
374 }
375 
MXC_LP_DisableVCorePORSignal(void)376 void MXC_LP_DisableVCorePORSignal(void)
377 {
378     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VCORE_POR_DIS;
379 }
380 
MXC_LP_EnableLDO(void)381 void MXC_LP_EnableLDO(void)
382 {
383     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_LDO_DIS;
384 }
385 
MXC_LP_DisableLDO(void)386 void MXC_LP_DisableLDO(void)
387 {
388     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_LDO_DIS;
389 }
390 
MXC_LP_EnableVCoreSVM(void)391 void MXC_LP_EnableVCoreSVM(void)
392 {
393     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS;
394 }
395 
MXC_LP_DisableVCoreSVM(void)396 void MXC_LP_DisableVCoreSVM(void)
397 {
398     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VCORE_SVM_DIS;
399 }
400 
MXC_LP_EnableVDDIOPorMonitoF(void)401 void MXC_LP_EnableVDDIOPorMonitoF(void)
402 {
403     MXC_PWRSEQ->lp_ctrl &= ~MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS;
404 }
405 
MXC_LP_DisableVDDIOPorMonitor(void)406 void MXC_LP_DisableVDDIOPorMonitor(void)
407 {
408     MXC_PWRSEQ->lp_ctrl |= MXC_F_PWRSEQ_LP_CTRL_VDDIO_POR_DIS;
409 }
410