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