All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V6 0/7] add a generic cpufreq driver
@ 2011-12-30  2:56 ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches

The driver is based on clock and regulator APIs and  support single core
and multi core ARM SoCs. For multi core, it assume all cores share the
same clock and voltage.

Thanks Arnd, Mark, Jamie, Shawn, Rob, for your review.

Changes in V6:
 - add scaling_available_freqs

Changes in V5:
 - add more comments
 - rename trans-latency to clk-trans-latency, and it only describe clk
   latency. Regulator latency is got from regulator_set_voltage_time.

Changes in v4:
 - add depends on HAVE_CLK && OF && REGULATOR
 - add set_cpu_freq fail check
 - regulator_put wehn module exit
 - add pr_fmt and convert all printk to pr_xxx
 - use voltage range
 - comment and doc fix
 - add cpu_volts value pre-check in module init
 - add helpfull module parameter max_freq
 - remove compatible string check on Arnd's comment.
 - remove generic-cpufreq to clk-reg-cpufreq

Changes in v3:
 - move adjusting smp loops_per_jiffy to arm common code,
   and also adjust global loops_per_jiffy.
 - remove adjusting loops_per_jiffy in imx and omap cpufreq drivers.
 - check compatible "generic-cpufreq" when module_init
 - change printk to pr_xxx
 - add generic-cpufreq DT binding doc

Changes in v2:
 - add volatage change support
 - change '_' in property name to '-'
 - use initial value to calculate loops_per_jiffy
 - fix reading cpu_volts property bug 
 - let cpufreq_frequency_table_cpuinfo routines handle cpu_freq_khz_max/min
 - don't change freq in arm_cpufreq_exit, because every core share the same freq.
 - use unsigned long describe frequency as much as possible. Because clk use
   unsigned long, but cpufreq use unsigned int.

