summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorDiwakar Tundlam <dtundlam@nvidia.com>2011-03-15 16:16:58 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-04-26 15:54:00 -0700
commitfb400c2353324bf98ec9e0316a5b8ba2e6a7cc68 (patch)
tree190f4bf2bed28dbfe0b27ad932e6a5264295b761 /arch/arm
parent67468efdb200fccd7419c82388a429923b064f3f (diff)
ARM: tegra: power: add cpu-dvs table for tegra3
Original-Change-Id: I3eac69eec691e4e75d698011461e578324fb4c1d Reviewed-on: http://git-master/r/23094 Tested-by: Diwakar Tundlam <dtundlam@nvidia.com> Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Change-Id: I9553f03a1947015c7a19c13eb2881835e04a5614
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/tegra3_dvfs.c114
1 files changed, 110 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c
index eecbad15e4e7..994d45715de2 100644
--- a/arch/arm/mach-tegra/tegra3_dvfs.c
+++ b/arch/arm/mach-tegra/tegra3_dvfs.c
@@ -1,10 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_dvfs.c
*
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@google.com>
+ * Copyright (C) 2010-2011 NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -20,11 +17,120 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/module.h>
#include "clock.h"
#include "dvfs.h"
#include "fuse.h"
+static bool tegra_dvfs_cpu_disabled = false;
+
+static const int cpu_millivolts[MAX_DVFS_FREQS] =
+ {750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1100, 1125};
+
+#define KHZ 1000
+#define MHZ 1000000
+
+static struct dvfs_rail tegra3_dvfs_rail_vdd_cpu = {
+ .reg_id = "vdd_cpu",
+ .max_millivolts = 1000,
+ .min_millivolts = 800,
+ .nominal_millivolts = 1000,
+};
+
+static struct dvfs_rail *tegra3_dvfs_rails[] = {
+ &tegra3_dvfs_rail_vdd_cpu,
+};
+
+#define CPU_DVFS(_clk_name, _speedo_id, _process_id, _mult, _freqs...) \
+ { \
+ .clk_name = _clk_name, \
+ .speedo_id = _speedo_id, \
+ .process_id = _process_id, \
+ .freqs = {_freqs}, \
+ .freqs_mult = _mult, \
+ .millivolts = cpu_millivolts, \
+ .auto_dvfs = true, \
+ .dvfs_rail = &tegra3_dvfs_rail_vdd_cpu, \
+ }
+
+static struct dvfs dvfs_init[] = {
+ /* Cpu voltages (mV): 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1100, 1125 */
+ CPU_DVFS("cpu", 0, 0, MHZ, 0, 0, 614, 614, 714, 714, 815, 815, 915, 915, 1000),
+};
+
+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(&tegra3_dvfs_rail_vdd_cpu);
+ else
+ tegra_dvfs_rail_enable(&tegra3_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_cpu_ops = {
+ .set = tegra_dvfs_disable_cpu_set,
+ .get = tegra_dvfs_disable_get,
+};
+
+module_param_cb(disable_cpu, &tegra_dvfs_disable_cpu_ops, &tegra_dvfs_cpu_disabled, 0644);
+
void __init tegra_soc_init_dvfs(void)
{
+ int i;
+ struct clk *c;
+ struct dvfs *d;
+ int process_id;
+ int cpu_process_id = 0;
+ int speedo_id = 0;
+ int ret;
+
+#ifndef CONFIG_TEGRA_CPU_DVFS
+ tegra_dvfs_cpu_disabled = true;
+#endif
+
+ tegra_dvfs_init_rails(tegra3_dvfs_rails, ARRAY_SIZE(tegra3_dvfs_rails));
+
+ /* FIXME: add [CPU/CORE/AON] relationships here */
+
+ for (i = 0; i < ARRAY_SIZE(dvfs_init); i++) {
+ d = &dvfs_init[i];
+
+ process_id = cpu_process_id;
+ if ((d->process_id != -1 && d->process_id != process_id) ||
+ (d->speedo_id != -1 && d->speedo_id != speedo_id)) {
+ pr_debug("tegra3_dvfs: rejected %s speedo %d,"
+ " process %d\n", d->clk_name, d->speedo_id,
+ d->process_id);
+ continue;
+ }
+
+ c = tegra_get_clock_by_name(d->clk_name);
+
+ if (!c) {
+ pr_debug("tegra3_dvfs: no clock found for %s\n",
+ d->clk_name);
+ continue;
+ }
+
+ ret = tegra_enable_dvfs_on_clk(c, d);
+ if (ret)
+ pr_err("tegra3_dvfs: failed to enable dvfs on %s\n",
+ c->name);
+ }
+
+ if (tegra_dvfs_cpu_disabled)
+ tegra_dvfs_rail_disable(&tegra3_dvfs_rail_vdd_cpu);
}