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 /***** Includes *****/
22 #include <stdio.h>
23 #include "lp.h"
24 #include "mxc_errors.h"
25 #include "mxc_device.h"
26 #include "mxc_sys.h"
27 #include "tmr.h"
28 #include "mxc_delay.h"
29 #include "mxc_assert.h"
30 #include "simo.h"
31 #include "icc_reva.h"
32 #include "icc_reva_regs.h"
33 
34 extern void Reset_Handler(void);
35 extern void Backup_Handler(void);
36 
37 /***** Variables *****/
38 #define CTRL_POS (0)
39 #define ICSD_POS (1)
40 uint32_t icc0_state, icc1_state, clkcn_state;
41 
42 /***** Functions *****/
MXC_LP_ClearWakeStatus(void)43 void MXC_LP_ClearWakeStatus(void)
44 {
45     /* Write 1 to clear */
46     MXC_PWRSEQ->lpwkst0 = 0xFFFFFFFF;
47     MXC_PWRSEQ->lpwkst1 = 0xFFFFFFFF;
48     MXC_PWRSEQ->lppwst = 0xFFFFFFFF;
49 }
50 
MXC_LP_EnableRTCAlarmWakeup(void)51 void MXC_LP_EnableRTCAlarmWakeup(void)
52 {
53     MXC_GCR->pm |= MXC_F_GCR_PM_RTCWKEN;
54 }
55 
MXC_LP_DisableRTCAlarmWakeup(void)56 void MXC_LP_DisableRTCAlarmWakeup(void)
57 {
58     MXC_GCR->pm &= ~MXC_F_GCR_PM_RTCWKEN;
59 }
60 
MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)61 void MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t *wu_pins)
62 {
63     MXC_GCR->pm |= MXC_F_GCR_PM_GPIOWKEN;
64     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
65     case MXC_GPIO_PORT_0:
66         MXC_PWRSEQ->lpwken0 |= wu_pins->mask;
67         break;
68     case MXC_GPIO_PORT_1:
69         MXC_PWRSEQ->lpwken1 |= wu_pins->mask;
70     }
71 }
72 
MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)73 void MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t *wu_pins)
74 {
75     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
76     case MXC_GPIO_PORT_0:
77         MXC_PWRSEQ->lpwken0 &= ~wu_pins->mask;
78         break;
79     case MXC_GPIO_PORT_1:
80         MXC_PWRSEQ->lpwken1 &= ~wu_pins->mask;
81     }
82 
83     if (MXC_PWRSEQ->lpwken1 == 0 && MXC_PWRSEQ->lpwken0 == 0) {
84         MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIOWKEN;
85     }
86 }
87 
MXC_LP_EnableWUTAlarmWakeup(void)88 void MXC_LP_EnableWUTAlarmWakeup(void)
89 {
90     MXC_GCR->pm |= MXC_F_GCR_PM_WUTWKEN;
91 }
92 
MXC_LP_DisableWUTAlarmWakeup(void)93 void MXC_LP_DisableWUTAlarmWakeup(void)
94 {
95     MXC_GCR->pm &= ~MXC_F_GCR_PM_WUTWKEN;
96 }
97 
MXC_LP_SysRam0LightSleepEnable(void)98 void MXC_LP_SysRam0LightSleepEnable(void)
99 {
100     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SYSRAM0LS;
101 }
102 
MXC_LP_SysRam1LightSleepEnable(void)103 void MXC_LP_SysRam1LightSleepEnable(void)
104 {
105     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SYSRAM1LS;
106 }
107 
MXC_LP_SysRam2LightSleepEnable(void)108 void MXC_LP_SysRam2LightSleepEnable(void)
109 {
110     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SYSRAM2LS;
111 }
112 
MXC_LP_SysRam3LightSleepEnable(void)113 void MXC_LP_SysRam3LightSleepEnable(void)
114 {
115     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SYSRAM3LS;
116 }
117 
MXC_LP_SysRam4LightSleepEnable(void)118 void MXC_LP_SysRam4LightSleepEnable(void)
119 {
120     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SYSRAM4LS;
121 }
122 
MXC_LP_SysRam5LightSleepEnable(void)123 void MXC_LP_SysRam5LightSleepEnable(void)
124 {
125     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SYSRAM5LS;
126 }
127 
MXC_LP_SysRam0Shutdown(void)128 void MXC_LP_SysRam0Shutdown(void)
129 {
130     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM0SD;
131 }
132 
MXC_LP_SysRam0PowerUp(void)133 void MXC_LP_SysRam0PowerUp(void)
134 {
135     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM0SD;
136 }
137 
MXC_LP_SysRam1Shutdown(void)138 void MXC_LP_SysRam1Shutdown(void)
139 {
140     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM1SD;
141 }
142 
MXC_LP_SysRam1PowerUp(void)143 void MXC_LP_SysRam1PowerUp(void)
144 {
145     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM1SD;
146 }
147 
MXC_LP_SysRam2Shutdown(void)148 void MXC_LP_SysRam2Shutdown(void)
149 {
150     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM2SD;
151 }
152 
MXC_LP_SysRam2PowerUp(void)153 void MXC_LP_SysRam2PowerUp(void)
154 {
155     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM2SD;
156 }
157 
MXC_LP_SysRam3Shutdown(void)158 void MXC_LP_SysRam3Shutdown(void)
159 {
160     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM3SD;
161 }
162 
MXC_LP_SysRam3PowerUp(void)163 void MXC_LP_SysRam3PowerUp(void)
164 {
165     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM3SD;
166 }
167 
MXC_LP_SysRam4Shutdown(void)168 void MXC_LP_SysRam4Shutdown(void)
169 {
170     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM4SD;
171 }
172 
MXC_LP_SysRam4PowerUp(void)173 void MXC_LP_SysRam4PowerUp(void)
174 {
175     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM4SD;
176 }
177 
MXC_LP_SysRam5Shutdown(void)178 void MXC_LP_SysRam5Shutdown(void)
179 {
180     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRAM5SD;
181 }
182 
MXC_LP_SysRam5PowerUp(void)183 void MXC_LP_SysRam5PowerUp(void)
184 {
185     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRAM5SD;
186 }
187 
MXC_LP_ICache0Shutdown(void)188 void MXC_LP_ICache0Shutdown(void)
189 {
190     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_ICACHESD;
191 }
192 
MXC_LP_ICache0PowerUp(void)193 void MXC_LP_ICache0PowerUp(void)
194 {
195     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_ICACHESD;
196 }
197 
MXC_LP_ICacheXIPShutdown(void)198 void MXC_LP_ICacheXIPShutdown(void)
199 {
200     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_ICACHEXIPSD;
201 }
202 
MXC_LP_ICacheXIPPowerUp(void)203 void MXC_LP_ICacheXIPPowerUp(void)
204 {
205     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_ICACHEXIPSD;
206 }
207 
MXC_LP_CryptoShutdown(void)208 void MXC_LP_CryptoShutdown(void)
209 {
210     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_CRYPTOSD;
211 }
212 
MXC_LP_CryptoPowerUp(void)213 void MXC_LP_CryptoPowerUp(void)
214 {
215     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_CRYPTOSD;
216 }
217 
MXC_LP_USBFIFOShutdown(void)218 void MXC_LP_USBFIFOShutdown(void)
219 {
220     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_USBFIFOSD;
221 }
222 
MXC_LP_USBFIFOPowerUp(void)223 void MXC_LP_USBFIFOPowerUp(void)
224 {
225     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_USBFIFOSD;
226 }
227 
MXC_LP_ROM0Shutdown(void)228 void MXC_LP_ROM0Shutdown(void)
229 {
230     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_ROMSD;
231 }
232 
MXC_LP_ROM0PowerUp(void)233 void MXC_LP_ROM0PowerUp(void)
234 {
235     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_ROMSD;
236 }
237 
MXC_LP_ROM1Shutdown(void)238 void MXC_LP_ROM1Shutdown(void)
239 {
240     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_ROM1SD;
241 }
242 
MXC_LP_ROM1PowerUp(void)243 void MXC_LP_ROM1PowerUp(void)
244 {
245     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_ROM1SD;
246 }
247 
MXC_LP_ICache1Shutdown(void)248 void MXC_LP_ICache1Shutdown(void)
249 {
250     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_IC1SD;
251 }
252 
MXC_LP_ICache1PowerUp(void)253 void MXC_LP_ICache1PowerUp(void)
254 {
255     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_IC1SD;
256 }
257 
MXC_LP_USBSWLPDisable(void)258 void MXC_LP_USBSWLPDisable(void)
259 {
260     MXC_MCR->ctrl |= MXC_F_MCR_CTRL_USBSWEN_N;
261 }
262 
MXC_LP_USBSWLPEnable(void)263 void MXC_LP_USBSWLPEnable(void)
264 {
265     MXC_MCR->ctrl &= ~MXC_F_MCR_CTRL_USBSWEN_N;
266 }
267 
MXC_LP_VDD2PowerDown(void)268 void MXC_LP_VDD2PowerDown(void)
269 {
270     MXC_PWRSEQ->lpvddpd |= MXC_F_PWRSEQ_LPVDDPD_VDD2PD;
271 }
272 
MXC_LP_VDD2PowerUp(void)273 void MXC_LP_VDD2PowerUp(void)
274 {
275     MXC_PWRSEQ->lpvddpd &= ~MXC_F_PWRSEQ_LPVDDPD_VDD2PD;
276 }
277 
MXC_LP_VDD3PowerDown(void)278 void MXC_LP_VDD3PowerDown(void)
279 {
280     MXC_PWRSEQ->lpvddpd |= MXC_F_PWRSEQ_LPVDDPD_VDD3PD;
281 }
282 
MXC_LP_VDD3PowerUp(void)283 void MXC_LP_VDD3PowerUp(void)
284 {
285     MXC_PWRSEQ->lpvddpd &= ~MXC_F_PWRSEQ_LPVDDPD_VDD3PD;
286 }
287 
MXC_LP_VDD4PowerDown(void)288 void MXC_LP_VDD4PowerDown(void)
289 {
290     MXC_PWRSEQ->lpvddpd |= MXC_F_PWRSEQ_LPVDDPD_VDD4PD;
291 }
292 
MXC_LP_VDD4PowerUp(void)293 void MXC_LP_VDD4PowerUp(void)
294 {
295     MXC_PWRSEQ->lpvddpd &= ~MXC_F_PWRSEQ_LPVDDPD_VDD4PD;
296 }
297 
MXC_LP_VDD5PowerDown(void)298 void MXC_LP_VDD5PowerDown(void)
299 {
300     MXC_PWRSEQ->lpvddpd |= MXC_F_PWRSEQ_LPVDDPD_VDD5PD;
301 }
302 
MXC_LP_VDD5PowerUp(void)303 void MXC_LP_VDD5PowerUp(void)
304 {
305     MXC_PWRSEQ->lpvddpd &= ~MXC_F_PWRSEQ_LPVDDPD_VDD5PD;
306 }
307 
MXC_LP_SIMOVregBPowerDown(void)308 void MXC_LP_SIMOVregBPowerDown(void)
309 {
310     MXC_PWRSEQ->lpvddpd |= MXC_F_PWRSEQ_LPVDDPD_VREGOBPD;
311 }
312 
MXC_LP_SIMOVregBPowerUp(void)313 void MXC_LP_SIMOVregBPowerUp(void)
314 {
315     MXC_PWRSEQ->lpvddpd &= ~MXC_F_PWRSEQ_LPVDDPD_VREGOBPD;
316 }
317 
MXC_LP_SIMOVregDPowerDown(void)318 void MXC_LP_SIMOVregDPowerDown(void)
319 {
320     MXC_PWRSEQ->lpvddpd |= MXC_F_PWRSEQ_LPVDDPD_VREGODPD;
321 }
322 
MXC_LP_SIMOVregDPowerUp(void)323 void MXC_LP_SIMOVregDPowerUp(void)
324 {
325     MXC_PWRSEQ->lpvddpd &= ~MXC_F_PWRSEQ_LPVDDPD_VREGODPD;
326 }
327 
MXC_LP_FastWakeupEnable(void)328 void __attribute__((deprecated("Causes SIMO soft start in wakeup"))) MXC_LP_FastWakeupEnable(void)
329 {
330     // Deprecated due to issues with SIMO in wakeup.
331     // MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_FWKM;
332 }
333 
MXC_LP_FastWakeupDisable(void)334 void MXC_LP_FastWakeupDisable(void)
335 {
336     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_FWKM;
337 }
338 
MXC_LP_SetRAMRetention(mxc_ram_retained_t ramRetained)339 void MXC_LP_SetRAMRetention(mxc_ram_retained_t ramRetained)
340 {
341     MXC_SETFIELD(MXC_PWRSEQ->lpcn, MXC_F_PWRSEQ_LPCN_RAMRET, ramRetained);
342 }
343 
MXC_LP_EnterSleepMode(void)344 void MXC_LP_EnterSleepMode(void)
345 {
346     MXC_LP_ClearWakeStatus();
347 
348     /* Clear SLEEPDEEP bit */
349     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
350 
351     /* Go into Sleep mode and wait for an interrupt to wake the processor */
352     __WFI();
353 }
354 
MXC_LP_EnterBackgroundMode(void)355 void MXC_LP_EnterBackgroundMode(void)
356 {
357     MXC_LP_ClearWakeStatus();
358 
359     /* Set BACKGROUND bit and SLEEPDEEP bit */
360     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BCKGRND;
361     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
362 
363     /* Go into Background mode and wait for an interrupt to wake the processor */
364     __WFI();
365 }
366 
MXC_LP_EnterShutDownMode(void)367 void MXC_LP_EnterShutDownMode(void)
368 {
369     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
370     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_SHUTDOWN;
371     while (1) {}
372     // Should never reach this line - device will reset on exit from shutdown mode.
373 }
374 
375 /*------------------------------------------------------------------------------------------------------------------------------------------------------*/
376 
MXC_LP_BandgapOn(void)377 void MXC_LP_BandgapOn(void)
378 {
379     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_BGOFF;
380 }
381 
MXC_LP_BandgapOff(void)382 void MXC_LP_BandgapOff(void)
383 {
384     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BGOFF;
385 }
386 
MXC_LP_BandgapIsOn(void)387 int MXC_LP_BandgapIsOn(void)
388 {
389     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_BGOFF);
390 }
391 
MXC_LP_EnableUSBWakeup(void)392 void MXC_LP_EnableUSBWakeup(void)
393 {
394     MXC_MCR->ctrl &= ~MXC_F_MCR_CTRL_USBSWEN_N;
395     MXC_PWRSEQ->lppwen |= (MXC_F_PWRSEQ_LPPWEN_USBVBUSWKEN | MXC_F_PWRSEQ_LPPWEN_USBLSWKEN);
396 }
397 
MXC_LP_DisableUSBWakeup(void)398 void MXC_LP_DisableUSBWakeup(void)
399 {
400     MXC_MCR->ctrl |= MXC_F_MCR_CTRL_USBSWEN_N;
401     MXC_PWRSEQ->lppwen &= ~(MXC_F_PWRSEQ_LPPWEN_USBVBUSWKEN | MXC_F_PWRSEQ_LPPWEN_USBLSWKEN);
402 }
403 
MXC_LP_FastWakeupIsEnabled(void)404 int MXC_LP_FastWakeupIsEnabled(void)
405 {
406     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_FWKM);
407 }
408 
MXC_LP_ConfigDeepSleepClocks(uint32_t mask)409 int MXC_LP_ConfigDeepSleepClocks(uint32_t mask)
410 {
411     if (!(mask & (MXC_F_GCR_PM_HIRCPD | MXC_F_GCR_PM_HIRC96MPD | MXC_F_GCR_PM_HIRC8MPD |
412                   MXC_F_GCR_PM_XTALPB))) {
413         return E_BAD_PARAM;
414     }
415 
416     MXC_GCR->pm |= mask;
417     return E_NO_ERROR;
418 }
419 
MXC_LP_ICache0LightSleepDisable(void)420 void MXC_LP_ICache0LightSleepDisable(void)
421 {
422     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_ICACHELS;
423 }
424 
MXC_LP_ICache1LightSleepDisable(void)425 void MXC_LP_ICache1LightSleepDisable(void)
426 {
427     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_ICACHE1LS;
428 }
429 
MXC_LP_ICacheXIPLightSleepDisable(void)430 void MXC_LP_ICacheXIPLightSleepDisable(void)
431 {
432     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_ICACHEXIPLS;
433 }
434 
MXC_LP_SRCCLightSleepEnable(void)435 void MXC_LP_SRCCLightSleepEnable(void)
436 {
437     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_SCACHELS;
438 }
439 
MXC_LP_CryptoLightSleepEnable(void)440 void MXC_LP_CryptoLightSleepEnable(void)
441 {
442     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_CRYPTOLS;
443 }
444 
MXC_LP_USBFIFOLightSleepEnable(void)445 void MXC_LP_USBFIFOLightSleepEnable(void)
446 {
447     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_USBLS;
448 }
449 
MXC_LP_ROM0LightSleepEnable(void)450 void MXC_LP_ROM0LightSleepEnable(void)
451 {
452     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_ROM0LS;
453 }
454 
MXC_LP_ROM1LightSleepEnable(void)455 void MXC_LP_ROM1LightSleepEnable(void)
456 {
457     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_ROM1LS;
458 }
459 
MXC_LP_SysRam0LightSleepDisable(void)460 void MXC_LP_SysRam0LightSleepDisable(void)
461 {
462     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SYSRAM0LS;
463 }
464 
MXC_LP_SysRam1LightSleepDisable(void)465 void MXC_LP_SysRam1LightSleepDisable(void)
466 {
467     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SYSRAM1LS;
468 }
469 
MXC_LP_SysRam2LightSleepDisable(void)470 void MXC_LP_SysRam2LightSleepDisable(void)
471 {
472     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SYSRAM2LS;
473 }
474 
MXC_LP_SysRam3LightSleepDisable(void)475 void MXC_LP_SysRam3LightSleepDisable(void)
476 {
477     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SYSRAM3LS;
478 }
479 
MXC_LP_SysRam4LightSleepDisable(void)480 void MXC_LP_SysRam4LightSleepDisable(void)
481 {
482     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SYSRAM4LS;
483 }
484 
MXC_LP_SysRam5LightSleepDisable(void)485 void MXC_LP_SysRam5LightSleepDisable(void)
486 {
487     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SYSRAM5LS;
488 }
489 
MXC_LP_SRCCLightSleepDisable(void)490 void MXC_LP_SRCCLightSleepDisable(void)
491 {
492     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_SCACHELS;
493 }
494 
MXC_LP_CryptoLightSleepDisable(void)495 void MXC_LP_CryptoLightSleepDisable(void)
496 {
497     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_CRYPTOLS;
498 }
499 
MXC_LP_USBFIFOLightSleepDisable(void)500 void MXC_LP_USBFIFOLightSleepDisable(void)
501 {
502     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_USBLS;
503 }
504 
MXC_LP_ROM0LightSleepDisable(void)505 void MXC_LP_ROM0LightSleepDisable(void)
506 {
507     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_ROM0LS;
508 }
509 
MXC_LP_ROM1LightSleepDisable(void)510 void MXC_LP_ROM1LightSleepDisable(void)
511 {
512     MXC_GCR->memckcn &= ~MXC_F_GCR_MEMCKCN_ROM1LS;
513 }
514 
MXC_LP_SRCCShutdown(void)515 void MXC_LP_SRCCShutdown(void)
516 {
517     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_SRCCSD;
518 }
519 
MXC_LP_SRCCPowerUp(void)520 void MXC_LP_SRCCPowerUp(void)
521 {
522     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_SRCCSD;
523 }
524 
MXC_LP_ICache0LightSleepEnable(void)525 void MXC_LP_ICache0LightSleepEnable(void)
526 {
527     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_ICACHELS;
528 }
529 
MXC_LP_ICache1LightSleepEnable(void)530 void MXC_LP_ICache1LightSleepEnable(void)
531 {
532     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_ICACHE1LS;
533 }
534 
MXC_LP_ICacheXIPLightSleepEnable(void)535 void MXC_LP_ICacheXIPLightSleepEnable(void)
536 {
537     MXC_GCR->memckcn |= MXC_F_GCR_MEMCKCN_ICACHEXIPLS;
538 }
539 
540 /*
541  *  Switch the system clock to the HIRC / 4
542  *
543  *  Enable the HIRC, set the divide ration to /4, and disable the 96 MHz oscillator.
544  */
switchToHIRCD4(void)545 static void switchToHIRCD4(void)
546 {
547     MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_PSC, MXC_S_GCR_CLKCN_PSC_DIV4);
548     MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC_EN;
549     MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, MXC_S_GCR_CLKCN_CLKSEL_HIRC);
550     /* Disable unused clocks */
551     while (!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CKRDY)) {}
552     /* Wait for the switch to occur */
553     MXC_GCR->clkcn &= ~(MXC_F_GCR_CLKCN_HIRC96M_EN);
554     SystemCoreClockUpdate();
555 }
556 
save_preDeepSleep_state(void)557 static void save_preDeepSleep_state(void)
558 {
559     /* Save ICC state */
560     icc0_state = 0;
561     if (MXC_ICC0->cache_ctrl & MXC_F_ICC_CACHE_CTRL_EN)
562         icc0_state |= (1 << CTRL_POS);
563     if (MXC_PWRSEQ->lpmemsd & MXC_F_PWRSEQ_LPMEMSD_ICACHESD)
564         icc0_state |= (1 << ICSD_POS);
565     icc1_state = 0;
566     if (MXC_ICC1->cache_ctrl & MXC_F_ICC_CACHE_CTRL_EN)
567         icc1_state |= (1 << CTRL_POS);
568     if (MXC_PWRSEQ->lpmemsd & MXC_F_PWRSEQ_LPMEMSD_IC1SD)
569         icc1_state |= (1 << ICSD_POS);
570 
571     /* Save CLKCN state */
572     clkcn_state = MXC_GCR->clkcn;
573 }
574 
restore_preDeepSleep_state(void)575 static void restore_preDeepSleep_state(void)
576 {
577     /* Restore CLKCN state */
578     MXC_GCR->clkcn = clkcn_state;
579     /* Wait for the switch to occur */
580     while (!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CKRDY)) {}
581     SystemCoreClockUpdate();
582 
583     /* Restore ICC1 state */
584     if (icc1_state & (1 << ICSD_POS)) {
585         /* ICC power down. Do not restore Enable state. */
586         MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_IC1SD;
587     } else {
588         /* ICC power up */
589         MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_IC1SD;
590         /* Enable */
591         if (icc1_state & (1 << CTRL_POS))
592             MXC_ICC_RevA_Enable((mxc_icc_reva_regs_t *)MXC_ICC1);
593     }
594 
595     /* Restore ICC0 state */
596     if (icc0_state & (1 << ICSD_POS)) {
597         /* ICC power down. Do not restore Enable state. */
598         MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_ICACHESD;
599     } else {
600         /* ICC power up */
601         MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_ICACHESD;
602         /* Enable */
603         if (icc0_state & (1 << CTRL_POS))
604             MXC_ICC_RevA_Enable((mxc_icc_reva_regs_t *)MXC_ICC0);
605     }
606 }
607 
MXC_LP_EnterDeepSleepMode(void)608 void MXC_LP_EnterDeepSleepMode(void)
609 {
610     save_preDeepSleep_state();
611 
612     MXC_ICC_Disable();
613     MXC_LP_ICache0Shutdown();
614 
615     /* Shutdown unused power domains */
616     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BGOFF;
617 
618     switchToHIRCD4();
619 
620     /* Prevent SIMO soft start on wakeup */
621     /* Set SIMO clock, VDDCSW, VregO_B voltage for DeepSleep */
622     MXC_LP_FastWakeupDisable();
623 
624     /* Enable VDDCSWEN=1 prior to enter DEEPSLEEP */
625     MXC_MCR->ctrl |= MXC_F_MCR_CTRL_VDDCSWEN;
626 
627     /* SIMO clock setup for deep sleep */
628     *(volatile int *)0x40005434 = 1; /* SIMOCLKDIV [1:0] : 0=div1; 1=div8; 2=div1 3=div16 */
629     /* BUCK_CLKSEL [25:24] : 0=8K; 1=16K; 2=30K; 3=RFU */
630     *(volatile int *)0x40005440 = (*(volatile int *)0x40005440 & (~(0x3 << 24))) | (0x2 << 24);
631     /* BUCK_CLKSEL_LP [7:6] : 0=8K; 1=16K; 2=30K; 3=RFU */
632     *(volatile int *)0x40005444 = (*(volatile int *)0x40005444 & (~(0x3 << 6))) | (0x2 << 6);
633 
634     /* Wait for VCOREB to be ready */
635     while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYB)) {}
636 
637     /* Lower VregB to reduce power consumption */
638     MXC_SIMO_SetVregO_B(900);
639 
640     /* Move VCORE switch to VCOREB (< VCOREA) */
641     MXC_MCR->ctrl = (MXC_MCR->ctrl & ~(MXC_F_MCR_CTRL_VDDCSW)) | (0x2 << MXC_F_MCR_CTRL_VDDCSW_POS);
642 
643     /* Wait for VCOREA ready.  Should be ready already */
644     while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYC)) {}
645 
646     MXC_LP_ClearWakeStatus();
647 
648     /* Set SLEEPDEEP bit */
649     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_BCKGRND;
650     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
651 
652     /* Go into Deepsleep mode and wait for an interrupt to wake the processor */
653     __WFI();
654 
655     /* SIMO soft start workaround on wakeup */
656     /* Check to see if VCOREA is ready on  */
657     if (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYC)) {
658         /* Wait for VCOREB to be ready */
659         while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYB)) {}
660 
661         /* Move VCORE switch back to VCOREB */
662         MXC_MCR->ctrl = (MXC_MCR->ctrl & ~(MXC_F_MCR_CTRL_VDDCSW)) |
663                         (0x1 << MXC_F_MCR_CTRL_VDDCSW_POS);
664 
665         /* Raise the VCORE_B voltage */
666         while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYB)) {}
667         MXC_SIMO_SetVregO_B(1000);
668         while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYB)) {}
669     } else {
670         if ((MXC_MCR->ctrl & MXC_F_MCR_CTRL_VDDCSW) == (1 << MXC_F_MCR_CTRL_VDDCSW_POS)) {
671             /* Raise the VCORE_B voltage */
672             while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYB)) {}
673             MXC_SIMO_SetVregO_B(1000);
674             while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYB)) {}
675         }
676     }
677     restore_preDeepSleep_state();
678 }
679 
MXC_LP_EnterBackupMode(void * func (void))680 void MXC_LP_EnterBackupMode(void *func(void))
681 {
682     MXC_ICC_Disable();
683     MXC_LP_ICache0Shutdown();
684 
685     /* Shutdown unused power domains */
686     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BGOFF;
687 
688     switchToHIRCD4();
689 
690     /* No RAM retention in BACKUP */
691     MXC_LP_SetRAMRetention(MXC_S_PWRSEQ_LPCN_RAMRET_DIS);
692 
693     /* Disable VregB, VregD in BACKUP */
694     MXC_LP_SIMOVregBPowerDown();
695     MXC_LP_SIMOVregDPowerDown();
696 
697     /* Set SIMO clock, VDDCSW, VregO_C voltage for Backup */
698     /* Prevent SIMO soft start on wakeup */
699     MXC_LP_FastWakeupDisable();
700 
701     /* Enable VDDCSWEN=1 prior to enter BACKUP */
702     MXC_MCR->ctrl |= MXC_F_MCR_CTRL_VDDCSWEN;
703 
704     /* SIMO softstart workaround: clock 8KHz/16 for BACKUP, 30KHz/1 in ACTIVE */
705     *(volatile int *)0x40005434 = 3; /* SIMOCLKDIV [1:0] : 0=div1; 1=div8; 2=div1 3=div16 */
706     /* BUCK_CLKSEL [25:24] : 0=8K; 1=16K; 2=30K; 3=RFU */
707     *(volatile int *)0x40005440 = (*(volatile int *)0x40005440 & (~(0x3 << 24))) | (0x2 << 24);
708     /* BUCK_CLKSEL_LP [7:6] : 0=8K; 1=16K; 2=30K; 3=RFU */
709     *(volatile int *)0x40005444 = (*(volatile int *)0x40005444 & (~(0x3 << 6))) | (0x0 << 6);
710 
711     /* Move VCORE switch to VCOREB (< VCOREA) */
712     MXC_MCR->ctrl = (MXC_MCR->ctrl & ~(MXC_F_MCR_CTRL_VDDCSW)) | (0x2 << MXC_F_MCR_CTRL_VDDCSW_POS);
713 
714     /* Lower VCOREA to save power */
715     MXC_SIMO_SetVregO_C(850);
716 
717     /* Wait for VCOREA ready. */
718     while (!(MXC_SIMO->buck_out_ready & MXC_F_SIMO_BUCK_OUT_READY_BUCKOUTRDYC)) {}
719 
720     MXC_LP_ClearWakeStatus();
721 
722     MXC_PWRSEQ->buretvec = (uint32_t)(&Backup_Handler) | 1;
723     if (func == NULL) {
724         MXC_PWRSEQ->buaod = (uint32_t)(&Reset_Handler) | 1;
725     } else {
726         MXC_PWRSEQ->buaod = (uint32_t)(&func) | 1;
727     }
728 
729     // Enable the VDDCSW to ensure we have enough power to start
730     MXC_MCR->ctrl |= MXC_F_MCR_CTRL_VDDCSWEN;
731 
732     // Enable backup mode
733     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
734     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
735     while (1) {}
736     // Should never reach this line - device will jump to backup vector on exit from background mode.
737 }
738