1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Support code for virtual Ranchu board for MIPS.
5 * Author: Miodrag Dinic <miodrag.dinic@mips.com>
8 #include <linux/of_address.h>
9 #include <linux/types.h>
11 #include <asm/machine.h>
12 #include <asm/mipsregs.h>
15 #define GOLDFISH_TIMER_LOW 0x00
16 #define GOLDFISH_TIMER_HIGH 0x04
18 static __init u64
read_rtc_time(void __iomem
*base
)
24 * Reading the low address latches the high value
25 * as well so there is no fear that we may read
26 * inaccurate high value.
28 time_low
= readl(base
+ GOLDFISH_TIMER_LOW
);
29 time_high
= readl(base
+ GOLDFISH_TIMER_HIGH
);
31 return ((u64
)time_high
<< 32) | time_low
;
34 static __init
unsigned int ranchu_measure_hpt_freq(void)
36 u64 rtc_start
, rtc_current
, rtc_delta
;
37 unsigned int start
, count
;
38 struct device_node
*np
;
39 void __iomem
*rtc_base
;
41 np
= of_find_compatible_node(NULL
, NULL
, "google,goldfish-rtc");
43 panic("%s(): Failed to find 'google,goldfish-rtc' dt node!",
46 rtc_base
= of_iomap(np
, 0);
48 panic("%s(): Failed to ioremap Goldfish RTC base!", __func__
);
51 * Poll the nanosecond resolution RTC for one
52 * second to calibrate the CPU frequency.
54 rtc_start
= read_rtc_time(rtc_base
);
55 start
= read_c0_count();
58 rtc_current
= read_rtc_time(rtc_base
);
59 rtc_delta
= rtc_current
- rtc_start
;
60 } while (rtc_delta
< NSEC_PER_SEC
);
62 count
= read_c0_count() - start
;
65 * Make sure the frequency will be a round number.
66 * Without this correction, the returned value may vary
67 * between subsequent emulation executions.
69 * TODO: Set this value using device tree.
72 count
-= count
% 10000;
79 static const struct of_device_id ranchu_of_match
[] __initconst
= {
81 .compatible
= "mti,ranchu",
86 MIPS_MACHINE(ranchu
) = {
87 .matches
= ranchu_of_match
,
88 .measure_hpt_freq
= ranchu_measure_hpt_freq
,