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