|
6 | 6 | #include <zephyr/kernel.h>
|
7 | 7 | #include <zephyr/pm/pm.h>
|
8 | 8 | #include <fsl_clock.h>
|
| 9 | +#include <fsl_rtc.h> |
9 | 10 | #include <zephyr/init.h>
|
10 | 11 | #include <zephyr/drivers/pinctrl.h>
|
11 | 12 | #if CONFIG_GPIO && (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin0)) || \
|
12 | 13 | DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin1)))
|
13 | 14 | #include <zephyr/drivers/gpio/gpio_mcux_lpc.h>
|
14 | 15 | #endif
|
15 | 16 | #include <zephyr/drivers/timer/system_timer.h>
|
| 17 | +#include <zephyr/drivers/timer/nxp_os_timer.h> |
16 | 18 |
|
17 | 19 | #include "fsl_power.h"
|
18 | 20 |
|
19 | 21 | #include <zephyr/logging/log.h>
|
20 |
| -#include <zephyr/drivers/timer/system_timer.h> |
21 | 22 |
|
22 | 23 | LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
|
23 | 24 |
|
@@ -143,24 +144,33 @@ static void restore_mpu_state(void)
|
143 | 144 | }
|
144 | 145 |
|
145 | 146 | #endif /* CONFIG_MPU */
|
| 147 | +static void config_wakeup_gpio_pins(void) |
| 148 | +{ |
| 149 | +#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin0)) |
| 150 | + pin_cfg = IOMUX_GPIO_IDX(24) | IOMUX_TYPE(IOMUX_GPIO); |
| 151 | + pinctrl_configure_pins(&pin_cfg, 1, 0); |
| 152 | +#endif |
| 153 | +#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin1)) |
| 154 | + pin_cfg = IOMUX_GPIO_IDX(25) | IOMUX_TYPE(IOMUX_GPIO); |
| 155 | + pinctrl_configure_pins(&pin_cfg, 1, 0); |
| 156 | +#endif |
| 157 | +} |
146 | 158 |
|
147 | 159 | /* Invoke Low Power/System Off specific Tasks */
|
148 | 160 | __weak void pm_state_set(enum pm_state state, uint8_t substate_id)
|
149 | 161 | {
|
150 | 162 | ARG_UNUSED(substate_id);
|
151 | 163 |
|
| 164 | + config_wakeup_gpio_pins(); |
| 165 | + |
152 | 166 | #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin0))
|
153 |
| - pin_cfg = IOMUX_GPIO_IDX(24) | IOMUX_TYPE(IOMUX_GPIO); |
154 |
| - pinctrl_configure_pins(&pin_cfg, 1, 0); |
155 | 167 | POWER_ConfigWakeupPin(kPOWER_WakeupPin0, DT_ENUM_IDX(DT_NODELABEL(pin0), wakeup_level));
|
156 | 168 | POWER_ClearWakeupStatus(DT_IRQN(DT_NODELABEL(pin0)));
|
157 | 169 | NVIC_ClearPendingIRQ(DT_IRQN(DT_NODELABEL(pin0)));
|
158 | 170 | EnableIRQ(DT_IRQN(DT_NODELABEL(pin0)));
|
159 | 171 | POWER_EnableWakeup(DT_IRQN(DT_NODELABEL(pin0)));
|
160 | 172 | #endif
|
161 | 173 | #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin1))
|
162 |
| - pin_cfg = IOMUX_GPIO_IDX(25) | IOMUX_TYPE(IOMUX_GPIO); |
163 |
| - pinctrl_configure_pins(&pin_cfg, 1, 0); |
164 | 174 | POWER_ConfigWakeupPin(kPOWER_WakeupPin1, DT_ENUM_IDX(DT_NODELABEL(pin1), wakeup_level));
|
165 | 175 | POWER_ClearWakeupStatus(DT_IRQN(DT_NODELABEL(pin1)));
|
166 | 176 | NVIC_ClearPendingIRQ(DT_IRQN(DT_NODELABEL(pin1)));
|
@@ -202,6 +212,22 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id)
|
202 | 212 | sys_clock_set_timeout(0, true);
|
203 | 213 |
|
204 | 214 | if (POWER_EnterPowerMode(POWER_MODE3, &slp_cfg)) {
|
| 215 | + /* Go back to PM Mode 3 if RTC wakeup is to be ignored.*/ |
| 216 | + while (z_nxp_os_timer_ignore_timer_wakeup() && |
| 217 | + (PMU->WAKEUP_STATUS & PMU_WAKEUP_STATUS_RTC_MASK)) { |
| 218 | + config_wakeup_gpio_pins(); |
| 219 | + /* Reinitialize the OS Timer */ |
| 220 | + CLOCK_AttachClk(kLPOSC_to_OSTIMER_CLK); |
| 221 | + /* Clear the RTC wakeup bits */ |
| 222 | + POWER_ClearWakeupStatus(DT_IRQN(DT_NODELABEL(rtc))); |
| 223 | + RTC_ClearStatusFlags(RTC, kRTC_WakeupFlag); |
| 224 | + NVIC_ClearPendingIRQ(DT_IRQN(DT_NODELABEL(rtc))); |
| 225 | + sys_clock_idle_exit(); |
| 226 | + sys_clock_set_timeout(0, true); |
| 227 | + if (!(POWER_EnterPowerMode(POWER_MODE3, &slp_cfg))) { |
| 228 | + break; |
| 229 | + } |
| 230 | + } |
205 | 231 | #ifdef CONFIG_MPU
|
206 | 232 | /* Restore MPU as is lost after PM3 exit*/
|
207 | 233 | restore_mpu_state();
|
|
0 commit comments