diff options
Diffstat (limited to 'arch/mips/kernel/time.c')
-rw-r--r-- | arch/mips/kernel/time.c | 112 |
1 files changed, 33 insertions, 79 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 3284b9b4ecac..52075426c373 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
@@ -50,14 +50,6 @@ int update_persistent_clock(struct timespec now) | |||
50 | return rtc_mips_set_mmss(now.tv_sec); | 50 | return rtc_mips_set_mmss(now.tv_sec); |
51 | } | 51 | } |
52 | 52 | ||
53 | /* | ||
54 | * High precision timer functions for a R4k-compatible timer. | ||
55 | */ | ||
56 | static cycle_t c0_hpt_read(void) | ||
57 | { | ||
58 | return read_c0_count(); | ||
59 | } | ||
60 | |||
61 | int (*mips_timer_state)(void); | 53 | int (*mips_timer_state)(void); |
62 | 54 | ||
63 | int null_perf_irq(void) | 55 | int null_perf_irq(void) |
@@ -84,55 +76,6 @@ EXPORT_SYMBOL(perf_irq); | |||
84 | 76 | ||
85 | unsigned int mips_hpt_frequency; | 77 | unsigned int mips_hpt_frequency; |
86 | 78 | ||
87 | static struct clocksource clocksource_mips = { | ||
88 | .name = "MIPS", | ||
89 | .read = c0_hpt_read, | ||
90 | .mask = CLOCKSOURCE_MASK(32), | ||
91 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
92 | }; | ||
93 | |||
94 | static unsigned int __init calibrate_hpt(void) | ||
95 | { | ||
96 | cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; | ||
97 | |||
98 | const int loops = HZ / 10; | ||
99 | int log_2_loops = 0; | ||
100 | int i; | ||
101 | |||
102 | /* | ||
103 | * We want to calibrate for 0.1s, but to avoid a 64-bit | ||
104 | * division we round the number of loops up to the nearest | ||
105 | * power of 2. | ||
106 | */ | ||
107 | while (loops > 1 << log_2_loops) | ||
108 | log_2_loops++; | ||
109 | i = 1 << log_2_loops; | ||
110 | |||
111 | /* | ||
112 | * Wait for a rising edge of the timer interrupt. | ||
113 | */ | ||
114 | while (mips_timer_state()); | ||
115 | while (!mips_timer_state()); | ||
116 | |||
117 | /* | ||
118 | * Now see how many high precision timer ticks happen | ||
119 | * during the calculated number of periods between timer | ||
120 | * interrupts. | ||
121 | */ | ||
122 | hpt_start = clocksource_mips.read(); | ||
123 | do { | ||
124 | while (mips_timer_state()); | ||
125 | while (!mips_timer_state()); | ||
126 | } while (--i); | ||
127 | hpt_end = clocksource_mips.read(); | ||
128 | |||
129 | hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask; | ||
130 | hz = HZ; | ||
131 | frequency = hpt_count * hz; | ||
132 | |||
133 | return frequency >> log_2_loops; | ||
134 | } | ||
135 | |||
136 | void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) | 79 | void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) |
137 | { | 80 | { |
138 | u64 temp; | 81 | u64 temp; |
@@ -166,16 +109,6 @@ void __cpuinit clockevent_set_clock(struct clock_event_device *cd, | |||
166 | cd->mult = (u32) temp; | 109 | cd->mult = (u32) temp; |
167 | } | 110 | } |
168 | 111 | ||
169 | static void __init init_mips_clocksource(void) | ||
170 | { | ||
171 | /* Calclate a somewhat reasonable rating value */ | ||
172 | clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; | ||
173 | |||
174 | clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); | ||
175 | |||
176 | clocksource_register(&clocksource_mips); | ||
177 | } | ||
178 | |||
179 | void __init __weak plat_time_init(void) | 112 | void __init __weak plat_time_init(void) |
180 | { | 113 | { |
181 | } | 114 | } |
@@ -194,21 +127,42 @@ void __init plat_timer_setup(void) | |||
194 | BUG(); | 127 | BUG(); |
195 | } | 128 | } |
196 | 129 | ||
130 | static __init int cpu_has_mfc0_count_bug(void) | ||
131 | { | ||
132 | switch (current_cpu_type()) { | ||
133 | case CPU_R4000PC: | ||
134 | case CPU_R4000SC: | ||
135 | case CPU_R4000MC: | ||
136 | /* | ||
137 | * V3.0 is documented as suffering from the mfc0 from count bug. | ||
138 | * Afaik this is the last version of the R4000. Later versions | ||
139 | * were marketed as R4400. | ||
140 | */ | ||
141 | return 1; | ||
142 | |||
143 | case CPU_R4400PC: | ||
144 | case CPU_R4400SC: | ||
145 | case CPU_R4400MC: | ||
146 | /* | ||
147 | * The published errata for the R4400 upto 3.0 say the CPU | ||
148 | * has the mfc0 from count bug. | ||
149 | */ | ||
150 | if ((current_cpu_data.processor_id & 0xff) <= 0x30) | ||
151 | return 1; | ||
152 | |||
153 | /* | ||
154 | * I don't have erratas for newer R4400 so be paranoid. | ||
155 | */ | ||
156 | return 1; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
197 | void __init time_init(void) | 162 | void __init time_init(void) |
198 | { | 163 | { |
199 | plat_time_init(); | 164 | plat_time_init(); |
200 | 165 | ||
201 | if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) { | 166 | if (mips_clockevent_init() || !cpu_has_mfc0_count_bug()) |
202 | /* We know counter frequency. Or we can get it. */ | ||
203 | if (!mips_hpt_frequency) | ||
204 | mips_hpt_frequency = calibrate_hpt(); | ||
205 | |||
206 | /* Report the high precision timer rate for a reference. */ | ||
207 | printk("Using %u.%03u MHz high precision timer.\n", | ||
208 | ((mips_hpt_frequency + 500) / 1000) / 1000, | ||
209 | ((mips_hpt_frequency + 500) / 1000) % 1000); | ||
210 | init_mips_clocksource(); | 167 | init_mips_clocksource(); |
211 | } | ||
212 | |||
213 | mips_clockevent_init(); | ||
214 | } | 168 | } |