diff options
Diffstat (limited to 'arch/mips/kernel/time.c')
-rw-r--r-- | arch/mips/kernel/time.c | 87 |
1 files changed, 33 insertions, 54 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 3284b9b4ecac..d7d52efff51f 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
@@ -91,48 +91,6 @@ static struct clocksource clocksource_mips = { | |||
91 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 91 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
92 | }; | 92 | }; |
93 | 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) | 94 | void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) |
137 | { | 95 | { |
138 | u64 temp; | 96 | u64 temp; |
@@ -194,21 +152,42 @@ void __init plat_timer_setup(void) | |||
194 | BUG(); | 152 | BUG(); |
195 | } | 153 | } |
196 | 154 | ||
155 | static __init int cpu_has_mfc0_count_bug(void) | ||
156 | { | ||
157 | switch (current_cpu_type()) { | ||
158 | case CPU_R4000PC: | ||
159 | case CPU_R4000SC: | ||
160 | case CPU_R4000MC: | ||
161 | /* | ||
162 | * V3.0 is documented as suffering from the mfc0 from count bug. | ||
163 | * Afaik this is the last version of the R4000. Later versions | ||
164 | * were marketed as R4400. | ||
165 | */ | ||
166 | return 1; | ||
167 | |||
168 | case CPU_R4400PC: | ||
169 | case CPU_R4400SC: | ||
170 | case CPU_R4400MC: | ||
171 | /* | ||
172 | * The published errata for the R4400 upto 3.0 say the CPU | ||
173 | * has the mfc0 from count bug. | ||
174 | */ | ||
175 | if ((current_cpu_data.processor_id & 0xff) <= 0x30) | ||
176 | return 1; | ||
177 | |||
178 | /* | ||
179 | * I don't have erratas for newer R4400 so be paranoid. | ||
180 | */ | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
197 | void __init time_init(void) | 187 | void __init time_init(void) |
198 | { | 188 | { |
199 | plat_time_init(); | 189 | plat_time_init(); |
200 | 190 | ||
201 | if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) { | 191 | 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(); | 192 | init_mips_clocksource(); |
211 | } | ||
212 | |||
213 | mips_clockevent_init(); | ||
214 | } | 193 | } |