1 /*
2  * Copyright (c) 2015 MediaTek Inc.
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <sys/types.h>
9 #include <lk/debug.h>
10 #include <lk/err.h>
11 #include <lk/reg.h>
12 #include <kernel/thread.h>
13 #include <mt_gic.h>
14 #include <platform/timer.h>
15 #include <platform/mt_typedefs.h>
16 #include <platform/mt_reg_base.h>
17 #include <platform/mt_gpt.h>
18 #include <platform/mt_irq.h>
19 
20 #define TIMER_TICK_RATE 32768
21 
22 static volatile lk_time_t ticks = 0;
23 static lk_time_t tick_interval;
24 static platform_timer_callback time_callback;
25 static void *callback_arg;
26 
timer_irq(void * arg)27 static enum handler_return timer_irq(void *arg) {
28     ticks += tick_interval;
29     return time_callback(callback_arg, ticks);
30 }
31 
lk_scheduler(void)32 enum handler_return lk_scheduler(void) {
33     static enum handler_return ret;
34 
35     /* ack GPT5 irq */
36     DRV_WriteReg32(GPT_IRQACK_REG, 0x10);
37     DRV_WriteReg32(GPT5_CON_REG, GPT_CLEAR);
38     DRV_WriteReg32(GPT5_CON_REG, GPT_DISABLE);
39 
40     ret = timer_irq(0);
41 
42     /* ack GIC irq */
43     mt_irq_ack(MT_GPT_IRQ_ID);
44 
45     /* enable GPT5 */
46     DRV_WriteReg32(GPT5_CON_REG, GPT_ENABLE|GPT_MODE4_ONE_SHOT);
47 
48     return ret;
49 }
50 
platform_set_periodic_timer(platform_timer_callback callback,void * arg,lk_time_t interval)51 status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) {
52     time_callback = callback;
53     tick_interval = interval;
54     callback_arg  = arg;
55 
56     DRV_WriteReg32(GPT_IRQEN_REG, 0);
57     DRV_WriteReg32(GPT_IRQACK_REG, 0x3f);
58 
59     mt_irq_set_sens(MT_GPT_IRQ_ID, MT65xx_LEVEL_SENSITIVE);
60     mt_irq_set_polarity(MT_GPT_IRQ_ID, MT65xx_POLARITY_LOW);
61 
62     DRV_WriteReg32(GPT5_CON_REG, 0x02);
63     DRV_WriteReg32(GPT_IRQACK_REG, 0x10);
64     DRV_WriteReg32(GPT5_CLK_REG, 0x10);
65 
66     DRV_WriteReg32(GPT5_COMPARE_REG, TIMER_TICK_RATE*interval/1000);
67     DRV_WriteReg32(GPT_IRQEN_REG, 0x10);
68 
69     mt_irq_unmask(MT_GPT_IRQ_ID);
70 
71     DRV_WriteReg32(GPT5_CON_REG, GPT_ENABLE|GPT_MODE4_ONE_SHOT);
72 
73     return NO_ERROR;
74 }
75 
current_time(void)76 lk_time_t current_time(void) {
77     return ticks;
78 }
79 
current_time_hires(void)80 lk_bigtime_t current_time_hires(void) {
81     lk_bigtime_t time;
82 
83     time = (lk_bigtime_t)ticks * 1000;
84     return time;
85 }
86 
87