1212#include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
1313LOG_MODULE_REGISTER (mcux_ctimer , CONFIG_COUNTER_LOG_LEVEL );
1414
15+ #ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
1516/* One of the CTimer channels is reserved to implement set_top_value API */
1617#define NUM_CHANNELS 3
18+ #else
19+ #define NUM_CHANNELS 4
20+ #endif
1721
1822struct mcux_lpc_ctimer_channel_data {
1923 counter_alarm_callback_t alarm_callback ;
@@ -70,6 +74,8 @@ static int mcux_lpc_ctimer_get_value(const struct device *dev, uint32_t *ticks)
7074static uint32_t mcux_lpc_ctimer_get_top_value (const struct device * dev )
7175{
7276 const struct mcux_lpc_ctimer_config * config = dev -> config ;
77+
78+ #ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
7379 CTIMER_Type * base = config -> base ;
7480
7581 /* Return the top value if it has been set, else return the max top value */
@@ -78,18 +84,21 @@ static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
7884 } else {
7985 return config -> info .max_top_value ;
8086 }
87+ #else
88+ return config -> info .max_top_value ;
89+ #endif
8190}
8291
8392static int mcux_lpc_ctimer_set_alarm (const struct device * dev , uint8_t chan_id ,
8493 const struct counter_alarm_cfg * alarm_cfg )
8594{
8695 const struct mcux_lpc_ctimer_config * config = dev -> config ;
8796 struct mcux_lpc_ctimer_data * data = dev -> data ;
88-
8997 uint32_t ticks = alarm_cfg -> ticks ;
9098 uint32_t current = mcux_lpc_ctimer_read (config -> base );
99+ uint32_t top = mcux_lpc_ctimer_get_top_value (dev );
91100
92- if (alarm_cfg -> ticks > mcux_lpc_ctimer_get_top_value ( dev ) ) {
101+ if (alarm_cfg -> ticks > top ) {
93102 return - EINVAL ;
94103 }
95104
@@ -100,6 +109,9 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
100109
101110 if ((alarm_cfg -> flags & COUNTER_ALARM_CFG_ABSOLUTE ) == 0 ) {
102111 ticks += current ;
112+ if (ticks > top ) {
113+ ticks %= top ;
114+ }
103115 }
104116
105117 data -> channels [chan_id ].alarm_callback = alarm_cfg -> callback ;
@@ -136,6 +148,15 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
136148 const struct mcux_lpc_ctimer_config * config = dev -> config ;
137149 struct mcux_lpc_ctimer_data * data = dev -> data ;
138150
151+ #ifndef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
152+ /* Only allow max value when we do not reserve a ctimer channel for setting top value */
153+ if (cfg -> ticks != config -> info .max_top_value ) {
154+ LOG_ERR ("Wrap can only be set to 0x%x" ,
155+ config -> info .max_top_value );
156+ return - ENOTSUP ;
157+ }
158+ #endif
159+
139160 data -> top_callback = cfg -> callback ;
140161 data -> top_user_data = cfg -> user_data ;
141162
@@ -148,6 +169,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
148169 return - ETIME ;
149170 }
150171
172+ #ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
151173 ctimer_match_config_t match_config = { .matchValue = cfg -> ticks ,
152174 .enableCounterReset = true,
153175 .enableCounterStop = false,
@@ -156,6 +178,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
156178 .enableInterrupt = true };
157179
158180 CTIMER_SetupMatch (config -> base , NUM_CHANNELS , & match_config );
181+ #endif
159182
160183 return 0 ;
161184}
@@ -216,9 +239,11 @@ static void mcux_lpc_ctimer_isr(const struct device *dev)
216239 }
217240 }
218241
242+ #ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
219243 if (((interrupt_stat & (0x01 << NUM_CHANNELS )) != 0 ) && data -> top_callback ) {
220244 data -> top_callback (dev , data -> top_user_data );
221245 }
246+ #endif
222247}
223248
224249static int mcux_lpc_ctimer_init (const struct device * dev )
0 commit comments