Commit | Line | Data |
---|---|---|
3070033a SH |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. | |
7 | */ | |
8 | #include <linux/init.h> | |
4060bbe9 | 9 | #include <linux/irqchip/mips-gic.h> |
3070033a | 10 | |
8ff374b9 | 11 | #include <asm/cpu.h> |
3070033a SH |
12 | #include <asm/setup.h> |
13 | #include <asm/time.h> | |
14 | #include <asm/irq.h> | |
15 | #include <asm/mips-boards/generic.h> | |
3070033a | 16 | |
3070033a SH |
17 | static void __iomem *status_reg = (void __iomem *)0xbf000410; |
18 | ||
19 | /* | |
20 | * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect. | |
21 | */ | |
22 | static unsigned int __init estimate_cpu_frequency(void) | |
23 | { | |
8ff374b9 | 24 | unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK); |
3070033a SH |
25 | unsigned int tick = 0; |
26 | unsigned int freq; | |
27 | unsigned int orig; | |
28 | unsigned long flags; | |
29 | ||
30 | local_irq_save(flags); | |
31 | ||
70342287 | 32 | orig = readl(status_reg) & 0x2; /* get original sample */ |
3070033a SH |
33 | /* wait for transition */ |
34 | while ((readl(status_reg) & 0x2) == orig) | |
35 | ; | |
70342287 | 36 | orig = orig ^ 0x2; /* flip the bit */ |
3070033a SH |
37 | |
38 | write_c0_count(0); | |
39 | ||
40 | /* wait 1 second (the sampling clock transitions every 10ms) */ | |
41 | while (tick < 100) { | |
42 | /* wait for transition */ | |
43 | while ((readl(status_reg) & 0x2) == orig) | |
44 | ; | |
70342287 | 45 | orig = orig ^ 0x2; /* flip the bit */ |
3070033a SH |
46 | tick++; |
47 | } | |
48 | ||
49 | freq = read_c0_count(); | |
50 | ||
51 | local_irq_restore(flags); | |
52 | ||
53 | mips_hpt_frequency = freq; | |
54 | ||
55 | /* Adjust for processor */ | |
56 | if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && | |
57 | (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) | |
58 | freq *= 2; | |
59 | ||
70342287 | 60 | freq += 5000; /* rounding */ |
3070033a SH |
61 | freq -= freq%10000; |
62 | ||
63 | return freq ; | |
64 | } | |
65 | ||
66 | void read_persistent_clock(struct timespec *ts) | |
67 | { | |
68 | ts->tv_sec = 0; | |
69 | ts->tv_nsec = 0; | |
70 | } | |
71 | ||
a669efc4 | 72 | int get_c0_perfcount_int(void) |
3070033a | 73 | { |
e9de688d | 74 | if (gic_present) |
44923c9c | 75 | return gic_get_c0_perfcount_int(); |
e9de688d AB |
76 | if (cp0_perfcount_irq >= 0) |
77 | return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; | |
78 | return -1; | |
3070033a | 79 | } |
0cb0985f | 80 | EXPORT_SYMBOL_GPL(get_c0_perfcount_int); |
3070033a | 81 | |
078a55fc | 82 | unsigned int get_c0_compare_int(void) |
3070033a | 83 | { |
e9de688d AB |
84 | if (gic_present) |
85 | return gic_get_c0_compare_int(); | |
86 | return MIPS_CPU_IRQ_BASE + cp0_compare_irq; | |
3070033a SH |
87 | } |
88 | ||
89 | void __init plat_time_init(void) | |
90 | { | |
91 | unsigned int est_freq; | |
92 | ||
93 | est_freq = estimate_cpu_frequency(); | |
94 | ||
95 | pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000), | |
96 | (est_freq % 1000000) * 100 / 1000000); | |
97 | ||
3070033a | 98 | mips_scroll_message(); |
3070033a | 99 | } |