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_sys.h"
24 #include "gcr_regs.h"
25 #include "lp.h"
26 
MXC_LP_EnterSleepMode(void)27 void MXC_LP_EnterSleepMode(void)
28 {
29     MXC_LP_ClearWakeStatus();
30 
31     // set block detect bit
32     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
33 
34     // Clear SLEEPDEEP bit
35     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
36 
37     // Go into Sleep mode and wait for an interrupt to wake the processor
38     __WFI();
39 }
40 
MXC_LP_EnterDeepSleepMode(void)41 void MXC_LP_EnterDeepSleepMode(void)
42 {
43     MXC_LP_ClearWakeStatus();
44 
45     // set block detect bit
46     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
47 
48     // Set SLEEPDEEP bit
49     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
50 
51     // Go into Deepsleep mode and wait for an interrupt to wake the processor
52     __WFI();
53 }
54 
MXC_LP_EnterBackupMode(void)55 void MXC_LP_EnterBackupMode(void)
56 {
57     MXC_LP_ClearWakeStatus();
58 
59     // set block detect bit
60     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
61 
62     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
63     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
64 
65     while (1) {}
66     // Should never reach this line - device will jump to backup vector on exit from background mode.
67 }
68 
MXC_LP_EnterStorageMode(void)69 void MXC_LP_EnterStorageMode(void)
70 {
71     MXC_LP_ClearWakeStatus();
72     /*set block detect bit */
73     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCORE_DET_BYPASS;
74 
75     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_STORAGE_EN;
76     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
77     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
78 
79     while (1) {}
80     // Should never reach this line - device will jump to backup vector on exit from background mode.
81 }
82 
MXC_LP_EnterShutDownMode(void)83 void MXC_LP_EnterShutDownMode(void)
84 {
85     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
86     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_SHUTDOWN;
87 
88     while (1) {}
89     // Should never reach this line - device will reset on exit from shutdown mode.
90 }
91 
MXC_LP_SetOVR(mxc_lp_ovr_t ovr)92 void MXC_LP_SetOVR(mxc_lp_ovr_t ovr)
93 {
94     //not supported yet
95 }
96 
MXC_LP_RetentionRegEnable(void)97 void MXC_LP_RetentionRegEnable(void)
98 {
99     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_RETREG_EN;
100 }
101 
MXC_LP_RetentionRegDisable(void)102 void MXC_LP_RetentionRegDisable(void)
103 {
104     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_RETREG_EN;
105 }
106 
MXC_LP_RetentionRegIsEnabled(void)107 int MXC_LP_RetentionRegIsEnabled(void)
108 {
109     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_RETREG_EN);
110 }
111 
MXC_LP_BandgapOn(void)112 void MXC_LP_BandgapOn(void)
113 {
114     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_BG_DIS;
115 }
116 
MXC_LP_BandgapOff(void)117 void MXC_LP_BandgapOff(void)
118 {
119     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BG_DIS;
120 }
121 
MXC_LP_BandgapIsOn(void)122 int MXC_LP_BandgapIsOn(void)
123 {
124     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_BG_DIS);
125 }
126 
MXC_LP_PORVCOREoreMonitorEnable(void)127 void MXC_LP_PORVCOREoreMonitorEnable(void)
128 {
129     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_VCOREPOR_DIS;
130 }
131 
MXC_LP_PORVCOREoreMonitorDisable(void)132 void MXC_LP_PORVCOREoreMonitorDisable(void)
133 {
134     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_VCOREPOR_DIS;
135 }
136 
MXC_LP_PORVCOREoreMonitorIsEnabled(void)137 int MXC_LP_PORVCOREoreMonitorIsEnabled(void)
138 {
139     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_VCOREPOR_DIS);
140 }
141 
MXC_LP_LDOEnable(void)142 void MXC_LP_LDOEnable(void)
143 {
144     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_LDO_DIS;
145 }
146 
MXC_LP_LDODisable(void)147 void MXC_LP_LDODisable(void)
148 {
149     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_LDO_DIS;
150 }
151 
MXC_LP_LDOIsEnabled(void)152 int MXC_LP_LDOIsEnabled(void)
153 {
154     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_LDO_DIS);
155 }
156 
MXC_LP_FastWakeupEnable(void)157 void MXC_LP_FastWakeupEnable(void)
158 {
159     MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_FASTWK_EN;
160 }
161 
MXC_LP_FastWakeupDisable(void)162 void MXC_LP_FastWakeupDisable(void)
163 {
164     MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_FASTWK_EN;
165 }
166 
MXC_LP_FastWakeupIsEnabled(void)167 int MXC_LP_FastWakeupIsEnabled(void)
168 {
169     return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_FASTWK_EN);
170 }
171 
MXC_LP_ClearWakeStatus(void)172 void MXC_LP_ClearWakeStatus(void)
173 {
174     // Write 1 to clear
175     MXC_PWRSEQ->lpwkst0 = 0xFFFFFFFF;
176     MXC_PWRSEQ->lpwkst1 = 0xFFFFFFFF;
177     MXC_PWRSEQ->lppwkst = 0xFFFFFFFF;
178 }
179 
MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)180 void MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t *wu_pins)
181 {
182     MXC_GCR->pm |= MXC_F_GCR_PM_GPIO_WE;
183 
184     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
185     case MXC_GPIO_PORT_0:
186         MXC_PWRSEQ->lpwken0 |= wu_pins->mask;
187         break;
188 
189     case MXC_GPIO_PORT_1:
190         MXC_PWRSEQ->lpwken1 |= wu_pins->mask;
191     }
192 }
193 
MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)194 void MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t *wu_pins)
195 {
196     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
197     case MXC_GPIO_PORT_0:
198         MXC_PWRSEQ->lpwken0 &= ~wu_pins->mask;
199         break;
200 
201     case MXC_GPIO_PORT_1:
202         MXC_PWRSEQ->lpwken1 &= ~wu_pins->mask;
203     }
204 
205     if (MXC_PWRSEQ->lpwken1 == 0 && MXC_PWRSEQ->lpwken0 == 0) {
206         MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIO_WE;
207     }
208 }
209 
MXC_LP_EnableRTCAlarmWakeup(void)210 void MXC_LP_EnableRTCAlarmWakeup(void)
211 {
212     MXC_GCR->pm |= MXC_F_GCR_PM_RTC_WE;
213 }
214 
MXC_LP_DisableRTCAlarmWakeup(void)215 void MXC_LP_DisableRTCAlarmWakeup(void)
216 {
217     MXC_GCR->pm &= ~MXC_F_GCR_PM_RTC_WE;
218 }
219 
MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t * tmr)220 void MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t *tmr)
221 {
222     MXC_ASSERT(MXC_TMR_GET_IDX(tmr) > 3);
223 
224     if (tmr == MXC_TMR4) {
225         MXC_PWRSEQ->lppwken |= MXC_F_PWRSEQ_LPPWKEN_LPTMR0;
226     } else {
227         MXC_PWRSEQ->lppwken |= MXC_F_PWRSEQ_LPPWKEN_LPTMR1;
228     }
229 }
230 
MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t * tmr)231 void MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t *tmr)
232 {
233     MXC_ASSERT(MXC_TMR_GET_IDX(tmr) > 3);
234 
235     if (tmr == MXC_TMR4) {
236         MXC_PWRSEQ->lppwken &= ~MXC_F_PWRSEQ_LPPWKEN_LPTMR0;
237     } else {
238         MXC_PWRSEQ->lppwken &= ~MXC_F_PWRSEQ_LPPWKEN_LPTMR1;
239     }
240 }
241 
MXC_LP_ConfigDeepSleepClocks(uint32_t mask)242 int MXC_LP_ConfigDeepSleepClocks(uint32_t mask)
243 {
244     if (!(mask & (MXC_F_GCR_PM_IBRO_PD | MXC_F_GCR_PM_IPO_PD | MXC_F_GCR_PM_ERFO_PD))) {
245         return E_BAD_PARAM;
246     }
247 
248     MXC_GCR->pm |= mask;
249     return E_NO_ERROR;
250 }
251 
MXC_LP_SysRam0LightSleepEnable(void)252 void MXC_LP_SysRam0LightSleepEnable(void)
253 {
254     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM0LS_EN;
255 }
256 
MXC_LP_SysRam1LightSleepEnable(void)257 void MXC_LP_SysRam1LightSleepEnable(void)
258 {
259     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM1LS_EN;
260 }
261 
MXC_LP_SysRam2LightSleepEnable(void)262 void MXC_LP_SysRam2LightSleepEnable(void)
263 {
264     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM2LS_EN;
265 }
266 
MXC_LP_SysRam3LightSleepEnable(void)267 void MXC_LP_SysRam3LightSleepEnable(void)
268 {
269     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM3LS_EN;
270 }
271 
MXC_LP_ROMLightSleepEnable(void)272 void MXC_LP_ROMLightSleepEnable(void)
273 {
274     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_ROMLS_EN;
275 }
276 
MXC_LP_SysRam0LightSleepDisable(void)277 void MXC_LP_SysRam0LightSleepDisable(void)
278 {
279     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM0LS_EN;
280 }
281 
MXC_LP_SysRam1LightSleepDisable(void)282 void MXC_LP_SysRam1LightSleepDisable(void)
283 {
284     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM1LS_EN;
285 }
286 
MXC_LP_SysRam2LightSleepDisable(void)287 void MXC_LP_SysRam2LightSleepDisable(void)
288 {
289     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM2LS_EN;
290 }
291 
MXC_LP_SysRam3LightSleepDisable(void)292 void MXC_LP_SysRam3LightSleepDisable(void)
293 {
294     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM3LS_EN;
295 }
296 
MXC_LP_ROMLightSleepDisable(void)297 void MXC_LP_ROMLightSleepDisable(void)
298 {
299     MXC_GCR->memctrl &= ~MXC_F_GCR_MEMCTRL_RAM0LS_EN;
300 }
301 
MXC_LP_SysRam0Shutdown(void)302 void MXC_LP_SysRam0Shutdown(void)
303 {
304     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM0;
305 }
306 
MXC_LP_SysRam0PowerUp(void)307 void MXC_LP_SysRam0PowerUp(void)
308 {
309     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM0;
310 }
311 
MXC_LP_SysRam1Shutdown(void)312 void MXC_LP_SysRam1Shutdown(void)
313 {
314     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM1;
315 }
316 
MXC_LP_SysRam1PowerUp(void)317 void MXC_LP_SysRam1PowerUp(void)
318 {
319     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM1;
320 }
321 
MXC_LP_SysRam2Shutdown(void)322 void MXC_LP_SysRam2Shutdown(void)
323 {
324     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM2;
325 }
326 
MXC_LP_SysRam2PowerUp(void)327 void MXC_LP_SysRam2PowerUp(void)
328 {
329     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM2;
330 }
331 
MXC_LP_SysRam3Shutdown(void)332 void MXC_LP_SysRam3Shutdown(void)
333 {
334     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM3;
335 }
336 
MXC_LP_SysRam3PowerUp(void)337 void MXC_LP_SysRam3PowerUp(void)
338 {
339     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM3;
340 }
341