avr32: Scale loops_per_jiffy when cpu frequency changes
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>
Thu, 23 Oct 2008 09:23:08 +0000 (11:23 +0200)
committerHaavard Skinnemoen <haavard.skinnemoen@atmel.com>
Thu, 23 Oct 2008 13:18:33 +0000 (15:18 +0200)
The loops_per_jiffy variable isn't updated when cpufreq changes the CPU
frequency. This could cause udelay() and friends to produce wrong
delays.

Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
arch/avr32/mach-at32ap/cpufreq.c

index d84efe4..024c586 100644 (file)
@@ -40,6 +40,9 @@ static unsigned int at32_get_speed(unsigned int cpu)
        return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000);
 }
 
+static unsigned int    ref_freq;
+static unsigned long   loops_per_jiffy_ref;
+
 static int at32_set_target(struct cpufreq_policy *policy,
                          unsigned int target_freq,
                          unsigned int relation)
@@ -61,8 +64,19 @@ static int at32_set_target(struct cpufreq_policy *policy,
        freqs.cpu = 0;
        freqs.flags = 0;
 
+       if (!ref_freq) {
+               ref_freq = freqs.old;
+               loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy;
+       }
+
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       if (freqs.old < freqs.new)
+               boot_cpu_data.loops_per_jiffy = cpufreq_scale(
+                               loops_per_jiffy_ref, ref_freq, freqs.new);
        clk_set_rate(cpuclk, freq);
+       if (freqs.new < freqs.old)
+               boot_cpu_data.loops_per_jiffy = cpufreq_scale(
+                               loops_per_jiffy_ref, ref_freq, freqs.new);
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
        pr_debug("cpufreq: set frequency %lu Hz\n", freq);