1 /*
2 * Copyright (c) 2022 Andes Technology
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/counter.h>
8 #include <zephyr/spinlock.h>
9 #include <zephyr/irq.h>
10 #include <zephyr/arch/cpu.h>
11 #include <string.h>
12
13 #define DT_DRV_COMPAT andestech_atcpit100
14
15 /* register definitions */
16 #define REG_IDR 0x00 /* ID and Revision Reg. */
17 #define REG_CFG 0x10 /* Configuration Reg. */
18 #define REG_INTE 0x14 /* Interrupt Enable Reg. */
19 #define REG_ISTA 0x18 /* Interrupt Status Reg. */
20 #define REG_CHEN 0x1C /* Channel Enable Reg. */
21 #define REG_CTRL0 0x20 /* Channel 0 Control Reg. */
22 #define REG_RELD0 0x24 /* Channel 0 Reload Reg. */
23 #define REG_CNTR0 0x28 /* Channel 0 Counter Reg. */
24 #define REG_CTRL1 0x30 /* Channel 1 Control Reg. */
25 #define REG_RELD1 0x34 /* Channel 1 Reload Reg. */
26 #define REG_CNTR1 0x38 /* Channel 1 Counter Reg. */
27 #define REG_CTRL2 0x40 /* Channel 2 Control Reg. */
28 #define REG_RELD2 0x44 /* Channel 2 Reload Reg. */
29 #define REG_CNTR2 0x48 /* Channel 2 Counter Reg. */
30 #define REG_CTRL3 0x50 /* Channel 3 Control Reg. */
31 #define REG_RELD3 0x54 /* Channel 3 Reload Reg. */
32 #define REG_CNTR3 0x58 /* Channel 3 Counter Reg. */
33
34 #define PIT_BASE (((const struct atcpit100_config *)(dev)->config)->base)
35 #define PIT_INTE(dev) (PIT_BASE + REG_INTE)
36 #define PIT_ISTA(dev) (PIT_BASE + REG_ISTA)
37 #define PIT_CHEN(dev) (PIT_BASE + REG_CHEN)
38 #define PIT_CH_CTRL(dev, ch) (PIT_BASE + REG_CTRL0 + (ch << 4))
39 #define PIT_CH_RELD(dev, ch) (PIT_BASE + REG_RELD0 + (ch << 4))
40 #define PIT_CH_CNTR(dev, ch) (PIT_BASE + REG_CNTR0 + (ch << 4))
41
42 #define CTRL_CH_SRC_PCLK BIT(3)
43 #define CTRL_CH_MODE_32BIT BIT(0)
44
45 #define CHANNEL_NUM (4)
46 #define CH_NUM_PER_COUNTER (CHANNEL_NUM - 1)
47 #define TIMER0_CHANNEL(ch) BIT(((ch) * CHANNEL_NUM))
48
49 typedef void (*atcpit100_cfg_func_t)(void);
50
51 struct atcpit100_config {
52 struct counter_config_info info;
53 uint32_t base;
54 uint32_t divider;
55 uint32_t irq_num;
56 atcpit100_cfg_func_t cfg_func;
57 };
58
59 struct counter_atcpit100_ch_data {
60 counter_alarm_callback_t alarm_callback;
61 void *alarm_user_data;
62 };
63
64 struct atcpit100_data {
65 counter_top_callback_t top_callback;
66 void *top_user_data;
67 uint32_t guard_period;
68 struct k_spinlock lock;
69 struct counter_atcpit100_ch_data ch_data[CH_NUM_PER_COUNTER];
70 };
71
get_current_tick(const struct device * dev,uint32_t ch)72 static inline uint32_t get_current_tick(const struct device *dev, uint32_t ch)
73 {
74 const struct atcpit100_config *config = dev->config;
75 uint32_t top, now_cnt;
76
77 /* Preload cycles is reload register + 1 */
78 top = sys_read32(PIT_CH_RELD(dev, ch)) + 1;
79 now_cnt = top - sys_read32(PIT_CH_CNTR(dev, ch));
80
81 return (now_cnt / config->divider);
82 }
83
atcpit100_irq_handler(void * arg)84 static void atcpit100_irq_handler(void *arg)
85 {
86 struct device *dev = (struct device *)arg;
87 struct atcpit100_data *data = dev->data;
88 counter_alarm_callback_t cb;
89 uint32_t int_status, int_enable, ch_enable, cur_ticks;
90 uint8_t i;
91
92 ch_enable = sys_read32(PIT_CHEN(dev));
93 int_enable = sys_read32(PIT_INTE(dev));
94 int_status = sys_read32(PIT_ISTA(dev));
95
96 if (int_status & TIMER0_CHANNEL(3)) {
97 if (data->top_callback) {
98 data->top_callback(dev, data->top_user_data);
99 }
100 }
101
102 for (i = 0; i < CH_NUM_PER_COUNTER; i++) {
103 if (int_status & TIMER0_CHANNEL(i)) {
104 int_enable &= ~TIMER0_CHANNEL(i);
105 ch_enable &= ~TIMER0_CHANNEL(i);
106 }
107 }
108
109 /* Disable channel and interrupt */
110 sys_write32(int_enable, PIT_INTE(dev));
111 sys_write32(ch_enable, PIT_CHEN(dev));
112
113 /* Clear interrupt status */
114 sys_write32(int_status, PIT_ISTA(dev));
115
116 for (i = 0; i < CH_NUM_PER_COUNTER; i++) {
117 if (int_status & TIMER0_CHANNEL(i)) {
118 cur_ticks = get_current_tick(dev, 3);
119 cb = data->ch_data[i].alarm_callback;
120 data->ch_data[i].alarm_callback = NULL;
121 if (cb != NULL) {
122 cb(dev, i, cur_ticks, data->ch_data[i].alarm_user_data);
123 }
124 }
125 }
126 }
127
counter_atcpit100_init(const struct device * dev)128 static int counter_atcpit100_init(const struct device *dev)
129 {
130 const struct atcpit100_config *config = dev->config;
131 uint32_t reg;
132
133 /* Disable all channels */
134 sys_write32(0, PIT_CHEN(dev));
135
136 /* Channel 0 ~ 3, 32 bits timer, PCLK source */
137 reg = CTRL_CH_MODE_32BIT | CTRL_CH_SRC_PCLK;
138 sys_write32(reg, PIT_CH_CTRL(dev, 0));
139 sys_write32(reg, PIT_CH_CTRL(dev, 1));
140 sys_write32(reg, PIT_CH_CTRL(dev, 2));
141 sys_write32(reg, PIT_CH_CTRL(dev, 3));
142
143 /* Disable all interrupt and clear all pending interrupt */
144 sys_write32(0, PIT_INTE(dev));
145 sys_write32(UINT32_MAX, PIT_ISTA(dev));
146
147 /* Select channel 3 as default counter and set max top value */
148 reg = config->info.max_top_value * config->divider;
149
150 /* Set cycle - 1 to reload register */
151 sys_write32((reg - 1), PIT_CH_RELD(dev, 3));
152
153 config->cfg_func();
154
155 irq_enable(config->irq_num);
156
157 return 0;
158 }
159
atcpit100_start(const struct device * dev)160 static int atcpit100_start(const struct device *dev)
161 {
162 struct atcpit100_data *data = dev->data;
163 k_spinlock_key_t key;
164 uint32_t reg;
165
166 key = k_spin_lock(&data->lock);
167
168 /* Enable channel */
169 reg = sys_read32(PIT_CHEN(dev));
170 reg |= TIMER0_CHANNEL(3);
171 sys_write32(reg, PIT_CHEN(dev));
172
173 k_spin_unlock(&data->lock, key);
174
175 return 0;
176 }
177
atcpit100_stop(const struct device * dev)178 static int atcpit100_stop(const struct device *dev)
179 {
180 struct atcpit100_data *data = dev->data;
181 k_spinlock_key_t key;
182 uint32_t reg;
183
184 key = k_spin_lock(&data->lock);
185
186 /* Disable channel interrupt */
187 reg = sys_read32(PIT_INTE(dev));
188 reg &= ~TIMER0_CHANNEL(3);
189 sys_write32(reg, PIT_INTE(dev));
190
191 /* Disable channel */
192 reg = sys_read32(PIT_CHEN(dev));
193 reg &= ~TIMER0_CHANNEL(3);
194 sys_write32(reg, PIT_CHEN(dev));
195
196 /* Clear interrupt status */
197 sys_write32(TIMER0_CHANNEL(3), PIT_ISTA(dev));
198
199 k_spin_unlock(&data->lock, key);
200
201 return 0;
202 }
203
atcpit100_get_value(const struct device * dev,uint32_t * ticks)204 static int atcpit100_get_value(const struct device *dev, uint32_t *ticks)
205 {
206 struct atcpit100_data *data = dev->data;
207 k_spinlock_key_t key;
208
209 key = k_spin_lock(&data->lock);
210
211 *ticks = get_current_tick(dev, 3);
212
213 k_spin_unlock(&data->lock, key);
214
215 return 0;
216 }
217
atcpit100_set_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)218 static int atcpit100_set_alarm(const struct device *dev, uint8_t chan_id,
219 const struct counter_alarm_cfg *alarm_cfg)
220 {
221 const struct atcpit100_config *config = dev->config;
222 struct atcpit100_data *data = dev->data;
223 uint32_t top, now_cnt, remain_cnt, alarm_cnt, flags, reg;
224 k_spinlock_key_t key;
225 int err = 0;
226
227 if (chan_id >= CH_NUM_PER_COUNTER) {
228 return -ENOTSUP;
229 }
230
231 if (!alarm_cfg->callback) {
232 return -EINVAL;
233 }
234
235 if (data->ch_data[chan_id].alarm_callback) {
236 return -EBUSY;
237 }
238
239 key = k_spin_lock(&data->lock);
240
241 /* Preload cycles is reload register + 1 */
242 top = sys_read32(PIT_CH_RELD(dev, 3)) + 1;
243 remain_cnt = sys_read32(PIT_CH_CNTR(dev, 3));
244 alarm_cnt = alarm_cfg->ticks * config->divider;
245
246 if (alarm_cnt > top) {
247 err = -EINVAL;
248 goto out;
249 }
250
251 flags = alarm_cfg->flags;
252 data->ch_data[chan_id].alarm_callback = alarm_cfg->callback;
253 data->ch_data[chan_id].alarm_user_data = alarm_cfg->user_data;
254
255 if (flags & COUNTER_ALARM_CFG_ABSOLUTE) {
256 uint32_t irq_on_late, max_rel_val;
257
258 now_cnt = top - remain_cnt;
259 max_rel_val = top - (data->guard_period * config->divider);
260 irq_on_late = flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
261
262 if (now_cnt < alarm_cnt) {
263 /* Absolute alarm is in this round counting */
264 reg = alarm_cnt - now_cnt;
265 irq_on_late = 0;
266 } else {
267 /* Absolute alarm is in the next round counting */
268 reg = alarm_cnt + remain_cnt;
269 }
270
271 if (reg > max_rel_val) {
272 /* Absolute alarm is in the guard period */
273 err = -ETIME;
274 if (!irq_on_late) {
275 data->ch_data[chan_id].alarm_callback = NULL;
276 goto out;
277 }
278 }
279
280 if (irq_on_late) {
281 /* Trigger interrupt immediately */
282 reg = 1;
283 }
284 } else {
285 /* Round up decreasing counter to tick boundary */
286 now_cnt = remain_cnt + config->divider - 1;
287 now_cnt = (now_cnt / config->divider) * config->divider;
288
289 /* Adjusting relative alarm counter to tick boundary */
290 reg = alarm_cnt - (now_cnt - remain_cnt);
291 }
292
293 /* Set cycle - 1 to reload register */
294 sys_write32((reg - 1), PIT_CH_RELD(dev, chan_id));
295
296 /* Enable channel interrupt */
297 reg = sys_read32(PIT_INTE(dev));
298 reg |= TIMER0_CHANNEL(chan_id);
299 sys_write32(reg, PIT_INTE(dev));
300
301 /* Enable channel */
302 reg = sys_read32(PIT_CHEN(dev));
303 reg |= TIMER0_CHANNEL(chan_id);
304 sys_write32(reg, PIT_CHEN(dev));
305
306 out:
307 k_spin_unlock(&data->lock, key);
308
309 return err;
310 }
311
atcpit100_cancel_alarm(const struct device * dev,uint8_t chan_id)312 static int atcpit100_cancel_alarm(const struct device *dev, uint8_t chan_id)
313 {
314 struct atcpit100_data *data = dev->data;
315 k_spinlock_key_t key;
316 uint32_t reg;
317
318 if (chan_id >= CH_NUM_PER_COUNTER) {
319 return -ENOTSUP;
320 }
321
322 key = k_spin_lock(&data->lock);
323
324 /* Disable channel interrupt */
325 reg = sys_read32(PIT_INTE(dev));
326 reg &= ~TIMER0_CHANNEL(chan_id);
327 sys_write32(reg, PIT_INTE(dev));
328
329 /* Disable channel */
330 reg = sys_read32(PIT_CHEN(dev));
331 reg &= ~TIMER0_CHANNEL(chan_id);
332 sys_write32(reg, PIT_CHEN(dev));
333
334 /* Clear interrupt status */
335 sys_write32(TIMER0_CHANNEL(chan_id), PIT_ISTA(dev));
336
337 data->ch_data[chan_id].alarm_callback = NULL;
338
339 k_spin_unlock(&data->lock, key);
340
341 return 0;
342 }
343
atcpit100_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)344 static int atcpit100_set_top_value(const struct device *dev,
345 const struct counter_top_cfg *cfg)
346 {
347 const struct atcpit100_config *config = dev->config;
348 struct atcpit100_data *data = dev->data;
349 uint32_t ticks, reg, reset_counter = 1;
350 k_spinlock_key_t key;
351 int err = 0;
352 uint8_t i;
353
354 for (i = 0; i < counter_get_num_of_channels(dev); i++) {
355 if (data->ch_data[i].alarm_callback) {
356 return -EBUSY;
357 }
358 }
359
360 if (cfg->ticks > config->info.max_top_value) {
361 return -ENOTSUP;
362 }
363
364 key = k_spin_lock(&data->lock);
365
366 if (cfg->callback) {
367 /* Disable channel interrupt */
368 reg = sys_read32(PIT_INTE(dev));
369 reg &= ~TIMER0_CHANNEL(3);
370 sys_write32(reg, PIT_INTE(dev));
371
372 data->top_callback = cfg->callback;
373 data->top_user_data = cfg->user_data;
374
375 /* Enable channel interrupt */
376 reg = sys_read32(PIT_INTE(dev));
377 reg |= TIMER0_CHANNEL(3);
378 sys_write32(reg, PIT_INTE(dev));
379 }
380
381 if (cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
382 /* Don't reset counter */
383 reset_counter = 0;
384 ticks = get_current_tick(dev, 3);
385 if (ticks >= cfg->ticks) {
386 err = -ETIME;
387 if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
388 /* Reset counter if current is late */
389 reset_counter = 1;
390 }
391 }
392 }
393
394 /* Set cycle - 1 to reload register */
395 reg = cfg->ticks * config->divider;
396 sys_write32((reg - 1), PIT_CH_RELD(dev, 3));
397
398 if (reset_counter) {
399 /* Disable channel */
400 reg = sys_read32(PIT_CHEN(dev));
401 reg &= ~TIMER0_CHANNEL(3);
402 sys_write32(reg, PIT_CHEN(dev));
403
404 /* Clear interrupt status */
405 sys_write32(TIMER0_CHANNEL(3), PIT_ISTA(dev));
406
407 /* Enable channel interrupt */
408 reg = sys_read32(PIT_INTE(dev));
409 reg |= TIMER0_CHANNEL(3);
410 sys_write32(reg, PIT_INTE(dev));
411
412 /* Enable channel */
413 reg = sys_read32(PIT_CHEN(dev));
414 reg |= TIMER0_CHANNEL(3);
415 sys_write32(reg, PIT_CHEN(dev));
416 }
417
418 k_spin_unlock(&data->lock, key);
419
420 return err;
421 }
422
atcpit100_get_pending_int(const struct device * dev)423 static uint32_t atcpit100_get_pending_int(const struct device *dev)
424 {
425 uint32_t reg = sys_read32(PIT_ISTA(dev));
426
427 reg &= (TIMER0_CHANNEL(0) | TIMER0_CHANNEL(1) |
428 TIMER0_CHANNEL(2) | TIMER0_CHANNEL(3));
429
430 return !(!reg);
431 }
432
atcpit100_get_top_value(const struct device * dev)433 static uint32_t atcpit100_get_top_value(const struct device *dev)
434 {
435 const struct atcpit100_config *config = dev->config;
436 uint32_t top = sys_read32(PIT_CH_RELD(dev, 3)) + 1;
437
438 return (top / config->divider);
439 }
440
atcpit100_get_guard_period(const struct device * dev,uint32_t flags)441 static uint32_t atcpit100_get_guard_period(const struct device *dev,
442 uint32_t flags)
443 {
444 struct atcpit100_data *data = dev->data;
445
446 return data->guard_period;
447 }
448
atcpit100_set_guard_period(const struct device * dev,uint32_t ticks,uint32_t flags)449 static int atcpit100_set_guard_period(const struct device *dev,
450 uint32_t ticks, uint32_t flags)
451 {
452 const struct atcpit100_config *config = dev->config;
453 struct atcpit100_data *data = dev->data;
454 uint32_t top = sys_read32(PIT_CH_RELD(dev, 3)) + 1;
455
456 if ((ticks * config->divider) > top) {
457 return -EINVAL;
458 }
459
460 data->guard_period = ticks;
461
462 return 0;
463 }
464
465 static DEVICE_API(counter, atcpit100_driver_api) = {
466 .start = atcpit100_start,
467 .stop = atcpit100_stop,
468 .get_value = atcpit100_get_value,
469 .set_alarm = atcpit100_set_alarm,
470 .cancel_alarm = atcpit100_cancel_alarm,
471 .set_top_value = atcpit100_set_top_value,
472 .get_pending_int = atcpit100_get_pending_int,
473 .get_top_value = atcpit100_get_top_value,
474 .get_guard_period = atcpit100_get_guard_period,
475 .set_guard_period = atcpit100_set_guard_period,
476 };
477
478 #define COUNTER_ATCPIT100_INIT(n) \
479 static void counter_atcpit100_cfg_##n(void); \
480 static struct atcpit100_data atcpit100_data_##n; \
481 \
482 static const struct atcpit100_config atcpit100_config_##n = { \
483 .info = { \
484 .max_top_value = \
485 (UINT32_MAX/DT_INST_PROP(n, prescaler)),\
486 .freq = (DT_INST_PROP(n, clock_frequency) / \
487 DT_INST_PROP(n, prescaler)), \
488 .flags = COUNTER_CONFIG_INFO_COUNT_UP, \
489 .channels = CH_NUM_PER_COUNTER, \
490 }, \
491 .base = DT_INST_REG_ADDR(n), \
492 .divider = DT_INST_PROP(n, prescaler), \
493 .irq_num = DT_INST_IRQN(n), \
494 .cfg_func = counter_atcpit100_cfg_##n, \
495 }; \
496 \
497 DEVICE_DT_INST_DEFINE(n, \
498 counter_atcpit100_init, \
499 NULL, \
500 &atcpit100_data_##n, \
501 &atcpit100_config_##n, \
502 PRE_KERNEL_1, \
503 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
504 &atcpit100_driver_api); \
505 \
506 static void counter_atcpit100_cfg_##n(void) \
507 { \
508 IRQ_CONNECT(DT_INST_IRQN(n), \
509 DT_INST_IRQ(n, priority), \
510 atcpit100_irq_handler, \
511 DEVICE_DT_INST_GET(n), \
512 0); \
513 }
514
515 DT_INST_FOREACH_STATUS_OKAY(COUNTER_ATCPIT100_INIT)
516