From 4e6feb548e091f6830c6509db33ff6a670ec24e7 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 1 Dec 2010 15:45:30 -0800 Subject: [PATCH] ARM: tegra: dvfs: Allow boot or run time disabling of dvfs rails Change-Id: Ie56cbf4ade1bbdb5835851f3c09668c1e0941a2c Signed-off-by: Colin Cross --- arch/arm/mach-tegra/board.h | 1 + arch/arm/mach-tegra/dvfs.c | 58 +++++++++++++++++++++++ arch/arm/mach-tegra/dvfs.h | 2 + arch/arm/mach-tegra/tegra2_dvfs.c | 76 ++++++++++++++++++++++++++++--- 4 files changed, 131 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index c47a21f71260..04f1538b1a37 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -32,6 +32,7 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size, void __init tegra_protected_aperture_init(unsigned long aperture); void tegra_move_framebuffer(unsigned long to, unsigned long from, unsigned long size); +int tegra_dvfs_rail_disable_by_name(const char *reg_id); extern unsigned long tegra_bootloader_fb_start; extern unsigned long tegra_bootloader_fb_size; diff --git a/arch/arm/mach-tegra/dvfs.c b/arch/arm/mach-tegra/dvfs.c index ff48ea0c64f0..bc1e1a391b5a 100644 --- a/arch/arm/mach-tegra/dvfs.c +++ b/arch/arm/mach-tegra/dvfs.c @@ -395,6 +395,64 @@ static struct notifier_block tegra_dvfs_nb = { .notifier_call = tegra_dvfs_pm_notify, }; +/* must be called with dvfs lock held */ +static void __tegra_dvfs_rail_disable(struct dvfs_rail *rail) +{ + int ret; + + if (!rail->disabled) { + ret = dvfs_rail_set_voltage(rail, rail->nominal_millivolts); + if (ret) + pr_info("dvfs: failed to set regulator %s to disable " + "voltage %d\n", rail->reg_id, + rail->nominal_millivolts); + rail->disabled = true; + } +} + +/* must be called with dvfs lock held */ +static void __tegra_dvfs_rail_enable(struct dvfs_rail *rail) +{ + if (rail->disabled) { + rail->disabled = false; + dvfs_rail_update(rail); + } +} + +void tegra_dvfs_rail_enable(struct dvfs_rail *rail) +{ + mutex_lock(&dvfs_lock); + __tegra_dvfs_rail_enable(rail); + mutex_unlock(&dvfs_lock); +} + +void tegra_dvfs_rail_disable(struct dvfs_rail *rail) +{ + mutex_lock(&dvfs_lock); + __tegra_dvfs_rail_disable(rail); + mutex_unlock(&dvfs_lock); +} + +int tegra_dvfs_rail_disable_by_name(const char *reg_id) +{ + struct dvfs_rail *rail; + int ret = 0; + + mutex_lock(&dvfs_lock); + list_for_each_entry(rail, &dvfs_rail_list, node) { + if (!strcmp(reg_id, rail->reg_id)) { + __tegra_dvfs_rail_disable(rail); + goto out; + } + } + + ret = -EINVAL; + +out: + mutex_unlock(&dvfs_lock); + return ret; +} + /* * Iterate through all the dvfs regulators, finding the regulator exported * by the regulator api for each one. Must be called in late init, after diff --git a/arch/arm/mach-tegra/dvfs.h b/arch/arm/mach-tegra/dvfs.h index 85764580c39d..68622b899c59 100644 --- a/arch/arm/mach-tegra/dvfs.h +++ b/arch/arm/mach-tegra/dvfs.h @@ -87,5 +87,7 @@ int dvfs_debugfs_init(struct dentry *clk_debugfs_root); int tegra_dvfs_late_init(void); int tegra_dvfs_init_rails(struct dvfs_rail *dvfs_rails[], int n); void tegra_dvfs_add_relationships(struct dvfs_relationship *rels, int n); +void tegra_dvfs_rail_enable(struct dvfs_rail *rail); +void tegra_dvfs_rail_disable(struct dvfs_rail *rail); #endif diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c index 1734e5ee700b..1bc1c4dce0d2 100644 --- a/arch/arm/mach-tegra/tegra2_dvfs.c +++ b/arch/arm/mach-tegra/tegra2_dvfs.c @@ -20,11 +20,23 @@ #include #include #include +#include #include "clock.h" #include "dvfs.h" #include "fuse.h" +#ifdef CONFIG_TEGRA_CORE_DVFS +static bool tegra_dvfs_core_disabled; +#else +static bool tegra_dvfs_core_disabled = true; +#endif +#ifdef CONFIG_TEGRA_CPU_DVFS +static bool tegra_dvfs_cpu_disabled; +#else +static bool tegra_dvfs_cpu_disabled = true; +#endif + static const int core_millivolts[MAX_DVFS_FREQS] = {950, 1000, 1100, 1200, 1275}; static const int cpu_millivolts[MAX_DVFS_FREQS] = @@ -38,9 +50,6 @@ static struct dvfs_rail tegra2_dvfs_rail_vdd_cpu = { .max_millivolts = 1100, .min_millivolts = 750, .nominal_millivolts = 1100, -#ifndef CONFIG_TEGRA_CPU_DVFS - .disabled = true, -#endif }; static struct dvfs_rail tegra2_dvfs_rail_vdd_core = { @@ -49,9 +58,6 @@ static struct dvfs_rail tegra2_dvfs_rail_vdd_core = { .min_millivolts = 950, .nominal_millivolts = 1200, .step = 150, /* step vdd_core by 150 mV to allow vdd_aon to follow */ -#ifndef CONFIG_TEGRA_CORE_DVFS - .disabled = true, -#endif }; static struct dvfs_rail tegra2_dvfs_rail_vdd_aon = { @@ -195,6 +201,58 @@ static struct dvfs dvfs_init[] = { CORE_DVFS("NVRM_DEVID_CLK_SRC", 1, MHZ, 480, 600, 800, 1067, 1067), }; +int tegra_dvfs_disable_core_set(const char *arg, const struct kernel_param *kp) +{ + int ret; + + ret = param_set_bool(arg, kp); + if (ret) + return ret; + + if (tegra_dvfs_core_disabled) + tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core); + else + tegra_dvfs_rail_enable(&tegra2_dvfs_rail_vdd_core); + + return 0; +} + +int tegra_dvfs_disable_cpu_set(const char *arg, const struct kernel_param *kp) +{ + int ret; + + ret = param_set_bool(arg, kp); + if (ret) + return ret; + + if (tegra_dvfs_cpu_disabled) + tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu); + else + tegra_dvfs_rail_enable(&tegra2_dvfs_rail_vdd_cpu); + + return 0; +} + +int tegra_dvfs_disable_get(char *buffer, const struct kernel_param *kp) +{ + return param_get_bool(buffer, kp); +} + +static struct kernel_param_ops tegra_dvfs_disable_core_ops = { + .set = tegra_dvfs_disable_core_set, + .get = tegra_dvfs_disable_get, +}; + +static struct kernel_param_ops tegra_dvfs_disable_cpu_ops = { + .set = tegra_dvfs_disable_cpu_set, + .get = tegra_dvfs_disable_get, +}; + +module_param_cb(disable_core, &tegra_dvfs_disable_core_ops, + &tegra_dvfs_core_disabled, 0644); +module_param_cb(disable_cpu, &tegra_dvfs_disable_cpu_ops, + &tegra_dvfs_cpu_disabled, 0644); + void __init tegra2_init_dvfs(void) { int i; @@ -230,4 +288,10 @@ void __init tegra2_init_dvfs(void) pr_err("tegra_dvfs: failed to enable dvfs on %s\n", c->name); } + + if (tegra_dvfs_core_disabled) + tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core); + + if (tegra_dvfs_cpu_disabled) + tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu); } -- 2.34.1