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 "lpcmp.h" 27 #include "lp.h" 28 MXC_LP_EnterSleepMode(void)29void MXC_LP_EnterSleepMode(void) 30 { 31 #ifndef __riscv 32 MXC_LP_ClearWakeStatus(); 33 34 /* Clear SLEEPDEEP bit on the Arm core*/ 35 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; 36 #endif 37 38 /* Go into Sleep mode and wait for an interrupt to wake the processor */ 39 __WFI(); 40 } 41 42 #ifndef __riscv MXC_LP_EnterLowPowerMode(void)43void MXC_LP_EnterLowPowerMode(void) 44 { 45 MXC_LP_ClearWakeStatus(); 46 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_ERTCO_EN; // Enabled for deep sleep mode 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 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_LPM; // LPM mode 53 __WFI(); 54 } 55 MXC_LP_EnterMicroPowerMode(void)56void MXC_LP_EnterMicroPowerMode(void) 57 { 58 MXC_LP_ClearWakeStatus(); 59 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_ERTCO_EN; // Enabled for deep sleep mode 60 61 /* Set SLEEPDEEP bit */ 62 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 63 64 /* Go into Deepsleep mode and wait for an interrupt to wake the processor */ 65 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_UPM; // UPM mode 66 __WFI(); 67 } 68 MXC_LP_EnterStandbyMode(void)69void MXC_LP_EnterStandbyMode(void) 70 { 71 MXC_LP_ClearWakeStatus(); 72 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_ERTCO_EN; // Enabled for deep sleep mode 73 74 /* Set SLEEPDEEP bit */ 75 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; 76 77 /* Go into standby mode and wait for an interrupt to wake the processor */ 78 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_STANDBY; // standby mode 79 __WFI(); 80 } 81 MXC_LP_EnterBackupMode(void)82void MXC_LP_EnterBackupMode(void) 83 { 84 MXC_LP_ClearWakeStatus(); 85 86 MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE; 87 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_BACKUP; 88 89 while (1) {} 90 // Should never reach this line - device will jump to backup vector on exit from background mode. 91 } 92 MXC_LP_EnterPowerDownMode(void)93void MXC_LP_EnterPowerDownMode(void) 94 { 95 MXC_GCR->pm &= ~MXC_F_GCR_PM_MODE; 96 MXC_GCR->pm |= MXC_S_GCR_PM_MODE_POWERDOWN; 97 98 while (1) {} 99 // Should never reach this line - device will reset on exit from shutdown mode. 100 } 101 MXC_LP_SetOVR(mxc_lp_ovr_t ovr)102void MXC_LP_SetOVR(mxc_lp_ovr_t ovr) 103 { 104 //not supported yet 105 } 106 107 /* 108 void MXC_LP_BandgapOn(void) 109 { 110 MXC_PWRSEQ->lpcn &= ~MXC_F_PWRSEQ_LPCN_BG_DIS; 111 } 112 113 void MXC_LP_BandgapOff(void) 114 { 115 MXC_PWRSEQ->lpcn |= MXC_F_PWRSEQ_LPCN_BG_DIS; 116 } 117 118 int MXC_LP_BandgapIsOn(void) 119 { 120 return (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_BG_DIS); 121 } 122 */ 123 MXC_LP_ClearWakeStatus(void)124void MXC_LP_ClearWakeStatus(void) 125 { 126 /* Write 1 to clear */ 127 MXC_PWRSEQ->lpwkst0 = 0xFFFFFFFF; 128 MXC_PWRSEQ->lpwkst1 = 0xFFFFFFFF; 129 MXC_PWRSEQ->lpwkst2 = 0xFFFFFFFF; 130 MXC_PWRSEQ->lpwkst3 = 0xFFFFFFFF; 131 MXC_PWRSEQ->lppwst = 0xFFFFFFFF; 132 } 133 MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)134void MXC_LP_EnableGPIOWakeup(mxc_gpio_cfg_t *wu_pins) 135 { 136 MXC_GCR->pm |= MXC_F_GCR_PM_GPIO_WE; 137 138 switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) { 139 case MXC_GPIO_PORT_0: 140 MXC_PWRSEQ->lpwken0 |= wu_pins->mask; 141 break; 142 143 case MXC_GPIO_PORT_1: 144 MXC_PWRSEQ->lpwken1 |= wu_pins->mask; 145 break; 146 case MXC_GPIO_PORT_2: 147 MXC_PWRSEQ->lpwken2 |= wu_pins->mask; 148 break; 149 case MXC_GPIO_PORT_3: 150 MXC_PWRSEQ->lpwken3 |= wu_pins->mask; 151 break; 152 } 153 } 154 MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t * wu_pins)155void MXC_LP_DisableGPIOWakeup(mxc_gpio_cfg_t *wu_pins) 156 { 157 switch (1 << MXC_GPIO_GET_IDX(wu_pins->port)) { 158 case MXC_GPIO_PORT_0: 159 MXC_PWRSEQ->lpwken0 &= ~wu_pins->mask; 160 break; 161 162 case MXC_GPIO_PORT_1: 163 MXC_PWRSEQ->lpwken1 &= ~wu_pins->mask; 164 break; 165 case MXC_GPIO_PORT_2: 166 MXC_PWRSEQ->lpwken2 &= ~wu_pins->mask; 167 break; 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