1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-11-22     Jesven       first version
9  */
10 
11 #include <rthw.h>
12 #include <rtthread.h>
13 #include <stdint.h>
14 
15 #include <board.h>
16 #include "mmu.h"
17 
18 #define TICK_PERIOD (g_sys_freq / RT_TICK_PER_SECOND)
19 static int g_sys_freq;
20 
21 #define IRQ_SECURE_PHY_TIMER   29  /* Secure physical timer event */
22 #define IRQ_NOSECURE_PHY_TIMER 30  /* No-Secure physical timer event */
23 
24 #define IRQ_SYS_TICK  IRQ_SECURE_PHY_TIMER
25 
26 
27 /* System Counter */
28 struct sctr_regs {
29     rt_uint32_t cntcr;
30     rt_uint32_t cntsr;
31     rt_uint32_t cntcv1;
32     rt_uint32_t cntcv2;
33     rt_uint32_t resv1[4];
34     rt_uint32_t cntfid0;
35     rt_uint32_t cntfid1;
36     rt_uint32_t cntfid2;
37     rt_uint32_t resv2[1001];
38     rt_uint32_t counterid[1];
39 };
40 
41 #define SC_CNTCR_ENABLE     (1 << 0)
42 #define SC_CNTCR_HDBG       (1 << 1)
43 #define SC_CNTCR_FREQ0      (1 << 8)
44 #define SC_CNTCR_FREQ1      (1 << 9)
45 
46 
47 #define isb() __asm__ __volatile__ ("" : : : "memory")
48 #define dsb() __asm__ __volatile__ ("" : : : "memory")
49 #define dmb() __asm__ __volatile__ ("" : : : "memory")
50 
51 
enable_cntp(void)52 static inline void enable_cntp(void)
53 {
54     rt_uint32_t cntv_ctl;
55     cntv_ctl = 1;
56     asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(cntv_ctl)); // write CNTP_CTL
57     isb();
58 }
59 
disable_cntp(void)60 static inline void disable_cntp(void)
61 {
62     rt_uint32_t cntv_ctl;
63     cntv_ctl = 0;
64     asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(cntv_ctl)); // write CNTP_CTL
65     isb();
66 }
67 
read_cntfrq(void)68 static inline rt_uint32_t read_cntfrq(void)
69 {
70     rt_uint32_t val;
71     asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val));
72     return val;
73 }
74 
write_cntp_tval(rt_uint32_t val)75 static inline  void write_cntp_tval(rt_uint32_t val)
76 {
77     asm volatile ("mcr p15, 0, %0, c14, c2, 0" :: "r"(val));
78     isb();
79     return;
80 }
81 
write_cntp_cval(rt_uint64_t val)82 static inline  void write_cntp_cval(rt_uint64_t val)
83 {
84     asm volatile ("mcrr p15, 2, %Q0, %R0, c14" :: "r" (val));
85     isb();
86     return;
87 }
88 
read_cntp_cval(void)89 static inline rt_uint64_t read_cntp_cval(void)
90 {
91     rt_uint64_t val;
92     asm volatile ("mrrc p15, 2, %Q0, %R0, c14" : "=r" (val));
93     return (val);
94 }
95 
96 volatile unsigned int *CCM_CLPCR;
97 
imx6ull_enable_clk_in_waitmode(void)98 static void imx6ull_enable_clk_in_waitmode(void)
99 {
100     CCM_CLPCR = rt_ioremap((void*)0x20C4054, 4);
101     *CCM_CLPCR &= ~((1 << 5) | 0x3);
102 }
103 
system_counter_clk_source_init(void)104 static void system_counter_clk_source_init(void)
105 {
106     /* to do */
107 }
108 
system_counter_init(void)109 static void system_counter_init(void)
110 {
111     /* enable system_counter */
112 #define SCTR_BASE_ADDR  0x021DC000
113 #define CONFIG_SC_TIMER_CLK  8000000
114 
115     /* imx6ull, enable system counter */
116     struct sctr_regs *sctr = (struct sctr_regs *)rt_ioremap((void*)SCTR_BASE_ADDR, sizeof(struct sctr_regs));
117     unsigned long val, freq;
118 
119     freq = CONFIG_SC_TIMER_CLK;
120     asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
121 
122     sctr->cntfid0 = freq;
123 
124     /* Enable system counter */
125     val = sctr->cntcr;
126     val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1);
127     val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG;
128     sctr->cntcr = val;
129 
130     imx6ull_enable_clk_in_waitmode();
131 }
132 
arch_timer_init(void)133 static void arch_timer_init(void)
134 {
135     g_sys_freq = read_cntfrq();
136 
137     /* set timeout val */
138     disable_cntp();
139     write_cntp_tval(TICK_PERIOD);
140 
141     /* start timer */
142     enable_cntp();
143 
144     /* enable irq */
145 }
146 
rt_hw_timer_isr(int vector,void * param)147 static void rt_hw_timer_isr(int vector, void *param)
148 {
149     rt_tick_increase();
150 
151     /* setup for next irq */
152     /* clear interrupt */
153     disable_cntp();
154     write_cntp_cval(read_cntp_cval() + TICK_PERIOD);
155     enable_cntp();
156 }
157 
rt_hw_timer_init(void)158 int rt_hw_timer_init(void)
159 {
160     /* Setup Timer for generating irq */
161     /* enable timer */
162     system_counter_clk_source_init();
163     system_counter_init();
164     arch_timer_init();
165 
166     /* insall irq, enable irq */
167     rt_hw_interrupt_install(IRQ_SYS_TICK, rt_hw_timer_isr, RT_NULL, "tick");
168     rt_hw_interrupt_umask(IRQ_SYS_TICK);
169 
170     return 0;
171 }
172 INIT_BOARD_EXPORT(rt_hw_timer_init);
173