1 /*
2 * Copyright 2022-2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_s32_sys_timer
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/counter.h>
11 #include <zephyr/drivers/clock_control.h>
12 #if defined(CONFIG_GIC)
13 #include <zephyr/drivers/interrupt_controller/gic.h>
14 #endif /* CONFIG_GIC */
15 #include <zephyr/logging/log.h>
16 #include <zephyr/irq.h>
17
18 LOG_MODULE_REGISTER(nxp_s32_sys_timer, CONFIG_COUNTER_LOG_LEVEL);
19
20 /* System Timer Module (STM) register definitions */
21 /* Control */
22 #define STM_CR 0x0
23 #define STM_CR_TEN_MASK BIT(0)
24 #define STM_CR_TEN(v) FIELD_PREP(STM_CR_TEN_MASK, (v))
25 #define STM_CR_FRZ_MASK BIT(1)
26 #define STM_CR_FRZ(v) FIELD_PREP(STM_CR_FRZ_MASK, (v))
27 #define STM_CR_CPS_MASK GENMASK(15, 8)
28 #define STM_CR_CPS(v) FIELD_PREP(STM_CR_CPS_MASK, (v))
29 /* Count */
30 #define STM_CNT 0x4
31 #define STM_CNT_CNT_MASK GENMASK(31, 0)
32 #define STM_CNT_CNT(v) FIELD_PREP(STM_CNT_CNT_MASK, (v))
33 /* Channel Control */
34 #define STM_CCR(n) (0x10 + 0x10 * (n))
35 #define STM_CCR_CEN_MASK BIT(0)
36 #define STM_CCR_CEN(v) FIELD_PREP(STM_CCR_CEN_MASK, (v))
37 /* Channel Interrupt */
38 #define STM_CIR(n) (0x14 + 0x10 * (n))
39 #define STM_CIR_CIF_MASK BIT(0)
40 #define STM_CIR_CIF(v) FIELD_PREP(STM_CIR_CIF_MASK, (v))
41 /* Channel Compare */
42 #define STM_CMP(n) (0x18 + 0x10 * (n))
43 #define STM_CMP_CMP_MASK GENMASK(31, 0)
44 #define STM_CMP_CMP(v) FIELD_PREP(STM_CMP_CMP_MASK, (v))
45
46 /* Handy accessors */
47 #define REG_READ(r) sys_read32(config->base + (r))
48 #define REG_WRITE(r, v) sys_write32((v), config->base + (r))
49
50 #define SYS_TIMER_MAX_VALUE 0xFFFFFFFFU
51 #define SYS_TIMER_NUM_CHANNELS 4
52
53 struct nxp_s32_sys_timer_chan_data {
54 counter_alarm_callback_t callback;
55 void *user_data;
56 };
57
58 struct nxp_s32_sys_timer_data {
59 struct nxp_s32_sys_timer_chan_data ch_data[SYS_TIMER_NUM_CHANNELS];
60 uint32_t guard_period;
61 atomic_t irq_pending;
62 };
63
64 struct nxp_s32_sys_timer_config {
65 struct counter_config_info info;
66 mem_addr_t base;
67 const struct device *clock_dev;
68 clock_control_subsys_t clock_subsys;
69 uint8_t prescaler;
70 bool freeze;
71 unsigned int irqn;
72 };
73
irq_set_pending(unsigned int irq)74 static ALWAYS_INLINE void irq_set_pending(unsigned int irq)
75 {
76 #if defined(CONFIG_GIC)
77 arm_gic_irq_set_pending(irq);
78 #else
79 NVIC_SetPendingIRQ(irq);
80 #endif /* CONFIG_GIC */
81 }
82
ticks_add(uint32_t val1,uint32_t val2,uint32_t top)83 static uint32_t ticks_add(uint32_t val1, uint32_t val2, uint32_t top)
84 {
85 uint32_t to_top;
86
87 if (likely(IS_BIT_MASK(top))) {
88 return (val1 + val2) & top;
89 }
90
91 /* top is not 2^n-1 */
92 to_top = top - val1;
93
94 return (val2 <= to_top) ? val1 + val2 : val2 - to_top;
95 }
96
ticks_sub(uint32_t val,uint32_t old,uint32_t top)97 static uint32_t ticks_sub(uint32_t val, uint32_t old, uint32_t top)
98 {
99 if (likely(IS_BIT_MASK(top))) {
100 return (val - old) & top;
101 }
102
103 /* top is not 2^n-1 */
104 return (val >= old) ? (val - old) : val + top + 1 - old;
105 }
106
stm_disable_channel(const struct nxp_s32_sys_timer_config * config,uint8_t channel)107 static ALWAYS_INLINE void stm_disable_channel(const struct nxp_s32_sys_timer_config *config,
108 uint8_t channel)
109 {
110 REG_WRITE(STM_CCR(channel), STM_CCR_CEN(0U));
111 REG_WRITE(STM_CIR(channel), STM_CIR_CIF(1U));
112 }
113
stm_set_alarm(const struct device * dev,uint8_t channel,uint32_t ticks,uint32_t flags)114 static int stm_set_alarm(const struct device *dev, uint8_t channel, uint32_t ticks, uint32_t flags)
115 {
116 const struct nxp_s32_sys_timer_config *config = dev->config;
117 struct nxp_s32_sys_timer_data *data = dev->data;
118 struct nxp_s32_sys_timer_chan_data *ch_data = &data->ch_data[channel];
119 const uint32_t now = REG_READ(STM_CNT);
120 const uint32_t top_val = config->info.max_top_value;
121 int err = 0;
122 uint32_t diff;
123 uint32_t max_rel_val;
124 bool irq_on_late;
125
126 if (flags & COUNTER_ALARM_CFG_ABSOLUTE) {
127 __ASSERT_NO_MSG(data->guard_period < top_val);
128 max_rel_val = top_val - data->guard_period;
129 irq_on_late = !!(flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE);
130 } else {
131 /*
132 * If relative value is smaller than half of the counter range it is assumed
133 * that there is a risk of setting value too late and late detection algorithm
134 * must be applied. When late setting is detected, interrupt shall be
135 * triggered for immediate expiration of the timer. Detection is performed
136 * by limiting relative distance between CMP and CNT.
137 *
138 * Note that half of counter range is an arbitrary value.
139 */
140 irq_on_late = ticks < (top_val / 2);
141 /* Limit max to detect short relative being set too late */
142 max_rel_val = irq_on_late ? top_val / 2 : top_val;
143 ticks = ticks_add(now, ticks, top_val);
144 }
145
146 /* Disable the channel before loading the new value so that it takes effect immediately */
147 stm_disable_channel(config, channel);
148 REG_WRITE(STM_CMP(channel), ticks);
149 REG_WRITE(STM_CCR(channel), STM_CCR_CEN(1U));
150
151 /*
152 * Decrement value to detect also case when ticks == CNT. Otherwise, condition would need
153 * to include comparing diff against 0.
154 */
155 diff = ticks_sub(ticks - 1, REG_READ(STM_CNT), top_val);
156 if (diff > max_rel_val) {
157 if (flags & COUNTER_ALARM_CFG_ABSOLUTE) {
158 err = -ETIME;
159 }
160
161 /*
162 * Interrupt is triggered always for relative alarm and for absolute depending
163 * on the flag
164 */
165 if (irq_on_late) {
166 atomic_or(&data->irq_pending, BIT(channel));
167 irq_set_pending(config->irqn);
168 } else {
169 ch_data->callback = NULL;
170 }
171 }
172
173 return err;
174 }
175
stm_isr(const struct device * dev)176 static void stm_isr(const struct device *dev)
177 {
178 const struct nxp_s32_sys_timer_config *config = dev->config;
179 struct nxp_s32_sys_timer_data *data = dev->data;
180 struct nxp_s32_sys_timer_chan_data *ch_data = NULL;
181 counter_alarm_callback_t cb = NULL;
182 void *cb_args = NULL;
183 uint8_t channel;
184 bool pending;
185
186 for (channel = 0; channel < SYS_TIMER_NUM_CHANNELS; ++channel) {
187 pending = FIELD_GET(STM_CCR_CEN_MASK, REG_READ(STM_CCR(channel))) &&
188 FIELD_GET(STM_CIR_CIF_MASK, REG_READ(STM_CIR(channel)));
189
190 if (pending || atomic_test_bit(&data->irq_pending, channel)) {
191 stm_disable_channel(config, channel);
192 atomic_and(&data->irq_pending, ~BIT(channel));
193
194 ch_data = &data->ch_data[channel];
195 if (ch_data->callback) {
196 cb = ch_data->callback;
197 cb_args = ch_data->user_data;
198 ch_data->callback = NULL;
199 ch_data->user_data = NULL;
200 cb(dev, channel, REG_READ(STM_CNT), cb_args);
201 }
202 }
203 }
204 }
205
nxp_s32_sys_timer_start(const struct device * dev)206 static int nxp_s32_sys_timer_start(const struct device *dev)
207 {
208 const struct nxp_s32_sys_timer_config *config = dev->config;
209
210 REG_WRITE(STM_CNT, 0U);
211 REG_WRITE(STM_CR, REG_READ(STM_CR) | STM_CR_TEN(1U));
212
213 return 0;
214 }
215
nxp_s32_sys_timer_stop(const struct device * dev)216 static int nxp_s32_sys_timer_stop(const struct device *dev)
217 {
218 const struct nxp_s32_sys_timer_config *config = dev->config;
219
220 REG_WRITE(STM_CR, REG_READ(STM_CR) & ~STM_CR_TEN_MASK);
221
222 return 0;
223 }
224
nxp_s32_sys_timer_get_value(const struct device * dev,uint32_t * ticks)225 static int nxp_s32_sys_timer_get_value(const struct device *dev, uint32_t *ticks)
226 {
227 const struct nxp_s32_sys_timer_config *config = dev->config;
228
229 *ticks = REG_READ(STM_CNT);
230
231 return 0;
232 }
233
nxp_s32_sys_timer_set_alarm(const struct device * dev,uint8_t channel,const struct counter_alarm_cfg * alarm_cfg)234 static int nxp_s32_sys_timer_set_alarm(const struct device *dev, uint8_t channel,
235 const struct counter_alarm_cfg *alarm_cfg)
236 {
237 const struct nxp_s32_sys_timer_config *config = dev->config;
238 struct nxp_s32_sys_timer_data *data = dev->data;
239 struct nxp_s32_sys_timer_chan_data *ch_data = &data->ch_data[channel];
240
241 if (ch_data->callback) {
242 return -EBUSY;
243 }
244
245 if (alarm_cfg->ticks > config->info.max_top_value) {
246 LOG_ERR("Invalid ticks value %d", alarm_cfg->ticks);
247 return -EINVAL;
248 }
249
250 ch_data->callback = alarm_cfg->callback;
251 ch_data->user_data = alarm_cfg->user_data;
252
253 return stm_set_alarm(dev, channel, alarm_cfg->ticks, alarm_cfg->flags);
254 }
255
nxp_s32_sys_timer_cancel_alarm(const struct device * dev,uint8_t channel)256 static int nxp_s32_sys_timer_cancel_alarm(const struct device *dev, uint8_t channel)
257 {
258 const struct nxp_s32_sys_timer_config *config = dev->config;
259 struct nxp_s32_sys_timer_data *data = dev->data;
260 struct nxp_s32_sys_timer_chan_data *ch_data = &data->ch_data[channel];
261
262 stm_disable_channel(config, channel);
263 ch_data->callback = NULL;
264 ch_data->user_data = NULL;
265
266 return 0;
267 }
268
nxp_s32_sys_timer_get_pending_int(const struct device * dev)269 static uint32_t nxp_s32_sys_timer_get_pending_int(const struct device *dev)
270 {
271 const struct nxp_s32_sys_timer_config *config = dev->config;
272 uint8_t i;
273
274 for (i = 0; i < counter_get_num_of_channels(dev); i++) {
275 if (REG_READ(STM_CIR(i)) & STM_CIR_CIF_MASK) {
276 return 1;
277 }
278 }
279
280 return 0;
281 }
282
nxp_s32_sys_timer_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)283 static int nxp_s32_sys_timer_set_top_value(const struct device *dev,
284 const struct counter_top_cfg *cfg)
285 {
286 ARG_UNUSED(dev);
287 ARG_UNUSED(cfg);
288
289 /* Overflow is fixed and cannot be changed */
290 return -ENOTSUP;
291 }
292
nxp_s32_sys_timer_get_top_value(const struct device * dev)293 static uint32_t nxp_s32_sys_timer_get_top_value(const struct device *dev)
294 {
295 const struct nxp_s32_sys_timer_config *config = dev->config;
296
297 return config->info.max_top_value;
298 }
299
nxp_s32_sys_timer_set_guard_period(const struct device * dev,uint32_t guard,uint32_t flags)300 static int nxp_s32_sys_timer_set_guard_period(const struct device *dev, uint32_t guard,
301 uint32_t flags)
302 {
303 struct nxp_s32_sys_timer_data *data = dev->data;
304
305 ARG_UNUSED(flags);
306
307 __ASSERT_NO_MSG(guard < nxp_s32_sys_timer_get_top_value(dev));
308 data->guard_period = guard;
309
310 return 0;
311 }
312
nxp_s32_sys_timer_get_guard_period(const struct device * dev,uint32_t flags)313 static uint32_t nxp_s32_sys_timer_get_guard_period(const struct device *dev, uint32_t flags)
314 {
315 struct nxp_s32_sys_timer_data *data = dev->data;
316
317 ARG_UNUSED(flags);
318
319 return data->guard_period;
320 }
321
nxp_s32_sys_timer_get_frequency(const struct device * dev)322 static uint32_t nxp_s32_sys_timer_get_frequency(const struct device *dev)
323 {
324 const struct nxp_s32_sys_timer_config *config = dev->config;
325 uint32_t clock_rate;
326
327 if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_rate)) {
328 LOG_ERR("Failed to get clock frequency");
329 return 0;
330 }
331
332 return clock_rate / (config->prescaler + 1U);
333 }
334
nxp_s32_sys_timer_init(const struct device * dev)335 static int nxp_s32_sys_timer_init(const struct device *dev)
336 {
337 const struct nxp_s32_sys_timer_config *config = dev->config;
338 struct nxp_s32_sys_timer_data *data = dev->data;
339 struct nxp_s32_sys_timer_chan_data *ch_data;
340 int i;
341 int err;
342
343 if (!device_is_ready(config->clock_dev)) {
344 LOG_ERR("Clock control device not ready");
345 return -ENODEV;
346 }
347
348 err = clock_control_on(config->clock_dev, config->clock_subsys);
349 if (err) {
350 LOG_ERR("Failed to enable clock");
351 return err;
352 }
353
354 REG_WRITE(STM_CNT, 0U);
355 REG_WRITE(STM_CR,
356 STM_CR_FRZ(config->freeze) |
357 STM_CR_CPS(config->prescaler) |
358 STM_CR_TEN(1U));
359
360 for (i = 0; i < counter_get_num_of_channels(dev); i++) {
361 ch_data = &data->ch_data[i];
362 ch_data->callback = NULL;
363 ch_data->user_data = NULL;
364
365 REG_WRITE(STM_CCR(i), STM_CCR_CEN(0U));
366 REG_WRITE(STM_CIR(i), STM_CIR_CIF(1U));
367 REG_WRITE(STM_CMP(i), 0U);
368 }
369
370 return 0;
371 }
372
373 static DEVICE_API(counter, nxp_s32_sys_timer_driver_api) = {
374 .start = nxp_s32_sys_timer_start,
375 .stop = nxp_s32_sys_timer_stop,
376 .get_value = nxp_s32_sys_timer_get_value,
377 .set_alarm = nxp_s32_sys_timer_set_alarm,
378 .cancel_alarm = nxp_s32_sys_timer_cancel_alarm,
379 .set_top_value = nxp_s32_sys_timer_set_top_value,
380 .get_top_value = nxp_s32_sys_timer_get_top_value,
381 .set_guard_period = nxp_s32_sys_timer_set_guard_period,
382 .get_guard_period = nxp_s32_sys_timer_get_guard_period,
383 .get_pending_int = nxp_s32_sys_timer_get_pending_int,
384 .get_freq = nxp_s32_sys_timer_get_frequency
385 };
386
387 #define SYS_TIMER_INIT_DEVICE(n) \
388 static int nxp_s32_sys_timer_##n##_init(const struct device *dev) \
389 { \
390 IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \
391 stm_isr, DEVICE_DT_INST_GET(n), \
392 COND_CODE_1(DT_INST_IRQ_HAS_CELL(n, flags), \
393 (DT_INST_IRQ(n, flags)), (0))); \
394 irq_enable(DT_INST_IRQN(n)); \
395 \
396 return nxp_s32_sys_timer_init(dev); \
397 } \
398 \
399 static struct nxp_s32_sys_timer_data nxp_s32_sys_timer_data_##n; \
400 \
401 static const struct nxp_s32_sys_timer_config nxp_s32_sys_timer_config_##n = { \
402 .info = { \
403 .max_top_value = SYS_TIMER_MAX_VALUE, \
404 .channels = SYS_TIMER_NUM_CHANNELS, \
405 .flags = COUNTER_CONFIG_INFO_COUNT_UP, \
406 }, \
407 .base = DT_INST_REG_ADDR(n), \
408 .freeze = DT_INST_PROP(n, freeze), \
409 .prescaler = DT_INST_PROP(n, prescaler) - 1, \
410 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
411 .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \
412 .irqn = DT_INST_IRQN(n), \
413 }; \
414 \
415 DEVICE_DT_INST_DEFINE(n, \
416 nxp_s32_sys_timer_##n##_init, \
417 NULL, \
418 &nxp_s32_sys_timer_data_##n, \
419 &nxp_s32_sys_timer_config_##n, \
420 POST_KERNEL, \
421 CONFIG_COUNTER_INIT_PRIORITY, \
422 &nxp_s32_sys_timer_driver_api);
423
424 DT_INST_FOREACH_STATUS_OKAY(SYS_TIMER_INIT_DEVICE)
425