[PATCH V6 1/7] ARM: add cpufreq transiton notifier to adjust
[PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate
[PATCH V6 3/7] cpufreq: OMAP: remove loops_per_jiffy recalculate for
[PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
[PATCH V6 5/7] dts/imx6q: add cpufreq property
[PATCH V6 6/7] arm/imx6q: register arm_clk as cpu to clkdev
[PATCH V6 7/7] arm/imx6q: select ARCH_HAS_CPUFREQ

Thanks
Richard


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 0/7] add a generic cpufreq driver
@ 2011-12-30  2:56 ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

The driver is based on clock and regulator APIs and  support single core
and multi core ARM SoCs. For multi core, it assume all cores share the
same clock and voltage.

Thanks Arnd, Mark, Jamie, Shawn, Rob, for your review.

Changes in V6:
 - add scaling_available_freqs

Changes in V5:
 - add more comments
 - rename trans-latency to clk-trans-latency, and it only describe clk
   latency. Regulator latency is got from regulator_set_voltage_time.

Changes in v4:
 - add depends on HAVE_CLK && OF && REGULATOR
 - add set_cpu_freq fail check
 - regulator_put wehn module exit
 - add pr_fmt and convert all printk to pr_xxx
 - use voltage range
 - comment and doc fix
 - add cpu_volts value pre-check in module init
 - add helpfull module parameter max_freq
 - remove compatible string check on Arnd's comment.
 - remove generic-cpufreq to clk-reg-cpufreq

Changes in v3:
 - move adjusting smp loops_per_jiffy to arm common code,
   and also adjust global loops_per_jiffy.
 - remove adjusting loops_per_jiffy in imx and omap cpufreq drivers.
 - check compatible "generic-cpufreq" when module_init
 - change printk to pr_xxx
 - add generic-cpufreq DT binding doc

Changes in v2:
 - add volatage change support
 - change '_' in property name to '-'
 - use initial value to calculate loops_per_jiffy
 - fix reading cpu_volts property bug 
 - let cpufreq_frequency_table_cpuinfo routines handle cpu_freq_khz_max/min
 - don't change freq in arm_cpufreq_exit, because every core share the same freq.
 - use unsigned long describe frequency as much as possible. Because clk use
   unsigned long, but cpufreq use unsigned int.

[PATCH V6 1/7] ARM: add cpufreq transiton notifier to adjust
[PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate
[PATCH V6 3/7] cpufreq: OMAP: remove loops_per_jiffy recalculate for
[PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
[PATCH V6 5/7] dts/imx6q: add cpufreq property
[PATCH V6 6/7] arm/imx6q: register arm_clk as cpu to clkdev
[PATCH V6 7/7] arm/imx6q: select ARCH_HAS_CPUFREQ

Thanks
Richard

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 1/7] ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

If CONFIG_SMP, cpufreq skips loops_per_jiffy update, because different
arch has different per-cpu loops_per_jiffy definition.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/kernel/smp.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ef5640b..ac9cadc 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -25,6 +25,7 @@
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
 #include <linux/completion.h>
+#include <linux/cpufreq.h>
 
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
@@ -631,3 +632,56 @@ int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
+
+#ifdef CONFIG_CPU_FREQ
+
+static DEFINE_PER_CPU(unsigned long, l_p_j_ref);
+static DEFINE_PER_CPU(unsigned long, l_p_j_ref_freq);
+static unsigned long global_l_p_j_ref;
+static unsigned long global_l_p_j_ref_freq;
+
+static int cpufreq_callback(struct notifier_block *nb,
+					unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freq = data;
+	int cpu = freq->cpu;
+
+	if (freq->flags & CPUFREQ_CONST_LOOPS)
+		return NOTIFY_OK;
+
+	if (!per_cpu(l_p_j_ref, cpu)) {
+		per_cpu(l_p_j_ref, cpu) =
+			per_cpu(cpu_data, cpu).loops_per_jiffy;
+		per_cpu(l_p_j_ref_freq, cpu) = freq->old;
+		if (!global_l_p_j_ref) {
+			global_l_p_j_ref = loops_per_jiffy;
+			global_l_p_j_ref_freq = freq->old;
+		}
+	}
+
+	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
+		loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
+						global_l_p_j_ref_freq,
+						freq->new);
+		per_cpu(cpu_data, cpu).loops_per_jiffy =
+			cpufreq_scale(per_cpu(l_p_j_ref, cpu),
+					per_cpu(l_p_j_ref_freq, cpu),
+					freq->new);
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_notifier = {
+	.notifier_call  = cpufreq_callback,
+};
+
+static int __init register_cpufreq_notifier(void)
+{
+	return cpufreq_register_notifier(&cpufreq_notifier,
+						CPUFREQ_TRANSITION_NOTIFIER);
+}
+core_initcall(register_cpufreq_notifier);
+
+#endif
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 1/7] ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

If CONFIG_SMP, cpufreq skips loops_per_jiffy update, because different
arch has different per-cpu loops_per_jiffy definition.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/kernel/smp.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ef5640b..ac9cadc 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -25,6 +25,7 @@
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
 #include <linux/completion.h>
+#include <linux/cpufreq.h>
 
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
@@ -631,3 +632,56 @@ int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
+
+#ifdef CONFIG_CPU_FREQ
+
+static DEFINE_PER_CPU(unsigned long, l_p_j_ref);
+static DEFINE_PER_CPU(unsigned long, l_p_j_ref_freq);
+static unsigned long global_l_p_j_ref;
+static unsigned long global_l_p_j_ref_freq;
+
+static int cpufreq_callback(struct notifier_block *nb,
+					unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freq = data;
+	int cpu = freq->cpu;
+
+	if (freq->flags & CPUFREQ_CONST_LOOPS)
+		return NOTIFY_OK;
+
+	if (!per_cpu(l_p_j_ref, cpu)) {
+		per_cpu(l_p_j_ref, cpu) =
+			per_cpu(cpu_data, cpu).loops_per_jiffy;
+		per_cpu(l_p_j_ref_freq, cpu) = freq->old;
+		if (!global_l_p_j_ref) {
+			global_l_p_j_ref = loops_per_jiffy;
+			global_l_p_j_ref_freq = freq->old;
+		}
+	}
+
+	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
+		loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
+						global_l_p_j_ref_freq,
+						freq->new);
+		per_cpu(cpu_data, cpu).loops_per_jiffy =
+			cpufreq_scale(per_cpu(l_p_j_ref, cpu),
+					per_cpu(l_p_j_ref_freq, cpu),
+					freq->new);
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_notifier = {
+	.notifier_call  = cpufreq_callback,
+};
+
+static int __init register_cpufreq_notifier(void)
+{
+	return cpufreq_register_notifier(&cpufreq_notifier,
+						CPUFREQ_TRANSITION_NOTIFIER);
+}
+core_initcall(register_cpufreq_notifier);
+
+#endif
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate for smp
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

arm registered cpufreq transition notifier to recalculate it.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/plat-mxc/cpufreq.c |   10 ----------
 1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index c937e75..364793a 100644
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -99,16 +99,6 @@ static int mxc_set_target(struct cpufreq_policy *policy,
 
 	ret = set_cpu_freq(freq_Hz);
 
-#ifdef CONFIG_SMP
-	/* loops_per_jiffy is not updated by the cpufreq core for SMP systems.
-	 * So update it for all CPUs.
-	 */
-	for_each_possible_cpu(cpu)
-		per_cpu(cpu_data, cpu).loops_per_jiffy =
-		cpufreq_scale(per_cpu(cpu_data, cpu).loops_per_jiffy,
-					freqs.old, freqs.new);
-#endif
-
 	for_each_possible_cpu(cpu) {
 		freqs.cpu = cpu;
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate for smp
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

arm registered cpufreq transition notifier to recalculate it.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/plat-mxc/cpufreq.c |   10 ----------
 1 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index c937e75..364793a 100644
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -99,16 +99,6 @@ static int mxc_set_target(struct cpufreq_policy *policy,
 
 	ret = set_cpu_freq(freq_Hz);
 
-#ifdef CONFIG_SMP
-	/* loops_per_jiffy is not updated by the cpufreq core for SMP systems.
-	 * So update it for all CPUs.
-	 */
-	for_each_possible_cpu(cpu)
-		per_cpu(cpu_data, cpu).loops_per_jiffy =
-		cpufreq_scale(per_cpu(cpu_data, cpu).loops_per_jiffy,
-					freqs.old, freqs.new);
-#endif
-
 	for_each_possible_cpu(cpu) {
 		freqs.cpu = cpu;
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 3/7] cpufreq: OMAP: remove loops_per_jiffy recalculate for smp
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

arm registered cpufreq transition notifier to recalculate it.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 drivers/cpufreq/omap-cpufreq.c |   36 ------------------------------------
 1 files changed, 0 insertions(+), 36 deletions(-)

diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 5d04c57..17da4c4 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -37,16 +37,6 @@
 
 #include <mach/hardware.h>
 
-#ifdef CONFIG_SMP
-struct lpj_info {
-	unsigned long	ref;
-	unsigned int	freq;
-};
-
-static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
-static struct lpj_info global_lpj_ref;
-#endif
-
 static struct cpufreq_frequency_table *freq_table;
 static atomic_t freq_table_users = ATOMIC_INIT(0);
 static struct clk *mpu_clk;
@@ -118,32 +108,6 @@ static int omap_target(struct cpufreq_policy *policy,
 	ret = clk_set_rate(mpu_clk, freqs.new * 1000);
 	freqs.new = omap_getspeed(policy->cpu);
 
-#ifdef CONFIG_SMP
-	/*
-	 * Note that loops_per_jiffy is not updated on SMP systems in
-	 * cpufreq driver. So, update the per-CPU loops_per_jiffy value
-	 * on frequency transition. We need to update all dependent CPUs.
-	 */
-	for_each_cpu(i, policy->cpus) {
-		struct lpj_info *lpj = &per_cpu(lpj_ref, i);
-		if (!lpj->freq) {
-			lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
-			lpj->freq = freqs.old;
-		}
-
-		per_cpu(cpu_data, i).loops_per_jiffy =
-			cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
-	}
-
-	/* And don't forget to adjust the global one */
-	if (!global_lpj_ref.freq) {
-		global_lpj_ref.ref = loops_per_jiffy;
-		global_lpj_ref.freq = freqs.old;
-	}
-	loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
-					freqs.new);
-#endif
-
 	/* notifiers */
 	for_each_cpu(i, policy->cpus) {
 		freqs.cpu = i;
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 3/7] cpufreq: OMAP: remove loops_per_jiffy recalculate for smp
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

arm registered cpufreq transition notifier to recalculate it.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 drivers/cpufreq/omap-cpufreq.c |   36 ------------------------------------
 1 files changed, 0 insertions(+), 36 deletions(-)

diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 5d04c57..17da4c4 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -37,16 +37,6 @@
 
 #include <mach/hardware.h>
 
-#ifdef CONFIG_SMP
-struct lpj_info {
-	unsigned long	ref;
-	unsigned int	freq;
-};
-
-static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
-static struct lpj_info global_lpj_ref;
-#endif
-
 static struct cpufreq_frequency_table *freq_table;
 static atomic_t freq_table_users = ATOMIC_INIT(0);
 static struct clk *mpu_clk;
@@ -118,32 +108,6 @@ static int omap_target(struct cpufreq_policy *policy,
 	ret = clk_set_rate(mpu_clk, freqs.new * 1000);
 	freqs.new = omap_getspeed(policy->cpu);
 
-#ifdef CONFIG_SMP
-	/*
-	 * Note that loops_per_jiffy is not updated on SMP systems in
-	 * cpufreq driver. So, update the per-CPU loops_per_jiffy value
-	 * on frequency transition. We need to update all dependent CPUs.
-	 */
-	for_each_cpu(i, policy->cpus) {
-		struct lpj_info *lpj = &per_cpu(lpj_ref, i);
-		if (!lpj->freq) {
-			lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
-			lpj->freq = freqs.old;
-		}
-
-		per_cpu(cpu_data, i).loops_per_jiffy =
-			cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
-	}
-
-	/* And don't forget to adjust the global one */
-	if (!global_lpj_ref.freq) {
-		global_lpj_ref.ref = loops_per_jiffy;
-		global_lpj_ref.freq = freqs.old;
-	}
-	loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
-					freqs.new);
-#endif
-
 	/* notifiers */
 	for_each_cpu(i, policy->cpus) {
 		freqs.cpu = i;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

The driver get cpu operation point table from device tree cpu0 node,
and adjusts operating points using clk and regulator APIs.

It support single core and multi-core ARM SoCs. But currently it assume
all cores share the same frequency and voltage.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
---
 .../devicetree/bindings/cpufreq/clk-reg-cpufreq    |   21 ++
 drivers/cpufreq/Kconfig                            |   10 +
 drivers/cpufreq/Makefile                           |    2 +
 drivers/cpufreq/clk-reg-cpufreq.c                  |  308 ++++++++++++++++++++
 4 files changed, 341 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq
 create mode 100644 drivers/cpufreq/clk-reg-cpufreq.c

diff --git a/Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq b/Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq
new file mode 100644
index 0000000..e8dc763
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq
@@ -0,0 +1,21 @@
+Generic cpufreq driver based on clk and regulator APIs
+
+Required properties in /cpus/cpu@0:
+- cpu-freqs : cpu frequency points it supports, in unit of Hz.
+	      Each point takes on cell.
+- cpu-volts : cpu voltage ranges required by the frequency points
+	      at the same index, in unit of uV.
+	      Each range takes two cells, one for min, the other for max.
+- clk-trans-latency :  cpu clk transition latency, in unit of ns.
+	      It takes one cell.
+
+An example:
+cpu@0 {
+			cpu-freqs = <996000000 792000000 396000000 198000000>;
+			cpu-volts = <	/* min		max */
+					1225000		1450000	/* 996M */
+					1100000		1450000	/* 792M */
+					950000		1450000	/* 396M */
+					850000		1450000>; /* 198M */
+			clk-trans-latency = <61036>; /* two CLK32 periods */
+};
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index e24a2a1..95470f1 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -179,6 +179,16 @@ config CPU_FREQ_GOV_CONSERVATIVE
 
 	  If in doubt, say N.
 
+config CLK_REG_CPUFREQ_DRIVER
+	tristate "Generic cpufreq driver using clk and regulator APIs"
+	depends on HAVE_CLK && OF && REGULATOR
+	select CPU_FREQ_TABLE
+	help
+	  This adds generic CPUFreq driver based on clk and regulator APIs.
+	  It assumes all cores of the CPU share the same clock and voltage.
+
+	  If in doubt, say N.
+
 menu "x86 CPU frequency scaling drivers"
 depends on X86
 source "drivers/cpufreq/Kconfig.x86"
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index ce75fcb..2c4eb33 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
 
+obj-$(CONFIG_CLK_REG_CPUFREQ_DRIVER)	+= clk-reg-cpufreq.o
+
 ##################################################################################
 # x86 drivers.
 # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
diff --git a/drivers/cpufreq/clk-reg-cpufreq.c b/drivers/cpufreq/clk-reg-cpufreq.c
new file mode 100644
index 0000000..77c4408
--- /dev/null
+++ b/drivers/cpufreq/clk-reg-cpufreq.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+static u32 *cpu_freqs; /* Hz */
+static u32 *cpu_volts; /* uV */
+static u32 trans_latency; /* ns */
+static int cpu_op_nr;
+static unsigned int cur_index;
+
+static struct clk *cpu_clk;
+static struct regulator *cpu_reg;
+static struct cpufreq_frequency_table *freq_table;
+
+static int set_cpu_freq(unsigned long freq, int index, int higher)
+{
+	int ret = 0;
+
+	if (higher && cpu_reg) {
+		ret = regulator_set_voltage(cpu_reg,
+				cpu_volts[index * 2], cpu_volts[index * 2 + 1]);
+		if (ret) {
+			pr_err("set cpu voltage failed!\n");
+			return ret;
+		}
+	}
+
+	ret = clk_set_rate(cpu_clk, freq);
+	if (ret) {
+		if (cpu_reg)
+			regulator_set_voltage(cpu_reg, cpu_volts[cur_index * 2],
+						cpu_volts[cur_index * 2 + 1]);
+		pr_err("cannot set CPU clock rate\n");
+		return ret;
+	}
+
+	if (!higher && cpu_reg) {
+		ret = regulator_set_voltage(cpu_reg,
+				cpu_volts[index * 2], cpu_volts[index * 2 + 1]);
+		if (ret)
+			pr_warn("set cpu voltage failed, might run on"
+				" higher voltage!\n");
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int clk_reg_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static unsigned int clk_reg_get_speed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int clk_reg_set_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	unsigned long freq_Hz;
+	int cpu;
+	int ret = 0;
+	unsigned int index;
+
+	cpufreq_frequency_table_target(policy, freq_table,
+			target_freq, relation, &index);
+	freq_Hz = clk_round_rate(cpu_clk, cpu_freqs[index]);
+	freq_Hz = freq_Hz ? freq_Hz : cpu_freqs[index];
+	freqs.old = clk_get_rate(cpu_clk) / 1000;
+	freqs.new = freq_Hz / 1000;
+	freqs.flags = 0;
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	for_each_possible_cpu(cpu) {
+		freqs.cpu = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
+
+	ret = set_cpu_freq(freq_Hz, index, (freqs.new > freqs.old));
+	if (ret)
+		freqs.new = clk_get_rate(cpu_clk) / 1000;
+	else
+		cur_index = index;
+
+	for_each_possible_cpu(cpu) {
+		freqs.cpu = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
+
+	return ret;
+}
+
+static int clk_reg_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	if (policy->cpu >= num_possible_cpus())
+		return -EINVAL;
+
+	policy->cur = clk_get_rate(cpu_clk) / 1000;
+	policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+	cpumask_setall(policy->cpus);
+	policy->cpuinfo.transition_latency = trans_latency;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+
+	if (ret < 0) {
+		pr_err("invalid frequency table for cpu %d\n",
+			policy->cpu);
+		return ret;
+	}
+
+	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+	cpufreq_frequency_table_target(policy, freq_table, policy->cur,
+					CPUFREQ_RELATION_H, &cur_index);
+	return 0;
+}
+
+static int clk_reg_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
+}
+
+static struct freq_attr *clk_reg_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver clk_reg_cpufreq_driver = {
+	.flags = CPUFREQ_STICKY,
+	.verify = clk_reg_verify_speed,
+	.target = clk_reg_set_target,
+	.get = clk_reg_get_speed,
+	.init = clk_reg_cpufreq_init,
+	.exit = clk_reg_cpufreq_exit,
+	.name = "clk-reg",
+	.attr = clk_reg_cpufreq_attr,
+};
+
+static u32 max_freq = UINT_MAX / 1000; /* kHz */
+module_param(max_freq, uint, 0);
+MODULE_PARM_DESC(max_freq, "max cpu frequency in unit of kHz");
+
+static int __devinit clk_reg_cpufreq_driver_init(void)
+{
+	struct device_node *cpu0;
+	const struct property *pp;
+	int max_idx = 0, min_idx = 0;
+	int i, ret;
+
+	cpu0 = of_find_node_by_path("/cpus/cpu@0");
+	if (!cpu0)
+		return -ENODEV;
+
+	pp = of_find_property(cpu0, "cpu-freqs", NULL);
+	if (!pp) {
+		ret = -ENODEV;
+		goto put_node;
+	}
+	cpu_op_nr = pp->length / sizeof(u32);
+	if (!cpu_op_nr) {
+		ret = -ENODEV;
+		goto put_node;
+	}
+	ret = -ENOMEM;
+	cpu_freqs = kzalloc(sizeof(*cpu_freqs) * cpu_op_nr, GFP_KERNEL);
+	if (!cpu_freqs)
+		goto put_node;
+	of_property_read_u32_array(cpu0, "cpu-freqs", cpu_freqs, cpu_op_nr);
+
+	pp = of_find_property(cpu0, "cpu-volts", NULL);
+	if (pp) {
+		if (cpu_op_nr * 2 == pp->length / sizeof(u32)) {
+			cpu_volts = kzalloc(sizeof(*cpu_volts) * cpu_op_nr * 2,
+						GFP_KERNEL);
+			if (!cpu_volts)
+				goto free_cpu_freqs;
+			of_property_read_u32_array(cpu0, "cpu-volts",
+						cpu_volts, cpu_op_nr * 2);
+		} else
+			pr_warn("invalid cpu_volts!\n");
+	}
+
+	if (of_property_read_u32(cpu0, "clk-trans-latency", &trans_latency))
+		trans_latency = CPUFREQ_ETERNAL;
+
+	cpu_clk = clk_get(NULL, "cpu");
+	if (IS_ERR(cpu_clk)) {
+		pr_err("failed to get cpu clock\n");
+		ret = PTR_ERR(cpu_clk);
+		goto free_cpu_volts;
+	}
+
+	if (cpu_volts) {
+		cpu_reg = regulator_get(NULL, "cpu");
+		if (IS_ERR(cpu_reg)) {
+			pr_warn("regulator cpu get failed.\n");
+			cpu_reg = NULL;
+		}
+	}
+
+	freq_table = kmalloc(sizeof(struct cpufreq_frequency_table)
+				* (cpu_op_nr + 1), GFP_KERNEL);
+	if (!freq_table) {
+		ret = -ENOMEM;
+		goto reg_put;
+	}
+
+	for (i = 0; i < cpu_op_nr; i++) {
+		freq_table[i].index = i;
+		if (cpu_freqs[i] > max_freq * 1000) {
+			freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			continue;
+		}
+
+		if (cpu_reg) {
+			ret = regulator_is_supported_voltage(cpu_reg,
+					cpu_volts[i * 2], cpu_volts[i * 2 + 1]);
+			if (ret <= 0) {
+				freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+				continue;
+			}
+		}
+		freq_table[i].frequency = cpu_freqs[i] / 1000;
+		max_idx = cpu_freqs[i] > cpu_freqs[max_idx] ? i : max_idx;
+		min_idx = cpu_freqs[i] < cpu_freqs[min_idx] ? i : min_idx;
+	}
+
+	freq_table[i].index = i;
+	freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+	if (cpu_reg && trans_latency != CPUFREQ_ETERNAL) {
+		ret = regulator_set_voltage_time(cpu_reg, cpu_volts[min_idx],
+						cpu_volts[max_idx]);
+		if (ret < 0) {
+			pr_warn("regulator_set_voltage_time failed. "
+				"Default use 1us\n");
+			ret = 1;
+		}
+		trans_latency += ret * 1000;
+	}
+
+	ret = cpufreq_register_driver(&clk_reg_cpufreq_driver);
+	if (ret)
+		goto free_freq_table;
+
+	of_node_put(cpu0);
+
+	return 0;
+
+free_freq_table:
+	kfree(freq_table);
+reg_put:
+	if (cpu_reg)
+		regulator_put(cpu_reg);
+	clk_put(cpu_clk);
+free_cpu_volts:
+	kfree(cpu_volts);
+free_cpu_freqs:
+	kfree(cpu_freqs);
+put_node:
+	of_node_put(cpu0);
+
+	return ret;
+}
+
+static void clk_reg_cpufreq_driver_exit(void)
+{
+	cpufreq_unregister_driver(&clk_reg_cpufreq_driver);
+	kfree(cpu_freqs);
+	kfree(cpu_volts);
+	clk_put(cpu_clk);
+	if (cpu_reg)
+		regulator_put(cpu_reg);
+	kfree(freq_table);
+}
+
+module_init(clk_reg_cpufreq_driver_init);
+module_exit(clk_reg_cpufreq_driver_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor Inc. Richard Zhao <richard.zhao@freescale.com>");
+MODULE_DESCRIPTION("Generic CPUFreq driver based on clk and regulator APIs");
+MODULE_LICENSE("GPL");
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

The driver get cpu operation point table from device tree cpu0 node,
and adjusts operating points using clk and regulator APIs.

It support single core and multi-core ARM SoCs. But currently it assume
all cores share the same frequency and voltage.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
---
 .../devicetree/bindings/cpufreq/clk-reg-cpufreq    |   21 ++
 drivers/cpufreq/Kconfig                            |   10 +
 drivers/cpufreq/Makefile                           |    2 +
 drivers/cpufreq/clk-reg-cpufreq.c                  |  308 ++++++++++++++++++++
 4 files changed, 341 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq
 create mode 100644 drivers/cpufreq/clk-reg-cpufreq.c

diff --git a/Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq b/Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq
new file mode 100644
index 0000000..e8dc763
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/clk-reg-cpufreq
@@ -0,0 +1,21 @@
+Generic cpufreq driver based on clk and regulator APIs
+
+Required properties in /cpus/cpu at 0:
+- cpu-freqs : cpu frequency points it supports, in unit of Hz.
+	      Each point takes on cell.
+- cpu-volts : cpu voltage ranges required by the frequency points
+	      at the same index, in unit of uV.
+	      Each range takes two cells, one for min, the other for max.
+- clk-trans-latency :  cpu clk transition latency, in unit of ns.
+	      It takes one cell.
+
+An example:
+cpu at 0 {
+			cpu-freqs = <996000000 792000000 396000000 198000000>;
+			cpu-volts = <	/* min		max */
+					1225000		1450000	/* 996M */
+					1100000		1450000	/* 792M */
+					950000		1450000	/* 396M */
+					850000		1450000>; /* 198M */
+			clk-trans-latency = <61036>; /* two CLK32 periods */
+};
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index e24a2a1..95470f1 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -179,6 +179,16 @@ config CPU_FREQ_GOV_CONSERVATIVE
 
 	  If in doubt, say N.
 
+config CLK_REG_CPUFREQ_DRIVER
+	tristate "Generic cpufreq driver using clk and regulator APIs"
+	depends on HAVE_CLK && OF && REGULATOR
+	select CPU_FREQ_TABLE
+	help
+	  This adds generic CPUFreq driver based on clk and regulator APIs.
+	  It assumes all cores of the CPU share the same clock and voltage.
+
+	  If in doubt, say N.
+
 menu "x86 CPU frequency scaling drivers"
 depends on X86
 source "drivers/cpufreq/Kconfig.x86"
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index ce75fcb..2c4eb33 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
 
+obj-$(CONFIG_CLK_REG_CPUFREQ_DRIVER)	+= clk-reg-cpufreq.o
+
 ##################################################################################
 # x86 drivers.
 # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
diff --git a/drivers/cpufreq/clk-reg-cpufreq.c b/drivers/cpufreq/clk-reg-cpufreq.c
new file mode 100644
index 0000000..77c4408
--- /dev/null
+++ b/drivers/cpufreq/clk-reg-cpufreq.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+static u32 *cpu_freqs; /* Hz */
+static u32 *cpu_volts; /* uV */
+static u32 trans_latency; /* ns */
+static int cpu_op_nr;
+static unsigned int cur_index;
+
+static struct clk *cpu_clk;
+static struct regulator *cpu_reg;
+static struct cpufreq_frequency_table *freq_table;
+
+static int set_cpu_freq(unsigned long freq, int index, int higher)
+{
+	int ret = 0;
+
+	if (higher && cpu_reg) {
+		ret = regulator_set_voltage(cpu_reg,
+				cpu_volts[index * 2], cpu_volts[index * 2 + 1]);
+		if (ret) {
+			pr_err("set cpu voltage failed!\n");
+			return ret;
+		}
+	}
+
+	ret = clk_set_rate(cpu_clk, freq);
+	if (ret) {
+		if (cpu_reg)
+			regulator_set_voltage(cpu_reg, cpu_volts[cur_index * 2],
+						cpu_volts[cur_index * 2 + 1]);
+		pr_err("cannot set CPU clock rate\n");
+		return ret;
+	}
+
+	if (!higher && cpu_reg) {
+		ret = regulator_set_voltage(cpu_reg,
+				cpu_volts[index * 2], cpu_volts[index * 2 + 1]);
+		if (ret)
+			pr_warn("set cpu voltage failed, might run on"
+				" higher voltage!\n");
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int clk_reg_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static unsigned int clk_reg_get_speed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int clk_reg_set_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	unsigned long freq_Hz;
+	int cpu;
+	int ret = 0;
+	unsigned int index;
+
+	cpufreq_frequency_table_target(policy, freq_table,
+			target_freq, relation, &index);
+	freq_Hz = clk_round_rate(cpu_clk, cpu_freqs[index]);
+	freq_Hz = freq_Hz ? freq_Hz : cpu_freqs[index];
+	freqs.old = clk_get_rate(cpu_clk) / 1000;
+	freqs.new = freq_Hz / 1000;
+	freqs.flags = 0;
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	for_each_possible_cpu(cpu) {
+		freqs.cpu = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
+
+	ret = set_cpu_freq(freq_Hz, index, (freqs.new > freqs.old));
+	if (ret)
+		freqs.new = clk_get_rate(cpu_clk) / 1000;
+	else
+		cur_index = index;
+
+	for_each_possible_cpu(cpu) {
+		freqs.cpu = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
+
+	return ret;
+}
+
+static int clk_reg_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	if (policy->cpu >= num_possible_cpus())
+		return -EINVAL;
+
+	policy->cur = clk_get_rate(cpu_clk) / 1000;
+	policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+	cpumask_setall(policy->cpus);
+	policy->cpuinfo.transition_latency = trans_latency;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+
+	if (ret < 0) {
+		pr_err("invalid frequency table for cpu %d\n",
+			policy->cpu);
+		return ret;
+	}
+
+	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+	cpufreq_frequency_table_target(policy, freq_table, policy->cur,
+					CPUFREQ_RELATION_H, &cur_index);
+	return 0;
+}
+
+static int clk_reg_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+	return 0;
+}
+
+static struct freq_attr *clk_reg_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver clk_reg_cpufreq_driver = {
+	.flags = CPUFREQ_STICKY,
+	.verify = clk_reg_verify_speed,
+	.target = clk_reg_set_target,
+	.get = clk_reg_get_speed,
+	.init = clk_reg_cpufreq_init,
+	.exit = clk_reg_cpufreq_exit,
+	.name = "clk-reg",
+	.attr = clk_reg_cpufreq_attr,
+};
+
+static u32 max_freq = UINT_MAX / 1000; /* kHz */
+module_param(max_freq, uint, 0);
+MODULE_PARM_DESC(max_freq, "max cpu frequency in unit of kHz");
+
+static int __devinit clk_reg_cpufreq_driver_init(void)
+{
+	struct device_node *cpu0;
+	const struct property *pp;
+	int max_idx = 0, min_idx = 0;
+	int i, ret;
+
+	cpu0 = of_find_node_by_path("/cpus/cpu at 0");
+	if (!cpu0)
+		return -ENODEV;
+
+	pp = of_find_property(cpu0, "cpu-freqs", NULL);
+	if (!pp) {
+		ret = -ENODEV;
+		goto put_node;
+	}
+	cpu_op_nr = pp->length / sizeof(u32);
+	if (!cpu_op_nr) {
+		ret = -ENODEV;
+		goto put_node;
+	}
+	ret = -ENOMEM;
+	cpu_freqs = kzalloc(sizeof(*cpu_freqs) * cpu_op_nr, GFP_KERNEL);
+	if (!cpu_freqs)
+		goto put_node;
+	of_property_read_u32_array(cpu0, "cpu-freqs", cpu_freqs, cpu_op_nr);
+
+	pp = of_find_property(cpu0, "cpu-volts", NULL);
+	if (pp) {
+		if (cpu_op_nr * 2 == pp->length / sizeof(u32)) {
+			cpu_volts = kzalloc(sizeof(*cpu_volts) * cpu_op_nr * 2,
+						GFP_KERNEL);
+			if (!cpu_volts)
+				goto free_cpu_freqs;
+			of_property_read_u32_array(cpu0, "cpu-volts",
+						cpu_volts, cpu_op_nr * 2);
+		} else
+			pr_warn("invalid cpu_volts!\n");
+	}
+
+	if (of_property_read_u32(cpu0, "clk-trans-latency", &trans_latency))
+		trans_latency = CPUFREQ_ETERNAL;
+
+	cpu_clk = clk_get(NULL, "cpu");
+	if (IS_ERR(cpu_clk)) {
+		pr_err("failed to get cpu clock\n");
+		ret = PTR_ERR(cpu_clk);
+		goto free_cpu_volts;
+	}
+
+	if (cpu_volts) {
+		cpu_reg = regulator_get(NULL, "cpu");
+		if (IS_ERR(cpu_reg)) {
+			pr_warn("regulator cpu get failed.\n");
+			cpu_reg = NULL;
+		}
+	}
+
+	freq_table = kmalloc(sizeof(struct cpufreq_frequency_table)
+				* (cpu_op_nr + 1), GFP_KERNEL);
+	if (!freq_table) {
+		ret = -ENOMEM;
+		goto reg_put;
+	}
+
+	for (i = 0; i < cpu_op_nr; i++) {
+		freq_table[i].index = i;
+		if (cpu_freqs[i] > max_freq * 1000) {
+			freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			continue;
+		}
+
+		if (cpu_reg) {
+			ret = regulator_is_supported_voltage(cpu_reg,
+					cpu_volts[i * 2], cpu_volts[i * 2 + 1]);
+			if (ret <= 0) {
+				freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+				continue;
+			}
+		}
+		freq_table[i].frequency = cpu_freqs[i] / 1000;
+		max_idx = cpu_freqs[i] > cpu_freqs[max_idx] ? i : max_idx;
+		min_idx = cpu_freqs[i] < cpu_freqs[min_idx] ? i : min_idx;
+	}
+
+	freq_table[i].index = i;
+	freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+	if (cpu_reg && trans_latency != CPUFREQ_ETERNAL) {
+		ret = regulator_set_voltage_time(cpu_reg, cpu_volts[min_idx],
+						cpu_volts[max_idx]);
+		if (ret < 0) {
+			pr_warn("regulator_set_voltage_time failed. "
+				"Default use 1us\n");
+			ret = 1;
+		}
+		trans_latency += ret * 1000;
+	}
+
+	ret = cpufreq_register_driver(&clk_reg_cpufreq_driver);
+	if (ret)
+		goto free_freq_table;
+
+	of_node_put(cpu0);
+
+	return 0;
+
+free_freq_table:
+	kfree(freq_table);
+reg_put:
+	if (cpu_reg)
+		regulator_put(cpu_reg);
+	clk_put(cpu_clk);
+free_cpu_volts:
+	kfree(cpu_volts);
+free_cpu_freqs:
+	kfree(cpu_freqs);
+put_node:
+	of_node_put(cpu0);
+
+	return ret;
+}
+
+static void clk_reg_cpufreq_driver_exit(void)
+{
+	cpufreq_unregister_driver(&clk_reg_cpufreq_driver);
+	kfree(cpu_freqs);
+	kfree(cpu_volts);
+	clk_put(cpu_clk);
+	if (cpu_reg)
+		regulator_put(cpu_reg);
+	kfree(freq_table);
+}
+
+module_init(clk_reg_cpufreq_driver_init);
+module_exit(clk_reg_cpufreq_driver_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor Inc. Richard Zhao <richard.zhao@freescale.com>");
+MODULE_DESCRIPTION("Generic CPUFreq driver based on clk and regulator APIs");
+MODULE_LICENSE("GPL");
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 5/7] dts/imx6q: add cpufreq property
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/boot/dts/imx6q.dtsi |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 263e8f3..d89b42d 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -29,6 +29,13 @@
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 			next-level-cache = <&L2>;
+			cpu-freqs = <996000000 792000000 396000000 198000000>;
+			cpu-volts = <	/* min		max */
+					1225000		1450000	/* 996M */
+					1100000		1450000	/* 792M */
+					950000		1450000	/* 396M */
+					850000		1450000>; /* 198M */
+			clk-trans-latency = <61036>; /* two CLK32 periods */
 		};
 
 		cpu@1 {
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 5/7] dts/imx6q: add cpufreq property
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/boot/dts/imx6q.dtsi |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 263e8f3..d89b42d 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -29,6 +29,13 @@
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 			next-level-cache = <&L2>;
+			cpu-freqs = <996000000 792000000 396000000 198000000>;
+			cpu-volts = <	/* min		max */
+					1225000		1450000	/* 996M */
+					1100000		1450000	/* 792M */
+					950000		1450000	/* 396M */
+					850000		1450000>; /* 198M */
+			clk-trans-latency = <61036>; /* two CLK32 periods */
 		};
 
 		cpu at 1 {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 6/7] arm/imx6q: register arm_clk as cpu to clkdev
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

cpufreq needs cpu clock to change frequency.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/mach-imx/clock-imx6q.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
index 039a7ab..72acbc2 100644
--- a/arch/arm/mach-imx/clock-imx6q.c
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -1911,6 +1911,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
 	_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
 	_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+	_REGISTER_CLOCK(NULL, "cpu", arm_clk),
 };
 
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 6/7] arm/imx6q: register arm_clk as cpu to clkdev
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

cpufreq needs cpu clock to change frequency.

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/mach-imx/clock-imx6q.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
index 039a7ab..72acbc2 100644
--- a/arch/arm/mach-imx/clock-imx6q.c
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -1911,6 +1911,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "gpmi_io_clk", gpmi_io_clk),
 	_REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk),
 	_REGISTER_CLOCK(NULL, "sata_clk", sata_clk),
+	_REGISTER_CLOCK(NULL, "cpu", arm_clk),
 };
 
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 7/7] arm/imx6q: select ARCH_HAS_CPUFREQ
  2011-12-30  2:56 ` Richard Zhao
@ 2011-12-30  2:56   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, davej, grant.likely, rob.herring, rdunlap, kernel,
	shawn.guo, catalin.marinas, eric.miao, mark.langsdorf, davidb,
	arnd, bryanh, jamie, marc.zyngier, linaro-dev, patches,
	Richard Zhao

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/mach-imx/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c44aa97..39cf00a 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -595,6 +595,7 @@ comment "i.MX6 family:"
 
 config SOC_IMX6Q
 	bool "i.MX6 Quad support"
+	select ARCH_HAS_CPUFREQ
 	select ARM_GIC
 	select CACHE_L2X0
 	select CPU_V7
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH V6 7/7] arm/imx6q: select ARCH_HAS_CPUFREQ
@ 2011-12-30  2:56   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2011-12-30  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Richard Zhao <richard.zhao@linaro.org>
---
 arch/arm/mach-imx/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c44aa97..39cf00a 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -595,6 +595,7 @@ comment "i.MX6 family:"
 
 config SOC_IMX6Q
 	bool "i.MX6 Quad support"
+	select ARCH_HAS_CPUFREQ
 	select ARM_GIC
 	select CACHE_L2X0
 	select CPU_V7
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 0/7] add a generic cpufreq driver
  2011-12-30  2:56 ` Richard Zhao
  (?)
