1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 #include "mxc_device.h"
22 #include "mxc_assert.h"
23 #include "mxc_errors.h"
24 #include "mxc_sys.h"
25 #include "gcr_regs.h"
26 #include "flc_regs.h"
27 #include "lp.h"
28 
MXC_LP_EnterSleepMode(void)29 void MXC_LP_EnterSleepMode(void)
30 {
31     MXC_LP_ClearWakeStatus();
32 
33     // set block detect bit
34     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
35 
36     // Clear SLEEPDEEP bit
37     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
38 
39     // Go into Sleep mode and wait for an interrupt to wake the processor
40     __WFI();
41 }
42 
MXC_LP_EnterDeepSleepMode(void)43 void MXC_LP_EnterDeepSleepMode(void)
44 {
45     MXC_LP_ClearWakeStatus();
46 
47     // set block detect bit
48     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
49 
50     // Set SLEEPDEEP bit
51     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
52 
53     // Go into Deepsleep mode and wait for an interrupt to wake the processor
54     __WFI();
55 }
56 
MXC_LP_EnterBackupMode(void)57 void MXC_LP_EnterBackupMode(void)
58 {
59     MXC_LP_ClearWakeStatus();
60 
61     // set block detect bit
62     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
63 
64     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
65     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
66 
67     while (1) {}
68     // Should never reach this line - device will jump to backup vector on exit from background mode.
69 }
70 
MXC_LP_EnterStorageMode(void)71 void MXC_LP_EnterStorageMode(void)
72 {
73     MXC_LP_ClearWakeStatus();
74     /*set block detect bit */
75     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
76 
77     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_STORAGE_EN;
78     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
79     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
80 
81     while (1) {}
82     // Should never reach this line - device will jump to backup vector on exit from background mode.
83 }
84 
MXC_LP_EnterShutDownMode(void)85 void MXC_LP_EnterShutDownMode(void)
86 {
87     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
88     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_SHUTDOWN;
89 
90     while (1) {}
91     // Should never reach this line - device will reset on exit from shutdown mode.
92 }
93 
MXC_LP_SetOVR(mxc_lp_ovr_t ovr)94 int MXC_LP_SetOVR(mxc_lp_ovr_t ovr)
95 {
96     uint32_t current_clock, div;
97     int error;
98 
99     // Ensure part is operating from internal LDO for core power
100     if (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_LDO_DIS) {
101         return E_BAD_STATE;
102     }
103 
104     // Select the 8KHz nanoring (no guarantee 32KHz is attached) as system clock source
105     current_clock = MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL;
106     if (current_clock == MXC_SYS_CLOCK_IPO) {
107         error = MXC_SYS_Clock_Select(MXC_SYS_CLOCK_INRO);
108         if (error != E_NO_ERROR) {
109             return error;
110         }
111     }
112 
113     // Set flash wait state for any clock so its not to low after clock changes.
114     MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
115                        (0x5UL << MXC_F_GCR_MEMCTRL_FWS_POS);
116 
117     // Set the OVR bits
118     //  The OVR enums in mxc_lp_ovr_t equals to their appropriate register setting.
119     MXC_SETFIELD(MXC_PWRSEQ->lpcn, MXC_F_PWRSEQ_LPCN_OVR, ovr);
120 
121     // Set LVE bit
122     if (ovr == MXC_LP_OVR_0_9) {
123         MXC_FLC0->ctrl |= MXC_F_FLC_CTRL_LVE;
124 
125     } else {
126         MXC_FLC0->ctrl &= ~(MXC_F_FLC_CTRL_LVE);
127     }
128 
129     // Revert the clock to original state if it was IPO
130     if (current_clock == MXC_SYS_CLOCK_IPO) {
131         error = MXC_SYS_Clock_Select(MXC_SYS_CLOCK_IPO);
132         if (error != E_NO_ERROR) {
133             return error;
134         }
135     }
136 
137     // Update SystemCoreClock variable
138     SystemCoreClockUpdate();
139 
140     // Get the clock divider
141     div = (MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_DIV) >> MXC_F_GCR_CLKCTRL_SYSCLK_DIV_POS;
142 
143     // Set Flash Wait States
144     if (ovr == MXC_LP_OVR_0_9) {
145         if (div == 0) {
146             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
147                                (0x2UL << MXC_F_GCR_MEMCTRL_FWS_POS);
148 
149         } else {
150             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
151                                (0x1UL << MXC_F_GCR_MEMCTRL_FWS_POS);
152         }
153 
154     } else if (ovr == MXC_LP_OVR_1_0) {
155         if (div == 0) {
156             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
157                                (0x2UL << MXC_F_GCR_MEMCTRL_FWS_POS);
158 
159         } else {
160             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
161                                (0x1UL << MXC_F_GCR_MEMCTRL_FWS_POS);
162         }
163 
164     } else {
165         if (div == 0) {
166             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
167                                (0x4UL << MXC_F_GCR_MEMCTRL_FWS_POS);
168 
169         } else if (div == 1) {
170             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
171                                (0x2UL << MXC_F_GCR_MEMCTRL_FWS_POS);
172 
173         } else {
174             MXC_GCR->memctrl = (MXC_GCR->memctrl & ~(MXC_F_GCR_MEMCTRL_FWS)) |
175                                (0x1UL << MXC_F_GCR_MEMCTRL_FWS_POS);
176         }
177     }
178 
179     // Caller must perform peripheral reset
180 
181     return E_NO_ERROR;
182 }
183 
MXC_LP_RetentionRegEnable(void)184 void MXC_LP_RetentionRegEnable(void)
185 {
186     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_RETREG_EN;
187 }
188 
MXC_LP_RetentionRegDisable(void)189 void MXC_LP_RetentionRegDisable(void)
190 {
191     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_RETREG_EN;
192 }
193 
MXC_LP_RetentionRegIsEnabled(void)194 int MXC_LP_RetentionRegIsEnabled(void)
195 {
196     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_RETREG_EN);
197 }
198 
MXC_LP_BandgapOn(void)199 void MXC_LP_BandgapOn(void)
200 {
201     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_BG_DIS;
202 }
203 
MXC_LP_BandgapOff(void)204 void MXC_LP_BandgapOff(void)
205 {
206     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BG_DIS;
207 }
208 
MXC_LP_BandgapIsOn(void)209 int MXC_LP_BandgapIsOn(void)
210 {
211     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_BG_DIS);
212 }
213 
MXC_LP_PORVCOREoreMonitorEnable(void)214 void MXC_LP_PORVCOREoreMonitorEnable(void)
215 {
216     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_VCOREPOR_DIS;
217 }
218 
MXC_LP_PORVCOREoreMonitorDisable(void)219 void MXC_LP_PORVCOREoreMonitorDisable(void)
220 {
221     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCOREPOR_DIS;
222 }
223 
MXC_LP_PORVCOREoreMonitorIsEnabled(void)224 int MXC_LP_PORVCOREoreMonitorIsEnabled(void)
225 {
226     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_VCOREPOR_DIS);
227 }
228 
MXC_LP_LDOEnable(void)229 void MXC_LP_LDOEnable(void)
230 {
231     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_LDO_DIS;
232 }
233 
MXC_LP_LDODisable(void)234 void MXC_LP_LDODisable(void)
235 {
236     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_LDO_DIS;
237 }
238 
MXC_LP_LDOIsEnabled(void)239 int MXC_LP_LDOIsEnabled(void)
240 {
241     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_LDO_DIS);
242 }
243 
MXC_LP_FastWakeupEnable(void)244 void MXC_LP_FastWakeupEnable(void)
245 {
246     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_FASTWK_EN;
247 }
248 
MXC_LP_FastWakeupDisable(void)249 void MXC_LP_FastWakeupDisable(void)
250 {
251     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_FASTWK_EN;
252 }
253 
MXC_LP_FastWakeupIsEnabled(void)254 int MXC_LP_FastWakeupIsEnabled(void)
255 {
256     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_FASTWK_EN);
257 }
258 
MXC_LP_ClearWakeStatus(void)259 void MXC_LP_ClearWakeStatus(void)
260 {
261     // Write 1 to clear
262     MXC_PWRSEQ->lpwkst0 = 0xFFFFFFFF;
263     MXC_PWRSEQ->lpwkst1 = 0xFFFFFFFF;
264     MXC_PWRSEQ->lppwkst = 0xFFFFFFFF;
265 }
266 
MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)267 void MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t *wu_pins)
268 {
269     MXC_GCR->pm |= MXC_F_GCR_PM_GPIO_WE;
270 
271     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
272     case MXC_GPIO_PORT_0:
273         MXC_PWRSEQ->lpwken0 |= wu_pins->mask;
274         break;
275 
276     case MXC_GPIO_PORT_1:
277         MXC_PWRSEQ->lpwken1 |= wu_pins->mask;
278     }
279 }
280 
MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)281 void MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t *wu_pins)
282 {
283     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
284     case MXC_GPIO_PORT_0:
285         MXC_PWRSEQ->lpwken0 &= ~wu_pins->mask;
286         break;
287 
288     case MXC_GPIO_PORT_1:
289         MXC_PWRSEQ->lpwken1 &= ~wu_pins->mask;
290     }
291 
292     if (MXC_PWRSEQ->lpwken1 == 0 && MXC_PWRSEQ->lpwken0 == 0) {
293         MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIO_WE;
294     }
295 }
296 
MXC_LP_EnableRTCAlarmWakeup(void)297 void MXC_LP_EnableRTCAlarmWakeup(void)
298 {
299     MXC_GCR->pm |= MXC_F_GCR_PM_RTC_WE;
300 }
301 
MXC_LP_DisableRTCAlarmWakeup(void)302 void MXC_LP_DisableRTCAlarmWakeup(void)
303 {
304     MXC_GCR->pm &= ~MXC_F_GCR_PM_RTC_WE;
305 }
306 
MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t * tmr)307 void MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t *tmr)
308 {
309     MXC_ASSERT(MXC_TMR_GET_IDX(tmr) > 3);
310 
311     if (tmr == MXC_TMR4) {
312         MXC_GCR->pm |= MXC_F_GCR_PM_LPTMR0_WE;
313         MXC_PWRSEQ->lppwken |= MXC_F_PWRSEQ_LPPWKEN_LPTMR0;
314     } else {
315         MXC_GCR->pm |= MXC_F_GCR_PM_LPTMR1_WE;
316         MXC_PWRSEQ->lppwken |= MXC_F_PWRSEQ_LPPWKEN_LPTMR1;
317     }
318 }
319 
MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t * tmr)320 void MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t *tmr)
321 {
322     MXC_ASSERT(MXC_TMR_GET_IDX(tmr) > 3);
323 
324     if (tmr == MXC_TMR4) {
325         MXC_GCR->pm &= ~MXC_F_GCR_PM_LPTMR0_WE;
326         MXC_PWRSEQ->lppwken &= ~MXC_F_PWRSEQ_LPPWKEN_LPTMR0;
327     } else {
328         MXC_GCR->pm &= ~MXC_F_GCR_PM_LPTMR1_WE;
329         MXC_PWRSEQ->lppwken &= ~MXC_F_PWRSEQ_LPPWKEN_LPTMR1;
330     }
331 }
332 
MXC_LP_EnableUARTWakeup(void)333 void MXC_LP_EnableUARTWakeup(void)
334 {
335     MXC_GCR->pm |= MXC_F_GCR_PM_LPUART0_WE;
336     MXC_PWRSEQ->lppwken |= MXC_F_PWRSEQ_LPPWKEN_LPUART0;
337 }
338 
MXC_LP_DisableUARTWakeup(void)339 void MXC_LP_DisableUARTWakeup(void)
340 {
341     MXC_GCR->pm &= ~MXC_F_GCR_PM_LPUART0_WE;
342     MXC_PWRSEQ->lppwken &= ~MXC_F_PWRSEQ_LPPWKEN_LPUART0;
343 }
344 
MXC_LP_ConfigDeepSleepClocks(uint32_t mask)345 int MXC_LP_ConfigDeepSleepClocks(uint32_t mask)
346 {
347     if (!(mask & (MXC_F_GCR_PM_IBRO_PD | MXC_F_GCR_PM_IPO_PD | MXC_F_GCR_PM_ERFO_PD))) {
348         return E_BAD_PARAM;
349     }
350 
351     MXC_GCR->pm |= mask;
352     return E_NO_ERROR;
353 }
354 
MXC_LP_SysRam0LightSleepEnable(void)355 void MXC_LP_SysRam0LightSleepEnable(void)
356 {
357     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM0LS_EN;
358 }
359 
MXC_LP_SysRam1LightSleepEnable(void)360 void MXC_LP_SysRam1LightSleepEnable(void)
361 {
362     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM1LS_EN;
363 }
364 
MXC_LP_SysRam2LightSleepEnable(void)365 void MXC_LP_SysRam2LightSleepEnable(void)
366 {
367     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM2LS_EN;
368 }
369 
MXC_LP_SysRam3LightSleepEnable(void)370 void MXC_LP_SysRam3LightSleepEnable(void)
371 {
372     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM3LS_EN;
373 }
374 
MXC_LP_ICache0LightSleepEnable(void)375 void MXC_LP_ICache0LightSleepEnable(void)
376 {
377     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_ICC0LS_EN;
378 }
379 
MXC_LP_ROMLightSleepEnable(void)380 void MXC_LP_ROMLightSleepEnable(void)
381 {
382     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_ROMLS_EN;
383 }
384 
MXC_LP_SysRam0LightSleepDisable(void)385 void MXC_LP_SysRam0LightSleepDisable(void)
386 {
387     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM0LS_EN;
388 }
389 
MXC_LP_SysRam1LightSleepDisable(void)390 void MXC_LP_SysRam1LightSleepDisable(void)
391 {
392     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM1LS_EN;
393 }
394 
MXC_LP_SysRam2LightSleepDisable(void)395 void MXC_LP_SysRam2LightSleepDisable(void)
396 {
397     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM2LS_EN;
398 }
399 
MXC_LP_SysRam3LightSleepDisable(void)400 void MXC_LP_SysRam3LightSleepDisable(void)
401 {
402     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM3LS_EN;
403 }
404 
MXC_LP_ICache0LightSleepDisable(void)405 void MXC_LP_ICache0LightSleepDisable(void)
406 {
407     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_ICC0LS_EN;
408 }
409 
MXC_LP_ROMLightSleepDisable(void)410 void MXC_LP_ROMLightSleepDisable(void)
411 {
412     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_ROMLS_EN;
413 }
414 
MXC_LP_SysRam0Shutdown(void)415 void MXC_LP_SysRam0Shutdown(void)
416 {
417     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM0;
418 }
419 
MXC_LP_SysRam0PowerUp(void)420 void MXC_LP_SysRam0PowerUp(void)
421 {
422     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM0;
423 }
424 
MXC_LP_SysRam1Shutdown(void)425 void MXC_LP_SysRam1Shutdown(void)
426 {
427     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM1;
428 }
429 
MXC_LP_SysRam1PowerUp(void)430 void MXC_LP_SysRam1PowerUp(void)
431 {
432     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM1;
433 }
434 
MXC_LP_SysRam2Shutdown(void)435 void MXC_LP_SysRam2Shutdown(void)
436 {
437     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM2;
438 }
439 
MXC_LP_SysRam2PowerUp(void)440 void MXC_LP_SysRam2PowerUp(void)
441 {
442     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM2;
443 }
444 
MXC_LP_SysRam3Shutdown(void)445 void MXC_LP_SysRam3Shutdown(void)
446 {
447     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM3;
448 }
449 
MXC_LP_SysRam3PowerUp(void)450 void MXC_LP_SysRam3PowerUp(void)
451 {
452     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM3;
453 }
454