/* * Copyright (c) 2020 Institute of Parallel And Distributed Systems (IPADS), * Shanghai Jiao Tong University (SJTU) OS-Lab-2020 (i.e., ChCore) is licensed * under the Mulan PSL v1. You can use this software according to the terms and * conditions of the Mulan PSL v1. You may obtain a copy of Mulan PSL v1 at: * http://license.coscl.org.cn/MulanPSL * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the * Mulan PSL v1 for more details. */ #include #include #include #include #include #include #include #include #include u64 cntv_tval; /* Per core IRQ SOURCE MMIO address */ u64 core_timer_irqcntl[PLAT_CPU_NUM] = { CORE0_TIMER_IRQCNTL, CORE1_TIMER_IRQCNTL, CORE2_TIMER_IRQCNTL, CORE3_TIMER_IRQCNTL }; void timer_init(void) { u64 cur_freq = 0; u64 cur_cnt = 0; u64 count_down = 0; u64 timer_ctl = 0; u32 cpuid = smp_get_cpu_id(); /* Since QEMU only emulate the generic timer, we use the generic timer * here */ asm volatile ("mrs %0, cntpct_el0":"=r" (cur_cnt)); kdebug("timer init cntpct_el0 = %lu\n", cur_cnt); asm volatile ("mrs %0, cntfrq_el0":"=r" (cur_freq)); kdebug("timer init cntfrq_el0 = %lu\n", cur_freq); /* Calculate the tv */ cntv_tval = (cur_freq * TICK_MS / 1000); kdebug("CPU freq %lu, set timer %lu\n", cur_freq, cntv_tval); /* set the timervalue here */ asm volatile ("msr cntv_tval_el0, %0"::"r" (cntv_tval)); asm volatile ("mrs %0, cntv_tval_el0":"=r" (count_down)); kdebug("timer init cntv_tval_el0 = %lu\n", count_down); put32(core_timer_irqcntl[cpuid], INT_SRC_TIMER3); /* Set the control register */ timer_ctl = 0 << 1 | 1; /* IMASK = 0 ENABLE = 1 */ asm volatile ("msr cntv_ctl_el0, %0"::"r" (timer_ctl)); asm volatile ("mrs %0, cntv_ctl_el0":"=r" (timer_ctl)); kdebug("timer init cntv_ctl_el0 = %lu\n", timer_ctl); /* enable interrupt controller */ return; } void plat_handle_timer_irq(void) { asm volatile ("msr cntv_tval_el0, %0"::"r" (cntv_tval)); } void plat_disable_timer(void) { u64 timer_ctl = 0x0; asm volatile ("msr cntv_ctl_el0, %0"::"r" (timer_ctl)); } void plat_enable_timer(void) { u64 timer_ctl = 0x1; asm volatile ("msr cntv_tval_el0, %0"::"r" (cntv_tval)); asm volatile ("msr cntv_ctl_el0, %0"::"r" (timer_ctl)); } void handle_timer_irq(void) { plat_handle_timer_irq(); sched_handle_timer_irq(); }