From abbfd79c153d775332664ac898e383abbf3ed72a Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Mon, 28 Feb 2011 17:30:34 +0530 Subject: Revert "OMAP3: cpufreq driver changes for DVFS support" This reverts commit de1c81cf2d50cba25e3ed399d3fe6c412781827f since there is another patch set for omap cpufreq changes at https://patchwork.kernel.org/patch/589081/ Signed-off-by: Vishwanath BS Signed-off-by: Nicolas Pitre --- arch/arm/plat-omap/cpu-omap.c | 69 ++----------------------------------------- 1 file changed, 3 insertions(+), 66 deletions(-) diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index 73452c700da..11c54ec8d47 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c @@ -8,10 +8,6 @@ * * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King * - * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Updated to support OMAP3 - * Rajendra Nayak - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -25,18 +21,10 @@ #include #include #include -#include #include #include #include -#include - -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) -#include -#include -#include -#endif #define VERY_HI_RATE 900000000 @@ -44,8 +32,6 @@ static struct cpufreq_frequency_table *freq_table; #ifdef CONFIG_ARCH_OMAP1 #define MPU_CLK "mpu" -#elif defined(CONFIG_ARCH_OMAP3) -#define MPU_CLK "arm_fck" #else #define MPU_CLK "virt_prcm_set" #endif @@ -88,12 +74,6 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int relation) { struct cpufreq_freqs freqs; -#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) - unsigned long freq; - int i; - struct cpufreq_freqs freqs_notify; - struct device *mpu_dev = omap2_get_mpuss_device(); -#endif int ret = 0; /* Ensure desired rate is within allowed range. Some govenors @@ -103,13 +83,13 @@ static int omap_target(struct cpufreq_policy *policy, if (target_freq > policy->max) target_freq = policy->max; -#ifdef CONFIG_ARCH_OMAP1 freqs.old = omap_getspeed(0); freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; freqs.cpu = 0; if (freqs.old == freqs.new) return ret; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); #ifdef CONFIG_CPU_FREQ_DEBUG printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n", @@ -117,39 +97,7 @@ static int omap_target(struct cpufreq_policy *policy, #endif ret = clk_set_rate(mpu_clk, freqs.new * 1000); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); -#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) - freqs.old = omap_getspeed(policy->cpu);; - freqs_notify.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; - freqs.cpu = policy->cpu; - if (freqs.old == freqs.new) - return ret; - - /* pre notifiers */ - for_each_cpu(i, policy->cpus) { - freqs.cpu = i; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - } - - /* scale the frequency */ - freq = target_freq * 1000; - if (opp_find_freq_ceil(mpu_dev, &freq)) - omap_device_scale(mpu_dev, mpu_dev, freq); - -#ifdef CONFIG_SMP - /* Update loops per jiffy */ - freqs.new = omap_getspeed(policy->cpu); - for_each_cpu(i, policy->cpus) - per_cpu(cpu_data, i).loops_per_jiffy = - cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, - freqs.old, freqs.new); -#endif - /* post notifiers */ - for_each_cpu(i, policy->cpus) { - freqs.cpu = i; - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - } -#endif return ret; } @@ -166,14 +114,7 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = omap_getspeed(0); - if (!cpu_is_omap34xx()) { - clk_init_cpufreq_table(&freq_table); - } else { - struct device *mpu_dev = omap2_get_mpuss_device(); - - opp_init_cpufreq_table(mpu_dev, &freq_table); - } - + clk_init_cpufreq_table(&freq_table); if (freq_table) { result = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (!result) @@ -185,10 +126,6 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) VERY_HI_RATE) / 1000; } - policy->min = policy->cpuinfo.min_freq; - policy->max = policy->cpuinfo.max_freq; - policy->cur = omap_getspeed(0); - /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; @@ -223,7 +160,7 @@ static int __init omap_cpufreq_init(void) return cpufreq_register_driver(&omap_driver); } -late_initcall(omap_cpufreq_init); +arch_initcall(omap_cpufreq_init); /* * if ever we want to remove this, upon cleanup call: -- cgit v1.2.3 From 7e02ae7fc4ecef01f2b8feea18a48ee231a1780c Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 25 Feb 2011 06:10:37 +0000 Subject: omap2plus: clock: Add an alias cpu_ck to be used in common cpufreq driver Add an alias clock node for cpu clock control on all OMAP2PLUS devices. The intention is avoid cpu_is_xxxx() checks in the common cpufreq driver. Signed-off-by: Santosh Shilimkar Signed-off-by: Nicolas Pitre --- arch/arm/mach-omap2/clock2420_data.c | 1 + arch/arm/mach-omap2/clock2430_data.c | 1 + arch/arm/mach-omap2/clock3xxx_data.c | 1 + arch/arm/mach-omap2/clock44xx_data.c | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 3c1712b045a..dd9fd87a731 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1799,6 +1799,7 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_242X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X), + CLK(NULL, "cpu_ck", &virt_prcm_set, CK_242X), /* general l4 interface ck, multi-parent functional clk */ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_242X), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_242X), diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 136171c92c6..c698c1c8778 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1903,6 +1903,7 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X), + CLK(NULL, "cpu_ck", &virt_prcm_set, CK_243X), /* general l4 interface ck, multi-parent functional clk */ CLK(NULL, "gpt1_ick", &gpt1_ick, CK_243X), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_243X), diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 414de70c7a3..b1c484cd891 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3224,6 +3224,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_3XXX), CLK(NULL, "sys_clkout1", &sys_clkout1, CK_3XXX), CLK(NULL, "dpll1_ck", &dpll1_ck, CK_3XXX), + CLK(NULL, "cpu_ck", &dpll1_ck, CK_3XXX), CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_3XXX), CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX), CLK(NULL, "dpll2_ck", &dpll2_ck, CK_34XX | CK_36XX), diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index bfaed63690d..95f2c4c9503 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3057,6 +3057,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, CK_443X), CLK(NULL, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, CK_443X), CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck, CK_443X), + CLK(NULL, "cpu_ck", &dpll_mpu_ck, CK_443X), CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck, CK_443X), CLK(NULL, "per_hs_clk_div_ck", &per_hs_clk_div_ck, CK_443X), CLK(NULL, "per_hsd_byp_clk_mux_ck", &per_hsd_byp_clk_mux_ck, CK_443X), -- cgit v1.2.3 From 7396a3b323962411f1b1cae3bcebc9741cbbd2c4 Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Mon, 28 Feb 2011 17:34:23 +0530 Subject: omap: cpufreq: Split omap1 and omap2plus cpufreq drivers. This patch is an attempt to cleanup the #ifdeferry in the omap cpufreq drivers. The split betwenn omap1 and omap2plus is logical because - omap1 doesn't support opp layer. - omap1 build is seperate from omap2plus. Signed-off-by: Santosh Shilimkar Cc: Kevin Hilman Cc: Vishwanath BS Signed-off-by: Nicolas Pitre --- arch/arm/mach-omap1/Makefile | 3 + arch/arm/mach-omap1/omap1-cpufreq.c | 176 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/Makefile | 3 + arch/arm/mach-omap2/omap2plus-cpufreq.c | 197 ++++++++++++++++++++++++++++++++ arch/arm/plat-omap/Makefile | 1 - 5 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index ba6009f2767..cb2d3a64858 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o +# CPUFREQ driver +obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o + # Power Management obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c new file mode 100644 index 00000000000..64faf3f28d9 --- /dev/null +++ b/arch/arm/mach-omap1/omap1-cpufreq.c @@ -0,0 +1,176 @@ +/* + * OMAP1 cpufreq driver + * + * CPU frequency scaling for OMAP + * + * Copyright (C) 2005 Nokia Corporation + * Written by Tony Lindgren + * + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Updated to support OMAP3 + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#define VERY_HI_RATE 900000000 + +static struct cpufreq_frequency_table *freq_table; +static struct clk *mpu_clk; + +static int omap_verify_speed(struct cpufreq_policy *policy) +{ + if (freq_table) + return cpufreq_frequency_table_verify(policy, freq_table); + + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + return 0; +} + +static unsigned int omap_getspeed(unsigned int cpu) +{ + unsigned long rate; + + if (cpu) + return 0; + + rate = clk_get_rate(mpu_clk) / 1000; + return rate; +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + int ret = 0; + + /* Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. */ + if (target_freq < policy->min) + target_freq = policy->min; + if (target_freq > policy->max) + target_freq = policy->max; + + freqs.old = omap_getspeed(0); + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; + freqs.cpu = 0; + + if (freqs.old == freqs.new) + return ret; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + +#ifdef CONFIG_CPU_FREQ_DEBUG + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); +#endif + ret = clk_set_rate(mpu_clk, freqs.new * 1000); + if (!ret) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +static int __init omap_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + + mpu_clk = clk_get(NULL, "mpu"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + if (policy->cpu != 0) + return -EINVAL; + + policy->cur = policy->min = policy->max = omap_getspeed(0); + + clk_init_cpufreq_table(&freq_table); + + if (freq_table) { + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!result) + cpufreq_frequency_table_get_attr(freq_table, + policy->cpu); + } else { + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, + VERY_HI_RATE) / 1000; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(0); + + /* FIXME: what's the actual transition time? */ + policy->cpuinfo.transition_latency = 300 * 1000; + + return 0; +} + +static int omap_cpu_exit(struct cpufreq_policy *policy) +{ + clk_exit_cpufreq_table(&freq_table); + clk_put(mpu_clk); + return 0; +} + +static struct freq_attr *omap_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver omap_driver = { + .flags = CPUFREQ_STICKY, + .verify = omap_verify_speed, + .target = omap_target, + .get = omap_getspeed, + .init = omap_cpu_init, + .exit = omap_cpu_exit, + .name = "omap1", + .attr = omap_cpufreq_attr, +}; + +static int __init omap_cpufreq_init(void) +{ + return cpufreq_register_driver(&omap_driver); +} + +static void __exit omap_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&omap_driver); +} + +MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs"); +MODULE_LICENSE("GPL"); +module_init(omap_cpufreq_init); +module_exit(omap_cpufreq_exit); diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index f6614a6898a..86a54ca1b6e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o endif +# CPUFREQ driver +obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o + # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c new file mode 100644 index 00000000000..48da8672443 --- /dev/null +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -0,0 +1,197 @@ +/* + * OMAP2PLUS cpufreq driver + * + * CPU frequency scaling for OMAP + * + * Copyright (C) 2005 Nokia Corporation + * Written by Tony Lindgren + * + * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King + * + * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Updated to support OMAP3 + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#define VERY_HI_RATE 900000000 + +static struct cpufreq_frequency_table *freq_table; +static struct clk *mpu_clk; + +static int omap_verify_speed(struct cpufreq_policy *policy) +{ + if (freq_table) + return cpufreq_frequency_table_verify(policy, freq_table); + + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + + policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; + policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000; + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); + return 0; +} + +static unsigned int omap_getspeed(unsigned int cpu) +{ + unsigned long rate; + + if (cpu) + return 0; + + rate = clk_get_rate(mpu_clk) / 1000; + return rate; +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + int ret = 0; + struct cpufreq_freqs freqs; + + /* Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. */ + if (target_freq < policy->min) + target_freq = policy->min; + if (target_freq > policy->max) + target_freq = policy->max; + + freqs.old = omap_getspeed(0); + freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; + freqs.cpu = 0; + + if (freqs.old == freqs.new) + return ret; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + +#ifdef CONFIG_CPU_FREQ_DEBUG + pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); +#endif + + ret = clk_set_rate(mpu_clk, freqs.new * 1000); + if (ret) + return ret; + + /* + * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies + * won't get updated when UP machine cpufreq build with + * CONFIG_SMP enabled. Below code is added only to manage that + * scenario + */ + if (!is_smp()) + loops_per_jiffy = + cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +static int __init omap_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + struct device *mpu_dev; + + mpu_clk = clk_get(NULL, "cpu_ck"); + if (IS_ERR(mpu_clk)) + return PTR_ERR(mpu_clk); + + if (policy->cpu != 0) + return -EINVAL; + + policy->cur = policy->min = policy->max = omap_getspeed(0); + + mpu_dev = omap2_get_mpuss_device(); + if (!mpu_dev) { + pr_warning("%s: unable to get the mpu device\n", __func__); + return -EINVAL; + } + opp_init_cpufreq_table(mpu_dev, &freq_table); + + if (freq_table) { + result = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!result) + cpufreq_frequency_table_get_attr(freq_table, + policy->cpu); + } else { + policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, + VERY_HI_RATE) / 1000; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = omap_getspeed(0); + + /* FIXME: what's the actual transition time? */ + policy->cpuinfo.transition_latency = 300 * 1000; + + return 0; +} + +static int omap_cpu_exit(struct cpufreq_policy *policy) +{ + clk_exit_cpufreq_table(&freq_table); + clk_put(mpu_clk); + return 0; +} + +static struct freq_attr *omap_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver omap_driver = { + .flags = CPUFREQ_STICKY, + .verify = omap_verify_speed, + .target = omap_target, + .get = omap_getspeed, + .init = omap_cpu_init, + .exit = omap_cpu_exit, + .name = "omap2plus", + .attr = omap_cpufreq_attr, +}; + +static int __init omap_cpufreq_init(void) +{ + return cpufreq_register_driver(&omap_driver); +} + +static void __exit omap_cpufreq_exit(void) +{ + cpufreq_unregister_driver(&omap_driver); +} + +MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs"); +MODULE_LICENSE("GPL"); +module_init(omap_cpufreq_init); +module_exit(omap_cpufreq_exit); diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index a4a12859fdd..ec7862e9149 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o -obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o -- cgit v1.2.3 From 1674746ea72d7817bd1e51d3b1266a540199718c Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 25 Feb 2011 06:10:39 +0000 Subject: omap2plus: cpufreq: Add SMP support to cater OMAP4430 On OMAP SMP configuartion, both processors share the voltage and clock. So both CPUs needs to be scaled together and hence needs software co-ordination. Signed-off-by: Santosh Shilimkar Cc: Kevin Hilman cc: Vishwanath BS Signed-off-by: Nicolas Pitre --- arch/arm/mach-omap2/omap2plus-cpufreq.c | 71 ++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c index 48da8672443..8c903c18e9b 100644 --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -26,9 +26,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu) { unsigned long rate; - if (cpu) + if (cpu >= NR_CPUS) return 0; rate = clk_get_rate(mpu_clk) / 1000; @@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { - int ret = 0; + int i, ret = 0; struct cpufreq_freqs freqs; + /* Wait untill all CPU's are initialized */ + if (is_smp() && (num_online_cpus() < NR_CPUS)) + return ret; + /* Ensure desired rate is within allowed range. Some govenors * (ondemand) will just pass target_freq=0 to get the minimum. */ if (target_freq < policy->min) @@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy, if (target_freq > policy->max) target_freq = policy->max; - freqs.old = omap_getspeed(0); + freqs.old = omap_getspeed(policy->cpu); freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; - freqs.cpu = 0; + freqs.cpu = policy->cpu; if (freqs.old == freqs.new) return ret; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (!is_smp()) { + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + goto set_freq; + } + + /* notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } +set_freq: #ifdef CONFIG_CPU_FREQ_DEBUG pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); #endif @@ -100,6 +116,7 @@ static int omap_target(struct cpufreq_policy *policy, ret = clk_set_rate(mpu_clk, freqs.new * 1000); if (ret) return ret; + freqs.new = omap_getspeed(policy->cpu); /* * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies @@ -107,12 +124,32 @@ static int omap_target(struct cpufreq_policy *policy, * CONFIG_SMP enabled. Below code is added only to manage that * scenario */ - if (!is_smp()) + if (!is_smp()) { loops_per_jiffy = cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + goto skip_lpj; + } - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +#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) + per_cpu(cpu_data, i).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy, + freqs.old, freqs.new); +#endif + + /* notifiers */ + for_each_cpu(i, policy->cpus) { + freqs.cpu = i; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } +skip_lpj: return ret; } @@ -120,15 +157,16 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) { int result = 0; struct device *mpu_dev; + static cpumask_var_t cpumask; mpu_clk = clk_get(NULL, "cpu_ck"); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); - if (policy->cpu != 0) + if (policy->cpu >= NR_CPUS) return -EINVAL; - policy->cur = policy->min = policy->max = omap_getspeed(0); + policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); mpu_dev = omap2_get_mpuss_device(); if (!mpu_dev) { @@ -150,7 +188,20 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) policy->min = policy->cpuinfo.min_freq; policy->max = policy->cpuinfo.max_freq; - policy->cur = omap_getspeed(0); + policy->cur = omap_getspeed(policy->cpu); + + /* + * On OMAP SMP configuartion, both processors share the voltage + * and clock. So both CPUs needs to be scaled together and hence + * needs software co-ordination. Use cpufreq affected_cpus + * interface to handle this scenario. Additional is_smp() check + * is to keep SMP_ON_UP builf working. + */ + if (is_smp()) { + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; + cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask); + cpumask_copy(policy->cpus, cpumask); + } /* FIXME: what's the actual transition time? */ policy->cpuinfo.transition_latency = 300 * 1000; -- cgit v1.2.3 From 61dde43f99d3977b31c23719a3967fd58a1c354b Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Fri, 25 Feb 2011 12:52:08 +0530 Subject: OMAP2PLUS: cpufreq DVFS changes This patch adds support for DVFS in cpufreq driver by replacing clock api with DVFS api. Signed-off-by: Vishwanath BS Signed-off-by: Nicolas Pitre --- arch/arm/mach-omap2/omap2plus-cpufreq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c index 8c903c18e9b..e982e13f2af 100644 --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -37,6 +37,7 @@ #include #include +#include #define VERY_HI_RATE 900000000 @@ -78,6 +79,7 @@ static int omap_target(struct cpufreq_policy *policy, { int i, ret = 0; struct cpufreq_freqs freqs; + struct device *mpu_dev = omap2_get_mpuss_device(); /* Wait untill all CPU's are initialized */ if (is_smp() && (num_online_cpus() < NR_CPUS)) @@ -113,7 +115,7 @@ set_freq: pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); #endif - ret = clk_set_rate(mpu_clk, freqs.new * 1000); + ret = omap_device_scale(mpu_dev, mpu_dev, freqs.new * 1000); if (ret) return ret; freqs.new = omap_getspeed(policy->cpu); -- cgit v1.2.3 From 3682a135ccaeeb5d7017eacfc7b54dda4b1af1cf Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Thu, 24 Feb 2011 16:53:28 +0530 Subject: OMAP4 PM: Add support for OMAP4 MPU DVFS This patchset adds support for OMAP4 MPU DVFS with following changes - add vdd information for omap4 - enable all relevant OPPs for MPU VDD - define and register get_rate and set_rate with DVFS layer Signed-off-by: Vishwanath BS Signed-off-by: Nicolas Pitre --- arch/arm/mach-omap2/dvfs.c | 19 +++++++++++++++++++ arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 1 + arch/arm/mach-omap2/opp4xxx_data.c | 4 ++-- arch/arm/mach-omap2/pm.c | 25 +++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c index 1e5492c2ecb..fb9215cb927 100644 --- a/arch/arm/mach-omap2/dvfs.c +++ b/arch/arm/mach-omap2/dvfs.c @@ -100,6 +100,19 @@ static struct voltagedomain omap3_vdd[] = { .name = "core", }, }; + +static struct voltagedomain omap4_vdd[] = { + { + .name = "mpu", + }, + { + .name = "iva", + }, + { + .name = "core", + }, +}; + static int omap_dvfs_voltage_scale(struct omap_vdd_dvfs_info *dvfs_info); static int __init omap_dvfs_init(void); @@ -723,6 +736,12 @@ static int __init omap_dvfs_init() if (cpu_is_omap34xx()) { omap_nr_vdd = 2; vdd_list = omap3_vdd; + } else if (cpu_is_omap44xx()) { + omap_nr_vdd = 3; + vdd_list = omap4_vdd; + } else { + pr_warning("DVFS not supported\n"); + return -EINVAL; } omap_dvfs_info_list = kzalloc(omap_nr_vdd * diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 0bd579e98e7..93d441798d1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2058,6 +2058,7 @@ static struct omap_hwmod omap44xx_mpu_hwmod = { .mpu_irqs = omap44xx_mpu_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_mpu_irqs), .main_clk = "dpll_mpu_m2_ck", + .vdd_name = "mpu", .prcm = { .omap4 = { .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL, diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index 80d08bcd612..2e8bb8a6ba9 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -30,9 +30,9 @@ static struct omap_opp_def __initdata omap44xx_opp_def_list[] = { /* MPU OPP2 - OPP100 */ OPP_INITIALIZER("mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV), /* MPU OPP3 - OPP-Turbo */ - OPP_INITIALIZER("mpu", false, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV), + OPP_INITIALIZER("mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV), /* MPU OPP4 - OPP-SB */ - OPP_INITIALIZER("mpu", false, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV), + OPP_INITIALIZER("mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV), /* L3 OPP1 - OPP50 */ OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV), /* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */ diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 1b94ad47b07..51b0dcdef60 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -130,6 +130,24 @@ static unsigned long omap3_l3_get_rate(struct device *dev) return dpll3_clk->rate / l3_div; } +static int omap4_mpu_set_rate(struct device *dev, unsigned long rate) +{ + int ret; + + ret = clk_set_rate(dpll1_clk, rate); + if (ret) { + dev_warn(dev, "%s: Unable to set rate to %ld\n", + __func__, rate); + return ret; + } + + return 0; +} + +static unsigned long omap4_mpu_get_rate(struct device *dev) +{ + return dpll1_clk->rate; +} /* * Build omap_devices for processors and bus. @@ -160,7 +178,14 @@ static void omap2_init_processor_devices(void) omap_device_register_dvfs_callbacks(l3_dev, omap3_l3_set_rate, omap3_l3_get_rate); + } else if (cpu_is_omap44xx()) { + dpll1_clk = clk_get(NULL, "dpll_mpu_ck"); + + if (mpu_dev) + omap_device_register_dvfs_callbacks(mpu_dev, + omap4_mpu_set_rate, omap4_mpu_get_rate); } + } /* Types of sleep_switch used in omap_set_pwrdm_state */ -- cgit v1.2.3 From 82544ce706497e311e4d0852f221ef9c0cd897d1 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Feb 2011 16:54:56 +0530 Subject: OMAP4: Fix CONFIG_NR_CPUS for OMAP4 Fix number of CPUs for OMAP4 Signed-off-by: Santosh Shilimkar Signed-off-by: Nicolas Pitre --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 9f2c5bd5fbc..ccfd51cd2bc 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -58,6 +58,7 @@ CONFIG_ARM_ERRATA_411920=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y +CONFIG_NR_CPUS=2 # CONFIG_LOCAL_TIMERS is not set CONFIG_AEABI=y CONFIG_LEDS=y -- cgit v1.2.3