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 "mcr_regs.h"
26 #include "lp.h"
27 
MXC_LP_EnterSleepMode(void)28 void MXC_LP_EnterSleepMode(void)
29 {
30     MXC_LP_ClearWakeStatus();
31 
32     /* Clear SLEEPDEEP bit */
33     SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
34 
35     /* Go into Sleep mode and wait for an interrupt to wake the processor */
36     __WFI();
37 }
38 
MXC_LP_EnterDeepSleepMode(void)39 void MXC_LP_EnterDeepSleepMode(void)
40 {
41     // Set SLEEPDEEP bit
42     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
43 
44     // // Auto-powerdown 96 MHz oscillator when in deep sleep
45     // MXC_GCR->pm |= MXC_F_GCR_PM_HFIOPD; // Not supported on ME12
46     // Go into Deepsleep mode and wait for an interrupt to wake the processor
47     __WFI();
48 }
49 
MXC_LP_EnterBackupMode(void)50 void MXC_LP_EnterBackupMode(void)
51 {
52     MXC_LP_ClearWakeStatus();
53 
54     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
55     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP;
56 
57     while (1) {}
58     // Should never reach this line - device will jump to backup vector on exit from background mode.
59 }
60 
MXC_LP_EnterShutDownMode(void)61 void MXC_LP_EnterShutDownMode(void)
62 {
63     MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE;
64     MXC_GCR->pm |= MXC_S_GCR_PM_MODE_SHUTDOWN;
65 
66     while (1) {}
67     // Should never reach this line - device will reset on exit from shutdown mode.
68 }
69 
MXC_LP_EnableSRAM3(void)70 void MXC_LP_EnableSRAM3(void)
71 {
72     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM3;
73 }
74 
MXC_LP_DisableSRAM3(void)75 void MXC_LP_DisableSRAM3(void)
76 {
77     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM3;
78 }
79 
MXC_LP_EnableSRAM2(void)80 void MXC_LP_EnableSRAM2(void)
81 {
82     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM2;
83 }
84 
MXC_LP_DisableSRAM2(void)85 void MXC_LP_DisableSRAM2(void)
86 {
87     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM2;
88 }
89 
MXC_LP_EnableSRAM1(void)90 void MXC_LP_EnableSRAM1(void)
91 {
92     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM1;
93 }
94 
MXC_LP_DisableSRAM1(void)95 void MXC_LP_DisableSRAM1(void)
96 {
97     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM1;
98 }
99 
MXC_LP_EnableSRAM0(void)100 void MXC_LP_EnableSRAM0(void)
101 {
102     MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM0;
103 }
104 
MXC_LP_DisableSRAM0(void)105 void MXC_LP_DisableSRAM0(void)
106 {
107     MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM0;
108 }
109 
MXC_LP_EnableSRAM(int instance)110 int MXC_LP_EnableSRAM(int instance)
111 {
112     if (instance == 0) {
113         MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM0;
114     } else if (instance == 1) {
115         MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM1;
116     } else if (instance == 2) {
117         MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM2;
118     } else if (instance == 3) {
119         MXC_PWRSEQ->lpmemsd &= ~MXC_F_PWRSEQ_LPMEMSD_RAM3;
120     } else {
121         return E_BAD_PARAM;
122     }
123 
124     return E_SUCCESS;
125 }
126 
MXC_LP_DisableSRAM(int instance)127 int MXC_LP_DisableSRAM(int instance)
128 {
129     if (instance == 0) {
130         MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM0;
131     } else if (instance == 1) {
132         MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM1;
133     } else if (instance == 2) {
134         MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM2;
135     } else if (instance == 3) {
136         MXC_PWRSEQ->lpmemsd |= MXC_F_PWRSEQ_LPMEMSD_RAM3;
137     } else {
138         return E_BAD_PARAM;
139     }
140 
141     return E_SUCCESS;
142 }
143 
MXC_LP_SetOVR(mxc_lp_ovr_t ovr)144 int MXC_LP_SetOVR(mxc_lp_ovr_t ovr)
145 {
146     return E_NOT_SUPPORTED;
147 }
148 
MXC_LP_BandgapOn(void)149 void MXC_LP_BandgapOn(void)
150 {
151     MXC_PWRSEQ->lpctrl &= ~MXC_F_PWRSEQ_LPCTRL_BG_DIS; // 0 = Bandgap is always ON
152 }
153 
MXC_LP_BandgapOff(void)154 void MXC_LP_BandgapOff(void)
155 {
156     MXC_PWRSEQ->lpctrl |= MXC_F_PWRSEQ_LPCTRL_BG_DIS; // 1 = Bandgap is always OFF.
157 }
158 
MXC_LP_BandgapIsOn(void)159 int MXC_LP_BandgapIsOn(void)
160 {
161     return ~(MXC_PWRSEQ->lpctrl & MXC_F_PWRSEQ_LPCTRL_BG_DIS); // Logic on Bandgap bit is inverted
162 }
163 
MXC_LP_ClearWakeStatus(void)164 void MXC_LP_ClearWakeStatus(void)
165 {
166     /* Write 1 to clear */
167     MXC_PWRSEQ->lpwkfl0 = 0xFFFFFFFF;
168     MXC_PWRSEQ->lppwkfl = 0xFFFFFFFF;
169 }
170 
MXC_LP_EnableGPIOWakeup(const mxc_gpio_cfg_t * wu_pins)171 void MXC_LP_EnableGPIOWakeup(const mxc_gpio_cfg_t *wu_pins)
172 {
173     MXC_GCR->pm |= MXC_F_GCR_PM_GPIO_WE;
174 
175     switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) {
176     case MXC_GPIO_PORT_0:
177         MXC_PWRSEQ->lpwken0 |= wu_pins->mask;
178         break;
179     }
180 }
181 
MXC_LP_DisableGPIOWakeup(const mxc_gpio_cfg_t * wu_pins)182 void MXC_LP_DisableGPIOWakeup(const mxc_gpio_cfg_t *wu_pins)
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 
190     if (MXC_PWRSEQ->lpwken0 == 0) {
191         MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIO_WE;
192     }
193 }
194 
MXC_LP_EnableRTCAlarmWakeup(void)195 void MXC_LP_EnableRTCAlarmWakeup(void)
196 {
197     MXC_GCR->pm |= MXC_F_GCR_PM_RTC_WE;
198 }
199 
MXC_LP_DisableRTCAlarmWakeup(void)200 void MXC_LP_DisableRTCAlarmWakeup(void)
201 {
202     MXC_GCR->pm &= ~MXC_F_GCR_PM_RTC_WE;
203 }
204 
MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t * tmr)205 void MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t *tmr)
206 {
207     if (tmr == MXC_TMR3) {
208         // MXC_TMR3 (LPTIMER0) is the only timer that supports WE
209         MXC_GCR->pm |= MXC_F_GCR_PM_TMR3_WE;
210     }
211 }
212 
MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t * tmr)213 void MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t *tmr)
214 {
215     if (tmr == MXC_TMR3) {
216         // MXC_TMR3 (LPTIMER0) is the only timer that supports WE
217         MXC_GCR->pm &= ~(MXC_F_GCR_PM_TMR3_WE);
218     }
219 }
220 
MXC_LP_EnableICacheLightSleep(void)221 void MXC_LP_EnableICacheLightSleep(void)
222 {
223     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_ICC0LS_EN;
224 }
225 
MXC_LP_DisableICacheLightSleep(void)226 void MXC_LP_DisableICacheLightSleep(void)
227 {
228     MXC_GCR->memctrl &= ~(MXC_F_GCR_MEMCTRL_ICC0LS_EN);
229 }
230 
MXC_LP_ROMLightSleepEnable(void)231 void MXC_LP_ROMLightSleepEnable(void)
232 {
233     MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_ROMLS_EN;
234 }
235 
MXC_LP_RomLightSleepDisable(void)236 void MXC_LP_RomLightSleepDisable(void)
237 {
238     MXC_GCR->memctrl &= ~(MXC_F_GCR_MEMCTRL_ROMLS_EN);
239 }
240 
MXC_LP_EnableSysRAMLightSleep(int instance)241 int MXC_LP_EnableSysRAMLightSleep(int instance)
242 {
243     if (instance == 0) {
244         MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM0LS_EN;
245     } else if (instance == 1) {
246         MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM1LS_EN;
247     } else if (instance == 2) {
248         MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM2LS_EN;
249     } else if (instance == 3) {
250         MXC_GCR->memctrl |= MXC_F_GCR_MEMCTRL_RAM3LS_EN;
251     } else {
252         return E_BAD_PARAM;
253     }
254 
255     return E_SUCCESS;
256 }
257 
MXC_LP_DisableSysRAMLightSleep(int instance)258 int MXC_LP_DisableSysRAMLightSleep(int instance)
259 {
260     if (instance == 0) {
261         MXC_GCR->memctrl &= ~(MXC_F_GCR_MEMCTRL_RAM0LS_EN);
262     } else if (instance == 1) {
263         MXC_GCR->memctrl &= ~(MXC_F_GCR_MEMCTRL_RAM1LS_EN);
264     } else if (instance == 2) {
265         MXC_GCR->memctrl &= ~(MXC_F_GCR_MEMCTRL_RAM2LS_EN);
266     } else if (instance == 3) {
267         MXC_GCR->memctrl &= ~(MXC_F_GCR_MEMCTRL_RAM1LS_EN);
268     } else {
269         return E_BAD_PARAM;
270     }
271 
272     return E_SUCCESS;
273 }
274