@ 2012-01-04 22:16   ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-04 22:16 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss
  Cc: linux, arnd, patches, marc.zyngier, catalin.marinas, rob.herring,
	rdunlap, eric.miao, kernel, jamie, davej, linaro-dev

hi Russell,

May I have your ACK, you merge it?

Thanks
Richard

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 0/7] add a generic cpufreq driver
@ 2012-01-04 22:16   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-04 22:16 UTC (permalink / raw)
  To: linux-arm-kernel

hi Russell,

May I have your ACK, you merge it?

Thanks
Richard

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 0/7] add a generic cpufreq driver
@ 2012-01-04 22:16   ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-04 22:16 UTC (permalink / raw)
  To: linux-arm-kernel, cpufreq, devicetree-discuss, linux-arm-kernel,
	cpufreq, devicetree-discuss
  Cc: linux, arnd, patches, marc.zyngier, catalin.marinas, rob.herring,
	rdunlap, eric.miao, kernel, jamie, davej, linaro-dev

hi Russell,

May I have your ACK, you merge it?

Thanks
Richard

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 0/7] add a generic cpufreq driver
  2012-01-04 22:16   ` Richard Zhao
@ 2012-01-06  0:53     ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-06  0:53 UTC (permalink / raw)
  To: linux
  Cc: linux-arm-kernel, cpufreq, devicetree-discuss, arnd, patches,
	marc.zyngier, catalin.marinas, rob.herring, rdunlap, eric.miao,
	kernel, davej, jamie, linaro-dev

On Thu, Jan 05, 2012 at 06:16:54AM +0800, Richard Zhao wrote:
> hi Russell,
> 
> May I have your ACK, you merge it?
Russell, ping
> 
> Thanks
> Richard
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 0/7] add a generic cpufreq driver
@ 2012-01-06  0:53     ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-06  0:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 05, 2012 at 06:16:54AM +0800, Richard Zhao wrote:
> hi Russell,
> 
> May I have your ACK, you merge it?
Russell, ping
> 
> Thanks
> Richard
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate for smp
  2011-12-30  2:56   ` Richard Zhao
