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