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)45void 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)54uint32_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)63void 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)84csi_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)105void 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)113uint32_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)122uint64_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)131static 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)152static 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)184void udelay(uint32_t us) 185 { 186 us /= 10U; 187 188 while (us) { 189 us--; 190 _10udelay(); 191 } 192 } 193 194