From ec68b0ceec876ea62394707f886d97caaf8174cf Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Fri, 16 Dec 2011 19:57:04 -0800 Subject: ARM: tegra: power: Update Tegra3 auto-hotplug states Updated Tegra3 auto-hotplug state machine: - no longer enter down state on LP CPU (there is no down path on LP) - no longer enter idle state on G CPU (since load distribution between G cores may change without CPU frequency change, continue polling) - allow only disabled or idle state to be set via auto-hotplug sysfs node, and synchronize with cpufreq governor in the latter case Change-Id: Ibb93ddca852bbe1341fc5c52b0c83c16e9963e9d Signed-off-by: Alex Frid Reviewed-on: http://git-master/r/71584 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Wen Yi Reviewed-by: Diwakar Tundlam Reviewed-by: Krishna Reddy --- arch/arm/mach-tegra/cpu-tegra3.c | 54 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 26 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 6aaa87e36918..78425f4f7643 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -143,30 +143,24 @@ static int hp_state_set(const char *arg, const struct kernel_param *kp) mutex_lock(tegra3_cpu_lock); old_state = hp_state; - ret = param_set_int(arg, kp); + ret = param_set_bool(arg, kp); /* set idle or disabled only */ if (ret == 0) { - switch (hp_state) { - case TEGRA_HP_DISABLED: - if (old_state != TEGRA_HP_DISABLED) - pr_info("Tegra auto-hotplug disabled\n"); - break; - case TEGRA_HP_IDLE: - case TEGRA_HP_DOWN: - case TEGRA_HP_UP: + if ((hp_state == TEGRA_HP_DISABLED) && + (old_state != TEGRA_HP_DISABLED)) + pr_info("Tegra auto-hotplug disabled\n"); + else if (hp_state != TEGRA_HP_DISABLED) { if (old_state == TEGRA_HP_DISABLED) { - hp_init_stats(); - queue_delayed_work( - hotplug_wq, &hotplug_work, down_delay); pr_info("Tegra auto-hotplug enabled\n"); + hp_init_stats(); } - break; - default: - pr_warn("%s: unable to set tegra hotplug state %d\n", - __func__, hp_state); - hp_state = old_state; + /* catch-up with governor target speed */ + tegra_cpu_set_speed_cap(NULL); } - } + } else + pr_warn("%s: unable to set tegra hotplug state %s\n", + __func__, arg); + mutex_unlock(tegra3_cpu_lock); return ret; } @@ -293,7 +287,7 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work) void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend) { - unsigned long up_delay; + unsigned long up_delay, top_freq, bottom_freq; if (!is_g_cluster_present()) return; @@ -303,37 +297,45 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend) return; } - up_delay = is_lp_cluster() ? up2g0_delay : up2gn_delay; + if (is_lp_cluster()) { + up_delay = up2g0_delay; + top_freq = idle_top_freq; + bottom_freq = 0; + } else { + up_delay = up2gn_delay; + top_freq = idle_bottom_freq; + bottom_freq = idle_bottom_freq; + } switch (hp_state) { case TEGRA_HP_DISABLED: break; case TEGRA_HP_IDLE: - if (cpu_freq > idle_top_freq) { + if (cpu_freq > top_freq) { hp_state = TEGRA_HP_UP; queue_delayed_work( hotplug_wq, &hotplug_work, up_delay); - } else if (cpu_freq <= idle_bottom_freq) { + } else if (cpu_freq <= bottom_freq) { hp_state = TEGRA_HP_DOWN; queue_delayed_work( hotplug_wq, &hotplug_work, down_delay); } break; case TEGRA_HP_DOWN: - if (cpu_freq > idle_top_freq) { + if (cpu_freq > top_freq) { hp_state = TEGRA_HP_UP; queue_delayed_work( hotplug_wq, &hotplug_work, up_delay); - } else if (cpu_freq > idle_bottom_freq) { + } else if (cpu_freq > bottom_freq) { hp_state = TEGRA_HP_IDLE; } break; case TEGRA_HP_UP: - if (cpu_freq <= idle_bottom_freq) { + if (cpu_freq <= bottom_freq) { hp_state = TEGRA_HP_DOWN; queue_delayed_work( hotplug_wq, &hotplug_work, down_delay); - } else if (cpu_freq <= idle_top_freq) { + } else if (cpu_freq <= top_freq) { hp_state = TEGRA_HP_IDLE; } break; -- cgit v1.2.3