10
10
11
11
#include <zephyr/init.h>
12
12
#include <zephyr/drivers/timer/system_timer.h>
13
+ #include <zephyr/drivers/timer/nxp_os_timer.h>
13
14
#include <zephyr/irq.h>
14
15
#include <zephyr/sys_clock.h>
15
16
#include <zephyr/spinlock.h>
@@ -45,6 +46,11 @@ static uint64_t cyc_sys_compensated;
45
46
static const struct device * counter_dev ;
46
47
/* Indicates if the counter is running. */
47
48
static bool counter_running ;
49
+ /* Indicates we received a call with ticks set to wait forever */
50
+ static bool wait_forever ;
51
+ /* Incase of counter overflow, track the remaining ticks left */
52
+ static uint32_t counter_remaining_ticks ;
53
+ static uint32_t counter_max_val ;
48
54
#endif
49
55
50
56
static uint64_t mcux_lpc_ostick_get_compensated_timer_value (void )
@@ -93,8 +99,21 @@ static uint32_t mcux_lpc_ostick_set_counter_timeout(int32_t curr_timeout)
93
99
uint32_t ticks ;
94
100
struct counter_top_cfg top_cfg = { 0 };
95
101
96
- ticks = counter_us_to_ticks (counter_dev , curr_timeout );
97
- ticks = CLAMP (ticks , 1 , counter_get_max_top_value (counter_dev ));
102
+ /* Check if we should use the remaining ticks from a prior overflow */
103
+ if (counter_remaining_ticks ) {
104
+ ticks = counter_remaining_ticks ;
105
+ } else {
106
+ ticks = counter_us_to_ticks (counter_dev , curr_timeout );
107
+ counter_remaining_ticks = ticks ;
108
+ }
109
+
110
+ /* Check if the counter overflows */
111
+ if (ticks > counter_max_val ) {
112
+ counter_remaining_ticks -= counter_max_val ;
113
+ } else {
114
+ counter_remaining_ticks = 0 ;
115
+ }
116
+ ticks = CLAMP (ticks , 1 , counter_max_val );
98
117
99
118
top_cfg .ticks = ticks ;
100
119
top_cfg .callback = NULL ;
@@ -175,6 +194,11 @@ static uint32_t mcux_lpc_ostick_compensate_system_timer(void)
175
194
return 0 ;
176
195
}
177
196
197
+ bool z_nxp_os_timer_ignore_timer_wakeup (void )
198
+ {
199
+ return (wait_forever || counter_remaining_ticks );
200
+ }
201
+
178
202
#endif
179
203
180
204
void sys_clock_set_timeout (int32_t ticks , bool idle )
@@ -194,17 +218,23 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
194
218
if (pm_state_next_get (0 )-> state == PM_STATE_STANDBY ) {
195
219
uint64_t timeout ;
196
220
197
- /* Check the amount of time left and switch to a counter
198
- * that is active in this power mode.
199
- */
200
- timeout = base -> MATCH_L ;
201
- timeout |= (uint64_t )(base -> MATCH_H ) << 32 ;
202
- timeout = OSTIMER_GrayToDecimal (timeout );
203
- timeout -= OSTIMER_GetCurrentTimerValue (base );
204
- /* Round up to the next tick boundary */
205
- timeout += (CYC_PER_TICK - 1 );
206
- /* Convert to microseconds and round up to the next value */
207
- timeout = (((timeout / CYC_PER_TICK ) * CYC_PER_TICK ) * CYC_PER_US );
221
+ if (wait_forever ) {
222
+ timeout = UINT32_MAX ;
223
+ } else if (counter_remaining_ticks ) {
224
+ timeout = counter_remaining_ticks ;
225
+ } else {
226
+ /* Check the amount of time left and switch to a counter
227
+ * that is active in this power mode.
228
+ */
229
+ timeout = base -> MATCH_L ;
230
+ timeout |= (uint64_t )(base -> MATCH_H ) << 32 ;
231
+ timeout = OSTIMER_GrayToDecimal (timeout );
232
+ timeout -= OSTIMER_GetCurrentTimerValue (base );
233
+ /* Round up to the next tick boundary */
234
+ timeout += (CYC_PER_TICK - 1 );
235
+ /* Convert to microseconds and round up to the next value */
236
+ timeout = (((timeout / CYC_PER_TICK ) * CYC_PER_TICK ) * CYC_PER_US );
237
+ }
208
238
if (mcux_lpc_ostick_set_counter_timeout (timeout ) == 0 ) {
209
239
/* A low power counter has been started. No need to
210
240
* go further, simply return
@@ -213,6 +243,10 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
213
243
}
214
244
}
215
245
}
246
+ /* When using a counter for certain low power modes, set this flag when the requested
247
+ * delay is forever. This is to keep track of wakeup sources in case of counter overflows.
248
+ */
249
+ wait_forever = (ticks == SYS_CLOCK_MAX_WAIT );
216
250
#else
217
251
ARG_UNUSED (idle );
218
252
#endif
@@ -304,6 +338,7 @@ static int sys_clock_driver_init(void)
304
338
/* On some SoC's, OS Timer cannot wakeup from low power mode in standby modes */
305
339
#if DT_NODE_HAS_STATUS_OKAY (DT_NODELABEL (standby )) && CONFIG_PM
306
340
counter_dev = DEVICE_DT_GET_OR_NULL (DT_INST_PHANDLE (0 , deep_sleep_counter ));
341
+ counter_max_val = counter_get_max_top_value (counter_dev );
307
342
#endif
308
343
309
344
return 0 ;
0 commit comments