@ 2012-01-06  0:56     ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-06  0:56 UTC (permalink / raw)
  To: shawn.guo, kernel
  Cc: linux-arm-kernel, cpufreq, devicetree-discuss, linux, arnd,
	mark.langsdorf, patches, marc.zyngier, catalin.marinas, bryanh,
	rob.herring, grant.likely, rdunlap, eric.miao, jamie, davej,
	davidb, linaro-dev

Hi Sascha & Shawn,

Could you look and ack the patch?

Thanks
Richard 


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate for smp
@ 2012-01-06  0:56     ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-06  0:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha & Shawn,

Could you look and ack the patch?

Thanks
Richard 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 3/7] cpufreq: OMAP: remove loops_per_jiffy recalculate for smp
  2011-12-30  2:56   ` Richard Zhao
@ 2012-01-06  1:02     ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-06  1:02 UTC (permalink / raw)
  To: khilman
  Cc: linux-arm-kernel, cpufreq, devicetree-discuss, linux, arnd,
	mark.langsdorf, patches, marc.zyngier, catalin.marinas, bryanh,
	rob.herring, grant.likely, rdunlap, eric.miao, kernel, jamie,
	davej, davidb, shawn.guo, linaro-dev

Hi Kevin,

Could you please look at and ack the patch if possible?
Sorry, I didn't cc you.

Thanks
Richard


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 3/7] cpufreq: OMAP: remove loops_per_jiffy recalculate for smp
@ 2012-01-06  1:02     ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-06  1:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

Could you please look at and ack the patch if possible?
Sorry, I didn't cc you.

Thanks
Richard

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate for smp
  2012-01-06  0:56     ` Richard Zhao
