diff options
author | Rebecca Schultz Zavin <rebecca@android.com> | 2010-12-21 11:51:15 -0800 |
---|---|---|
committer | Rebecca Schultz Zavin <rebecca@android.com> | 2010-12-21 11:51:15 -0800 |
commit | 78cab34c4a199f61044c0ff71fe091289d96ff9a (patch) | |
tree | bda9eee4570904aa061680a176e88be9778fcad5 | |
parent | 8ab30a059d66645d6ddf69f18a7342d761f3c0b9 (diff) | |
parent | e87ec4d59e1f96381547e614c5279bed63775719 (diff) |
Merge remote branch 'tegra/linux-tegra-2.6.36' into android-tegra-2.6.36
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana-power.c | 84 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu-tegra.c | 263 | ||||
-rw-r--r-- | drivers/mfd/tps6586x.c | 6 |
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) |