Skip to content

Commit 4a67a61

Browse files
mmahadevan108kartben
authored andcommitted
soc: rw612: Handle counter overflow in Power Mode 3
The RTC counter that is used in Power Mode 3 to track System time could overflow for large timeouts. Add code to catch wakeup events due to this overflow and re-enter Power Mode 3. Signed-off-by: Mahesh Mahadevan <[email protected]>
1 parent 4da30d0 commit 4a67a61

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

soc/nxp/rw/power.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@
66
#include <zephyr/kernel.h>
77
#include <zephyr/pm/pm.h>
88
#include <fsl_clock.h>
9+
#include <fsl_rtc.h>
910
#include <zephyr/init.h>
1011
#include <zephyr/drivers/pinctrl.h>
1112
#if CONFIG_GPIO && (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin0)) || \
1213
DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(pin1)))
1314
#include <zephyr/drivers/gpio/gpio_mcux_lpc.h>
1415
#endif
1516
#include <zephyr/drivers/timer/system_timer.h>
17+
#include <zephyr/drivers/timer/nxp_os_timer.h>
1618

1719
#include "fsl_power.h"
1820

1921
#include <zephyr/logging/log.h>
20-
#include <zephyr/drivers/timer/system_timer.h>
2122

2223
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
2324

@@ -143,24 +144,33 @@ static void restore_mpu_state(void)
143144
}
144145

145146
#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+
}
146158

147159
/* Invoke Low Power/System Off specific Tasks */
148160
__weak void pm_state_set(enum pm_state state, uint8_t substate_id)
149161
{
150162
ARG_UNUSED(substate_id);
151163

164+
config_wakeup_gpio_pins();
165+
152166
#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);
155167
POWER_ConfigWakeupPin(kPOWER_WakeupPin0, DT_ENUM_IDX(DT_NODELABEL(pin0), wakeup_level));
156168
POWER_ClearWakeupStatus(DT_IRQN(DT_NODELABEL(pin0)));
157169
NVIC_ClearPendingIRQ(DT_IRQN(DT_NODELABEL(pin0)));
158170
EnableIRQ(DT_IRQN(DT_NODELABEL(pin0)));
159171
POWER_EnableWakeup(DT_IRQN(DT_NODELABEL(pin0)));
160172
#endif
161173
#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);
164174
POWER_ConfigWakeupPin(kPOWER_WakeupPin1, DT_ENUM_IDX(DT_NODELABEL(pin1), wakeup_level));
165175
POWER_ClearWakeupStatus(DT_IRQN(DT_NODELABEL(pin1)));
166176
NVIC_ClearPendingIRQ(DT_IRQN(DT_NODELABEL(pin1)));
@@ -202,6 +212,22 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id)
202212
sys_clock_set_timeout(0, true);
203213

204214
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+
}
205231
#ifdef CONFIG_MPU
206232
/* Restore MPU as is lost after PM3 exit*/
207233
restore_mpu_state();

0 commit comments

Comments
 (0)