@ 2012-01-06 13:19       ` Shawn Guo
  -1 siblings, 0 replies; 39+ messages in thread
From: Shawn Guo @ 2012-01-06 13:19 UTC (permalink / raw)
  To: Richard Zhao
  Cc: kernel, linux-arm-kernel, cpufreq, devicetree-discuss, linux,
	arnd, mark.langsdorf, patches, marc.zyngier, catalin.marinas,
	bryanh, rob.herring, grant.likely, rdunlap, eric.miao, jamie,
	davej, davidb, linaro-dev

On Fri, Jan 06, 2012 at 08:56:50AM +0800, Richard Zhao wrote:
> Hi Sascha & Shawn,
> 
> Could you look and ack the patch?
> 
The patch looks good to me.  But it really depends on how the patch #1
looks to Russell.

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate for smp
@ 2012-01-06 13:19       ` Shawn Guo
  0 siblings, 0 replies; 39+ messages in thread
From: Shawn Guo @ 2012-01-06 13:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 06, 2012 at 08:56:50AM +0800, Richard Zhao wrote:
> Hi Sascha & Shawn,
> 
> Could you look and ack the patch?
> 
The patch looks good to me.  But it really depends on how the patch #1
looks to Russell.

-- 
Regards,
Shawn

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 0/7] add a generic cpufreq driver
  2012-01-06  0:53     ` Richard Zhao
@ 2012-01-09 14:52       ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-09 14:52 UTC (permalink / raw)
  To: linux
  Cc: linaro-dev, arnd, patches, marc.zyngier, catalin.marinas,
	devicetree-discuss, cpufreq, rdunlap, eric.miao, rob.herring,
	kernel, jamie, davej, linux-arm-kernel

On Fri, Jan 06, 2012 at 08:53:37AM +0800, Richard Zhao wrote:
> On Thu, Jan 05, 2012 at 06:16:54AM +0800, Richard Zhao wrote:
> > hi Russell,
> > 
> > May I have your ACK, you merge it?
> Russell, ping
would you have time to look at this patch series?
> > 
> > Thanks
> > Richard
> > 
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> > 
> 
> 
> _______________________________________________
> linaro-dev mailing list
> linaro-dev@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-dev

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 0/7] add a generic cpufreq driver
@ 2012-01-09 14:52       ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-09 14:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 06, 2012 at 08:53:37AM +0800, Richard Zhao wrote:
> On Thu, Jan 05, 2012 at 06:16:54AM +0800, Richard Zhao wrote:
> > hi Russell,
> > 
> > May I have your ACK, you merge it?
> Russell, ping
would you have time to look at this patch series?
> > 
> > Thanks
> > Richard
> > 
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> > 
> 
> 
> _______________________________________________
> linaro-dev mailing list
> linaro-dev at lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-dev

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
  2011-12-30  2:56   ` Richard Zhao
