1 /* 2 * Support code for virtual Ranchu board for MIPS. 3 * 4 * Author: Miodrag Dinic <miodrag.dinic@mips.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 */ 11 12 #include <linux/of_address.h> 13 #include <linux/types.h> 14 15 #include <asm/machine.h> 16 #include <asm/mipsregs.h> 17 #include <asm/time.h> 18 19 #define GOLDFISH_TIMER_LOW 0x00 20 #define GOLDFISH_TIMER_HIGH 0x04 21 22 static __init u64 read_rtc_time(void __iomem *base) 23 { 24 u32 time_low; 25 u32 time_high; 26 27 /* 28 * Reading the low address latches the high value 29 * as well so there is no fear that we may read 30 * inaccurate high value. 31 */ 32 time_low = readl(base + GOLDFISH_TIMER_LOW); 33 time_high = readl(base + GOLDFISH_TIMER_HIGH); 34 35 return ((u64)time_high << 32) | time_low; 36 } 37 38 static __init unsigned int ranchu_measure_hpt_freq(void) 39 { 40 u64 rtc_start, rtc_current, rtc_delta; 41 unsigned int start, count; 42 struct device_node *np; 43 void __iomem *rtc_base; 44 45 np = of_find_compatible_node(NULL, NULL, "google,goldfish-rtc"); 46 if (!np) 47 panic("%s(): Failed to find 'google,goldfish-rtc' dt node!", 48 __func__); 49 50 rtc_base = of_iomap(np, 0); 51 if (!rtc_base) 52 panic("%s(): Failed to ioremap Goldfish RTC base!", __func__); 53 54 /* 55 * Poll the nanosecond resolution RTC for one 56 * second to calibrate the CPU frequency. 57 */ 58 rtc_start = read_rtc_time(rtc_base); 59 start = read_c0_count(); 60 61 do { 62 rtc_current = read_rtc_time(rtc_base); 63 rtc_delta = rtc_current - rtc_start; 64 } while (rtc_delta < NSEC_PER_SEC); 65 66 count = read_c0_count() - start; 67 68 /* 69 * Make sure the frequency will be a round number. 70 * Without this correction, the returned value may vary 71 * between subsequent emulation executions. 72 * 73 * TODO: Set this value using device tree. 74 */ 75 count += 5000; 76 count -= count % 10000; 77 78 iounmap(rtc_base); 79 80 return count; 81 } 82 83 static const struct of_device_id ranchu_of_match[] __initconst = { 84 { 85 .compatible = "mti,ranchu", 86 }, 87 {} 88 }; 89 90 MIPS_MACHINE(ranchu) = { 91 .matches = ranchu_of_match, 92 .measure_hpt_freq = ranchu_measure_hpt_freq, 93 }; 94