summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRebecca Schultz Zavin <rebecca@android.com>2010-12-21 11:51:15 -0800
committerRebecca Schultz Zavin <rebecca@android.com>2010-12-21 11:51:15 -0800
commit78cab34c4a199f61044c0ff71fe091289d96ff9a (patch)
treebda9eee4570904aa061680a176e88be9778fcad5
parent8ab30a059d66645d6ddf69f18a7342d761f3c0b9 (diff)
parente87ec4d59e1f96381547e614c5279bed63775719 (diff)
Merge remote branch 'tegra/linux-tegra-2.6.36' into android-tegra-2.6.36
-rw-r--r--arch/arm/mach-tegra/Kconfig7
-rw-r--r--arch/arm/mach-tegra/board-ventana-power.c84
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c263
-rw-r--r--drivers/mfd/tps6586x.c6
4 files changed, 141 insertions, 219 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index edaff55f1f01..e94c092b1560 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -103,3 +103,10 @@ config TEGRA_IOVMM
config TEGRA_ARB_SEMAPHORE
bool
+
+config TEGRA_THERMAL_THROTTLE
+ bool "Enable throttling of CPU speed on overtemp"
+ depends on CPU_FREQ
+ default y
+ help
+ Also requires enabling a temperature sensor such as NCT1008.
diff --git a/arch/arm/mach-tegra/board-ventana-power.c b/arch/arm/mach-tegra/board-ventana-power.c
index e2c6f3349206..fe1af074ab9e 100644
--- a/arch/arm/mach-tegra/board-ventana-power.c
+++ b/arch/arm/mach-tegra/board-ventana-power.c
@@ -34,88 +34,7 @@
#include "board.h"
#define PMC_CTRL 0x0
- #define PMC_CTRL_INTR_LOW (1 << 17)
-
-static int ac_ok = TEGRA_GPIO_PV3;
-static int charge_disable = TEGRA_GPIO_PR6;
-
-static int charge_init(struct device *dev)
-{
- int ret = gpio_request(charge_disable, "chg_disable");
- if (ret < 0)
- return ret;
-
- ret = gpio_request(ac_ok, "ac_ok");
- if (ret < 0) {
- gpio_free(charge_disable);
- return ret;
- }
-
- ret = gpio_direction_output(charge_disable, 0);
- if (ret < 0)
- goto cleanup;
-
- ret = gpio_direction_input(ac_ok);
- if (ret < 0)
- goto cleanup;
-
- tegra_gpio_enable(ac_ok);
- tegra_gpio_enable(charge_disable);
-
- return 0;
-
-cleanup:
- gpio_free(ac_ok);
- gpio_free(charge_disable);
- return ret;
-}
-
-static void charge_exit(struct device *dev)
-{
- gpio_free(charge_disable);
-}
-
-static int ac_online(void)
-{
- return !gpio_get_value(ac_ok);
-}
-
-static void set_charge(int flags)
-{
- if (flags == PDA_POWER_CHARGE_AC)
- gpio_set_value(charge_disable, 0);
- else if (!flags)
- gpio_set_value(charge_disable, 1);
- /* USB charging not supported on Ventana */
-}
-
-static struct resource ventana_pda_resources[] = {
- [0] = {
- .name = "ac",
- .start = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV3),
- .end = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV3),
- .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
- IORESOURCE_IRQ_LOWEDGE),
- },
-};
-
-static struct pda_power_pdata ventana_pda_data = {
- .is_ac_online = ac_online,
- .exit = charge_exit,
- .init = charge_init,
- .set_charge = set_charge,
-};
-
-static struct platform_device ventana_pda_power_device = {
- .name = "pda-power",
- .id = -1,
- .resource = ventana_pda_resources,
- .num_resources = ARRAY_SIZE(ventana_pda_resources),
- .dev = {
- .platform_data = &ventana_pda_data,
- },
-};
-
+#define PMC_CTRL_INTR_LOW (1 << 17)
static struct regulator_consumer_supply tps658621_sm0_supply[] = {
REGULATOR_SUPPLY("vdd_core", NULL),
@@ -264,7 +183,6 @@ int __init ventana_regulator_init(void)
* interrupts when low */
pmc_ctrl = readl(pmc + PMC_CTRL);
writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
- platform_device_register(&ventana_pda_power_device);
i2c_register_board_info(4, ventana_regulators, 1);
tegra_init_suspend(&ventana_suspend_data);
return 0;
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index d8c103e8964c..a878545d2740 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -50,27 +50,131 @@ static struct cpufreq_frequency_table freq_table[] = {
{ 8, CPUFREQ_TABLE_END },
};
-/* CPU frequency is gradually lowered when throttling is enabled */
-#define THROTTLE_START_INDEX 2
-#define THROTTLE_END_INDEX 6
-#define THROTTLE_DELAY msecs_to_jiffies(2000)
-#define NO_DELAY msecs_to_jiffies(0)
-
#define NUM_CPUS 2
static struct clk *cpu_clk;
static struct clk *emc_clk;
-static struct workqueue_struct *workqueue;
-
static unsigned long target_cpu_speed[NUM_CPUS];
static DEFINE_MUTEX(tegra_cpu_lock);
static bool is_suspended;
+unsigned int tegra_getspeed(unsigned int cpu);
+static int tegra_update_cpu_speed(unsigned long rate);
+
+/* CPU frequency is gradually lowered when throttling is enabled */
+#define THROTTLE_START_INDEX 2
+#define THROTTLE_END_INDEX 6
+
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+#define THROTTLE_DELAY msecs_to_jiffies(2000)
+#define NO_DELAY msecs_to_jiffies(0)
+
static DEFINE_MUTEX(throttling_lock);
static bool is_throttling;
static struct delayed_work throttle_work;
+static struct workqueue_struct *workqueue;
+
+#define tegra_cpu_is_throttling() (is_throttling)
+
+static bool tegra_throttling_needed(unsigned long *rate)
+{
+ unsigned int current_freq = tegra_getspeed(0);
+ int i;
+
+ for (i = THROTTLE_END_INDEX; i >= THROTTLE_START_INDEX; i--) {
+ if (freq_table[i].frequency < current_freq) {
+ *rate = freq_table[i].frequency;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void tegra_throttle_work_func(struct work_struct *work)
+{
+ unsigned long rate;
+
+ mutex_lock(&tegra_cpu_lock);
+
+ if (tegra_throttling_needed(&rate) && tegra_update_cpu_speed(rate) == 0) {
+ queue_delayed_work(workqueue, &throttle_work, THROTTLE_DELAY);
+ }
+
+ mutex_unlock(&tegra_cpu_lock);
+}
+
+/*
+ * tegra_throttling_enable
+ * This function may sleep
+ */
+void tegra_throttling_enable(bool enable)
+{
+ mutex_lock(&throttling_lock);
+
+ if (enable && !is_throttling) {
+ is_throttling = true;
+ queue_delayed_work(workqueue, &throttle_work, NO_DELAY);
+ } else if (!enable && is_throttling) {
+ cancel_delayed_work_sync(&throttle_work);
+ is_throttling = false;
+ }
+
+ mutex_unlock(&throttling_lock);
+}
+EXPORT_SYMBOL_GPL(tegra_throttling_enable);
+
+#ifdef CONFIG_DEBUG_FS
+static int throttle_debug_set(void *data, u64 val)
+{
+ tegra_throttling_enable(val);
+ return 0;
+}
+static int throttle_debug_get(void *data, u64 *val)
+{
+ *val = (u64) is_throttling;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(throttle_fops, throttle_debug_get, throttle_debug_set, "%llu\n");
+
+static struct dentry *cpu_tegra_debugfs_root;
+
+static int __init tegra_cpu_debug_init(void)
+{
+ cpu_tegra_debugfs_root = debugfs_create_dir("cpu-tegra", 0);
+
+ if (!cpu_tegra_debugfs_root)
+ return -ENOMEM;
+
+ if (!debugfs_create_file("throttle", 0644, cpu_tegra_debugfs_root, NULL, &throttle_fops))
+ goto err_out;
+
+ return 0;
+
+err_out:
+ debugfs_remove_recursive(cpu_tegra_debugfs_root);
+ return -ENOMEM;
+
+}
+
+static void __exit tegra_cpu_debug_exit(void)
+{
+ debugfs_remove_recursive(cpu_tegra_debugfs_root);
+}
+
+late_initcall(tegra_cpu_debug_init);
+module_exit(tegra_cpu_debug_exit);
+#endif /* CONFIG_DEBUG_FS */
+
+#else /* CONFIG_TEGRA_THERMAL_THROTTLE */
+#define tegra_cpu_is_throttling() (0)
+void tegra_throttling_enable(bool enable)
+{
+}
+#endif /* CONFIG_TEGRA_THERMAL_THROTTLE */
int tegra_verify_speed(struct cpufreq_policy *policy)
{
@@ -169,8 +273,7 @@ static int tegra_target(struct cpufreq_policy *policy,
{
int idx;
unsigned int freq;
- unsigned int highest_speed;
- unsigned int limit_when_throttling;
+ unsigned int new_speed;
int ret = 0;
mutex_lock(&tegra_cpu_lock);
@@ -187,136 +290,30 @@ static int tegra_target(struct cpufreq_policy *policy,
target_cpu_speed[policy->cpu] = freq;
- highest_speed = tegra_cpu_highest_speed();
+ new_speed = tegra_cpu_highest_speed();
/* Do not go above this frequency when throttling */
- limit_when_throttling = freq_table[THROTTLE_START_INDEX].frequency;
-
- if (is_throttling && highest_speed > limit_when_throttling) {
- if (tegra_getspeed(0) < limit_when_throttling) {
- ret = tegra_update_cpu_speed(limit_when_throttling);
- goto out;
- } else {
- ret = -EBUSY;
- goto out;
+
+ if (tegra_cpu_is_throttling()) {
+ unsigned int throttle_limit =
+ freq_table[THROTTLE_START_INDEX].frequency;
+
+ if (new_speed > throttle_limit) {
+ if (tegra_getspeed(0) < throttle_limit) {
+ new_speed = throttle_limit;
+ } else {
+ ret = -EBUSY;
+ goto out;
+ }
}
}
- ret = tegra_update_cpu_speed(highest_speed);
+ ret = tegra_update_cpu_speed(new_speed);
out:
mutex_unlock(&tegra_cpu_lock);
return ret;
}
-static bool tegra_throttling_needed(unsigned long *rate)
-{
- unsigned int current_freq = tegra_getspeed(0);
- int i;
-
- for (i = THROTTLE_END_INDEX; i >= THROTTLE_START_INDEX; i--) {
- if (freq_table[i].frequency < current_freq) {
- *rate = freq_table[i].frequency;
- return true;
- }
- }
-
- return false;
-}
-
-static void tegra_throttle_work_func(struct work_struct *work)
-{
- unsigned long rate;
-
- mutex_lock(&tegra_cpu_lock);
-
- if (tegra_throttling_needed(&rate) && tegra_update_cpu_speed(rate) == 0) {
- queue_delayed_work(workqueue, &throttle_work, THROTTLE_DELAY);
- }
-
- mutex_unlock(&tegra_cpu_lock);
-}
-
-/**
- * tegra_throttling_enable
- * This functions may sleep
- */
-void tegra_throttling_enable(void)
-{
- mutex_lock(&throttling_lock);
-
- if (!is_throttling) {
- is_throttling = true;
- queue_delayed_work(workqueue, &throttle_work, NO_DELAY);
- }
-
- mutex_unlock(&throttling_lock);
-}
-EXPORT_SYMBOL_GPL(tegra_throttling_enable);
-
-/**
- * tegra_throttling_disable
- * This functions may sleep
- */
-void tegra_throttling_disable(void)
-{
- mutex_lock(&throttling_lock);
-
- if (is_throttling) {
- cancel_delayed_work_sync(&throttle_work);
- is_throttling = false;
- }
-
- mutex_unlock(&throttling_lock);
-}
-EXPORT_SYMBOL_GPL(tegra_throttling_disable);
-
-#ifdef CONFIG_DEBUG_FS
-static int throttle_debug_set(void *data, u64 val)
-{
- if (val) {
- tegra_throttling_enable();
- } else {
- tegra_throttling_disable();
- }
-
- return 0;
-}
-static int throttle_debug_get(void *data, u64 *val)
-{
- *val = (u64) is_throttling;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(throttle_fops, throttle_debug_get, throttle_debug_set, "%llu\n");
-
-static struct dentry *cpu_tegra_debugfs_root;
-
-static int __init tegra_cpu_debug_init(void)
-{
- cpu_tegra_debugfs_root = debugfs_create_dir("cpu-tegra", 0);
-
- if (!cpu_tegra_debugfs_root)
- return -ENOMEM;
-
- if (!debugfs_create_file("throttle", 0644, cpu_tegra_debugfs_root, NULL, &throttle_fops))
- goto err_out;
-
- return 0;
-
-err_out:
- debugfs_remove_recursive(cpu_tegra_debugfs_root);
- return -ENOMEM;
-
-}
-
-static void __exit tegra_cpu_debug_exit(void)
-{
- debugfs_remove_recursive(cpu_tegra_debugfs_root);
-}
-
-late_initcall(tegra_cpu_debug_init);
-module_exit(tegra_cpu_debug_exit);
-#endif
static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
void *dummy)
@@ -367,7 +364,6 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
cpumask_copy(policy->related_cpus, cpu_possible_mask);
if (policy->cpu == 0) {
- INIT_DELAYED_WORK(&throttle_work, tegra_throttle_work_func);
register_pm_notifier(&tegra_cpu_pm_notifier);
}
@@ -400,15 +396,20 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
static int __init tegra_cpufreq_init(void)
{
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
workqueue = create_singlethread_workqueue("cpu-tegra");
if (!workqueue)
return -ENOMEM;
+ INIT_DELAYED_WORK(&throttle_work, tegra_throttle_work_func);
+#endif
return cpufreq_register_driver(&tegra_cpufreq_driver);
}
static void __exit tegra_cpufreq_exit(void)
{
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
destroy_workqueue(workqueue);
+#endif
cpufreq_unregister_driver(&tegra_cpufreq_driver);
}
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 626081c5c281..ab667f296897 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -46,7 +46,6 @@
/* device id */
#define TPS6586X_VERSIONCRC 0xcd
-#define TPS658621A_VERSIONCRC 0x15
struct tps6586x_irq_data {
u8 mask_reg;
@@ -491,10 +490,7 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
return -EIO;
}
- if (ret != TPS658621A_VERSIONCRC) {
- dev_err(&client->dev, "Unsupported chip ID: %x\n", ret);
- return -ENODEV;
- }
+ dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
if (tps6586x == NULL)