@ 2012-01-11 23:22     ` Kevin Hilman
  -1 siblings, 0 replies; 39+ messages in thread
From: Kevin Hilman @ 2012-01-11 23:22 UTC (permalink / raw)
  To: Richard Zhao
  Cc: linux-arm-kernel, cpufreq, devicetree-discuss, linux, arnd,
	patches, marc.zyngier, catalin.marinas, rob.herring, rdunlap,
	eric.miao, kernel, jamie, davej, linaro-dev

Richard Zhao <richard.zhao@linaro.org> writes:

> The driver get cpu operation point table from device tree cpu0 node,

Since we already have an existing OPP infrastructure in the kernel,
seems like  this driver should get OPPs by asking the OPP layer.

This approach assumes the OPP layer is static at boot time and not
changing, however that's not the case in practice.

The OPP layer could be extended to read boot-time OPPs from DT if
desired, but since the OPPs are also populated/enabled/disabled
dynamicaly on some platforms (e.g. OMAP), I think the any generic
CPUfreq driver should use the OPP interface and not DT directly.

> and adjusts operating points using clk and regulator APIs.

For a generic driver, the regulator used should also be configurable.

For example, this driver currently assumes a regulator named "cpu" for
all instances.   If you had separate clusters with independent voltage
control, you'd likely have a separate regulator for each cluster.

Kevin

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
@ 2012-01-11 23:22     ` Kevin Hilman
  0 siblings, 0 replies; 39+ messages in thread
