1 /*
2 * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
3 * Copyright (c) 2022 TOKITA Hiroshi <tokita.hiroshi@gmail.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #define DT_DRV_COMPAT gd_gd32_timer
9
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/drivers/clock_control/gd32.h>
13 #include <zephyr/drivers/counter.h>
14 #include <zephyr/drivers/reset.h>
15 #include <zephyr/irq.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/sys/atomic.h>
18
19 #include <gd32_timer.h>
20
21 LOG_MODULE_REGISTER(counter_gd32_timer);
22
23 #define TIMER_INT_CH(ch) (TIMER_INT_CH0 << ch)
24 #define TIMER_FLAG_CH(ch) (TIMER_FLAG_CH0 << ch)
25 #define TIMER_INT_ALL (0xFFu)
26
27 struct counter_gd32_ch_data {
28 counter_alarm_callback_t callback;
29 void *user_data;
30 };
31
32 struct counter_gd32_data {
33 counter_top_callback_t top_cb;
34 void *top_user_data;
35 uint32_t guard_period;
36 atomic_t cc_int_pending;
37 uint32_t freq;
38 struct counter_gd32_ch_data alarm[];
39 };
40
41 struct counter_gd32_config {
42 struct counter_config_info counter_info;
43 uint32_t reg;
44 uint16_t clkid;
45 struct reset_dt_spec reset;
46 uint16_t prescaler;
47 void (*irq_config)(const struct device *dev);
48 void (*set_irq_pending)(void);
49 uint32_t (*get_irq_pending)(void);
50 };
51
get_autoreload_value(const struct device * dev)52 static uint32_t get_autoreload_value(const struct device *dev)
53 {
54 const struct counter_gd32_config *config = dev->config;
55
56 return TIMER_CAR(config->reg);
57 }
58
set_autoreload_value(const struct device * dev,uint32_t value)59 static void set_autoreload_value(const struct device *dev, uint32_t value)
60 {
61 const struct counter_gd32_config *config = dev->config;
62
63 TIMER_CAR(config->reg) = value;
64 }
65
get_counter(const struct device * dev)66 static uint32_t get_counter(const struct device *dev)
67 {
68 const struct counter_gd32_config *config = dev->config;
69
70 return TIMER_CNT(config->reg);
71 }
72
set_counter(const struct device * dev,uint32_t value)73 static void set_counter(const struct device *dev, uint32_t value)
74 {
75 const struct counter_gd32_config *config = dev->config;
76
77 TIMER_CNT(config->reg) = value;
78 }
79
set_software_event_gen(const struct device * dev,uint8_t evt)80 static void set_software_event_gen(const struct device *dev, uint8_t evt)
81 {
82 const struct counter_gd32_config *config = dev->config;
83
84 TIMER_SWEVG(config->reg) |= evt;
85 }
86
set_prescaler(const struct device * dev,uint16_t prescaler)87 static void set_prescaler(const struct device *dev, uint16_t prescaler)
88 {
89 const struct counter_gd32_config *config = dev->config;
90
91 TIMER_PSC(config->reg) = prescaler;
92 }
93
set_compare_value(const struct device * dev,uint16_t chan,uint32_t compare_value)94 static void set_compare_value(const struct device *dev, uint16_t chan,
95 uint32_t compare_value)
96 {
97 const struct counter_gd32_config *config = dev->config;
98
99 switch (chan) {
100 case 0:
101 TIMER_CH0CV(config->reg) = compare_value;
102 break;
103 case 1:
104 TIMER_CH1CV(config->reg) = compare_value;
105 break;
106 case 2:
107 TIMER_CH2CV(config->reg) = compare_value;
108 break;
109 case 3:
110 TIMER_CH3CV(config->reg) = compare_value;
111 break;
112 }
113 }
114
interrupt_enable(const struct device * dev,uint32_t interrupt)115 static void interrupt_enable(const struct device *dev, uint32_t interrupt)
116 {
117 const struct counter_gd32_config *config = dev->config;
118
119 TIMER_DMAINTEN(config->reg) |= interrupt;
120 }
121
interrupt_disable(const struct device * dev,uint32_t interrupt)122 static void interrupt_disable(const struct device *dev, uint32_t interrupt)
123 {
124 const struct counter_gd32_config *config = dev->config;
125
126 TIMER_DMAINTEN(config->reg) &= ~interrupt;
127 }
128
interrupt_flag_get(const struct device * dev,uint32_t interrupt)129 static uint32_t interrupt_flag_get(const struct device *dev, uint32_t interrupt)
130 {
131 const struct counter_gd32_config *config = dev->config;
132
133 return (TIMER_DMAINTEN(config->reg) & TIMER_INTF(config->reg) &
134 interrupt);
135 }
136
interrupt_flag_clear(const struct device * dev,uint32_t interrupt)137 static void interrupt_flag_clear(const struct device *dev, uint32_t interrupt)
138 {
139 const struct counter_gd32_config *config = dev->config;
140
141 TIMER_INTF(config->reg) &= ~interrupt;
142 }
143
counter_gd32_timer_start(const struct device * dev)144 static int counter_gd32_timer_start(const struct device *dev)
145 {
146 const struct counter_gd32_config *config = dev->config;
147
148 TIMER_CTL0(config->reg) |= (uint32_t)TIMER_CTL0_CEN;
149
150 return 0;
151 }
152
counter_gd32_timer_stop(const struct device * dev)153 static int counter_gd32_timer_stop(const struct device *dev)
154 {
155 const struct counter_gd32_config *config = dev->config;
156
157 TIMER_CTL0(config->reg) &= ~(uint32_t)TIMER_CTL0_CEN;
158
159 return 0;
160 }
161
counter_gd32_timer_get_value(const struct device * dev,uint32_t * ticks)162 static int counter_gd32_timer_get_value(const struct device *dev,
163 uint32_t *ticks)
164 {
165 *ticks = get_counter(dev);
166
167 return 0;
168 }
169
counter_gd32_timer_get_top_value(const struct device * dev)170 static uint32_t counter_gd32_timer_get_top_value(const struct device *dev)
171 {
172 return get_autoreload_value(dev);
173 }
174
ticks_add(uint32_t val1,uint32_t val2,uint32_t top)175 static uint32_t ticks_add(uint32_t val1, uint32_t val2, uint32_t top)
176 {
177 uint32_t to_top;
178
179 if (likely(IS_BIT_MASK(top))) {
180 return (val1 + val2) & top;
181 }
182
183 to_top = top - val1;
184
185 return (val2 <= to_top) ? val1 + val2 : val2 - to_top;
186 }
187
ticks_sub(uint32_t val,uint32_t old,uint32_t top)188 static uint32_t ticks_sub(uint32_t val, uint32_t old, uint32_t top)
189 {
190 if (likely(IS_BIT_MASK(top))) {
191 return (val - old) & top;
192 }
193
194 /* if top is not 2^n-1 */
195 return (val >= old) ? (val - old) : val + top + 1 - old;
196 }
197
set_cc_int_pending(const struct device * dev,uint8_t chan)198 static void set_cc_int_pending(const struct device *dev, uint8_t chan)
199 {
200 const struct counter_gd32_config *config = dev->config;
201 struct counter_gd32_data *data = dev->data;
202
203 atomic_or(&data->cc_int_pending, TIMER_INT_CH(chan));
204 config->set_irq_pending();
205 }
206
set_cc(const struct device * dev,uint8_t chan,uint32_t val,uint32_t flags)207 static int set_cc(const struct device *dev, uint8_t chan, uint32_t val,
208 uint32_t flags)
209 {
210 const struct counter_gd32_config *config = dev->config;
211 struct counter_gd32_data *data = dev->data;
212
213 __ASSERT_NO_MSG(data->guard_period <
214 counter_gd32_timer_get_top_value(dev));
215 bool absolute = flags & COUNTER_ALARM_CFG_ABSOLUTE;
216 uint32_t top = counter_gd32_timer_get_top_value(dev);
217 uint32_t now, diff, max_rel_val;
218 bool irq_on_late;
219 int err = 0;
220
221 ARG_UNUSED(config);
222 __ASSERT(!(TIMER_DMAINTEN(config->reg) & TIMER_INT_CH(chan)),
223 "Expected that CC interrupt is disabled.");
224
225 /* First take care of a risk of an event coming from CC being set to
226 * next tick. Reconfigure CC to future (now tick is the furthest
227 * future).
228 */
229 now = get_counter(dev);
230 set_compare_value(dev, chan, now);
231 interrupt_flag_clear(dev, TIMER_FLAG_CH(chan));
232
233 if (absolute) {
234 max_rel_val = top - data->guard_period;
235 irq_on_late = flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
236 } else {
237 /* If relative value is smaller than half of the counter range
238 * it is assumed that there is a risk of setting value too late
239 * and late detection algorithm must be applied. When late
240 * setting is detected, interrupt shall be triggered for
241 * immediate expiration of the timer. Detection is performed
242 * by limiting relative distance between CC and counter.
243 *
244 * Note that half of counter range is an arbitrary value.
245 */
246 irq_on_late = val < (top / 2);
247 /* limit max to detect short relative being set too late. */
248 max_rel_val = irq_on_late ? top / 2 : top;
249 val = ticks_add(now, val, top);
250 }
251
252 set_compare_value(dev, chan, val);
253
254 /* decrement value to detect also case when val == get_counter(dev).
255 * Otherwise, condition would need to include comparing diff against 0.
256 */
257 diff = ticks_sub(val - 1, get_counter(dev), top);
258 if (diff > max_rel_val) {
259 if (absolute) {
260 err = -ETIME;
261 }
262
263 /* Interrupt is triggered always for relative alarm and
264 * for absolute depending on the flag.
265 */
266 if (irq_on_late) {
267 set_cc_int_pending(dev, chan);
268 } else {
269 data->alarm[chan].callback = NULL;
270 }
271 } else {
272 interrupt_enable(dev, TIMER_INT_CH(chan));
273 }
274
275 return err;
276 }
277
278 static int
counter_gd32_timer_set_alarm(const struct device * dev,uint8_t chan,const struct counter_alarm_cfg * alarm_cfg)279 counter_gd32_timer_set_alarm(const struct device *dev, uint8_t chan,
280 const struct counter_alarm_cfg *alarm_cfg)
281 {
282 struct counter_gd32_data *data = dev->data;
283 struct counter_gd32_ch_data *chdata = &data->alarm[chan];
284
285 if (alarm_cfg->ticks > counter_gd32_timer_get_top_value(dev)) {
286 return -EINVAL;
287 }
288
289 if (chdata->callback) {
290 return -EBUSY;
291 }
292
293 chdata->callback = alarm_cfg->callback;
294 chdata->user_data = alarm_cfg->user_data;
295
296 return set_cc(dev, chan, alarm_cfg->ticks, alarm_cfg->flags);
297 }
298
counter_gd32_timer_cancel_alarm(const struct device * dev,uint8_t chan)299 static int counter_gd32_timer_cancel_alarm(const struct device *dev,
300 uint8_t chan)
301 {
302 struct counter_gd32_data *data = dev->data;
303
304 interrupt_disable(dev, TIMER_INT_CH(chan));
305 data->alarm[chan].callback = NULL;
306
307 return 0;
308 }
309
counter_gd32_timer_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)310 static int counter_gd32_timer_set_top_value(const struct device *dev,
311 const struct counter_top_cfg *cfg)
312 {
313 const struct counter_gd32_config *config = dev->config;
314 struct counter_gd32_data *data = dev->data;
315 int err = 0;
316
317 for (uint32_t i = 0; i < config->counter_info.channels; i++) {
318 /* Overflow can be changed only when all alarms are
319 * disables.
320 */
321 if (data->alarm[i].callback) {
322 return -EBUSY;
323 }
324 }
325
326 interrupt_disable(dev, TIMER_INT_UP);
327 set_autoreload_value(dev, cfg->ticks);
328 interrupt_flag_clear(dev, TIMER_INT_FLAG_UP);
329
330 data->top_cb = cfg->callback;
331 data->top_user_data = cfg->user_data;
332
333 if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
334 set_counter(dev, 0);
335 } else if (get_counter(dev) >= cfg->ticks) {
336 err = -ETIME;
337 if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
338 set_counter(dev, 0);
339 }
340 }
341
342 if (cfg->callback) {
343 interrupt_enable(dev, TIMER_INT_UP);
344 }
345
346 return err;
347 }
348
counter_gd32_timer_get_pending_int(const struct device * dev)349 static uint32_t counter_gd32_timer_get_pending_int(const struct device *dev)
350 {
351 const struct counter_gd32_config *cfg = dev->config;
352
353 return cfg->get_irq_pending();
354 }
355
counter_gd32_timer_get_freq(const struct device * dev)356 static uint32_t counter_gd32_timer_get_freq(const struct device *dev)
357 {
358 struct counter_gd32_data *data = dev->data;
359
360 return data->freq;
361 }
362
counter_gd32_timer_get_guard_period(const struct device * dev,uint32_t flags)363 static uint32_t counter_gd32_timer_get_guard_period(const struct device *dev,
364 uint32_t flags)
365 {
366 struct counter_gd32_data *data = dev->data;
367
368 return data->guard_period;
369 }
370
counter_gd32_timer_set_guard_period(const struct device * dev,uint32_t guard,uint32_t flags)371 static int counter_gd32_timer_set_guard_period(const struct device *dev,
372 uint32_t guard, uint32_t flags)
373 {
374 struct counter_gd32_data *data = dev->data;
375
376 __ASSERT_NO_MSG(guard < counter_gd32_timer_get_top_value(dev));
377
378 data->guard_period = guard;
379 return 0;
380 }
381
top_irq_handle(const struct device * dev)382 static void top_irq_handle(const struct device *dev)
383 {
384 struct counter_gd32_data *data = dev->data;
385 counter_top_callback_t cb = data->top_cb;
386
387 if (interrupt_flag_get(dev, TIMER_INT_FLAG_UP) != 0) {
388 interrupt_flag_clear(dev, TIMER_INT_FLAG_UP);
389 __ASSERT(cb != NULL, "top event enabled - expecting callback");
390 cb(dev, data->top_user_data);
391 }
392 }
393
alarm_irq_handle(const struct device * dev,uint32_t chan)394 static void alarm_irq_handle(const struct device *dev, uint32_t chan)
395 {
396 struct counter_gd32_data *data = dev->data;
397 struct counter_gd32_ch_data *alarm = &data->alarm[chan];
398 counter_alarm_callback_t cb;
399 bool hw_irq_pending = !!(interrupt_flag_get(dev, TIMER_FLAG_CH(chan)));
400 bool sw_irq_pending = data->cc_int_pending & TIMER_INT_CH(chan);
401
402 if (hw_irq_pending || sw_irq_pending) {
403 atomic_and(&data->cc_int_pending, ~TIMER_INT_CH(chan));
404 interrupt_disable(dev, TIMER_INT_CH(chan));
405 interrupt_flag_clear(dev, TIMER_FLAG_CH(chan));
406
407 cb = alarm->callback;
408 alarm->callback = NULL;
409
410 if (cb) {
411 cb(dev, chan, get_counter(dev), alarm->user_data);
412 }
413 }
414 }
415
irq_handler(const struct device * dev)416 static void irq_handler(const struct device *dev)
417 {
418 const struct counter_gd32_config *cfg = dev->config;
419
420 top_irq_handle(dev);
421
422 for (uint32_t i = 0; i < cfg->counter_info.channels; i++) {
423 alarm_irq_handle(dev, i);
424 }
425 }
426
counter_gd32_timer_init(const struct device * dev)427 static int counter_gd32_timer_init(const struct device *dev)
428 {
429 const struct counter_gd32_config *cfg = dev->config;
430 struct counter_gd32_data *data = dev->data;
431 uint32_t pclk;
432
433 clock_control_on(GD32_CLOCK_CONTROLLER,
434 (clock_control_subsys_t)&cfg->clkid);
435 clock_control_get_rate(GD32_CLOCK_CONTROLLER,
436 (clock_control_subsys_t)&cfg->clkid, &pclk);
437
438 data->freq = pclk / (cfg->prescaler + 1);
439
440 interrupt_disable(dev, TIMER_INT_ALL);
441 reset_line_toggle_dt(&cfg->reset);
442
443 cfg->irq_config(dev);
444 set_prescaler(dev, cfg->prescaler);
445 set_autoreload_value(dev, cfg->counter_info.max_top_value);
446 set_software_event_gen(dev, TIMER_SWEVG_UPG);
447
448 return 0;
449 }
450
451 static const struct counter_driver_api counter_api = {
452 .start = counter_gd32_timer_start,
453 .stop = counter_gd32_timer_stop,
454 .get_value = counter_gd32_timer_get_value,
455 .set_alarm = counter_gd32_timer_set_alarm,
456 .cancel_alarm = counter_gd32_timer_cancel_alarm,
457 .set_top_value = counter_gd32_timer_set_top_value,
458 .get_pending_int = counter_gd32_timer_get_pending_int,
459 .get_top_value = counter_gd32_timer_get_top_value,
460 .get_guard_period = counter_gd32_timer_get_guard_period,
461 .set_guard_period = counter_gd32_timer_set_guard_period,
462 .get_freq = counter_gd32_timer_get_freq,
463 };
464
465 #define TIMER_IRQ_CONFIG(n) \
466 static void irq_config_##n(const struct device *dev) \
467 { \
468 IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, global, irq), \
469 DT_INST_IRQ_BY_NAME(n, global, priority), \
470 irq_handler, DEVICE_DT_INST_GET(n), 0); \
471 irq_enable(DT_INST_IRQ_BY_NAME(n, global, irq)); \
472 } \
473 static void set_irq_pending_##n(void) \
474 { \
475 (NVIC_SetPendingIRQ(DT_INST_IRQ_BY_NAME(n, global, irq))); \
476 } \
477 static uint32_t get_irq_pending_##n(void) \
478 { \
479 return NVIC_GetPendingIRQ( \
480 DT_INST_IRQ_BY_NAME(n, global, irq)); \
481 }
482
483 #define TIMER_IRQ_CONFIG_ADVANCED(n) \
484 static void irq_config_##n(const struct device *dev) \
485 { \
486 IRQ_CONNECT((DT_INST_IRQ_BY_NAME(n, up, irq)), \
487 (DT_INST_IRQ_BY_NAME(n, up, priority)), \
488 irq_handler, (DEVICE_DT_INST_GET(n)), 0); \
489 irq_enable((DT_INST_IRQ_BY_NAME(n, up, irq))); \
490 IRQ_CONNECT((DT_INST_IRQ_BY_NAME(n, cc, irq)), \
491 (DT_INST_IRQ_BY_NAME(n, cc, priority)), \
492 irq_handler, (DEVICE_DT_INST_GET(n)), 0); \
493 irq_enable((DT_INST_IRQ_BY_NAME(n, cc, irq))); \
494 } \
495 static void set_irq_pending_##n(void) \
496 { \
497 (NVIC_SetPendingIRQ(DT_INST_IRQ_BY_NAME(n, cc, irq))); \
498 } \
499 static uint32_t get_irq_pending_##n(void) \
500 { \
501 return NVIC_GetPendingIRQ(DT_INST_IRQ_BY_NAME(n, cc, irq)); \
502 }
503
504 #define GD32_TIMER_INIT(n) \
505 COND_CODE_1(DT_INST_PROP(n, is_advanced), \
506 (TIMER_IRQ_CONFIG_ADVANCED(n)), (TIMER_IRQ_CONFIG(n))); \
507 static struct counter_gd32_data_##n { \
508 struct counter_gd32_data data; \
509 struct counter_gd32_ch_data alarm[DT_INST_PROP(n, channels)]; \
510 } timer_data_##n = {0}; \
511 static const struct counter_gd32_config timer_config_##n = { \
512 .counter_info = {.max_top_value = COND_CODE_1( \
513 DT_INST_PROP(n, is_32bit), \
514 (UINT32_MAX), (UINT16_MAX)), \
515 .flags = COUNTER_CONFIG_INFO_COUNT_UP, \
516 .freq = 0, \
517 .channels = DT_INST_PROP(n, channels)}, \
518 .reg = DT_INST_REG_ADDR(n), \
519 .clkid = DT_INST_CLOCKS_CELL(n, id), \
520 .reset = RESET_DT_SPEC_INST_GET(n), \
521 .prescaler = DT_INST_PROP(n, prescaler), \
522 .irq_config = irq_config_##n, \
523 .set_irq_pending = set_irq_pending_##n, \
524 .get_irq_pending = get_irq_pending_##n, \
525 }; \
526 \
527 DEVICE_DT_INST_DEFINE(n, counter_gd32_timer_init, NULL, \
528 &timer_data_##n, &timer_config_##n, \
529 PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \
530 &counter_api);
531
532 DT_INST_FOREACH_STATUS_OKAY(GD32_TIMER_INIT);
533