1  /*
2  * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <soc.h>
20 #include <csi_core.h>
21 #include <csi_config.h>
22 #include <sys_clk.h>
23 #include <drv/common.h>
24 #include <drv/irq.h>
25 #include <drv/tick.h>
26 #include <drv/porting.h>
27 #include <drv/timer.h>
28 #include <rtthread.h>
29 
30 #define __WEAK         __attribute__((weak))
31 
32 #if defined(CONFIG_SMP) && CONFIG_SMP
33 static volatile uint32_t csi_tick[CONFIG_NR_CPUS] = {0U};
34 #else
35 static volatile uint32_t csi_tick = 0U;
36 #endif
37 static volatile uint32_t last_time_ms = 0U;
38 static volatile uint64_t last_time_us = 0U;
39 static volatile uint64_t timer_init_value = 0U;
40 
41 #if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC
42 static csi_dev_t tick_dev;
43 #endif
44 
csi_tick_increase(void)45 void csi_tick_increase(void)
46 {
47 #if defined(CONFIG_SMP) && CONFIG_SMP
48     csi_tick[csi_get_cpu_id()]++;
49 #else
50     csi_tick++;
51 #endif
52 }
53 
csi_tick_get(void)54 uint32_t csi_tick_get(void)
55 {
56 #if defined(CONFIG_SMP) && CONFIG_SMP
57     return csi_tick[csi_get_cpu_id()];
58 #else
59     return csi_tick;
60 #endif
61 }
62 
tick_irq_handler(void * arg)63 void tick_irq_handler(void *arg)
64 {
65     csi_tick_increase();
66     csi_coret_config((soc_get_coretim_freq() / RT_TICK_PER_SECOND), CORET_IRQn);
67 #if CONFIG_AOS_OSAL
68     extern void aos_sys_tick_handler(void);
69     aos_sys_tick_handler();
70 #else
71 #ifdef CONFIG_KERNEL_FREERTOS
72     extern void xPortSysTickHandler(void);
73     xPortSysTickHandler();
74 #elif defined(CONFIG_KERNEL_RTTHREAD)
75     rt_interrupt_enter();
76     extern void rt_tick_increase(void);
77     rt_tick_increase();
78     rt_interrupt_leave();
79 #else
80 #endif
81 #endif /* end CONFIG_AOS_OSAL */
82 }
83 
csi_tick_init(void)84 csi_error_t csi_tick_init(void)
85 {
86 #if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC
87     tick_dev.irq_num = CORET_IRQn;
88     csi_vic_set_prio(tick_dev.irq_num, 31U);
89     csi_irq_attach(tick_dev.irq_num, &tick_irq_handler, &tick_dev);
90 #endif
91 
92 #if defined(CONFIG_SMP) && CONFIG_SMP
93     csi_tick[csi_get_cpu_id()] = 0;
94 #else
95     csi_tick = 0U;
96 #endif
97     timer_init_value = csi_coret_get_value2();
98     csi_coret_reset_value2();
99     csi_coret_config((soc_get_coretim_freq() / RT_TICK_PER_SECOND), CORET_IRQn);
100     csi_coret_irq_enable();
101 
102     return CSI_OK;
103 }
104 
csi_tick_uninit(void)105 void csi_tick_uninit(void)
106 {
107     csi_coret_irq_disable();
108 #if CONFIG_CPU_XUANTIE_E9XX || CONFIG_INTC_CLIC_PLIC
109     csi_irq_detach(tick_dev.irq_num);
110 #endif
111 }
112 
csi_tick_get_ms(void)113 uint32_t csi_tick_get_ms(void)
114 {
115     uint32_t time;
116 
117     time = (uint32_t)((csi_coret_get_value2() - timer_init_value) * 1000U / (uint64_t)soc_get_coretim_freq());
118     last_time_ms = time;
119     return time;
120 }
121 
csi_tick_get_us(void)122 uint64_t csi_tick_get_us(void)
123 {
124     uint64_t time;
125 
126     time = (csi_coret_get_value2() - timer_init_value) * 1000U * 1000U / (uint64_t)soc_get_coretim_freq();
127     last_time_us = time;
128     return time;
129 }
130 
_mdelay(void)131 static void _mdelay(void)
132 {
133     uint64_t start = csi_coret_get_value2();
134     uint64_t cur;
135     uint32_t cnt = (soc_get_coretim_freq() / 1000U);
136 
137     while (1) {
138         cur = csi_coret_get_value2();
139 
140         if (start > cur) {
141             if ((start - cur) >= cnt) {
142                 break;
143             }
144         } else {
145             if (cur - start >= cnt) {
146                 break;
147             }
148         }
149     }
150 }
151 
_10udelay(void)152 static void _10udelay(void)
153 {
154     uint64_t cur;
155     uint64_t start = csi_coret_get_value2();
156     uint32_t cnt = (soc_get_coretim_freq() / 1000U / 100U);
157 
158     while (1) {
159         cur = csi_coret_get_value2();
160 
161         if (start > cur) {
162             if ((start - cur) >= cnt) {
163                 break;
164             }
165         } else {
166             if (cur - start >= cnt) {
167                 break;
168             }
169         }
170     }
171 }
172 
mdelay(uint32_t ms)173 __WEAK void mdelay(uint32_t ms)
174 {
175     while (ms) {
176         ms--;
177         _mdelay();
178     }
179 }
180 
181 /**
182  * Ps: At least delay over 10us
183 */
udelay(uint32_t us)184 void udelay(uint32_t us)
185 {
186     us /= 10U;
187 
188     while (us) {
189         us--;
190         _10udelay();
191     }
192 }
193 
194