1 /*
2 * Copyright (c) 2020 ITE Corporation. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #define DT_DRV_COMPAT ite_it8xxx2_timer
7
8 #include <zephyr/init.h>
9 #include <zephyr/drivers/timer/system_timer.h>
10 #include <zephyr/dt-bindings/interrupt-controller/ite-intc.h>
11 #include <soc.h>
12 #include <zephyr/spinlock.h>
13 #include <zephyr/sys_clock.h>
14
15 #include <zephyr/logging/log.h>
16 #include <zephyr/irq.h>
17 LOG_MODULE_REGISTER(timer, LOG_LEVEL_ERR);
18
19 #define COUNT_1US (EC_FREQ / USEC_PER_SEC - 1)
20
21 BUILD_ASSERT(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 32768,
22 "ITE RTOS timer HW frequency is fixed at 32768Hz");
23
24 /* Event timer configurations */
25 #define EVENT_TIMER EXT_TIMER_3
26 #define EVENT_TIMER_IRQ DT_INST_IRQ_BY_IDX(0, 0, irq)
27 #define EVENT_TIMER_FLAG DT_INST_IRQ_BY_IDX(0, 0, flags)
28 /* Event timer max count is 512 sec (base on clock source 32768Hz) */
29 #define EVENT_TIMER_MAX_CNT 0x00FFFFFFUL
30
31 /* Busy wait low timer configurations */
32 #define BUSY_WAIT_L_TIMER EXT_TIMER_5
33 #define BUSY_WAIT_L_TIMER_IRQ DT_INST_IRQ_BY_IDX(0, 2, irq)
34 #define BUSY_WAIT_L_TIMER_FLAG DT_INST_IRQ_BY_IDX(0, 2, flags)
35
36 /* Busy wait high timer configurations */
37 #define BUSY_WAIT_H_TIMER EXT_TIMER_6
38 #define BUSY_WAIT_H_TIMER_IRQ DT_INST_IRQ_BY_IDX(0, 3, irq)
39 #define BUSY_WAIT_H_TIMER_FLAG DT_INST_IRQ_BY_IDX(0, 3, flags)
40 /* Busy wait high timer max count is 71.58min (base on clock source 1MHz) */
41 #define BUSY_WAIT_TIMER_H_MAX_CNT 0xFFFFFFFFUL
42
43 #if defined(CONFIG_TEST)
44 const int32_t z_sys_timer_irq_for_test = DT_IRQ_BY_IDX(DT_NODELABEL(timer), 5, irq);
45 #endif
46
47 #ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
48 /*
49 * One shot timer configurations
50 *
51 * NOTE: Timer1/2 register address isn't regular like timer3/4/5/6/7/8, and
52 * timer1 is used for printing watchdog warning message. So now we use
53 * timer2 only one shot to wake up chip and change pll.
54 */
55 #define WDT_BASE DT_REG_ADDR(DT_NODELABEL(twd0))
56 #define WDT_REG (struct wdt_it8xxx2_regs *)(WDT_BASE)
57 #define ONE_SHOT_TIMER_IRQ DT_IRQ_BY_IDX(DT_NODELABEL(twd0), 1, irq)
58 #define ONE_SHOT_TIMER_FLAG DT_IRQ_BY_IDX(DT_NODELABEL(twd0), 1, flags)
59 #endif
60
61 #define MS_TO_COUNT(hz, ms) ((hz) * (ms) / 1000)
62 /*
63 * One system (kernel) tick is as how much HW timer counts
64 *
65 * NOTE: Event and free run timer individually select the same clock source
66 * frequency, so they can use the same HW_CNT_PER_SYS_TICK to transform
67 * unit between HW count and system tick. If clock source frequency is
68 * different, then we should define another to transform.
69 */
70 #define HW_CNT_PER_SYS_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \
71 / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
72 /* Event timer max count is as how much system (kernel) tick */
73 #define EVEN_TIMER_MAX_CNT_SYS_TICK (EVENT_TIMER_MAX_CNT \
74 / HW_CNT_PER_SYS_TICK)
75
76 static struct k_spinlock lock;
77 /* Last HW count that we called sys_clock_announce() */
78 static volatile uint32_t last_announced_hw_cnt;
79
80 enum ext_timer_raw_cnt {
81 EXT_NOT_RAW_CNT = 0,
82 EXT_RAW_CNT,
83 };
84
85 enum ext_timer_init {
86 EXT_NOT_FIRST_TIME_ENABLE = 0,
87 EXT_FIRST_TIME_ENABLE,
88 };
89
90 enum ext_timer_int {
91 EXT_WITHOUT_TIMER_INT = 0,
92 EXT_WITH_TIMER_INT,
93 };
94
95 enum ext_timer_start {
96 EXT_NOT_START_TIMER = 0,
97 EXT_START_TIMER,
98 };
99
100 #ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
timer_5ms_one_shot_isr(const void * unused)101 static void timer_5ms_one_shot_isr(const void *unused)
102 {
103 ARG_UNUSED(unused);
104
105 /*
106 * We are here because we have completed changing PLL sequence,
107 * so disabled one shot timer interrupt.
108 */
109 irq_disable(ONE_SHOT_TIMER_IRQ);
110 }
111
112 /*
113 * This timer is used to wake up chip from sleep mode to complete
114 * changing PLL sequence.
115 */
timer_5ms_one_shot(void)116 void timer_5ms_one_shot(void)
117 {
118 struct wdt_it8xxx2_regs *const timer2_reg = WDT_REG;
119 uint32_t hw_cnt;
120
121 /* Initialize interrupt handler of one shot timer */
122 IRQ_CONNECT(ONE_SHOT_TIMER_IRQ, 0, timer_5ms_one_shot_isr, NULL,
123 ONE_SHOT_TIMER_FLAG);
124
125 /* Set rising edge triggered of one shot timer */
126 ite_intc_irq_polarity_set(ONE_SHOT_TIMER_IRQ, ONE_SHOT_TIMER_FLAG);
127
128 /* Clear interrupt status of one shot timer */
129 ite_intc_isr_clear(ONE_SHOT_TIMER_IRQ);
130
131 /* Set clock source of one shot timer */
132 timer2_reg->ET2PSR = EXT_PSR_32P768K;
133
134 /*
135 * Set count of one shot timer,
136 * and after write ET2CNTLLR timer will start
137 */
138 hw_cnt = MS_TO_COUNT(32768, 5/*ms*/);
139 timer2_reg->ET2CNTLH2R = (uint8_t)((hw_cnt >> 16) & 0xff);
140 timer2_reg->ET2CNTLHR = (uint8_t)((hw_cnt >> 8) & 0xff);
141 timer2_reg->ET2CNTLLR = (uint8_t)(hw_cnt & 0xff);
142
143 irq_enable(ONE_SHOT_TIMER_IRQ);
144 }
145 #endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */
146
147 #ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT
arch_busy_wait(uint32_t usec_to_wait)148 void arch_busy_wait(uint32_t usec_to_wait)
149 {
150 if (!usec_to_wait) {
151 return;
152 }
153
154 /* Decrease 1us here to calibrate our access registers latency */
155 usec_to_wait--;
156
157 /*
158 * We want to set the bit(1) re-start busy wait timer as soon
159 * as possible, so we directly write 0xb instead of | bit(1).
160 */
161 IT8XXX2_EXT_CTRLX(BUSY_WAIT_L_TIMER) = IT8XXX2_EXT_ETX_COMB_RST_EN;
162
163 for (;;) {
164 uint32_t curr = IT8XXX2_EXT_CNTOX(BUSY_WAIT_H_TIMER);
165
166 if (curr >= usec_to_wait) {
167 break;
168 }
169 }
170 }
171 #endif
172
evt_timer_enable(void)173 static void evt_timer_enable(void)
174 {
175 /* Enable and re-start event timer */
176 IT8XXX2_EXT_CTRLX(EVENT_TIMER) |= (IT8XXX2_EXT_ETXEN |
177 IT8XXX2_EXT_ETXRST);
178 }
179
evt_timer_isr(const void * unused)180 static void evt_timer_isr(const void *unused)
181 {
182 ARG_UNUSED(unused);
183
184 /* Disable event timer */
185 IT8XXX2_EXT_CTRLX(EVENT_TIMER) &= ~IT8XXX2_EXT_ETXEN;
186 /* W/C event timer interrupt status */
187 ite_intc_isr_clear(EVENT_TIMER_IRQ);
188
189 if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
190 /*
191 * Get free run observer count from last time announced and
192 * transform unit to system tick
193 */
194 uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)) -
195 last_announced_hw_cnt) / HW_CNT_PER_SYS_TICK;
196 last_announced_hw_cnt += (dticks * HW_CNT_PER_SYS_TICK);
197
198 sys_clock_announce(dticks);
199 } else {
200 /* enable event timer */
201 evt_timer_enable();
202 /* Informs kernel that one system tick has elapsed */
203 sys_clock_announce(1);
204 }
205 }
206
free_run_timer_overflow_isr(const void * unused)207 static void free_run_timer_overflow_isr(const void *unused)
208 {
209 ARG_UNUSED(unused);
210
211 /* Read to clear terminal count flag */
212 __unused uint8_t rc_tc = IT8XXX2_EXT_CTRLX(FREE_RUN_TIMER);
213
214 /*
215 * TODO: to increment 32-bit "top half" here for software 64-bit
216 * timer emulation.
217 */
218 }
219
sys_clock_set_timeout(int32_t ticks,bool idle)220 void sys_clock_set_timeout(int32_t ticks, bool idle)
221 {
222 uint32_t hw_cnt;
223
224 ARG_UNUSED(idle);
225
226 if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
227 /* Always return for non-tickless kernel system */
228 return;
229 }
230
231 /* Critical section */
232 k_spinlock_key_t key = k_spin_lock(&lock);
233
234 /* Disable event timer */
235 IT8XXX2_EXT_CTRLX(EVENT_TIMER) &= ~IT8XXX2_EXT_ETXEN;
236
237 if (ticks == K_TICKS_FOREVER) {
238 /*
239 * If kernel doesn't have a timeout:
240 * 1.CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE = y (no future timer interrupts
241 * are expected), kernel pass K_TICKS_FOREVER (0xFFFF FFFF FFFF FFFF),
242 * we handle this case in here.
243 * 2.CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE = n (schedule timeout as far
244 * into the future as possible), kernel pass INT_MAX (0x7FFF FFFF),
245 * we handle it in later else {}.
246 */
247 k_spin_unlock(&lock, key);
248 return;
249 } else if (ticks <= 1) {
250 /*
251 * Ticks <= 1 means the kernel wants the tick announced
252 * as soon as possible, ideally no more than one system tick
253 * in the future. So set event timer count to 1 system tick or
254 * at least 1 hw count.
255 */
256 hw_cnt = MAX((1 * HW_CNT_PER_SYS_TICK), 1);
257 } else {
258 /*
259 * Set event timer count to EVENT_TIMER_MAX_CNT, after
260 * interrupt fired the remaining time will be set again
261 * by sys_clock_announce().
262 */
263 hw_cnt = MIN((ticks * HW_CNT_PER_SYS_TICK), EVENT_TIMER_MAX_CNT);
264 }
265
266 /* Set event timer 24-bit count */
267 IT8XXX2_EXT_CNTX(EVENT_TIMER) = hw_cnt;
268
269 /* W/C event timer interrupt status */
270 ite_intc_isr_clear(EVENT_TIMER_IRQ);
271
272 /* enable event timer */
273 evt_timer_enable();
274
275 k_spin_unlock(&lock, key);
276
277 LOG_DBG("timeout is 0x%x, set hw count 0x%x", ticks, hw_cnt);
278 }
279
sys_clock_elapsed(void)280 uint32_t sys_clock_elapsed(void)
281 {
282 if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
283 /* Always return 0 for non-tickless kernel system */
284 return 0;
285 }
286
287 /* Critical section */
288 k_spinlock_key_t key = k_spin_lock(&lock);
289 /*
290 * Get free run observer count from last time announced and transform
291 * unit to system tick
292 */
293 uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)) -
294 last_announced_hw_cnt) / HW_CNT_PER_SYS_TICK;
295 k_spin_unlock(&lock, key);
296
297 return dticks;
298 }
299
sys_clock_cycle_get_32(void)300 uint32_t sys_clock_cycle_get_32(void)
301 {
302 /*
303 * Get free run observer count
304 *
305 * NOTE: Timer is counting down from 0xffffffff. In not combined
306 * mode, the observer count value is the same as count, so after
307 * NOT count operation we can get counting up value; In
308 * combined mode, the observer count value is the same as NOT
309 * count operation.
310 */
311 uint32_t dticks = ~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER));
312
313 return dticks;
314 }
315
timer_init(enum ext_timer_idx ext_timer,enum ext_clk_src_sel clock_source_sel,enum ext_timer_raw_cnt raw,uint32_t ms,enum ext_timer_init first_time_enable,uint32_t irq_num,uint32_t irq_flag,enum ext_timer_int with_int,enum ext_timer_start start)316 static int timer_init(enum ext_timer_idx ext_timer,
317 enum ext_clk_src_sel clock_source_sel,
318 enum ext_timer_raw_cnt raw,
319 uint32_t ms,
320 enum ext_timer_init first_time_enable,
321 uint32_t irq_num,
322 uint32_t irq_flag,
323 enum ext_timer_int with_int,
324 enum ext_timer_start start)
325 {
326 uint32_t hw_cnt;
327
328 if (raw == EXT_RAW_CNT) {
329 hw_cnt = ms;
330 } else {
331 if (clock_source_sel == EXT_PSR_32P768K)
332 hw_cnt = MS_TO_COUNT(32768, ms);
333 else if (clock_source_sel == EXT_PSR_1P024K)
334 hw_cnt = MS_TO_COUNT(1024, ms);
335 else if (clock_source_sel == EXT_PSR_32)
336 hw_cnt = MS_TO_COUNT(32, ms);
337 else if (clock_source_sel == EXT_PSR_EC_CLK)
338 hw_cnt = MS_TO_COUNT(EC_FREQ, ms);
339 else {
340 LOG_ERR("Timer %d clock source error !", ext_timer);
341 return -1;
342 }
343 }
344
345 if (hw_cnt == 0) {
346 LOG_ERR("Timer %d count shouldn't be 0 !", ext_timer);
347 return -1;
348 }
349
350 if (first_time_enable == EXT_FIRST_TIME_ENABLE) {
351 /* Enable and re-start external timer x */
352 IT8XXX2_EXT_CTRLX(ext_timer) |= (IT8XXX2_EXT_ETXEN |
353 IT8XXX2_EXT_ETXRST);
354 /* Disable external timer x */
355 IT8XXX2_EXT_CTRLX(ext_timer) &= ~IT8XXX2_EXT_ETXEN;
356 }
357
358 /* Set rising edge triggered of external timer x */
359 ite_intc_irq_polarity_set(irq_num, irq_flag);
360
361 /* Clear interrupt status of external timer x */
362 ite_intc_isr_clear(irq_num);
363
364 /* Set clock source of external timer x */
365 IT8XXX2_EXT_PSRX(ext_timer) = clock_source_sel;
366
367 /* Set count of external timer x */
368 IT8XXX2_EXT_CNTX(ext_timer) = hw_cnt;
369
370 /* Disable external timer x */
371 IT8XXX2_EXT_CTRLX(ext_timer) &= ~IT8XXX2_EXT_ETXEN;
372 if (start == EXT_START_TIMER)
373 /* Enable and re-start external timer x */
374 IT8XXX2_EXT_CTRLX(ext_timer) |= (IT8XXX2_EXT_ETXEN |
375 IT8XXX2_EXT_ETXRST);
376
377 if (with_int == EXT_WITH_TIMER_INT) {
378 irq_enable(irq_num);
379 } else {
380 irq_disable(irq_num);
381 }
382
383 return 0;
384 }
385
sys_clock_driver_init(void)386 static int sys_clock_driver_init(void)
387 {
388 int ret;
389
390
391 /* Enable 32-bit free run timer overflow interrupt */
392 IRQ_CONNECT(FREE_RUN_TIMER_IRQ, 0, free_run_timer_overflow_isr, NULL,
393 FREE_RUN_TIMER_FLAG);
394 /* Set 32-bit timer4 for free run*/
395 ret = timer_init(FREE_RUN_TIMER, EXT_PSR_32P768K, EXT_RAW_CNT,
396 FREE_RUN_TIMER_MAX_CNT, EXT_FIRST_TIME_ENABLE,
397 FREE_RUN_TIMER_IRQ, FREE_RUN_TIMER_FLAG,
398 EXT_WITH_TIMER_INT, EXT_START_TIMER);
399 if (ret < 0) {
400 LOG_ERR("Init free run timer failed");
401 return ret;
402 }
403
404 /* Set 24-bit timer3 for timeout event */
405 IRQ_CONNECT(EVENT_TIMER_IRQ, 0, evt_timer_isr, NULL, EVENT_TIMER_FLAG);
406 if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
407 ret = timer_init(EVENT_TIMER, EXT_PSR_32P768K, EXT_RAW_CNT,
408 EVENT_TIMER_MAX_CNT, EXT_FIRST_TIME_ENABLE,
409 EVENT_TIMER_IRQ, EVENT_TIMER_FLAG,
410 EXT_WITH_TIMER_INT, EXT_NOT_START_TIMER);
411 } else {
412 /* Start a event timer in one system tick */
413 ret = timer_init(EVENT_TIMER, EXT_PSR_32P768K, EXT_RAW_CNT,
414 MAX((1 * HW_CNT_PER_SYS_TICK), 1),
415 EXT_FIRST_TIME_ENABLE, EVENT_TIMER_IRQ,
416 EVENT_TIMER_FLAG, EXT_WITH_TIMER_INT,
417 EXT_START_TIMER);
418 }
419 if (ret < 0) {
420 LOG_ERR("Init event timer failed");
421 return ret;
422 }
423
424 if (IS_ENABLED(CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT)) {
425 /* Set timer5 and timer6 combinational mode for busy wait */
426 IT8XXX2_EXT_CTRLX(BUSY_WAIT_L_TIMER) |= IT8XXX2_EXT_ETXCOMB;
427
428 /* Set 32-bit timer6 to count-- every 1us */
429 ret = timer_init(BUSY_WAIT_H_TIMER, EXT_PSR_EC_CLK, EXT_RAW_CNT,
430 BUSY_WAIT_TIMER_H_MAX_CNT, EXT_FIRST_TIME_ENABLE,
431 BUSY_WAIT_H_TIMER_IRQ, BUSY_WAIT_H_TIMER_FLAG,
432 EXT_WITHOUT_TIMER_INT, EXT_START_TIMER);
433 if (ret < 0) {
434 LOG_ERR("Init busy wait high timer failed");
435 return ret;
436 }
437
438 /*
439 * Set 24-bit timer5 to overflow every 1us
440 * NOTE: When the timer5 count down to overflow in combinational
441 * mode, timer6 counter will automatically decrease one count
442 * and timer5 will automatically re-start counting down
443 * from COUNT_1US. Timer5 clock source is EC_FREQ, so the
444 * time period from COUNT_1US to overflow is
445 * (1 / EC_FREQ) * (EC_FREQ / USEC_PER_SEC) = 1us.
446 */
447 ret = timer_init(BUSY_WAIT_L_TIMER, EXT_PSR_EC_CLK, EXT_RAW_CNT,
448 COUNT_1US, EXT_FIRST_TIME_ENABLE,
449 BUSY_WAIT_L_TIMER_IRQ, BUSY_WAIT_L_TIMER_FLAG,
450 EXT_WITHOUT_TIMER_INT, EXT_START_TIMER);
451 if (ret < 0) {
452 LOG_ERR("Init busy wait low timer failed");
453 return ret;
454 }
455 }
456
457 return 0;
458 }
459
460 SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2,
461 CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
462