From: Kevin Hilman @ 2012-01-11 23:22 UTC (permalink / raw)
  To: linux-arm-kernel

Richard Zhao <richard.zhao@linaro.org> writes:

> The driver get cpu operation point table from device tree cpu0 node,

Since we already have an existing OPP infrastructure in the kernel,
seems like  this driver should get OPPs by asking the OPP layer.

This approach assumes the OPP layer is static at boot time and not
changing, however that's not the case in practice.

The OPP layer could be extended to read boot-time OPPs from DT if
desired, but since the OPPs are also populated/enabled/disabled
dynamicaly on some platforms (e.g. OMAP), I think the any generic
CPUfreq driver should use the OPP interface and not DT directly.

> and adjusts operating points using clk and regulator APIs.

For a generic driver, the regulator used should also be configurable.

For example, this driver currently assumes a regulator named "cpu" for
all instances.   If you had separate clusters with independent voltage
control, you'd likely have a separate regulator for each cluster.

Kevin

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
  2012-01-11 23:22     ` Kevin Hilman
@ 2012-01-12  8:23       ` Richard Zhao
  -1 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-12  8:23 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Richard Zhao, linux, arnd, patches, marc.zyngier,
	catalin.marinas, devicetree-discuss, cpufreq, rdunlap, eric.miao,
	rob.herring, kernel, davej, jamie, linaro-dev, linux-arm-kernel

On Wed, Jan 11, 2012 at 03:22:34PM -0800, Kevin Hilman wrote:
> Richard Zhao <richard.zhao@linaro.org> writes:
> 
> > The driver get cpu operation point table from device tree cpu0 node,
> 
> Since we already have an existing OPP infrastructure in the kernel,
> seems like  this driver should get OPPs by asking the OPP layer.
When I created the patch, there's only omap cpufreq driver using
OPP. If it depends on OPP, it might prevent users who have not
adopted OPP from using the driver.
> 
> This approach assumes the OPP layer is static at boot time and not
> changing, however that's not the case in practice.
> 
> The OPP layer could be extended to read boot-time OPPs from DT if
> desired, but since the OPPs are also populated/enabled/disabled
> dynamicaly on some platforms (e.g. OMAP), I think the any generic
> CPUfreq driver should use the OPP interface and not DT directly.
> 
> > and adjusts operating points using clk and regulator APIs.
> 
> For a generic driver, the regulator used should also be configurable.
> 
> For example, this driver currently assumes a regulator named "cpu" for
> all instances.   If you had separate clusters with independent voltage
> control, you'd likely have a separate regulator for each cluster.
The driver, for now, assumes all cpu cores uses the same clk and voltage.
It's correct for most arm multi-core SoC.
Do you have real case to need different voltage/clk?
And the regulator will be specified in dts after cpu convert from sys
device to normal device.

Thanks
Richard
> 
> Kevin
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
@ 2012-01-12  8:23       ` Richard Zhao
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Zhao @ 2012-01-12  8:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 11, 2012 at 03:22:34PM -0800, Kevin Hilman wrote:
> Richard Zhao <richard.zhao@linaro.org> writes:
> 
> > The driver get cpu operation point table from device tree cpu0 node,
> 
> Since we already have an existing OPP infrastructure in the kernel,
> seems like  this driver should get OPPs by asking the OPP layer.
When I created the patch, there's only omap cpufreq driver using
OPP. If it depends on OPP, it might prevent users who have not
adopted OPP from using the driver.
> 
> This approach assumes the OPP layer is static at boot time and not
> changing, however that's not the case in practice.
> 
> The OPP layer could be extended to read boot-time OPPs from DT if
> desired, but since the OPPs are also populated/enabled/disabled
> dynamicaly on some platforms (e.g. OMAP), I think the any generic
> CPUfreq driver should use the OPP interface and not DT directly.
> 
> > and adjusts operating points using clk and regulator APIs.
> 
> For a generic driver, the regulator used should also be configurable.
> 
> For example, this driver currently assumes a regulator named "cpu" for
> all instances.   If you had separate clusters with independent voltage
> control, you'd likely have a separate regulator for each cluster.
The driver, for now, assumes all cpu cores uses the same clk and voltage.
It's correct for most arm multi-core SoC.
Do you have real case to need different voltage/clk?
And the regulator will be specified in dts after cpu convert from sys
device to normal device.

Thanks
Richard
> 
> Kevin
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
  2012-01-12  8:23       ` Richard Zhao
@ 2012-01-12 22:52         ` Kevin Hilman
  -1 siblings, 0 replies; 39+ messages in thread
From: Kevin Hilman @ 2012-01-12 22:52 UTC (permalink / raw)
  To: Richard Zhao
  Cc: linux, arnd, patches, marc.zyngier, catalin.marinas,
	devicetree-discuss, cpufreq, rdunlap, eric.miao, kernel, jamie,
	davej, linaro-dev, rob.herring, Richard Zhao, linux-arm-kernel

Richard Zhao <richard.zhao@freescale.com> writes:

> On Wed, Jan 11, 2012 at 03:22:34PM -0800, Kevin Hilman wrote:
>> Richard Zhao <richard.zhao@linaro.org> writes:
>> 
>> > The driver get cpu operation point table from device tree cpu0 node,
>> 
>> Since we already have an existing OPP infrastructure in the kernel,
>> seems like  this driver should get OPPs by asking the OPP layer.
>
> When I created the patch, there's only omap cpufreq driver using
> OPP. If it depends on OPP, it might prevent users who have not
> adopted OPP from using the driver.

Then they should probably adopt to OPP, since it was created exactly for
this purpose.   What this patch creates is an alternate way of adding
OPPs using the device tree.  

The point is using a static list of OPPs from boot time simply doesn't
work.  You need the ability to dynamically add/remove OPPs at runtime to
adjust for various operating conditons (or HW bugs) as well as for
thermal considerations.   The OPP layer provides this.

A generic driver should get available OPPs using the OPP layer.

The DT can certainly be used at boot time to create the initial list of
OPPs, but as the list of available OPPs changes at runtime, the only way
to track that is to use the OPP layer.


>> This approach assumes the OPP layer is static at boot time and not
>> changing, however that's not the case in practice.
>> 
>> The OPP layer could be extended to read boot-time OPPs from DT if
>> desired, but since the OPPs are also populated/enabled/disabled
>> dynamicaly on some platforms (e.g. OMAP), I think the any generic
>> CPUfreq driver should use the OPP interface and not DT directly.
>> 
>> > and adjusts operating points using clk and regulator APIs.
>> 
>> For a generic driver, the regulator used should also be configurable.
>> 
>> For example, this driver currently assumes a regulator named "cpu" for
>> all instances.   If you had separate clusters with independent voltage
>> control, you'd likely have a separate regulator for each cluster.
> The driver, for now, assumes all cpu cores uses the same clk and voltage.
> It's correct for most arm multi-core SoC.

Sure, but a "generic" driver such as the one proposed is not just for
ARM, and not just for today's SoCs.  
flexible enough

> Do you have real case to need different voltage/clk?

Sure, any system with independently scalable CPUs/clusters.

Kevin

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
@ 2012-01-12 22:52         ` Kevin Hilman
  0 siblings, 0 replies; 39+ messages in thread
From: Kevin Hilman @ 2012-01-12 22:52 UTC (permalink / raw)
  To: linux-arm-kernel

Richard Zhao <richard.zhao@freescale.com> writes:

> On Wed, Jan 11, 2012 at 03:22:34PM -0800, Kevin Hilman wrote:
>> Richard Zhao <richard.zhao@linaro.org> writes:
>> 
>> > The driver get cpu operation point table from device tree cpu0 node,
>> 
>> Since we already have an existing OPP infrastructure in the kernel,
>> seems like  this driver should get OPPs by asking the OPP layer.
>
> When I created the patch, there's only omap cpufreq driver using
> OPP. If it depends on OPP, it might prevent users who have not
> adopted OPP from using the driver.

