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 cb = data->ch_data[i].alarm_callback;
108 data->ch_data[i].alarm_callback = NULL;
109
110 cur_ticks = get_current_tick(dev, 3);
111 cb(dev, i, cur_ticks, data->ch_data[i].alarm_user_data);
112 }
113 }
114
115 /* Disable channel and interrupt */
116 sys_write32(int_enable, PIT_INTE(dev));
117 sys_write32(ch_enable, PIT_CHEN(dev));
118
119 /* Clear interrupt status */
120 sys_write32(int_status, PIT_ISTA(dev));
121 }
122
counter_atcpit100_init(const struct device * dev)123 static int counter_atcpit100_init(const struct device *dev)
124 {
125 const struct atcpit100_config *config = dev->config;
126 uint32_t reg;
127
128 /* Disable all channels */
129 sys_write32(0, PIT_CHEN(dev));
130
131 /* Channel 0 ~ 3, 32 bits timer, PCLK source */
132 reg = CTRL_CH_MODE_32BIT | CTRL_CH_SRC_PCLK;
133 sys_write32(reg, PIT_CH_CTRL(dev, 0));
134 sys_write32(reg, PIT_CH_CTRL(dev, 1));
135 sys_write32(reg, PIT_CH_CTRL(dev, 2));
136 sys_write32(reg, PIT_CH_CTRL(dev, 3));
137
138 /* Disable all interrupt and clear all pending interrupt */
139 sys_write32(0, PIT_INTE(dev));
140 sys_write32(UINT32_MAX, PIT_ISTA(dev));
141
142 /* Select channel 3 as default counter and set max top value */
143 reg = config->info.max_top_value * config->divider;
144
145 /* Set cycle - 1 to reload register */
146 sys_write32((reg - 1), PIT_CH_RELD(dev, 3));
147
148 config->cfg_func();
149
150 irq_enable(config->irq_num);
151
152 return 0;
153 }
154
atcpit100_start(const struct device * dev)155 static int atcpit100_start(const struct device *dev)
156 {
157 struct atcpit100_data *data = dev->data;
158 k_spinlock_key_t key;
159 uint32_t reg;
160
161 key = k_spin_lock(&data->lock);
162
163 /* Enable channel */
164 reg = sys_read32(PIT_CHEN(dev));
165 reg |= TIMER0_CHANNEL(3);
166 sys_write32(reg, PIT_CHEN(dev));
167
168 k_spin_unlock(&data->lock, key);
169
170 return 0;
171 }
172
atcpit100_stop(const struct device * dev)173 static int atcpit100_stop(const struct device *dev)
174 {
175 struct atcpit100_data *data = dev->data;
176 k_spinlock_key_t key;
177 uint32_t reg;
178
179 key = k_spin_lock(&data->lock);
180
181 /* Disable channel interrupt */
182 reg = sys_read32(PIT_INTE(dev));
183 reg &= ~TIMER0_CHANNEL(3);
184 sys_write32(reg, PIT_INTE(dev));
185
186 /* Disable channel */
187 reg = sys_read32(PIT_CHEN(dev));
188 reg &= ~TIMER0_CHANNEL(3);
189 sys_write32(reg, PIT_CHEN(dev));
190
191 /* Clear interrupt status */
192 sys_write32(TIMER0_CHANNEL(3), PIT_ISTA(dev));
193
194 k_spin_unlock(&data->lock, key);
195
196 return 0;
197 }
198
atcpit100_get_value(const struct device * dev,uint32_t * ticks)199 static int atcpit100_get_value(const struct device *dev, uint32_t *ticks)
200 {
201 struct atcpit100_data *data = dev->data;
202 k_spinlock_key_t key;
203
204 key = k_spin_lock(&data->lock);
205
206 *ticks = get_current_tick(dev, 3);
207
208 k_spin_unlock(&data->lock, key);
209
210 return 0;
211 }
212
atcpit100_set_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)213 static int atcpit100_set_alarm(const struct device *dev, uint8_t chan_id,
214 const struct counter_alarm_cfg *alarm_cfg)
215 {
216 const struct atcpit100_config *config = dev->config;
217 struct atcpit100_data *data = dev->data;
218 uint32_t top, now_cnt, remain_cnt, alarm_cnt, flags, reg;
219 k_spinlock_key_t key;
220 int err = 0;
221
222 if (chan_id >= CH_NUM_PER_COUNTER) {
223 return -ENOTSUP;
224 }
225
226 if (!alarm_cfg->callback) {
227 return -EINVAL;
228 }
229
230 if (data->ch_data[chan_id].alarm_callback) {
231 return -EBUSY;
232 }
233
234 key = k_spin_lock(&data->lock);
235
236 /* Preload cycles is reload register + 1 */
237 top = sys_read32(PIT_CH_RELD(dev, 3)) + 1;
238 remain_cnt = sys_read32(PIT_CH_CNTR(dev, 3));
239 alarm_cnt = alarm_cfg->ticks * config->divider;
240
241 if (alarm_cnt > top) {
242 err = -EINVAL;
243 goto out;
244 }
245
246 flags = alarm_cfg->flags;
247 data->ch_data[chan_id].alarm_callback = alarm_cfg->callback;
248 data->ch_data[chan_id].alarm_user_data = alarm_cfg->user_data;
249
250 if (flags & COUNTER_ALARM_CFG_ABSOLUTE) {
251 uint32_t irq_on_late, max_rel_val;
252
253 now_cnt = top - remain_cnt;
254 max_rel_val = top - (data->guard_period * config->divider);
255 irq_on_late = flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
256
257 if (now_cnt < alarm_cnt) {
258 /* Absolute alarm is in this round counting */
259 reg = alarm_cnt - now_cnt;
260 irq_on_late = 0;
261 } else {
262 /* Absolute alarm is in the next round counting */
263 reg = alarm_cnt + remain_cnt;
264 }
265
266 if (reg > max_rel_val) {
267 /* Absolute alarm is in the guard period */
268 err = -ETIME;
269 if (!irq_on_late) {
270 data->ch_data[chan_id].alarm_callback = NULL;
271 goto out;
272 }
273 }
274
275 if (irq_on_late) {
276 /* Trigger interrupt immediately */
277 reg = 1;
278 }
279 } else {
280 /* Round up decreasing counter to tick boundary */
281 now_cnt = remain_cnt + config->divider - 1;
282 now_cnt = (now_cnt / config->divider) * config->divider;
283
284 /* Adjusting relative alarm counter to tick boundary */
285 reg = alarm_cnt - (now_cnt - remain_cnt);
286 }
287
288 /* Set cycle - 1 to reload register */
289 sys_write32((reg - 1), PIT_CH_RELD(dev, chan_id));
290
291 /* Enable channel interrupt */
292 reg = sys_read32(PIT_INTE(dev));
293 reg |= TIMER0_CHANNEL(chan_id);
294 sys_write32(reg, PIT_INTE(dev));
295
296 /* Enable channel */
297 reg = sys_read32(PIT_CHEN(dev));
298 reg |= TIMER0_CHANNEL(chan_id);
299 sys_write32(reg, PIT_CHEN(dev));
300
301 out:
302 k_spin_unlock(&data->lock, key);
303
304 return err;
305 }
306
atcpit100_cancel_alarm(const struct device * dev,uint8_t chan_id)307 static int atcpit100_cancel_alarm(const struct device *dev, uint8_t chan_id)
308 {
309 struct atcpit100_data *data = dev->data;
310 k_spinlock_key_t key;
311 uint32_t reg;
312
313 if (chan_id >= CH_NUM_PER_COUNTER) {
314 return -ENOTSUP;
315 }
316
317 key = k_spin_lock(&data->lock);
318
319 /* Disable channel interrupt */
320 reg = sys_read32(PIT_INTE(dev));
321 reg &= ~TIMER0_CHANNEL(chan_id);
322 sys_write32(reg, PIT_INTE(dev));
323
324 /* Disable channel */
325 reg = sys_read32(PIT_CHEN(dev));
326 reg &= ~TIMER0_CHANNEL(chan_id);
327 sys_write32(reg, PIT_CHEN(dev));
328
329 /* Clear interrupt status */
330 sys_write32(TIMER0_CHANNEL(chan_id), PIT_ISTA(dev));
331
332 data->ch_data[chan_id].alarm_callback = NULL;
333
334 k_spin_unlock(&data->lock, key);
335
336 return 0;
337 }
338
atcpit100_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)339 static int atcpit100_set_top_value(const struct device *dev,
340 const struct counter_top_cfg *cfg)
341 {
342 const struct atcpit100_config *config = dev->config;
343 struct atcpit100_data *data = dev->data;
344 uint32_t ticks, reg, reset_counter = 1;
345 k_spinlock_key_t key;
346 int err = 0;
347 uint8_t i;
348
349 for (i = 0; i < counter_get_num_of_channels(dev); i++) {
350 if (data->ch_data[i].alarm_callback) {
351 return -EBUSY;
352 }
353 }
354
355 if (cfg->ticks > config->info.max_top_value) {
356 return -ENOTSUP;
357 }
358
359 key = k_spin_lock(&data->lock);
360
361 if (cfg->callback) {
362 /* Disable channel interrupt */
363 reg = sys_read32(PIT_INTE(dev));
364 reg &= ~TIMER0_CHANNEL(3);
365 sys_write32(reg, PIT_INTE(dev));
366
367 data->top_callback = cfg->callback;
368 data->top_user_data = cfg->user_data;
369
370 /* Enable channel interrupt */
371 reg = sys_read32(PIT_INTE(dev));
372 reg |= TIMER0_CHANNEL(3);
373 sys_write32(reg, PIT_INTE(dev));
374 }
375
376 if (cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
377 /* Don't reset counter */
378 reset_counter = 0;
379 ticks = get_current_tick(dev, 3);
380 if (ticks >= cfg->ticks) {
381 err = -ETIME;
382 if (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
383 /* Reset counter if current is late */
384 reset_counter = 1;
385 }
386 }
387 }
388
389 /* Set cycle - 1 to reload register */
390 reg = cfg->ticks * config->divider;
391 sys_write32((reg - 1), PIT_CH_RELD(dev, 3));
392
393 if (reset_counter) {
394 /* Disable channel */
395 reg = sys_read32(PIT_CHEN(dev));
396 reg &= ~TIMER0_CHANNEL(3);
397 sys_write32(reg, PIT_CHEN(dev));
398
399 /* Clear interrupt status */
400 sys_write32(TIMER0_CHANNEL(3), PIT_ISTA(dev));
401
402 /* Enable channel interrupt */
403 reg = sys_read32(PIT_INTE(dev));
404 reg |= TIMER0_CHANNEL(3);
405 sys_write32(reg, PIT_INTE(dev));
406
407 /* Enable channel */
408 reg = sys_read32(PIT_CHEN(dev));
409 reg |= TIMER0_CHANNEL(3);
410 sys_write32(reg, PIT_CHEN(dev));
411 }
412
413 k_spin_unlock(&data->lock, key);
414
415 return err;
416 }
417
atcpit100_get_pending_int(const struct device * dev)418 static uint32_t atcpit100_get_pending_int(const struct device *dev)
419 {
420 uint32_t reg = sys_read32(PIT_ISTA(dev));
421
422 reg &= (TIMER0_CHANNEL(0) | TIMER0_CHANNEL(1) |
423 TIMER0_CHANNEL(2) | TIMER0_CHANNEL(3));
424
425 return !(!reg);
426 }
427
atcpit100_get_top_value(const struct device * dev)428 static uint32_t atcpit100_get_top_value(const struct device *dev)
429 {
430 const struct atcpit100_config *config = dev->config;
431 uint32_t top = sys_read32(PIT_CH_RELD(dev, 3)) + 1;
432
433 return (top / config->divider);
434 }
435
atcpit100_get_guard_period(const struct device * dev,uint32_t flags)436 static uint32_t atcpit100_get_guard_period(const struct device *dev,
437 uint32_t flags)
438 {
439 struct atcpit100_data *data = dev->data;
440
441 return data->guard_period;
442 }
443
atcpit100_set_guard_period(const struct device * dev,uint32_t ticks,uint32_t flags)444 static int atcpit100_set_guard_period(const struct device *dev,
445 uint32_t ticks, uint32_t flags)
446 {
447 const struct atcpit100_config *config = dev->config;
448 struct atcpit100_data *data = dev->data;
449 uint32_t top = sys_read32(PIT_CH_RELD(dev, 3)) + 1;
450
451 if ((ticks * config->divider) > top) {
452 return -EINVAL;
453 }
454
455 data->guard_period = ticks;
456
457 return 0;
458 }
459
460 static const struct counter_driver_api atcpit100_driver_api = {
461 .start = atcpit100_start,
462 .stop = atcpit100_stop,
463 .get_value = atcpit100_get_value,
464 .set_alarm = atcpit100_set_alarm,
465 .cancel_alarm = atcpit100_cancel_alarm,
466 .set_top_value = atcpit100_set_top_value,
467 .get_pending_int = atcpit100_get_pending_int,
468 .get_top_value = atcpit100_get_top_value,
469 .get_guard_period = atcpit100_get_guard_period,
470 .set_guard_period = atcpit100_set_guard_period,
471 };
472
473 #define COUNTER_ATCPIT100_INIT(n) \
474 static void counter_atcpit100_cfg_##n(void); \
475 static struct atcpit100_data atcpit100_data_##n; \
476 \
477 static const struct atcpit100_config atcpit100_config_##n = { \
478 .info = { \
479 .max_top_value = \
480 (UINT32_MAX/DT_INST_PROP(n, prescaler)),\
481 .freq = (DT_INST_PROP(n, clock_frequency) / \
482 DT_INST_PROP(n, prescaler)), \
483 .flags = COUNTER_CONFIG_INFO_COUNT_UP, \
484 .channels = CH_NUM_PER_COUNTER, \
485 }, \
486 .base = DT_INST_REG_ADDR(n), \
487 .divider = DT_INST_PROP(n, prescaler), \
488 .irq_num = DT_INST_IRQN(n), \
489 .cfg_func = counter_atcpit100_cfg_##n, \
490 }; \
491 \
492 DEVICE_DT_INST_DEFINE(n, \
493 counter_atcpit100_init, \
494 NULL, \
495 &atcpit100_data_##n, \
496 &atcpit100_config_##n, \
497 POST_KERNEL, \
498 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
499 &atcpit100_driver_api); \
500 \
501 static void counter_atcpit100_cfg_##n(void) \
502 { \
503 IRQ_CONNECT(DT_INST_IRQN(n), \
504 DT_INST_IRQ(n, priority), \
505 atcpit100_irq_handler, \
506 DEVICE_DT_INST_GET(n), \
507 0); \
508 }
509
510 DT_INST_FOREACH_STATUS_OKAY(COUNTER_ATCPIT100_INIT)
511