From 4f325a029dc651dd924002a456b039a7bc00385b Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Sun, 13 Mar 2011 00:41:14 -0800 Subject: ARM: tegra: clock: Re-factor Tegra3 cpu clocks Added second level virtualization (on top of virtual cpu rate control) to support different Tegra3 CPU power modes: low power (LP) mode and geared performance (G) mode. Virtual cpu complex (cpu_cmplx) clock is defined as a child with two parents: virtual cpu_lp and virtual cpu_g clocks for the respective modes. Mode switch sequence was integrated into cpu_cmplx set parent implementation. (Before this commit mode switch was triggered outside the clock framework, which created cpu clock/mode synchronization problems). Each mode clock is derived from its own super clock mux (cclk_lp and cclk_g) to statically match Tegra3 h/w layout. (Before this commit the code had to dynamically synchronize CPU mode and active mux selection). This change also allowed to support PLLX output divider for low power mode as fixed 1:2 divider with bypass control embedded into cclk_lp parent section. Updated auto and sysfs CPU mode switch calls to use new clock framework, and removed clock manipulation from the low level mode switch implementation. Original-Change-Id: Ibc3cc495b2ff29e2d3417eff2bfd45535cbd015b Reviewed-on: http://git-master/r/24734 Reviewed-by: Aleksandr Frid Tested-by: Aleksandr Frid Tested-by: Jin Qian Reviewed-by: Scott Williams Original-Change-Id: I23ae80edbf14fb22727a6fc317cd9e5baf8bd6be Rebase-Id: Rdcd4a2165ebd92bf4caa35d68ca81d19a3789351 --- arch/arm/mach-tegra/cpu-tegra3.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'arch/arm/mach-tegra/cpu-tegra3.c') diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c index b7c6e9726e5c..c8059030df7c 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -29,10 +29,12 @@ #include #include #include +#include #include #include #include "pm.h" +#include "clock.h" #define INITIAL_STATE TEGRA_HP_DISABLED #define IDLE_HYSTERESIS 100000 @@ -62,6 +64,9 @@ module_param(idle_bottom_freq, uint, 0644); static unsigned int lpcpu_max_freq; +static struct clk *cpu_clk; +static struct clk *cpu_g_clk; +static struct clk *cpu_lp_clk; static struct { cputime64_t time_up_total; @@ -189,18 +194,20 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work) hotplug_wq, &hotplug_work, down_delay); hp_stats_update(cpu, false); } else if (!is_lp_cluster() && !no_lp) { - tegra_cluster_control(0, TEGRA_POWER_CLUSTER_LP | - TEGRA_POWER_CLUSTER_IMMEDIATE); - hp_stats_update(CONFIG_NR_CPUS, true); - hp_stats_update(0, false); + if(!clk_set_parent(cpu_clk, cpu_lp_clk)) { + hp_stats_update(CONFIG_NR_CPUS, true); + hp_stats_update(0, false); + } else + queue_delayed_work( + hotplug_wq, &hotplug_work, down_delay); } break; case TEGRA_HP_UP: if (is_lp_cluster() && !no_lp) { - tegra_cluster_control(0, TEGRA_POWER_CLUSTER_G | - TEGRA_POWER_CLUSTER_IMMEDIATE); - hp_stats_update(CONFIG_NR_CPUS, false); - hp_stats_update(0, true); + if(!clk_set_parent(cpu_clk, cpu_g_clk)) { + hp_stats_update(CONFIG_NR_CPUS, false); + hp_stats_update(0, true); + } queue_delayed_work( hotplug_wq, &hotplug_work, up2gn_delay); } else { @@ -281,7 +288,7 @@ int tegra_auto_hotplug_init(void) { /* * Not bound to the issuer CPU (=> high-priority), has rescue worker - * task, single-threaded, frrezeable. + * task, single-threaded, freezable. */ hotplug_wq = alloc_workqueue( "cpu-tegra3", WQ_UNBOUND | WQ_RESCUER | WQ_FREEZEABLE, 1); @@ -289,7 +296,13 @@ int tegra_auto_hotplug_init(void) return -ENOMEM; INIT_DELAYED_WORK(&hotplug_work, tegra_auto_hotplug_work_func); - lpcpu_max_freq = tegra_get_lpcpu_max_rate() / 1000; + cpu_clk = clk_get_sys(NULL, "cpu"); + cpu_g_clk = clk_get_sys(NULL, "cpu_g"); + cpu_lp_clk = clk_get_sys(NULL, "cpu_lp"); + if (IS_ERR(cpu_clk) || IS_ERR(cpu_g_clk) || IS_ERR(cpu_lp_clk)) + return -ENOENT; + + lpcpu_max_freq = clk_get_max_rate(cpu_lp_clk) / 1000; idle_top_freq = lpcpu_max_freq; idle_bottom_freq = idle_top_freq - IDLE_HYSTERESIS; -- cgit v1.2.3