Then they should probably adopt to OPP, since it was created exactly for
this purpose.   What this patch creates is an alternate way of adding
OPPs using the device tree.  

The point is using a static list of OPPs from boot time simply doesn't
work.  You need the ability to dynamically add/remove OPPs at runtime to
adjust for various operating conditons (or HW bugs) as well as for
thermal considerations.   The OPP layer provides this.

A generic driver should get available OPPs using the OPP layer.

The DT can certainly be used at boot time to create the initial list of
OPPs, but as the list of available OPPs changes at runtime, the only way
to track that is to use the OPP layer.


>> This approach assumes the OPP layer is static at boot time and not
>> changing, however that's not the case in practice.
>> 
>> The OPP layer could be extended to read boot-time OPPs from DT if
>> desired, but since the OPPs are also populated/enabled/disabled
>> dynamicaly on some platforms (e.g. OMAP), I think the any generic
>> CPUfreq driver should use the OPP interface and not DT directly.
>> 
>> > and adjusts operating points using clk and regulator APIs.
>> 
>> For a generic driver, the regulator used should also be configurable.
>> 
>> For example, this driver currently assumes a regulator named "cpu" for
>> all instances.   If you had separate clusters with independent voltage
>> control, you'd likely have a separate regulator for each cluster.
> The driver, for now, assumes all cpu cores uses the same clk and voltage.
> It's correct for most arm multi-core SoC.

Sure, but a "generic" driver such as the one proposed is not just for
ARM, and not just for today's SoCs.  
flexible enough

> Do you have real case to need different voltage/clk?

Sure, any system with independently scalable CPUs/clusters.

Kevin

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
  2012-01-12 22:52         ` Kevin Hilman
@ 2012-01-13 17:16             ` Cousson, Benoit
  -1 siblings, 0 replies; 39+ messages in thread
From: Cousson, Benoit @ 2012-01-13 17:16 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-lFZ/pmaqli7XmaaqVzeoHQ, patches-QSEj5FYQhm4dnm+yROfE0A,
	catalin.marinas-5wv7dgnIgG8,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	cpufreq-u79uwXL29TY76Z2rM5mHXA, rdunlap-/UHa2rfvQTnk1uMJSBkQmQ,
	Richard Zhao, eric.miao-QSEj5FYQhm4dnm+yROfE0A,
	kernel-bIcnvbaLZ9MEGnE8C9+IrQ, davej-H+wXaHxf7aLQT0dZR+AlfA,
	linaro-dev-cunTk1MwBs8s++Sfvej+rw,
	rob.herring-bsGFqQB8/DxBDgjK7y7TUQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 1/12/2012 11:52 PM, Kevin Hilman wrote:
> Richard Zhao<richard.zhao-KZfg59tc24xl57MIdRCFDg@public.gmane.org>  writes:

[...]

>> Do you have real case to need different voltage/clk?
>
> Sure, any system with independently scalable CPUs/clusters.

AFAIK, in the ARM SoC world there is a least the MSM8660 that does 
support that today.

Regards,
Benoit

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver
@ 2012-01-13 17:16             ` Cousson, Benoit
  0 siblings, 0 replies; 39+ messages in thread
From: Cousson, Benoit @ 2012-01-13 17:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 1/12/2012 11:52 PM, Kevin Hilman wrote:
> Richard Zhao<richard.zhao@freescale.com>  writes:

[...]

>> Do you have real case to need different voltage/clk?
>
> Sure, any system with independently scalable CPUs/clusters.

AFAIK, in the ARM SoC world there is a least the MSM8660 that does 
support that today.

Regards,
Benoit

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH V6 0/7] add a generic cpufreq driver
  2012-01-09 14:52       ` Richard Zhao
@ 2012-02-03 16:28         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2012-02-03 16:28 UTC (permalink / raw)
  To: Richard Zhao
  Cc: linaro-dev-cunTk1MwBs8s++Sfvej+rw, arnd-r2nGTMty4D4,
	patches-QSEj5FYQhm4dnm+yROfE0A, marc.zyngier-5wv7dgnIgG8,
	catalin.marinas-5wv7dgnIgG8,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	cpufreq-u79uwXL29TY76Z2rM5mHXA, rdunlap-/UHa2rfvQTnk1uMJSBkQmQ,
	eric.miao-QSEj5FYQhm4dnm+yROfE0A, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	davej-H+wXaHxf7aLQT0dZR+AlfA, jamie-wmLquQDDieKakBO8gow8eQ,
	rob.herring-bsGFqQB8/DxBDgjK7y7TUQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Mon, Jan 09, 2012 at 10:52:48PM +0800, Richard Zhao wrote:
> On Fri, Jan 06, 2012 at 08:53:37AM +0800, Richard Zhao wrote:
> > On Thu, Jan 05, 2012 at 06:16:54AM +0800, Richard Zhao wrote:
> > > hi Russell,
> > > 
> > > May I have your ACK, you merge it?
> > Russell, ping
> would you have time to look at this patch series?

Sorry, kept missing this.  Yes, patch 1 is fine, and _that_ patch alone
gets:

Acked-by: Russell King <rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH V6 0/7] add a generic cpufreq driver
@ 2012-02-03 16:28         ` Russell King - ARM Linux
  0 siblings, 0 replies; 39+ messages in thread
From: Russell King - ARM Linux @ 2012-02-03 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 09, 2012 at 10:52:48PM +0800, Richard Zhao wrote:
> On Fri, Jan 06, 2012 at 08:53:37AM +0800, Richard Zhao wrote:
> > On Thu, Jan 05, 2012 at 06:16:54AM +0800, Richard Zhao wrote:
> > > hi Russell,
> > > 
> > > May I have your ACK, you merge it?
> > Russell, ping
> would you have time to look at this patch series?

Sorry, kept missing this.  Yes, patch 1 is fine, and _that_ patch alone
gets:

Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2012-02-03 16:28 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-30  2:56 [PATCH V6 0/7] add a generic cpufreq driver Richard Zhao
2011-12-30  2:56 ` Richard Zhao
2011-12-30  2:56 ` [PATCH V6 1/7] ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2011-12-30  2:56 ` [PATCH V6 2/7] arm/imx: cpufreq: remove loops_per_jiffy recalculate " Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2012-01-06  0:56   ` Richard Zhao
2012-01-06  0:56     ` Richard Zhao
2012-01-06 13:19     ` Shawn Guo
2012-01-06 13:19       ` Shawn Guo
2011-12-30  2:56 ` [PATCH V6 3/7] cpufreq: OMAP: " Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2012-01-06  1:02   ` Richard Zhao
2012-01-06  1:02     ` Richard Zhao
2011-12-30  2:56 ` [PATCH V6 4/7] cpufreq: add clk-reg cpufreq driver Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2012-01-11 23:22   ` Kevin Hilman
2012-01-11 23:22     ` Kevin Hilman
2012-01-12  8:23     ` Richard Zhao
2012-01-12  8:23       ` Richard Zhao
2012-01-12 22:52       ` Kevin Hilman
2012-01-12 22:52         ` Kevin Hilman
     [not found]         ` <874nw0sfdn.fsf-l0cyMroinI0@public.gmane.org>
2012-01-13 17:16           ` Cousson, Benoit
2012-01-13 17:16             ` Cousson, Benoit
2011-12-30  2:56 ` [PATCH V6 5/7] dts/imx6q: add cpufreq property Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2011-12-30  2:56 ` [PATCH V6 6/7] arm/imx6q: register arm_clk as cpu to clkdev Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2011-12-30  2:56 ` [PATCH V6 7/7] arm/imx6q: select ARCH_HAS_CPUFREQ Richard Zhao
2011-12-30  2:56   ` Richard Zhao
2012-01-04 22:16 ` [PATCH V6 0/7] add a generic cpufreq driver Richard Zhao
2012-01-04 22:16   ` Richard Zhao
2012-01-04 22:16   ` Richard Zhao
2012-01-06  0:53   ` Richard Zhao
2012-01-06  0:53     ` Richard Zhao
2012-01-09 14:52     ` Richard Zhao
2012-01-09 14:52       ` Richard Zhao
2012-02-03 16:28       ` Russell King - ARM Linux
2012-02-03 16:28         ` Russell King - ARM Linux

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.