diff -urN -x lib1funcs.S -X linux-3.0.1/Documentation/dontdiff linux-3.0.1-old/arch/arm/Kconfig linux-3.0.1/arch/arm/Kconfig
--- linux-3.0.1-old/arch/arm/Kconfig	2011-08-13 14:17:04.000000000 +0100
+++ linux-3.0.1/arch/arm/Kconfig	2011-08-22 21:07:03.000000000 +0100
@@ -482,6 +482,7 @@
 config ARCH_KIRKWOOD
 	bool "Marvell Kirkwood"
 	select CPU_FEROCEON
+	select ARCH_HAS_CPUFREQ
 	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
diff -urN -x lib1funcs.S -X linux-3.0.1/Documentation/dontdiff linux-3.0.1-old/arch/arm/mach-kirkwood/cpufreq.c linux-3.0.1/arch/arm/mach-kirkwood/cpufreq.c
--- linux-3.0.1-old/arch/arm/mach-kirkwood/cpufreq.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.0.1/arch/arm/mach-kirkwood/cpufreq.c	2011-08-22 21:11:33.000000000 +0100
@@ -0,0 +1,254 @@
+/*
+ * arch/arm/mach-kirkwood/cpufreq.c
+ *
+ * Clock scaling for Kirkwood SoC
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/io.h>
+#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
+
+
+enum kw_cpufreq_range {
+	KW_CPUFREQ_LOW 		= 0,
+	KW_CPUFREQ_HIGH 	= 1
+};
+
+static struct cpufreq_frequency_table kw_freqs[] = {
+	{ KW_CPUFREQ_LOW, 0                  },
+	{ KW_CPUFREQ_HIGH, 0                  },
+	{ 0, CPUFREQ_TABLE_END  }
+};
+
+
+static inline void kw_set_powersave_on(void)
+{
+	unsigned long old,temp;
+	/* Disable int */
+	__asm__ __volatile__("mrs %0, cpsr\n"
+			     "orr %1, %0, #0xc0\n"
+			     "msr cpsr_c, %1"
+			     : "=r" (old), "=r" (temp)
+			     :
+			     : "memory");
+
+	/* Set SoC in power save */
+	writel(readl(CLOCK_GATING_CTRL) | (1 << 11), CLOCK_GATING_CTRL);
+
+	/* Wait for int */
+	__asm__ __volatile__("mcr    p15, 0, r0, c7, c0, 4");
+
+	/* Enabled int */
+	__asm__ __volatile__("msr cpsr_c, %0"
+			     :
+			     : "r" (old)
+			     : "memory");
+}
+
+static inline void kw_set_powersave_off(void)
+{
+	unsigned long old,temp;
+	/* Disable int */
+	__asm__ __volatile__("mrs %0, cpsr\n"
+			     "orr %1, %0, #0xc0\n"
+			     "msr cpsr_c, %1"
+			     : "=r" (old), "=r" (temp)
+			     :
+			     : "memory");
+
+	/* Set SoC in power save */
+	writel(readl(CLOCK_GATING_CTRL) & (~(1 << 11)), CLOCK_GATING_CTRL);
+
+	/* Wait for int */
+	__asm__ __volatile__("mcr    p15, 0, r0, c7, c0, 4");
+
+	/* Enabled int */
+	__asm__ __volatile__("msr cpsr_c, %0"
+			     :
+			     : "r" (old)
+			     : "memory");
+}
+
+/*
+ * Power management function: set or unset powersave mode
+ * FIXME: a better place ?
+ */
+static inline void kw_set_powersave(int on)
+{
+	printk(KERN_DEBUG "cpufreq: Setting PowerSaveState to %s\n",
+		on ? "on" : "off");
+
+	if (on)
+		kw_set_powersave_on();
+	else
+		kw_set_powersave_off();
+}
+
+static int kw_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	if (unlikely(!cpu_online(policy->cpu)))
+		return -ENODEV;
+
+	return cpufreq_frequency_table_verify(policy, kw_freqs);
+}
+
+/*
+ * Get the current frequency for a given cpu.
+ */
+static unsigned int kw_cpufreq_get(unsigned int cpu)
+{
+	unsigned int freq;
+	u32 reg;
+
+	if (unlikely(!cpu_online(cpu)))
+		return -ENODEV;
+
+	/* To get the current frequency, we have to check if
+	* the powersave mode is set. */
+	reg = readl(CLOCK_GATING_CTRL);
+
+	if (reg & (1 << 11))
+		freq = kw_freqs[KW_CPUFREQ_LOW].frequency;
+	else
+		freq = kw_freqs[KW_CPUFREQ_HIGH].frequency;
+
+	return freq;
+}
+
+/*
+ * Set the frequency for a given cpu.
+ */
+static int kw_cpufreq_target(struct cpufreq_policy *policy,
+		unsigned int target_freq, unsigned int relation)
+{
+	unsigned int index;
+	struct cpufreq_freqs freqs;
+
+	if (unlikely(!cpu_online(policy->cpu)))
+		return -ENODEV;
+
+	/* Lookup the next frequency */
+	if (unlikely(cpufreq_frequency_table_target(policy,
+		kw_freqs, target_freq, relation, &index)))
+		return -EINVAL;
+
+
+	freqs.old = policy->cur;
+	freqs.new = kw_freqs[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	printk(KERN_DEBUG "cpufreq: Setting CPU Frequency to %u KHz\n",freqs.new);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* Interruptions will be disabled in the low level power mode
+	* functions. */
+	if (index == KW_CPUFREQ_LOW)
+		kw_set_powersave(1);
+	else if (index == KW_CPUFREQ_HIGH)
+		kw_set_powersave(0);
+	else
+		return -EINVAL;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+static int kw_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	if (unlikely(!cpu_online(policy->cpu)))
+		return -ENODEV;
+
+#if 0
+	/*
+	 * As 6180 board have different reset sample register values,
+	 * the board type must be checked first.
+	 */
+	if (dev_id == MV_6180_DEV_ID) {
+
+		kw_freqs[KW_CPUFREQ_HIGH].frequency = mvCpuPclkGet()/1000;
+		/* At the lowest frequency CPU goes to DDR data clock rate:
+		 * (2 x DDR clock rate). */
+		kw_freqs[KW_CPUFREQ_LOW].frequency = mvBoardSysClkGet()*2/1000;
+
+	} else if ((dev_id == MV_6281_DEV_ID) ||
+		(dev_id == MV_6192_DEV_ID)) {
+
+		kw_freqs[KW_CPUFREQ_HIGH].frequency = mvCpuPclkGet()/1000;
+		/* CPU low frequency is the DDR frequency. */
+		kw_freqs[KW_CPUFREQ_LOW].frequency  = mvBoardSysClkGet()/1000;
+
+	} else {
+		return -ENODEV;
+	}
+#endif
+	/* God knows */
+	kw_freqs[KW_CPUFREQ_HIGH].frequency = 1200000;
+	kw_freqs[KW_CPUFREQ_LOW].frequency  =  400000;
+
+	printk(KERN_DEBUG
+		"cpufreq: High frequency: %uKHz - Low frequency: %uKHz\n",
+		kw_freqs[KW_CPUFREQ_HIGH].frequency,
+		kw_freqs[KW_CPUFREQ_LOW].frequency);
+
+	policy->cpuinfo.transition_latency = 1000000;
+	policy->cur = kw_cpufreq_get(0);
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+	cpufreq_frequency_table_get_attr(kw_freqs, policy->cpu);
+
+	return cpufreq_frequency_table_cpuinfo(policy, kw_freqs);
+}
+
+
+static int kw_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
+}
+
+static struct freq_attr *kw_freq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+
+static struct cpufreq_driver kw_freq_driver = {
+	.owner          = THIS_MODULE,
+	.name           = "kw_cpufreq",
+	.init           = kw_cpufreq_cpu_init,
+	.verify         = kw_cpufreq_verify,
+	.exit		= kw_cpufreq_cpu_exit,
+	.target         = kw_cpufreq_target,
+	.get            = kw_cpufreq_get,
+	.attr           = kw_freq_attr,
+};
+
+
+static int __init kw_cpufreq_init(void)
+{
+	printk(KERN_INFO "cpufreq: Init kirkwood cpufreq driver\n");
+
+	return cpufreq_register_driver(&kw_freq_driver);
+}
+
+static void __exit kw_cpufreq_exit(void)
+{
+	cpufreq_unregister_driver(&kw_freq_driver);
+}
+
+
+MODULE_AUTHOR("Marvell Semiconductors ltd.");
+MODULE_DESCRIPTION("CPU frequency scaling for Kirkwood SoC");
+MODULE_LICENSE("GPL");
+module_init(kw_cpufreq_init);
+module_exit(kw_cpufreq_exit);
+
diff -urN -x lib1funcs.S -X linux-3.0.1/Documentation/dontdiff linux-3.0.1-old/arch/arm/mach-kirkwood/Makefile linux-3.0.1/arch/arm/mach-kirkwood/Makefile
--- linux-3.0.1-old/arch/arm/mach-kirkwood/Makefile	2011-03-15 01:20:32.000000000 +0000
+++ linux-3.0.1/arch/arm/mach-kirkwood/Makefile	2011-08-22 21:04:26.000000000 +0100
@@ -20,3 +20,4 @@
 obj-$(CONFIG_MACH_T5325)		+= t5325-setup.o
 
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
+obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o
