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