Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Support code for virtual Ranchu board for MIPS.
0004  *
0005  * Author: Miodrag Dinic <miodrag.dinic@mips.com>
0006  */
0007 
0008 #include <linux/of_address.h>
0009 #include <linux/types.h>
0010 
0011 #include <asm/machine.h>
0012 #include <asm/mipsregs.h>
0013 #include <asm/time.h>
0014 
0015 #define GOLDFISH_TIMER_LOW      0x00
0016 #define GOLDFISH_TIMER_HIGH     0x04
0017 
0018 static __init u64 read_rtc_time(void __iomem *base)
0019 {
0020     u32 time_low;
0021     u32 time_high;
0022 
0023     /*
0024      * Reading the low address latches the high value
0025      * as well so there is no fear that we may read
0026      * inaccurate high value.
0027      */
0028     time_low = readl(base + GOLDFISH_TIMER_LOW);
0029     time_high = readl(base + GOLDFISH_TIMER_HIGH);
0030 
0031     return ((u64)time_high << 32) | time_low;
0032 }
0033 
0034 static __init unsigned int ranchu_measure_hpt_freq(void)
0035 {
0036     u64 rtc_start, rtc_current, rtc_delta;
0037     unsigned int start, count;
0038     struct device_node *np;
0039     void __iomem *rtc_base;
0040 
0041     np = of_find_compatible_node(NULL, NULL, "google,goldfish-rtc");
0042     if (!np)
0043         panic("%s(): Failed to find 'google,goldfish-rtc' dt node!",
0044               __func__);
0045 
0046     rtc_base = of_iomap(np, 0);
0047     of_node_put(np);
0048     if (!rtc_base)
0049         panic("%s(): Failed to ioremap Goldfish RTC base!", __func__);
0050 
0051     /*
0052      * Poll the nanosecond resolution RTC for one
0053      * second to calibrate the CPU frequency.
0054      */
0055     rtc_start = read_rtc_time(rtc_base);
0056     start = read_c0_count();
0057 
0058     do {
0059         rtc_current = read_rtc_time(rtc_base);
0060         rtc_delta = rtc_current - rtc_start;
0061     } while (rtc_delta < NSEC_PER_SEC);
0062 
0063     count = read_c0_count() - start;
0064 
0065     /*
0066      * Make sure the frequency will be a round number.
0067      * Without this correction, the returned value may vary
0068      * between subsequent emulation executions.
0069      *
0070      * TODO: Set this value using device tree.
0071      */
0072     count += 5000;
0073     count -= count % 10000;
0074 
0075     iounmap(rtc_base);
0076 
0077     return count;
0078 }
0079 
0080 static const struct of_device_id ranchu_of_match[] __initconst = {
0081     {
0082         .compatible = "mti,ranchu",
0083     },
0084     {}
0085 };
0086 
0087 MIPS_MACHINE(ranchu) = {
0088     .matches = ranchu_of_match,
0089     .measure_hpt_freq = ranchu_measure_hpt_freq,
0090 };