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