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 <drivers/timer/system_timer.h>
9 #include <dt-bindings/interrupt-controller/ite-intc.h>
10 #include <soc.h>
11 #include <spinlock.h>
12 #include <sys_clock.h>
13 
14 #include <logging/log.h>
15 LOG_MODULE_REGISTER(timer, LOG_LEVEL_ERR);
16 
17 /* Event timer configurations */
18 #define EVENT_TIMER		EXT_TIMER_3
19 #define EVENT_TIMER_IRQ		DT_INST_IRQ_BY_IDX(0, 0, irq)
20 #define EVENT_TIMER_FLAG	DT_INST_IRQ_BY_IDX(0, 0, flags)
21 /* Event timer max count is 512 sec (base on clock source 32768Hz) */
22 #define EVENT_TIMER_MAX_CNT	0x00FFFFFFUL
23 
24 #ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
25 /*
26  * One shot timer configurations
27  *
28  * NOTE: Timer1/2 register address isn't regular like timer3/4/5/6/7/8, and
29  *       timer1 is used for printing watchdog warning message. So now we use
30  *       timer2 only one shot to wake up chip and change pll.
31  */
32 #define WDT_BASE		DT_REG_ADDR(DT_NODELABEL(twd0))
33 #define WDT_REG			(struct wdt_it8xxx2_regs *)(WDT_BASE)
34 #define ONE_SHOT_TIMER_IRQ	DT_IRQ_BY_IDX(DT_NODELABEL(twd0), 1, irq)
35 #define ONE_SHOT_TIMER_FLAG	DT_IRQ_BY_IDX(DT_NODELABEL(twd0), 1, flags)
36 #endif
37 
38 #define MS_TO_COUNT(hz, ms)	((hz) * (ms) / 1000)
39 /*
40  * One system (kernel) tick is as how much HW timer counts
41  *
42  * NOTE: Event and free run timer individually select the same clock source
43  *       frequency, so they can use the same HW_CNT_PER_SYS_TICK to tranform
44  *       unit between HW count and system tick. If clock source frequency is
45  *       different, then we should define another to tranform.
46  */
47 #define HW_CNT_PER_SYS_TICK	(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \
48 				 / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
49 /* Event timer max count is as how much system (kernal) tick */
50 #define EVEN_TIMER_MAX_CNT_SYS_TICK	(EVENT_TIMER_MAX_CNT \
51 					/ HW_CNT_PER_SYS_TICK)
52 
53 static struct k_spinlock lock;
54 /* Last HW count that we called sys_clock_announce() */
55 static volatile uint32_t last_announced_hw_cnt;
56 
57 #ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
timer_5ms_one_shot_isr(const void * unused)58 static void timer_5ms_one_shot_isr(const void *unused)
59 {
60 	ARG_UNUSED(unused);
61 
62 	/*
63 	 * We are here because we have completed changing PLL sequence,
64 	 * so disabled one shot timer interrupt.
65 	 */
66 	irq_disable(ONE_SHOT_TIMER_IRQ);
67 }
68 
69 /*
70  * This timer is used to wake up chip from sleep mode to complete
71  * changing PLL sequence.
72  */
timer_5ms_one_shot(void)73 void timer_5ms_one_shot(void)
74 {
75 	struct wdt_it8xxx2_regs *const timer2_reg = WDT_REG;
76 	uint32_t hw_cnt;
77 
78 	/* Initialize interrupt handler of one shot timer */
79 	IRQ_CONNECT(ONE_SHOT_TIMER_IRQ, 0, timer_5ms_one_shot_isr, NULL,
80 			ONE_SHOT_TIMER_FLAG);
81 
82 	/* Set rising edge triggered of one shot timer */
83 	ite_intc_irq_priority_set(ONE_SHOT_TIMER_IRQ, 0, ONE_SHOT_TIMER_FLAG);
84 
85 	/* Clear interrupt status of one shot timer */
86 	ite_intc_isr_clear(ONE_SHOT_TIMER_IRQ);
87 
88 	/* Set clock source of one shot timer */
89 	timer2_reg->ET2PSR = EXT_PSR_32P768K;
90 
91 	/*
92 	 * Set count of one shot timer,
93 	 * and after write ET2CNTLLR timer will start
94 	 */
95 	hw_cnt = MS_TO_COUNT(32768, 5/*ms*/);
96 	timer2_reg->ET2CNTLH2R = (uint8_t)((hw_cnt >> 16) & 0xff);
97 	timer2_reg->ET2CNTLHR = (uint8_t)((hw_cnt >> 8) & 0xff);
98 	timer2_reg->ET2CNTLLR = (uint8_t)(hw_cnt & 0xff);
99 
100 	irq_enable(ONE_SHOT_TIMER_IRQ);
101 }
102 #endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */
103 
evt_timer_isr(const void * unused)104 static void evt_timer_isr(const void *unused)
105 {
106 	ARG_UNUSED(unused);
107 
108 	/* Disable event timer */
109 	IT8XXX2_EXT_CTRLX(EVENT_TIMER) &= ~IT8XXX2_EXT_ETXEN;
110 	/* W/C event timer interrupt status */
111 	ite_intc_isr_clear(EVENT_TIMER_IRQ);
112 
113 	if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
114 		/*
115 		 * Get free run observer count from last time announced and
116 		 * trnaform unit to system tick
117 		 */
118 		uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)) -
119 				   last_announced_hw_cnt) / HW_CNT_PER_SYS_TICK;
120 		last_announced_hw_cnt += (dticks * HW_CNT_PER_SYS_TICK);
121 
122 		sys_clock_announce(dticks);
123 	} else {
124 		/* Enable and re-start event timer */
125 		IT8XXX2_EXT_CTRLX(EVENT_TIMER) |= (IT8XXX2_EXT_ETXEN |
126 						   IT8XXX2_EXT_ETXRST);
127 
128 		/* Informs kernel that one system tick has elapsed */
129 		sys_clock_announce(1);
130 	}
131 }
132 
sys_clock_set_timeout(int32_t ticks,bool idle)133 void sys_clock_set_timeout(int32_t ticks, bool idle)
134 {
135 	uint32_t hw_cnt;
136 
137 	ARG_UNUSED(idle);
138 
139 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
140 		/* Always return for non-tickless kernel system */
141 		return;
142 	}
143 
144 	/* Critical section */
145 	k_spinlock_key_t key = k_spin_lock(&lock);
146 
147 	/* Disable event timer */
148 	IT8XXX2_EXT_CTRLX(EVENT_TIMER) &= ~IT8XXX2_EXT_ETXEN;
149 
150 	if (ticks == K_TICKS_FOREVER) {
151 		/* Return since no future timer interrupts are required */
152 		k_spin_unlock(&lock, key);
153 		return;
154 	} else if (ticks <= 1) {
155 		/*
156 		 * Ticks <= 1 means the kernel wants the tick announced
157 		 * as soon as possible, ideally no more than one system tick
158 		 * in the future. So set event timer count to 1 system tick or
159 		 * at least 1 hw count.
160 		 */
161 		hw_cnt = MAX((1 * HW_CNT_PER_SYS_TICK), 1);
162 	} else {
163 		if (ticks > EVEN_TIMER_MAX_CNT_SYS_TICK)
164 			/*
165 			 * Set event timer count to EVENT_TIMER_MAX_CNT, after
166 			 * interrupt fired the remaining time will be set again
167 			 * by sys_clock_announce().
168 			 */
169 			hw_cnt = EVENT_TIMER_MAX_CNT;
170 		else
171 			/*
172 			 * Set event timer count to system tick or at least
173 			 * 1 hw count
174 			 */
175 			hw_cnt = MAX((ticks * HW_CNT_PER_SYS_TICK), 1);
176 	}
177 
178 	/* Set event timer 24-bit count */
179 	IT8XXX2_EXT_CNTX(EVENT_TIMER) = hw_cnt;
180 
181 	/* W/C event timer interrupt status */
182 	ite_intc_isr_clear(EVENT_TIMER_IRQ);
183 
184 	/*
185 	 * When timer enable bit is from 0->1, timer will reload counts and
186 	 * start countdown.
187 	 */
188 	IT8XXX2_EXT_CTRLX(EVENT_TIMER) |= IT8XXX2_EXT_ETXEN;
189 
190 	k_spin_unlock(&lock, key);
191 
192 	LOG_DBG("timeout is 0x%x, set hw count 0x%x", ticks, hw_cnt);
193 }
194 
sys_clock_elapsed(void)195 uint32_t sys_clock_elapsed(void)
196 {
197 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
198 		/* Always return 0 for non-tickless kernel system */
199 		return 0;
200 	}
201 
202 	/* Critical section */
203 	k_spinlock_key_t key = k_spin_lock(&lock);
204 	/*
205 	 * Get free run observer count from last time announced and trnaform
206 	 * unit to system tick
207 	 */
208 	uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)) -
209 				last_announced_hw_cnt) / HW_CNT_PER_SYS_TICK;
210 	k_spin_unlock(&lock, key);
211 
212 	return dticks;
213 }
214 
sys_clock_cycle_get_32(void)215 uint32_t sys_clock_cycle_get_32(void)
216 {
217 	/*
218 	 * Get free run observer count and trnaform unit to system tick
219 	 *
220 	 * NOTE: Timer is counting down from 0xffffffff. In not combined
221 	 *       mode, the observer count value is the same as count, so after
222 	 *       NOT count operation we can get counting up value; In
223 	 *       combined mode, the observer count value is the same as NOT
224 	 *       count operation.
225 	 */
226 	uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)))
227 				/ HW_CNT_PER_SYS_TICK;
228 
229 	return dticks;
230 }
231 
timer_init(enum ext_timer_idx ext_timer,enum ext_clk_src_sel clock_source_sel,uint32_t raw,uint32_t ms,uint8_t first_time_enable,uint32_t irq_num,uint32_t irq_flag,uint8_t with_int,uint8_t start)232 static int timer_init(enum ext_timer_idx ext_timer,
233 			enum ext_clk_src_sel clock_source_sel,
234 			uint32_t raw,
235 			uint32_t ms,
236 			uint8_t first_time_enable,
237 			uint32_t irq_num,
238 			uint32_t irq_flag,
239 			uint8_t with_int,
240 			uint8_t start)
241 {
242 	uint32_t hw_cnt;
243 
244 	if (raw) {
245 		hw_cnt = ms;
246 	} else {
247 		if (clock_source_sel == EXT_PSR_32P768K)
248 			hw_cnt = MS_TO_COUNT(32768, ms);
249 		else if (clock_source_sel == EXT_PSR_1P024K)
250 			hw_cnt = MS_TO_COUNT(1024, ms);
251 		else if (clock_source_sel == EXT_PSR_32)
252 			hw_cnt = MS_TO_COUNT(32, ms);
253 		else if (clock_source_sel == EXT_PSR_8M)
254 			hw_cnt = 8000 * ms;
255 		else {
256 			LOG_ERR("Timer %d clock source error !", ext_timer);
257 			return -1;
258 		}
259 	}
260 
261 	if (hw_cnt == 0) {
262 		LOG_ERR("Timer %d count shouldn't be 0 !", ext_timer);
263 		return -1;
264 	}
265 
266 	if (first_time_enable) {
267 		/* Enable and re-start external timer x */
268 		IT8XXX2_EXT_CTRLX(ext_timer) |= (IT8XXX2_EXT_ETXEN |
269 						 IT8XXX2_EXT_ETXRST);
270 		/* Disable external timer x */
271 		IT8XXX2_EXT_CTRLX(ext_timer) &= ~IT8XXX2_EXT_ETXEN;
272 	}
273 
274 	/* Set rising edge triggered of external timer x */
275 	ite_intc_irq_priority_set(irq_num, 0, irq_flag);
276 
277 	/* Clear interrupt status of external timer x */
278 	ite_intc_isr_clear(irq_num);
279 
280 	/* Set clock source of external timer x */
281 	IT8XXX2_EXT_PSRX(ext_timer) = clock_source_sel;
282 
283 	/* Set count of external timer x */
284 	IT8XXX2_EXT_CNTX(ext_timer) = hw_cnt;
285 
286 	/* Disable external timer x */
287 	IT8XXX2_EXT_CTRLX(ext_timer) &= ~IT8XXX2_EXT_ETXEN;
288 	if (start)
289 		/* Enable and re-start external timer x */
290 		IT8XXX2_EXT_CTRLX(ext_timer) |= (IT8XXX2_EXT_ETXEN |
291 						 IT8XXX2_EXT_ETXRST);
292 
293 	if (with_int)
294 		irq_enable(irq_num);
295 	else
296 		irq_disable(irq_num);
297 
298 	return 0;
299 }
300 
sys_clock_driver_init(const struct device * dev)301 int sys_clock_driver_init(const struct device *dev)
302 {
303 	int ret;
304 
305 	ARG_UNUSED(dev);
306 
307 	/* Set 32-bit timer4 for free run*/
308 	ret = timer_init(FREE_RUN_TIMER, EXT_PSR_32P768K, TRUE,
309 			 FREE_RUN_TIMER_MAX_CNT, TRUE, FREE_RUN_TIMER_IRQ,
310 			 FREE_RUN_TIMER_FLAG, FALSE, TRUE);
311 	if (ret < 0) {
312 		LOG_ERR("Init free run timer failed");
313 		return ret;
314 	}
315 
316 	/* Set 24-bit timer3 for timeout event */
317 	IRQ_CONNECT(EVENT_TIMER_IRQ, 0, evt_timer_isr, NULL, EVENT_TIMER_FLAG);
318 	if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
319 		ret = timer_init(EVENT_TIMER, EXT_PSR_32P768K, TRUE,
320 				 EVENT_TIMER_MAX_CNT, TRUE, EVENT_TIMER_IRQ,
321 				 EVENT_TIMER_FLAG, TRUE, FALSE);
322 	} else {
323 		/* Start a event timer in one system tick */
324 		ret = timer_init(EVENT_TIMER, EXT_PSR_32P768K, TRUE,
325 				 MAX((1 * HW_CNT_PER_SYS_TICK), 1), TRUE,
326 				 EVENT_TIMER_IRQ, EVENT_TIMER_FLAG,
327 				 TRUE, TRUE);
328 	}
329 	if (ret < 0) {
330 		LOG_ERR("Init event timer failed");
331 		return ret;
332 	}
333 
334 	return 0;
335 }
336