• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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