1
1
/*
2
- * Copyright 2023, NXP
2
+ * Copyright 2023-2025 NXP
3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
11
11
#include "fsl_power.h"
12
12
13
13
#include <zephyr/logging/log.h>
14
+ #include <zephyr/drivers/timer/system_timer.h>
15
+
14
16
LOG_MODULE_DECLARE (soc , CONFIG_SOC_LOG_LEVEL );
15
17
16
18
/* Active mode */
@@ -26,6 +28,8 @@ LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
26
28
27
29
#define NODE_ID DT_INST(0, nxp_pdcfg_power)
28
30
31
+ extern void clock_init (void );
32
+
29
33
power_sleep_config_t slp_cfg ;
30
34
31
35
#if DT_NODE_HAS_STATUS_OKAY (DT_NODELABEL (pin0 )) || DT_NODE_HAS_STATUS_OKAY (DT_NODELABEL (pin1 ))
@@ -56,6 +60,81 @@ static void pin1_isr(const struct device *dev)
56
60
}
57
61
#endif
58
62
63
+ #ifdef CONFIG_MPU
64
+
65
+ #define MPU_NUM_REGIONS 8
66
+
67
+ typedef struct mpu_conf {
68
+ uint32_t CTRL ;
69
+ uint32_t RNR ;
70
+ uint32_t RBAR [MPU_NUM_REGIONS ];
71
+ uint32_t RLAR [MPU_NUM_REGIONS ];
72
+ uint32_t RBAR_A1 ;
73
+ uint32_t RLAR_A1 ;
74
+ uint32_t RBAR_A2 ;
75
+ uint32_t RLAR_A2 ;
76
+ uint32_t RBAR_A3 ;
77
+ uint32_t RLAR_A3 ;
78
+ uint32_t MAIR0 ;
79
+ uint32_t MAIR1 ;
80
+ } mpu_conf ;
81
+ mpu_conf saved_mpu_conf ;
82
+
83
+ static void save_mpu_state (void )
84
+ {
85
+ uint32_t index ;
86
+
87
+ /*
88
+ * MPU is divided in `MPU_NUM_REGIONS` regions.
89
+ * Here we save those regions configuration to be restored after PM3 entry
90
+ */
91
+ for (index = 0U ; index < MPU_NUM_REGIONS ; index ++ ) {
92
+ MPU -> RNR = index ;
93
+ saved_mpu_conf .RBAR [index ] = MPU -> RBAR ;
94
+ saved_mpu_conf .RLAR [index ] = MPU -> RLAR ;
95
+ }
96
+
97
+ saved_mpu_conf .CTRL = MPU -> CTRL ;
98
+ saved_mpu_conf .RNR = MPU -> RNR ;
99
+ saved_mpu_conf .RBAR_A1 = MPU -> RBAR_A1 ;
100
+ saved_mpu_conf .RLAR_A1 = MPU -> RLAR_A1 ;
101
+ saved_mpu_conf .RBAR_A2 = MPU -> RBAR_A2 ;
102
+ saved_mpu_conf .RLAR_A2 = MPU -> RLAR_A2 ;
103
+ saved_mpu_conf .RBAR_A3 = MPU -> RBAR_A3 ;
104
+ saved_mpu_conf .RLAR_A3 = MPU -> RLAR_A3 ;
105
+ saved_mpu_conf .MAIR0 = MPU -> MAIR0 ;
106
+ saved_mpu_conf .MAIR1 = MPU -> MAIR1 ;
107
+ }
108
+
109
+ static void restore_mpu_state (void )
110
+ {
111
+ uint32_t index ;
112
+
113
+ for (index = 0U ; index < MPU_NUM_REGIONS ; index ++ ) {
114
+ MPU -> RNR = index ;
115
+ MPU -> RBAR = saved_mpu_conf .RBAR [index ];
116
+ MPU -> RLAR = saved_mpu_conf .RLAR [index ];
117
+ }
118
+
119
+ MPU -> RNR = saved_mpu_conf .RNR ;
120
+ MPU -> RBAR_A1 = saved_mpu_conf .RBAR_A1 ;
121
+ MPU -> RLAR_A1 = saved_mpu_conf .RLAR_A1 ;
122
+ MPU -> RBAR_A2 = saved_mpu_conf .RBAR_A2 ;
123
+ MPU -> RLAR_A2 = saved_mpu_conf .RLAR_A2 ;
124
+ MPU -> RBAR_A3 = saved_mpu_conf .RBAR_A3 ;
125
+ MPU -> RLAR_A3 = saved_mpu_conf .RLAR_A3 ;
126
+ MPU -> MAIR0 = saved_mpu_conf .MAIR0 ;
127
+ MPU -> MAIR1 = saved_mpu_conf .MAIR1 ;
128
+
129
+ /*
130
+ * CTRL register must be restored last in case MPU was enabled,
131
+ * because some MPU registers can't be programmed while the MPU is enabled
132
+ */
133
+ MPU -> CTRL = saved_mpu_conf .CTRL ;
134
+ }
135
+
136
+ #endif /* CONFIG_MPU */
137
+
59
138
/* Invoke Low Power/System Off specific Tasks */
60
139
__weak void pm_state_set (enum pm_state state , uint8_t substate_id )
61
140
{
@@ -92,6 +171,28 @@ __weak void pm_state_set(enum pm_state state, uint8_t substate_id)
92
171
break ;
93
172
case PM_STATE_SUSPEND_TO_IDLE :
94
173
POWER_EnterPowerMode (POWER_MODE2 , & slp_cfg );
174
+ break ;
175
+ case PM_STATE_STANDBY :
176
+ #ifdef CONFIG_MPU
177
+ /* Save MPU state before entering PM3 */
178
+ save_mpu_state ();
179
+ #endif /* CONFIG_MPU */
180
+
181
+ POWER_EnableWakeup (DT_IRQN (DT_NODELABEL (rtc )));
182
+ if (POWER_EnterPowerMode (POWER_MODE3 , & slp_cfg )) {
183
+ #ifdef CONFIG_MPU
184
+ /* Restore MPU as is lost after PM3 exit*/
185
+ restore_mpu_state ();
186
+ #endif /* CONFIG_MPU */
187
+ clock_init ();
188
+
189
+ sys_clock_idle_exit ();
190
+ }
191
+
192
+ /* Clear the RTC wakeup bits */
193
+ POWER_ClearWakeupStatus (DT_IRQN (DT_NODELABEL (rtc )));
194
+ POWER_DisableWakeup (DT_IRQN (DT_NODELABEL (rtc )));
195
+
95
196
break ;
96
197
default :
97
198
LOG_DBG ("Unsupported power state %u" , state );
@@ -142,4 +243,8 @@ void nxp_rw6xx_power_init(void)
142
243
IRQ_CONNECT (DT_IRQN (DT_NODELABEL (pin1 )), DT_IRQ (DT_NODELABEL (pin1 ), priority ), pin1_isr ,
143
244
NULL , 0 );
144
245
#endif
246
+
247
+ /* Clear the RTC wakeup bits */
248
+ POWER_ClearWakeupStatus (DT_IRQN (DT_NODELABEL (rtc )));
249
+ POWER_DisableWakeup (DT_IRQN (DT_NODELABEL (rtc )));
145
250
}
0 commit comments