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