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 #include "mxc_device.h" 21 #include "mxc_assert.h" 22 #include "mxc_sys.h" 23 #include "gcr_regs.h" 24 #include "mcr_regs.h" 25 #include "lp.h" 26 #include "lpcmp.h" 27 28 #ifndef __riscv 29 /* ARM */ 30 #define SET_SLEEPDEEP(X) (SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk) 31 #define CLR_SLEEPDEEP(X) (SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk) 32 #else 33 /* RISCV */ 34 /* These bits do not exist for RISCV core */ 35 #define SET_SLEEPDEEP(X) 36 #define CLR_SLEEPDEEP(X) 37 #endif 38 MXC_LP_EnterSleepMode(void)39void MXC_LP_EnterSleepMode(void) 40 { 41 MXC_LP_ClearWakeStatus(); 42 43 /* Clear SLEEPDEEP bit */ 44 CLR_SLEEPDEEP(); 45 46 /* Go into Sleep mode and wait for an interrupt to wake the processor */ 47 __WFI(); 48 } 49 MXC_LP_EnterLowPowerMode(void)50void MXC_LP_EnterLowPowerMode(void) 51 { 52 MXC_LP_ClearWakeStatus(); 53 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_ERTCO_EN; // Enabled for deep sleep mode 54 55 /* Set SLEEPDEEP bit */ 56 SET_SLEEPDEEP(); 57 58 /* Go into low power mode and wait for an interrupt to wake the processor */ 59 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_LPM; 60 __WFI(); 61 } 62 MXC_LP_EnterMicroPowerMode(void)63void MXC_LP_EnterMicroPowerMode(void) 64 { 65 MXC_LP_ClearWakeStatus(); 66 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_ERTCO_EN; // Enabled for deep sleep mode 67 68 /* Set SLEEPDEEP bit */ 69 SET_SLEEPDEEP(); 70 71 /* Go into Deepsleep mode and wait for an interrupt to wake the processor */ 72 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_UPM; // UPM mode 73 __WFI(); 74 } 75 MXC_LP_EnterStandbyMode(void)76void MXC_LP_EnterStandbyMode(void) 77 { 78 MXC_LP_ClearWakeStatus(); 79 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_ERTCO_EN; // Enabled for deep sleep mode 80 81 /* Set SLEEPDEEP bit */ 82 SET_SLEEPDEEP(); 83 84 /* Go into standby mode and wait for an interrupt to wake the processor */ 85 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_STANDBY; // standby mode 86 __WFI(); 87 } 88 MXC_LP_EnterBackupMode(void)89void MXC_LP_EnterBackupMode(void) 90 { 91 MXC_LP_ClearWakeStatus(); 92 93 MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE; 94 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP; 95 96 while (1) {} 97 // Should never reach this line - device will jump to backup vector on exit from background mode. 98 } 99 MXC_LP_EnterPowerDownMode(void)100void MXC_LP_EnterPowerDownMode(void) 101 { 102 MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE; 103 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_POWERDOWN; 104 105 while (1) {} 106 // Should never reach this line - device will reset on exit from shutdown mode. 107 } 108 MXC_LP_SetOVR(mxc_lp_ovr_t ovr)109void MXC_LP_SetOVR(mxc_lp_ovr_t ovr) 110 { 111 //not supported yet 112 } 113 MXC_LP_BandgapOn(void)114void MXC_LP_BandgapOn(void) 115 { 116 MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_BG_DIS; 117 } 118 MXC_LP_BandgapOff(void)119void MXC_LP_BandgapOff(void) 120 { 121 MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BG_DIS; 122 } 123 MXC_LP_BandgapIsOn(void)124int MXC_LP_BandgapIsOn(void) 125 { 126 return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_BG_DIS); 127 } 128 MXC_LP_ClearWakeStatus(void)129void MXC_LP_ClearWakeStatus(void) 130 { 131 /* Write 1 to clear */ 132 MXC_PWRSEQ->lpwkst0 = 0xFFFFFFFF; 133 MXC_PWRSEQ->lpwkst1 = 0xFFFFFFFF; 134 MXC_PWRSEQ->lpwkst2 = 0xFFFFFFFF; 135 MXC_PWRSEQ->lpwkst3 = 0xFFFFFFFF; 136 MXC_PWRSEQ->lppwst = 0xFFFFFFFF; 137 } 138 MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)139void MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t *wu_pins) 140 { 141 MXC_GCR->pm |= MXC_F_GCR_PM_GPIO_WE; 142 143 switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) { 144 case MXC_GPIO_PORT_0: 145 MXC_PWRSEQ->lpwken0 |= wu_pins->mask; 146 break; 147 148 case MXC_GPIO_PORT_1: 149 MXC_PWRSEQ->lpwken1 |= wu_pins->mask; 150 break; 151 case MXC_GPIO_PORT_2: 152 MXC_PWRSEQ->lpwken2 |= wu_pins->mask; 153 break; 154 case MXC_GPIO_PORT_3: 155 MXC_PWRSEQ->lpwken3 |= wu_pins->mask; 156 break; 157 } 158 } 159 MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)160void MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t *wu_pins) 161 { 162 switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) { 163 case MXC_GPIO_PORT_0: 164 MXC_PWRSEQ->lpwken0 &= ~wu_pins->mask; 165 break; 166 167 case MXC_GPIO_PORT_1: 168 MXC_PWRSEQ->lpwken1 &= ~wu_pins->mask; 169 break; 170 case MXC_GPIO_PORT_2: 171 MXC_PWRSEQ->lpwken2 &= ~wu_pins->mask; 172 break; 173 case MXC_GPIO_PORT_3: 174 MXC_PWRSEQ->lpwken3 &= ~wu_pins->mask; 175 break; 176 } 177 178 if (MXC_PWRSEQ->lpwken3 == 0 && MXC_PWRSEQ->lpwken2 == 0 && MXC_PWRSEQ->lpwken1 == 0 && 179 MXC_PWRSEQ->lpwken0 == 0) { 180 MXC_GCR->pm &= ~MXC_F_GCR_PM_GPIO_WE; 181 } 182 } 183 MXC_LP_EnableRTCAlarmWakeup(void)184void MXC_LP_EnableRTCAlarmWakeup(void) 185 { 186 MXC_GCR->pm |= MXC_F_GCR_PM_RTC_WE; 187 } 188 MXC_LP_DisableRTCAlarmWakeup(void)189void MXC_LP_DisableRTCAlarmWakeup(void) 190 { 191 MXC_GCR->pm &= ~MXC_F_GCR_PM_RTC_WE; 192 } 193 MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t * tmr)194void MXC_LP_EnableTimerWakeup(mxc_tmr_regs_t *tmr) 195 { 196 MXC_ASSERT(MXC_TMR_GET_IDX(tmr) > 3); 197 198 if (tmr == MXC_TMR4) { 199 MXC_PWRSEQ->lppwen |= MXC_F_PWRSEQ_LPPWEN_TMR4; 200 } else { 201 MXC_PWRSEQ->lppwen |= MXC_F_PWRSEQ_LPPWEN_TMR5; 202 } 203 } 204 MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t * tmr)205void MXC_LP_DisableTimerWakeup(mxc_tmr_regs_t *tmr) 206 { 207 MXC_ASSERT(MXC_TMR_GET_IDX(tmr) > 3); 208 209 if (tmr == MXC_TMR4) { 210 MXC_PWRSEQ->lppwen &= ~MXC_F_PWRSEQ_LPPWEN_TMR4; 211 } else { 212 MXC_PWRSEQ->lppwen &= ~MXC_F_PWRSEQ_LPPWEN_TMR5; 213 } 214 } 215 MXC_LP_EnableWUTAlarmWakeup(void)216void MXC_LP_EnableWUTAlarmWakeup(void) 217 { 218 MXC_GCR->pm |= MXC_F_GCR_PM_WUT_WE; 219 } 220 MXC_LP_DisableWUTAlarmWakeup(void)221void MXC_LP_DisableWUTAlarmWakeup(void) 222 { 223 MXC_GCR->pm &= ~MXC_F_GCR_PM_WUT_WE; 224 } 225 MXC_LP_EnableLPCMPWakeup(mxc_lpcmp_cmpsel_t cmp)226void MXC_LP_EnableLPCMPWakeup(mxc_lpcmp_cmpsel_t cmp) 227 { 228 MXC_ASSERT((cmp >= MXC_LPCMP_CMP0) && (cmp <= MXC_LPCMP_CMP3)); 229 230 if (cmp == MXC_LPCMP_CMP0) { 231 MXC_PWRSEQ->lppwen |= MXC_F_PWRSEQ_LPPWEN_AINCOMP0; 232 } else { 233 MXC_PWRSEQ->lppwen |= MXC_F_PWRSEQ_LPPWEN_LPCMP; 234 } 235 } 236 MXC_LP_DisableLPCMPWakeup(mxc_lpcmp_cmpsel_t cmp)237void MXC_LP_DisableLPCMPWakeup(mxc_lpcmp_cmpsel_t cmp) 238 { 239 MXC_ASSERT((cmp >= MXC_LPCMP_CMP0) && (cmp <= MXC_LPCMP_CMP3)); 240 241 if (cmp == MXC_LPCMP_CMP0) { 242 MXC_PWRSEQ->lppwen &= ~MXC_F_PWRSEQ_LPPWEN_AINCOMP0; 243 } else { 244 MXC_PWRSEQ->lppwen &= ~MXC_F_PWRSEQ_LPPWEN_LPCMP; 245 } 246 } 247 MXC_LP_ConfigDeepSleepClocks(uint32_t mask)248int MXC_LP_ConfigDeepSleepClocks(uint32_t mask) 249 { 250 if (!(mask & (MXC_F_GCR_PM_IBRO_PD | MXC_F_GCR_PM_IPO_PD))) { 251 return E_BAD_PARAM; 252 } 253 254 MXC_GCR->pm |= mask; 255 return E_NO_ERROR; 256 } 257