xref: /linux/arch/riscv/kernel/time.c (revision 5c35a02c545a7bbe77f3a1ae337d9e29beed079b)
1 /*
2  * Copyright (C) 2012 Regents of the University of California
3  * Copyright (C) 2017 SiFive
4  *
5  *   This program is free software; you can redistribute it and/or
6  *   modify it under the terms of the GNU General Public License
7  *   as published by the Free Software Foundation, version 2.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  */
14 
15 #include <linux/clocksource.h>
16 #include <linux/clockchips.h>
17 #include <linux/delay.h>
18 
19 #ifdef CONFIG_RISCV_TIMER
20 #include <linux/timer_riscv.h>
21 #endif
22 
23 #include <asm/sbi.h>
24 
25 unsigned long riscv_timebase;
26 
27 DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event);
28 
29 void riscv_timer_interrupt(void)
30 {
31 #ifdef CONFIG_RISCV_TIMER
32 	/*
33 	 * FIXME: This needs to be cleaned up along with the rest of the IRQ
34 	 * handling cleanup.  See irq.c for more details.
35 	 */
36 	struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
37 
38 	evdev->event_handler(evdev);
39 #endif
40 }
41 
42 void __init init_clockevent(void)
43 {
44 	timer_probe();
45 	csr_set(sie, SIE_STIE);
46 }
47 
48 void __init time_init(void)
49 {
50 	struct device_node *cpu;
51 	u32 prop;
52 
53 	cpu = of_find_node_by_path("/cpus");
54 	if (!cpu || of_property_read_u32(cpu, "timebase-frequency", &prop))
55 		panic(KERN_WARNING "RISC-V system with no 'timebase-frequency' in DTS\n");
56 	riscv_timebase = prop;
57 
58 	lpj_fine = riscv_timebase / HZ;
59 
60 	init_clockevent();
61 }
62