* Colin Cross <ccross@google.com>
* Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation
*
- * Copyright (C) 2010-2012 NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2010-2013 NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
ret = param_set_bool(arg, kp);
if ((ret == 0) && (old_policy != force_policy_max))
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
mutex_unlock(&tegra_cpu_lock);
return ret;
cpu_user_cap = freq_table[i].frequency;
}
#endif
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
}
void tegra_cpu_user_cap_set(unsigned int speed_khz)
return limit;
}
+/* Must be called while holding cpu_tegra_lock */
static void edp_update_limit(void)
{
unsigned int limit = edp_predict_limit(cpumask_weight(&edp_cpumask));
-
+ BUG_ON(!mutex_is_locked(&tegra_cpu_lock));
#ifdef CONFIG_TEGRA_EDP_EXACT_FREQ
edp_limit = limit;
#else
tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, true, 0);
if (target_cpu_speed[0]) {
edp_update_limit();
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
}
tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false, 0);
mutex_unlock(&tegra_cpu_lock);
or alarm is canceled */
if (target_cpu_speed[0]) {
edp_update_limit();
- ret = tegra_cpu_set_speed_cap(NULL);
+ ret = tegra_cpu_set_speed_cap_locked(NULL);
}
if (!ret || !alarm)
tegra_edp_throttle_cpu_now(0);
cpu_speed = tegra_getspeed(0);
new_speed = edp_governor_speed(cpu_speed);
if (new_speed < cpu_speed) {
- ret = tegra_cpu_set_speed_cap(NULL);
+ ret = tegra_cpu_set_speed_cap_locked(NULL);
printk(KERN_DEBUG "cpu-tegra:%sforce EDP limit %u kHz"
"\n", ret ? " failed to " : " ", new_speed);
}
tegra_cpu_dvfs_alter(
edp_thermal_index, &edp_cpumask, true, event);
edp_update_limit();
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
mutex_unlock(&tegra_cpu_lock);
break;
}
mutex_lock(&tegra_cpu_lock);
if (cap != volt_capped_speed) {
volt_capped_speed = cap;
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
}
mutex_unlock(&tegra_cpu_lock);
if (cap)
return requested_speed;
}
-int tegra_cpu_set_speed_cap(unsigned int *speed_cap)
+/* Must be called with tegra_cpu_lock held */
+int tegra_cpu_set_speed_cap_locked(unsigned int *speed_cap)
{
int ret = 0;
unsigned int new_speed = tegra_cpu_highest_speed();
-
+ BUG_ON(!mutex_is_locked(&tegra_cpu_lock));
#ifdef CONFIG_TEGRA_EDP_LIMITS
edp_update_limit();
#endif
return ret;
}
+int tegra_cpu_set_speed_cap(unsigned int *speed_cap)
+{
+ int ret;
+ mutex_lock(&tegra_cpu_lock);
+ ret = tegra_cpu_set_speed_cap_locked(speed_cap);
+ mutex_unlock(&tegra_cpu_lock);
+ return ret;
+}
+
+
int tegra_suspended_target(unsigned int target_freq)
{
unsigned int new_speed = target_freq;
freq = freq_table[idx].frequency;
target_cpu_speed[policy->cpu] = freq;
- ret = tegra_cpu_set_speed_cap(&new_speed);
+ ret = tegra_cpu_set_speed_cap_locked(&new_speed);
_out:
mutex_unlock(&tegra_cpu_lock);
unsigned int freq;
is_suspended = false;
tegra_cpu_edp_init(true);
- tegra_cpu_set_speed_cap(&freq);
+ tegra_cpu_set_speed_cap_locked(&freq);
pr_info("Tegra cpufreq resume: restoring frequency to %d kHz\n",
freq);
}
return ret;
freq_table = table_data->freq_table;
+ mutex_lock(&tegra_cpu_lock);
tegra_cpu_edp_init(false);
+ mutex_unlock(&tegra_cpu_lock);
ret = register_pm_notifier(&tegra_cpu_pm_notifier);
*
* CPU auto-hotplug for Tegra3 CPUs
*
- * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011-2013, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define UP2Gn_DELAY_MS 100
#define DOWN_DELAY_MS 2000
+/* tegra3_cpu_lock is tegra_cpu_lock from cpu-tegra.c */
static struct mutex *tegra3_cpu_lock;
static struct workqueue_struct *hotplug_wq;
hp_init_stats();
}
/* catch-up with governor target speed */
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
}
} else
pr_warn("%s: unable to set tegra hotplug state %s\n",
hp_stats_update(CONFIG_NR_CPUS, true);
hp_stats_update(0, false);
/* catch-up with governor target speed */
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
break;
}
}
hp_stats_update(CONFIG_NR_CPUS, false);
hp_stats_update(0, true);
/* catch-up with governor target speed */
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
}
} else {
switch (tegra_cpu_speed_balance()) {
}
}
/* update governor state machine */
- tegra_cpu_set_speed_cap(NULL);
+ tegra_cpu_set_speed_cap_locked(NULL);
mutex_unlock(tegra3_cpu_lock);
return NOTIFY_OK;
}