1 /*
2  * Copyright (c) 2008 Travis Geiselbrecht
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 <platform/timer.h>
13 #include <platform/mt_typedefs.h>
14 #include <platform/mt_reg_base.h>
15 #include <platform/mt_gpt.h>
16 #include <platform/mt_irq.h>
17 
18 #include <kernel/thread.h>
19 
20 static volatile lk_time_t ticks = 0;
21 static lk_time_t tick_interval;
22 
23 static platform_timer_callback time_callback;
24 static void *callback_arg;
25 
26 #define AP_PERI_GLOBALCON_PDN0 (PERICFG_BASE+0x10)
27 
28 #define TIMER_TICK_RATE 32768
29 
timer_irq(void * arg)30 static enum handler_return timer_irq(void *arg) {
31     ticks += tick_interval;
32     return time_callback(callback_arg, ticks);
33 }
34 
lk_scheduler(void)35 void lk_scheduler(void) {
36     //static enum handler_return ret;
37 
38     /* ack GPT5 irq */
39     DRV_WriteReg32(GPT_IRQACK_REG, 0x10);
40     DRV_WriteReg32(GPT5_CON_REG, GPT_CLEAR);
41     DRV_WriteReg32(GPT5_CON_REG, GPT_DISABLE);
42 
43     timer_irq(0);
44 
45     /*
46      * CAUTION! The de-assert signal to GIC might delay serveral clocks.
47      * Here must have enough delay to make sure the GPT signal had arrived GIC.
48      */
49     /* ack GIC irq */
50     mt_irq_ack(MT_GPT_IRQ_ID);
51 
52     /* enable GPT5 */
53     DRV_WriteReg32(GPT5_CON_REG, GPT_ENABLE|GPT_MODE4_ONE_SHOT);
54 
55 }
56 
platform_set_periodic_timer(platform_timer_callback callback,void * arg,lk_time_t interval)57 status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) {
58     time_callback = callback;
59     tick_interval = interval;
60     callback_arg  = arg;
61 
62     DRV_WriteReg32(GPT_IRQEN_REG, 0);
63     DRV_WriteReg32(GPT_IRQACK_REG, 0x3f);
64 
65     mt_irq_set_sens(MT_GPT_IRQ_ID, MT65xx_LEVEL_SENSITIVE);
66     mt_irq_set_polarity(MT_GPT_IRQ_ID, MT65xx_POLARITY_LOW);
67 
68     DRV_WriteReg32(GPT5_CON_REG, 0x02);
69     DRV_WriteReg32(GPT_IRQACK_REG, 0x10);
70     DRV_WriteReg32(GPT5_CLK_REG, 0x10);
71 
72     DRV_WriteReg32(GPT5_COMPARE_REG, TIMER_TICK_RATE*interval/1000);
73     DRV_WriteReg32(GPT_IRQEN_REG, 0x10);
74 
75     mt_irq_unmask(MT_GPT_IRQ_ID);
76 
77     DRV_WriteReg32(GPT5_CON_REG, GPT_ENABLE|GPT_MODE4_ONE_SHOT);
78 
79     return NO_ERROR;
80 }
81 
current_time(void)82 lk_time_t current_time(void) {
83     return ticks;
84 }
85 
current_time_hires(void)86 lk_bigtime_t current_time_hires(void) {
87     lk_bigtime_t time;
88 
89     time = (lk_bigtime_t)ticks * 1000;
90     return time;
91 }
92 
gpt_power_on(bool bPowerOn)93 static void gpt_power_on (bool bPowerOn) {
94     if (!bPowerOn) {
95         DRV_SetReg32(AP_PERI_GLOBALCON_PDN0, 1<<13);
96     } else {
97         DRV_ClrReg32(AP_PERI_GLOBALCON_PDN0, 1<<13);
98     }
99 }
100 
platform_early_init_timer(void)101 void platform_early_init_timer(void) {
102     //dprintf(SPEW, "platform_early_init_timer\n");
103 
104     gpt_power_on(1);
105 }
106