summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig34
-rw-r--r--arch/arm/mach-integrator/Makefile3
-rw-r--r--arch/arm/mach-integrator/cpu.c171
-rw-r--r--arch/arm/mach-sa1100/Makefile11
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c72
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c71
-rw-r--r--arch/arm/mach-sa1100/generic.c39
-rw-r--r--arch/arm/mach-sa1100/generic.h1
-rw-r--r--arch/arm/mach-sa1100/system3.c14
-rw-r--r--drivers/pcmcia/sa1100_generic.c1
-rw-r--r--drivers/video/sa1100fb.c12
-rw-r--r--kernel/cpufreq.c7
12 files changed, 262 insertions, 174 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index da598aa394e5..2bba98f290e1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -534,15 +534,43 @@ config CPU_FREQ
written) to implement the policy. If you don't understand what this
is all about, it's safe to say 'N'.
+config CPU_FREQ_SA1100
+ bool
+ depends on CPU_FREQ && SA1100_LART
+ default y
+
+config CPU_FREQ_SA1110
+ bool
+ depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
+ default y
+
+config CPU_FREQ_INTEGRATOR
+ tristate "CPUfreq driver for ARM Integrator CPUs"
+ depends on ARCH_INTEGRATOR && CPU_FREQ
+ default y
+ help
+ This enables the CPUfreq driver for ARM Integrator CPUs.
+
+ For details, take a look at linux/Documentation/cpufreq.
+
+ If in doubt, say Y.
+
config CPU_FREQ_24_API
bool
depends on CPU_FREQ
default y
config CPU_FREQ_PROC_INTF
- tristate
- depends on CPU_FREQ
- default y
+ tristate "/proc/cpufreq interface (deprecated)"
+ depends on CPU_FREQ && PROC_FS
+ help
+ This enables the /proc/cpufreq interface for controlling
+ CPUFreq. Please note that it is recommended to use the sysfs
+ interface instead (which is built automatically).
+
+ For details, take a look at linux/Documentation/cpufreq.
+
+ If in doubt, say N.
source "drivers/pci/Kconfig"
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index b4dd5f03596d..8cc51265ad6c 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -4,10 +4,11 @@
# Object file lists.
-obj-y := arch.o cpu.o irq.o mm.o time.o
+obj-y := arch.o irq.o mm.o time.o
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o
+obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
index 9a55cfdb6cbe..3864ded0566f 100644
--- a/arch/arm/mach-integrator/cpu.c
+++ b/arch/arm/mach-integrator/cpu.c
@@ -23,6 +23,8 @@
#include <asm/hardware.h>
#include <asm/io.h>
+static struct cpufreq_driver integrator_driver;
+
#define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET)
#define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET)
#define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET)
@@ -43,7 +45,6 @@ static unsigned int vco_to_freq(struct vco vco, int factor)
return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor;
}
-#ifdef CONFIG_CPU_FREQ
/*
* Divisor indexes in ascending divisor order
*/
@@ -69,21 +70,17 @@ static struct vco freq_to_vco(unsigned int freq_khz, int factor)
return vco;
}
+
/*
- * Validate the speed in khz. If it is outside our
- * range, then return the lowest.
+ * Validate the speed policy.
*/
-static int integrator_verify_speed(struct cpufreq_policy *policy)
+static int integrator_verify_policy(struct cpufreq_policy *policy)
{
struct vco vco;
- if (policy->max > policy->cpuinfo.max_freq)
- policy->max = policy->cpuinfo.max_freq;
-
- if (policy->max < 12000)
- policy->max = 12000;
- if (policy->max > 160000)
- policy->max = 160000;
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
vco = freq_to_vco(policy->max, 1);
@@ -92,12 +89,28 @@ static int integrator_verify_speed(struct cpufreq_policy *policy)
if (vco.vdw > 152)
vco.vdw = 152;
- policy->min = policy->max = vco_to_freq(vco, 1);
+ policy->max = vco_to_freq(vco, 1);
+
+ vco = freq_to_vco(policy->min, 1);
+
+ if (vco.vdw < 4)
+ vco.vdw = 4;
+ if (vco.vdw > 152)
+ vco.vdw = 152;
+
+ policy->min = vco_to_freq(vco, 1);
+
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
return 0;
}
-static int integrator_set_policy(struct cpufreq_policy *policy)
+
+static int integrator_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
unsigned long cpus_allowed;
int cpu = policy->cpu;
@@ -121,9 +134,18 @@ static int integrator_set_policy(struct cpufreq_policy *policy)
cm_osc = __raw_readl(CM_OSC);
vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
-
freqs.old = vco_to_freq(vco, 1);
- freqs.new = target_freq;
+
+ /* freq_to_vco rounds down -- so we need the next larger freq in
+ * case of CPUFREQ_RELATION_L.
+ */
+ if (relation == CPUFREQ_RELATION_L)
+ target_freq += 1999;
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+ vco = freq_to_vco(target_freq, 1);
+ freqs.new = vco_to_freq(vco, 1);
+
freqs.cpu = policy->cpu;
if (freqs.old == freqs.new) {
@@ -132,7 +154,6 @@ static int integrator_set_policy(struct cpufreq_policy *policy)
}
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- vco = freq_to_vco(policy->max, 1);
cm_osc = __raw_readl(CM_OSC);
cm_osc &= 0xfffff800;
@@ -152,80 +173,64 @@ static int integrator_set_policy(struct cpufreq_policy *policy)
return 0;
}
-static struct cpufreq_policy integrator_policy = {
- .cpu = 0,
- .policy = CPUFREQ_POLICY_POWERSAVE,
- .cpuinfo = {
- .max_freq = 160000,
- .min_freq = 12000,
- .transition_latency = CPUFREQ_ETERNAL,
- },
-};
+static int integrator_cpufreq_init(struct cpufreq *policy)
+{
+ unsigned long cus_allowed;
+ unsigned int cpu = policy->cpu;
+ u_int cm_osc, cm_stat, mem_freq_khz;
+ struct vco vco;
-static struct cpufreq_driver integrator_driver = {
- .verify = integrator_verify_speed,
- .setpolicy = integrator_set_policy,
- .policy = &integrator_policy,
- .name = "integrator",
-};
-#endif
+ cpus_allowed = current->cpus_allowed;
-static int __init integrator_cpu_init(void)
-{
- struct cpufreq_policy *policies;
- unsigned long cpus_allowed;
- int cpu;
+ set_cpus_allowed(current, 1 << cpu);
+ BUG_ON(cpu != smp_processor_id());
- policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS,
- GFP_KERNEL);
- if (!policies) {
- printk(KERN_ERR "CPU: unable to allocate policies structure\n");
- return -ENOMEM;
- }
+ /* detect memory etc. */
+ cm_stat = __raw_readl(CM_STAT);
+ cm_osc = __raw_readl(CM_OSC);
+ vco.od = (cm_osc >> 20) & 7;
+ vco.vdw = (cm_osc >> 12) & 255;
+ mem_freq_khz = vco_to_freq(vco, 2);
- cpus_allowed = current->cpus_allowed;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- u_int cm_osc, cm_stat, mem_freq_khz;
- struct vco vco;
-
- if (!cpu_online(cpu))
- continue;
-
- set_cpus_allowed(current, 1 << cpu);
- BUG_ON(cpu != smp_processor_id());
-
- cm_stat = __raw_readl(CM_STAT);
- cm_osc = __raw_readl(CM_OSC);
- vco.od = (cm_osc >> 20) & 7;
- vco.vdw = (cm_osc >> 12) & 255;
- mem_freq_khz = vco_to_freq(vco, 2);
-
- printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
- printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
- cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
-
- vco.od = (cm_osc >> 8) & 7;
- vco.vdw = cm_osc & 255;
-
- policies[cpu].cpu = cpu;
- policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
- policies[cpu].cpuinfo.max_freq = 160000;
- policies[cpu].cpuinfo.min_freq = 12000;
- policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
- policies[cpu].min =
- policies[cpu].max = vco_to_freq(vco, 1);
- }
+ printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
+ printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
+ cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
- set_cpus_allowed(current, cpus_allowed);
+ vco.od = (cm_osc >> 8) & 7;
+ vco.vdw = cm_osc & 255;
+
+ /* set default policy and cpuinfo */
+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+ policy->cpuinfo.max_freq = 160000;
+ policy->cpuinfo.min_freq = 12000;
+ policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */
+ integrator_driver.cpu_cur_freq[policy->cpu] = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */
-#ifdef CONFIG_CPU_FREQ
- integrator_driver.policy = policies;
- cpufreq_register(&integrator_driver);
-#else
- kfree(policies);
-#endif
+ set_cpus_allowed(current, cpus_allowed);
return 0;
}
-arch_initcall(integrator_cpu_init);
+static struct cpufreq_driver integrator_driver = {
+ .verify = integrator_verify_policy,
+ .target = integrator_set_target,
+ .init = integrator_cpufreq_init,
+ .name = "integrator",
+};
+
+static int __init integrator_cpu_init(void)
+{
+ return cpufreq_register_driver(&integrator_driver);
+}
+
+static void __exit integrator_cpu_exit(void)
+{
+ cpufreq_unregister_driver(&integrator_driver);
+}
+
+MODULE_AUTHOR ("Russell M. King");
+MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
+MODULE_LICENSE ("GPL");
+
+module_init(integrator_cpu_init);
+module_exit(integrator_cpu_exit);
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index dbcc33dd5ac2..2206d68fc61c 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -9,15 +9,8 @@ obj-n :=
obj- :=
led-y := leds.o
-# This needs to be cleaned up. We probably need to have SA1100
-# and SA1110 config symbols.
-ifeq ($(CONFIG_CPU_FREQ),y)
-obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
-obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
-obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o
-obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o
-obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
-endif
+obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o
+obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o
# Specific board support
obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 9c1c4ba81c4e..9ca312c415e4 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -101,7 +101,7 @@ typedef struct {
} sa1100_dram_regs_t;
-
+static struct cpufreq_driver sa1100_driver;
static sa1100_dram_regs_t sa1100_dram_settings[] =
{
@@ -176,60 +176,72 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
}
}
-static int sa1100_setspeed(struct cpufreq_policy *policy)
+static int sa1100_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
unsigned int cur = sa11x0_getspeed();
+ unsigned int new_ppcr;
+
struct cpufreq_freqs freqs;
+ switch(relation){
+ case CPUFREQ_RELATION_L:
+ new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
+ new_ppcr--;
+ break;
+ case CPUFREQ_RELATION_H:
+ new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
+ (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
+ mew_ppcr--;
+ break;
+ }
freqs.old = cur;
- freqs.new = policy->max;
+ freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
freqs.cpu = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- if (policy->max > cur)
- sa1100_update_dram_timings(cur, policy->max);
+ if (freqs.new > cur)
+ sa1100_update_dram_timings(cur, freqs.new);
- PPCR = sa11x0_freq_to_ppcr(policy->max);
+ PPCR = new_ppcr;
- if (policy->max < cur)
- sa1100_update_dram_timings(cur, policy->max);
+ if (freqs.new < cur)
+ sa1100_update_dram_timings(cur, freqs.new);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0;
}
-static struct cpufreq_policy sa1100_policy = {
- .cpu = 0,
- .policy = CPUFREQ_POLICY_POWERSAVE,
- .cpuinfo = {
- .max_freq = 287000,
- .min_freq = 59000,
- .transition_latency = CPUFREQ_ETERNAL,
- },
-};
+static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+ sa1100_driver.cpu_cur_freq[policy->cpu] = policy->min = policy->max = sa11x0_getspeed();
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ policy->cpuinfo.min_freq = 59000;
+ policy->cpuinfo.max_freq = 287000;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ return 0;
+}
static struct cpufreq_driver sa1100_driver = {
.verify = sa11x0_verify_speed,
- .setpolicy = sa1100_setspeed,
- .policy = &sa1100_policy,
+ .target = sa1100_target,
+ .init = sa1100_cpu_init,
.name = "sa1100",
};
static int __init sa1100_dram_init(void)
{
- int ret = -ENODEV;
-
- if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
- sa1100_driver.cpu_cur_freq[0] =
- sa1100_policy.min =
- sa1100_policy.max = sa11x0_getspeed();
-
- ret = cpufreq_register(&sa1100_driver);
- }
-
- return ret;
+ if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID)
+ return cpufreq_register_driver(&sa1100_driver);
+ else
+ return -ENODEV;
}
arch_initcall(sa1100_dram_init);
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index ecfc2c113a7e..18deba6f5eb9 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -32,6 +32,8 @@
#undef DEBUG
+static struct cpufreq_driver sa1110_driver;
+
struct sdram_params {
u_char rows; /* bits */
u_char cas_latency; /* cycles */
@@ -208,11 +210,11 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
}
/*
- * Ok, set the CPU frequency. Since we've done the validation
- * above, we can match for an exact frequency. If we don't find
- * an exact match, we will to set the lowest frequency to be safe.
+ * Ok, set the CPU frequency.
*/
-static int sa1110_setspeed(struct cpufreq_policy *policy)
+static int sa1110_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
struct sdram_params *sdram = &sdram_params;
struct cpufreq_freqs freqs;
@@ -220,8 +222,25 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
unsigned long flags;
unsigned int ppcr, unused;
- ppcr = sa11x0_freq_to_ppcr(policy->max);
- sdram_calculate_timing(&sd, policy->max, sdram);
+ switch(relation){
+ case CPUFREQ_RELATION_L:
+ ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
+ ppcr--;
+ break;
+ case CPUFREQ_RELATION_H:
+ ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
+ (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
+ ppcr--;
+ break;
+ }
+
+ freqs.old = sa11x0_getspeed();
+ freqs.new = sa11x0_ppcr_to_freq(ppcr);
+ freqs.cpu = 0;
+
+ sdram_calculate_timing(&sd, freqs.new, sdram);
#if 0
/*
@@ -240,10 +259,6 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
sd.mdcas[2] = 0xaaaaaaaa;
#endif
- freqs.old = sa11x0_getspeed();
- freqs.new = policy->max;
- freqs.cpu = 0;
-
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/*
@@ -288,27 +303,29 @@ static int sa1110_setspeed(struct cpufreq_policy *policy)
/*
* Now, return the SDRAM refresh back to normal.
*/
- sdram_update_refresh(policy->max, sdram);
+ sdram_update_refresh(freqs.new, sdram);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0;
}
-static struct cpufreq_policy sa1110_policy = {
- .cpu = 0,
- .policy = CPUFREQ_POLICY_POWERSAVE,
- .cpuinfo = {
- .max_freq = 287000,
- .min_freq = 59000,
- .transition_latency = CPUFREQ_ETERNAL,
- },
-};
+static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+ sa1110_driver.cpu_cur_freq[policy->cpu] = policy->min = policy->max = sa11x0_getspeed();
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ policy->cpuinfo.min_freq = 59000;
+ policy->cpuinfo.max_freq = 287000;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ return 0;
+}
static struct cpufreq_driver sa1110_driver = {
- .verify = sa11x0_verify_speed,
- .setpolicy = sa1110_setspeed,
- .policy = &sa1110_policy,
+ .verify = sa11x0_verify_speed,
+ .target = sa1110_target,
+ .init = sa1110_cpu_init,
.name = "sa1110",
};
@@ -333,13 +350,7 @@ static int __init sa1110_clk_init(void)
memcpy(&sdram_params, sdram, sizeof(sdram_params));
- sa1110_driver.cpu_cur_freq[0] =
- sa1110_policy.min =
- sa1110_policy.max = sa11x0_getspeed();
-
- sa1110_setspeed(&sa1110_policy);
-
- return cpufreq_register(&sa1110_driver);
+ return cpufreq_register_driver(&sa1110_driver);
}
return 0;
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 7fc165ab752b..a14a6fae4901 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -48,33 +48,48 @@ static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
2802 /* 280.2 MHz */
};
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
+/* rounds up(!) */
unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
{
int i;
khz /= 100;
- for (i = NR_FREQS - 1; i > 0; i--)
- if (cclk_frequency_100khz[i] <= khz)
+ for (i = 0; i < NR_FREQS; i++)
+ if (cclk_frequency_100khz[i] >= khz)
break;
return i;
}
-/*
- * Validate the policy. We aren't able to do any fancy in-kernel
- * scaling, so we force min=max, and set the policy to "performance".
- * If we can't generate the precise frequency requested, round it up.
+unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
+{
+ if (idx >= NR_FREQS)
+ return 0;
+ else
+ return cclk_frequency_100khz[idx];
+}
+
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
*/
int sa11x0_verify_speed(struct cpufreq_policy *policy)
{
- if (policy->max > policy->cpuinfo.max_freq)
- policy->max = policy->cpuinfo.max_freq;
+ unsigned int tmp;
+ if (policy->cpu)
+ return -EINVAL;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+ /* make sure that at least one frequency is within the policy */
+ tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
+ if (tmp > policy->max)
+ policy->max = tmp;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
- policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
- policy->min = policy->max;
- policy->policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index fd5cb2900b51..956ede770ab4 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -23,3 +23,4 @@ struct cpufreq_policy;
extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
extern unsigned int sa11x0_getspeed(void);
+extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
index 6e47c1cda8eb..a7177a023a79 100644
--- a/arch/arm/mach-sa1100/system3.c
+++ b/arch/arm/mach-sa1100/system3.c
@@ -213,11 +213,17 @@ static void __init system3_init_irq(void)
static int sdram_notifier(struct notifier_block *nb, unsigned long event,
void *data)
{
+ struct cpufreq_policy *policy = data;
switch (event) {
- case CPUFREQ_MINMAX:
- cpufreq_updateminmax(data, 147500, 206000);
+ case CPUFREQ_ADJUST:
+ case CPUFREQ_INCOMPATIBLE:
+ cpufreq_verify_within_limits(policy, 147500, 206000);
+ break;
+ case CPUFREQ_NOTIFY:
+ if ((policy->min < 147500) ||
+ (policy->max > 206000))
+ panic("cpufreq failed to limit the speed\n");
break;
-
}
return 0;
}
@@ -405,7 +411,7 @@ static int __init system3_init(void)
goto DONE;
}
-#if defined( CONFIG_CPU_FREQ )
+#ifdef CONFIG_CPU_FREQ
ret = cpufreq_register_notifier(&system3_clkchg_block);
if ( ret != 0 ) {
printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index c0c991f122d0..3b7bd42aca97 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -47,7 +47,6 @@
#include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
-#include <linux/cpufreq.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 3d96bd9bd6dc..3a2df13bed59 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1590,11 +1590,21 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
struct sa1100fb_info *fbi = TO_INF(nb, freq_policy);
struct cpufreq_policy *policy = data;
- if (val == CPUFREQ_INCOMPATIBLE) {
+ switch (val) {
+ case CPUFREQ_ADJUST:
+ case CPUFREQ_INCOMPATIBLE:
printk(KERN_DEBUG "min dma period: %d ps, "
"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
policy->max);
/* todo: fill in min/max values */
+ break;
+ case CPUFREQ_NOTIFY:
+ do {} while(0);
+ /* todo: panic if min/max values aren't fulfilled
+ * [can't really happen unless there's a bug in the
+ * CPU policy verififcation process *
+ */
+ break;
}
return 0;
}
diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c
index 0d32c6103731..8155b2860169 100644
--- a/kernel/cpufreq.c
+++ b/kernel/cpufreq.c
@@ -336,6 +336,13 @@ static int cpufreq_add_dev (struct device * dev)
&cpufreq_driver->policy[cpu],
sizeof(struct cpufreq_policy));
+ /* 2.4-API init for this CPU */
+#ifdef CONFIG_CPU_FREQ_24_API
+ cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
+ cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
+ cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
+#endif
+
if (cpufreq_driver->target)
cpufreq_governor(cpu, CPUFREQ_GOV_START);