1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <common/bk_include.h>
16 #include <common/bk_compiler.h>
17 #include <os/mem.h>
18 #include "icu_driver.h"
19 #include "timer_driver.h"
20 #include "timer_hal.h"
21 #include <driver/timer.h>
22 #include "clock_driver.h"
23 #include "power_driver.h"
24 #include <driver/int.h>
25 #include "sys_driver.h"
26
27 #if (SOC_TIMER_INTERRUPT_NUM > 1)
28 static void timer1_isr(void) __BK_SECTION(".itcm");
29 #endif
30 static void timer_isr(void) __BK_SECTION(".itcm");
31
32 typedef struct {
33 timer_hal_t hal;
34 } timer_driver_t;
35
36 static timer_driver_t s_timer = {0};
37 static timer_isr_t s_timer_isr[SOC_TIMER_CHAN_NUM_PER_UNIT] = {NULL};
38 static bool s_timer_driver_is_init = false;
39
40 #define TIMER_RETURN_ON_NOT_INIT() do {\
41 if (!s_timer_driver_is_init) {\
42 return BK_ERR_TIMER_NOT_INIT;\
43 }\
44 } while(0)
45
46 #define TIMER_RETURN_ON_INVALID_ID(id) do {\
47 if ((id) >= SOC_TIMER_CHAN_NUM_PER_UNIT) {\
48 return BK_ERR_TIMER_ID;\
49 }\
50 } while(0)
51
52 #define TIMER_RETURN_ON_IS_RUNNING(id, status) do {\
53 if ((status) & BIT((id))) {\
54 return BK_ERR_TIMER_IS_RUNNING;\
55 }\
56 } while(0)
57
58 #define TIMER_RETURN_TIMER_ID_IS_ERR(id) do {\
59 if ((~CONFIG_TIMER_SUPPORT_ID_BITS) & BIT((id))) {\
60 return BK_ERR_TIMER_ID_ON_DEFCONFIG;\
61 }\
62 } while(0)
63
64 #if (CONFIG_SYSTEM_CTRL)
timer_clock_select(timer_id_t id,timer_src_clk_t mode)65 static void timer_clock_select(timer_id_t id, timer_src_clk_t mode)
66 {
67 uint32_t group_index = 0;
68
69 group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
70 switch(group_index)
71 {
72 case 0:
73 sys_drv_timer_select_clock(SYS_SEL_TIMER0, mode);
74 break;
75 case 1:
76 sys_drv_timer_select_clock(SYS_SEL_TIMER1, mode);
77 break;
78 default:
79 break;
80 }
81 }
82
timer_clock_enable(timer_id_t id)83 static void timer_clock_enable(timer_id_t id)
84 {
85 uint32_t group_index = 0;
86
87 group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
88 switch(group_index)
89 {
90 case 0:
91 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_1, CLK_PWR_CTRL_PWR_UP);
92 break;
93 case 1:
94 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_2, CLK_PWR_CTRL_PWR_UP);
95 break;
96 case 2:
97 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_3, CLK_PWR_CTRL_PWR_UP);
98 break;
99 default:
100 break;
101 }
102 }
103
timer_clock_disable(timer_id_t id)104 static void timer_clock_disable(timer_id_t id)
105 {
106 uint32_t group_index = 0;
107
108 group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
109 switch(group_index)
110 {
111 case 0:
112 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_1, CLK_PWR_CTRL_PWR_DOWN);
113 break;
114 case 1:
115 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_2, CLK_PWR_CTRL_PWR_DOWN);
116 break;
117 case 2:
118 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_TIMER_3, CLK_PWR_CTRL_PWR_DOWN);
119 break;
120 default:
121 break;
122 }
123 }
124
timer_interrupt_enable(timer_id_t id)125 static void timer_interrupt_enable(timer_id_t id)
126 {
127 uint32_t group_index = 0;
128
129 group_index = id / SOC_TIMER_CHAN_NUM_PER_GROUP;
130 switch(group_index)
131 {
132 case 0:
133 sys_drv_int_enable(TIMER_INTERRUPT_CTRL_BIT);
134 break;
135
136 case 1:
137 sys_drv_int_enable(TIMER1_INTERRUPT_CTRL_BIT);
138 break;
139 default:
140 break;
141 }
142 }
143 #endif
144
timer_chan_init_common(timer_id_t timer_id)145 static void timer_chan_init_common(timer_id_t timer_id)
146 {
147 #if (CONFIG_SYSTEM_CTRL)
148 timer_clock_select(timer_id, TIMER_SCLK_XTAL);
149 timer_clock_enable(timer_id);
150 #else
151 power_pwr_up_timer(timer_id);
152 #endif
153 }
154
timer_chan_deinit_common(timer_id_t timer_id)155 static void timer_chan_deinit_common(timer_id_t timer_id)
156 {
157 timer_hal_stop_common(&s_timer.hal, timer_id);
158 timer_hal_reset_config_to_default(&s_timer.hal, timer_id);
159 #if (CONFIG_SYSTEM_CTRL)
160 timer_clock_disable(timer_id);
161 #else
162 power_pwr_down_timer(timer_id);
163 #endif
164 }
165
timer_chan_enable_interrupt_common(timer_id_t timer_id)166 static void timer_chan_enable_interrupt_common(timer_id_t timer_id)
167 {
168 #if (CONFIG_SYSTEM_CTRL)
169 timer_interrupt_enable(timer_id);
170 #else
171 icu_enable_timer_interrupt();
172 #endif
173 timer_hal_enable_interrupt(&s_timer.hal, timer_id);
174 }
175
176 static void timer_isr(void) __BK_SECTION(".itcm");
177
bk_timer_driver_init(void)178 bk_err_t bk_timer_driver_init(void)
179 {
180 if (s_timer_driver_is_init) {
181 return BK_OK;
182 }
183
184 os_memset(&s_timer, 0, sizeof(s_timer));
185 os_memset(&s_timer_isr, 0, sizeof(s_timer_isr));
186 bk_int_isr_register(INT_SRC_TIMER, timer_isr, NULL);
187 #if (SOC_TIMER_INTERRUPT_NUM > 1)
188 bk_int_isr_register(INT_SRC_TIMER1, timer1_isr, NULL);
189 #endif
190 timer_hal_init(&s_timer.hal);
191 s_timer_driver_is_init = true;
192
193 return BK_OK;
194 }
195
bk_timer_driver_deinit(void)196 bk_err_t bk_timer_driver_deinit(void)
197 {
198 if (!s_timer_driver_is_init) {
199 return BK_OK;
200 }
201
202 for (int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
203 timer_chan_deinit_common(chan);
204 }
205
206 s_timer_driver_is_init = false;
207
208 return BK_OK;
209 }
210
211 extern void delay(int num);//TODO fix me
212
bk_timer_start_without_callback(timer_id_t timer_id,uint32_t time_ms)213 bk_err_t bk_timer_start_without_callback(timer_id_t timer_id, uint32_t time_ms)
214 {
215 uint32_t en_status = 0;
216
217 TIMER_RETURN_ON_NOT_INIT();
218 TIMER_RETURN_ON_INVALID_ID(timer_id);
219
220 timer_chan_init_common(timer_id);
221 timer_chan_enable_interrupt_common(timer_id);
222
223 en_status = timer_hal_get_enable_status(&s_timer.hal);
224 if (en_status & BIT(timer_id)) {
225 TIMER_LOGD("timer(%d) is running, stop it\r\n", timer_id);
226 timer_hal_disable(&s_timer.hal, timer_id);
227 /* Delay to fix the bug that timer counter becomes bigger than
228 * timer period. Once timer counter becomes bigger than timer period,
229 * the timer will never timeout, or takes very very long time to
230 * timeout.
231 *
232 * This issue is firstly observed in HOS tick timer. HOS restarts
233 * the tick timer with different time_ms(timer period) again and again,
234 * without the delay, the tick timer counter becomes bigger than timer
235 * period very soon, then the tick interrupt will never be triggered.
236 * */
237 delay(4);
238 }
239
240 timer_hal_init_timer(&s_timer.hal, timer_id, time_ms, TIMER_UNIT_MS);
241 timer_hal_start_common(&s_timer.hal, timer_id);
242
243 return BK_OK;
244 }
245
bk_timer_start(timer_id_t timer_id,uint32_t time_ms,timer_isr_t callback)246 bk_err_t bk_timer_start(timer_id_t timer_id, uint32_t time_ms, timer_isr_t callback)
247 {
248 #if CONFIG_TIMER_SUPPORT_ID_BITS
249 TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
250 #endif
251 BK_LOG_ON_ERR(bk_timer_start_without_callback(timer_id, time_ms));
252
253 if (timer_id < SOC_TIMER_CHAN_NUM_PER_UNIT){
254 s_timer_isr[timer_id] = callback;
255 }
256
257 return BK_OK;
258 }
259
bk_timer_stop(timer_id_t timer_id)260 bk_err_t bk_timer_stop(timer_id_t timer_id)
261 {
262 TIMER_RETURN_ON_NOT_INIT();
263 #if CONFIG_TIMER_SUPPORT_ID_BITS
264 TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
265 #endif
266 TIMER_RETURN_ON_INVALID_ID(timer_id);
267
268 timer_hal_stop_common(&s_timer.hal, timer_id);
269
270 return BK_OK;
271 }
272
bk_timer_cancel(timer_id_t timer_id)273 bk_err_t bk_timer_cancel(timer_id_t timer_id)
274 {
275 TIMER_RETURN_ON_NOT_INIT();
276 #if CONFIG_TIMER_SUPPORT_ID_BITS
277 TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
278 #endif
279 TIMER_RETURN_ON_INVALID_ID(timer_id);
280
281 timer_ll_reset_config_to_default(s_timer.hal.hw, timer_id);
282
283 s_timer_isr[timer_id] = NULL;
284
285 return BK_OK;
286 }
287
bk_timer_get_cnt(timer_id_t timer_id)288 uint32_t bk_timer_get_cnt(timer_id_t timer_id)
289 {
290 TIMER_RETURN_ON_NOT_INIT();
291 TIMER_RETURN_ON_INVALID_ID(timer_id);
292
293 return timer_hal_get_count(&s_timer.hal, timer_id);
294 }
295
bk_timer_enable(timer_id_t timer_id)296 bk_err_t bk_timer_enable(timer_id_t timer_id)
297 {
298 TIMER_RETURN_ON_NOT_INIT();
299 TIMER_RETURN_ON_INVALID_ID(timer_id);
300 timer_hal_enable(&s_timer.hal, timer_id);
301 return BK_OK;
302 }
303
bk_timer_disable(timer_id_t timer_id)304 bk_err_t bk_timer_disable(timer_id_t timer_id)
305 {
306 TIMER_RETURN_ON_NOT_INIT();
307 TIMER_RETURN_ON_INVALID_ID(timer_id);
308 timer_hal_disable(&s_timer.hal, timer_id);
309 return BK_OK;
310 }
311
bk_timer_get_period(timer_id_t timer_id)312 uint32_t bk_timer_get_period(timer_id_t timer_id)
313 {
314 TIMER_RETURN_ON_NOT_INIT();
315 TIMER_RETURN_ON_INVALID_ID(timer_id);
316 return timer_hal_get_end_count(&s_timer.hal, timer_id);
317 }
318
bk_timer_get_enable_status(void)319 uint32_t bk_timer_get_enable_status(void)
320 {
321 TIMER_RETURN_ON_NOT_INIT();
322 return timer_hal_get_enable_status(&s_timer.hal);
323 }
324
bk_timer_is_interrupt_triggered(timer_id_t timer_id)325 bool bk_timer_is_interrupt_triggered(timer_id_t timer_id)
326 {
327 TIMER_RETURN_ON_NOT_INIT();
328 TIMER_RETURN_ON_INVALID_ID(timer_id);
329 uint32_t int_status = timer_hal_get_interrupt_status(&s_timer.hal);
330 return timer_hal_is_interrupt_triggered(&s_timer.hal, timer_id, int_status);
331 }
332
timer_isr(void)333 static void timer_isr(void)
334 {
335 timer_hal_t *hal = &s_timer.hal;
336 uint32_t int_status = 0;
337
338 int_status = timer_hal_get_interrupt_status(hal);
339 timer_hal_clear_interrupt_status(hal, int_status);
340 #if (SOC_TIMER_INTERRUPT_NUM > 1)
341 for(int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_GROUP; chan++) {
342 #else
343 for(int chan = 0; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
344 #endif
345 if(timer_hal_is_interrupt_triggered(hal, chan, int_status)) {
346 if(s_timer_isr[chan]) {
347 s_timer_isr[chan](chan);
348 }
349 }
350 }
351 }
352
353 #if (SOC_TIMER_INTERRUPT_NUM > 1)
354 static void timer1_isr(void)
355 {
356 timer_hal_t *hal = &s_timer.hal;
357 uint32_t int_status = 0;
358
359 int_status = timer_hal_get_interrupt_status(hal);
360 timer_hal_clear_interrupt_status(hal, int_status);
361 for(int chan = SOC_TIMER_CHAN_NUM_PER_GROUP; chan < SOC_TIMER_CHAN_NUM_PER_UNIT; chan++) {
362 if(timer_hal_is_interrupt_triggered(hal, chan, int_status)) {
363 if(s_timer_isr[chan]) {
364 s_timer_isr[chan](chan);
365 }
366 }
367 }
368 }
369 #endif
370
371 uint64_t bk_timer_get_time(timer_id_t timer_id, uint32_t div, uint32_t last_count, timer_value_unit_t unit_type)
372 {
373 TIMER_RETURN_ON_NOT_INIT();
374 TIMER_RETURN_ON_INVALID_ID(timer_id);
375
376 uint64_t current_time = 0;
377 uint16_t unit_factor = 1;
378
379 uint32_t current_count = timer_hal_get_count(&s_timer.hal, timer_id) + last_count;
380
381 if (div == 0) {
382 div = 1;
383 }
384
385 #if (CONFIG_SYSTEM_CTRL)
386 uint32_t group_index = 0;
387 uint32_t timer_clock = TIMER_SCLK_XTAL;
388
389 group_index = timer_id / SOC_TIMER_CHAN_NUM_PER_GROUP;
390 switch(group_index)
391 {
392 case 0:
393 timer_clock = sys_hal_timer_select_clock_get(SYS_SEL_TIMER0);
394 break;
395 case 1:
396 timer_clock = sys_hal_timer_select_clock_get(SYS_SEL_TIMER1);
397 break;
398 default:
399 break;
400 }
401
402 unit_factor = (unit_type == TIMER_UNIT_MS) ? 1 : 1000;
403
404 if(timer_clock == TIMER_SCLK_XTAL) {
405 current_time = unit_factor * current_count * div / TIMER_CLOCK_FREQ_26M;
406 } else {
407 current_time = unit_factor * current_count * div / TIMER_CLOCK_FREQ_32K;
408 }
409
410 #else
411 if (timer_id < SOC_TIMER_CHAN_NUM_PER_GROUP) {
412 current_time = unit_factor * current_count * div / TIMER_CLOCK_FREQ_26M;
413 } else {
414 current_time = unit_factor * current_count * div / TIMER_CLOCK_FREQ_32K;
415 }
416 #endif
417
418 return current_time;
419 }
420
421 bk_err_t bk_timer_delay_with_callback(timer_id_t timer_id, uint64_t time_us, timer_isr_t callback)
422 {
423 TIMER_RETURN_ON_NOT_INIT();
424 TIMER_RETURN_ON_INVALID_ID(timer_id);
425
426 #if CONFIG_TIMER_SUPPORT_ID_BITS
427 TIMER_RETURN_TIMER_ID_IS_ERR(timer_id);
428 #endif
429 uint64_t current_count = 0;
430 uint64_t delta_count = 0;
431 uint64_t end_count = 0;
432
433 timer_chan_init_common(timer_id);
434 timer_chan_enable_interrupt_common(timer_id);
435
436 current_count = timer_hal_get_count(&s_timer.hal, timer_id);
437 delta_count = timer_hal_cal_end_count(timer_id, time_us, 1, TIMER_UNIT_US);
438 end_count = current_count + delta_count;
439
440 if(end_count > 0xFFFFFFFFFFFFFFFF){
441 end_count = 0xFFFFFFFFFFFFFFFF;
442 }
443
444 timer_ll_set_end_count(s_timer.hal.hw, timer_id, (uint32_t)end_count);
445 timer_ll_set_clk_div(s_timer.hal.hw, timer_id, 0);
446 timer_ll_clear_chan_interrupt_status(s_timer.hal.hw, timer_id);
447
448 timer_hal_start_common(&s_timer.hal, timer_id);
449
450 s_timer_isr[timer_id] = callback;
451
452 return BK_OK;
453 }
454