2021-05-16 18:27:01 +08:00

91 lines
2.6 KiB
C

/*
* 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 <common/kprint.h>
#include <common/machine.h>
#include <common/smp.h>
#include <common/tools.h>
#include <common/types.h>
#include <exception/irq.h>
#include <exception/timer.h>
#include <process/thread.h>
#include <sched/sched.h>
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();
}