summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2012-05-29 13:16:05 -0700
committerSimone Willett <swillett@nvidia.com>2012-06-07 13:06:54 -0700
commit009db50dd4fd10c47d7b0ceb738bafa32b41f041 (patch)
tree8f265b881e43d2cdca73f6b15e982926f1317524 /arch
parentd47cd91dfd01671681caa2ad1b8afc761e78d927 (diff)
ARM: tegra: dvfs: Separate Tegra3 single core dvfs table
On Tegra3 added mechanism to alter dvfs table between single and multiple CPU cores. This mechanism is dormant since no single-core table is available yet. Change-Id: I63bd513bd5fd7347f64c88f46974cf7fac55c419 Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/105508 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra3_dvfs.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c
index e71e52dea1f7..e34eb946e4f1 100644
--- a/arch/arm/mach-tegra/tegra3_dvfs.c
+++ b/arch/arm/mach-tegra/tegra3_dvfs.c
@@ -202,6 +202,10 @@ static struct dvfs cpu_dvfs_table[] = {
CPU_DVFS("cpu_g", -1, -1, MHZ, 1, 1, 216, 216, 300),
};
+static struct dvfs cpu_0_dvfs_table[] = {
+ /* Cpu voltages (mV): 800, 825, 850, 875, 900, 916, 950, 975, 1000, 1007, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237 */
+};
+
#define CORE_DVFS(_clk_name, _speedo_id, _auto, _mult, _freqs...) \
{ \
.clk_name = _clk_name, \
@@ -355,6 +359,9 @@ static struct dvfs core_dvfs_table[] = {
/* CPU alternative DVFS table for cold zone */
static unsigned long cpu_cold_freqs[MAX_DVFS_FREQS];
+/* CPU alternative DVFS table for single G CPU core 0 */
+static unsigned long *cpu_0_freqs;
+
int tegra_dvfs_disable_core_set(const char *arg, const struct kernel_param *kp)
{
int ret;
@@ -501,6 +508,35 @@ static bool __init match_dvfs_one(struct dvfs *d, int speedo_id, int process_id)
return true;
}
+static void __init init_cpu_0_dvfs(struct dvfs *cpud)
+{
+ int i;
+ struct dvfs *d = NULL;
+
+ /* Init single G CPU core 0 dvfs if this particular SKU/bin has it.
+ Max rates in multi-core and single-core tables must be the same */
+ for (i = 0; i < ARRAY_SIZE(cpu_0_dvfs_table); i++) {
+ if (match_dvfs_one(&cpu_0_dvfs_table[i],
+ cpud->speedo_id, cpud->process_id)) {
+ d = &cpu_0_dvfs_table[i];
+ break;
+ }
+ }
+
+ if (d) {
+ for (i = 0; i < cpud->num_freqs; i++) {
+ d->freqs[i] *= d->freqs_mult;
+ if (d->freqs[i] == 0) {
+ BUG_ON(i == 0);
+ d->freqs[i] = d->freqs[i - 1];
+ }
+ }
+ BUG_ON(cpud->freqs[cpud->num_freqs - 1] !=
+ d->freqs[cpud->num_freqs - 1]);
+ cpu_0_freqs = d->freqs;
+ }
+}
+
static int __init get_cpu_nominal_mv_index(
int speedo_id, int process_id, struct dvfs **cpu_dvfs)
{
@@ -647,7 +683,10 @@ void __init tegra_soc_init_dvfs(void)
/* Initialize matching cpu dvfs entry already found when nominal
voltage was determined */
init_dvfs_one(cpu_dvfs, cpu_nominal_mv_index);
+
+ /* Initialize alternative cold zone and single core tables */
init_dvfs_cold(cpu_dvfs, cpu_nominal_mv_index);
+ init_cpu_0_dvfs(cpu_dvfs);
/* Finally disable dvfs on rails if necessary */
if (tegra_dvfs_core_disabled)
@@ -667,12 +706,14 @@ void tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus,
bool before_clk_update)
{
bool cpu_warm = !!edp_thermal_index;
- unsigned long *alt_freqs = cpu_warm ? NULL : cpu_cold_freqs;
+ unsigned int n = cpumask_weight(cpus);
+ unsigned long *alt_freqs = cpu_warm ?
+ (n > 1 ? NULL : cpu_0_freqs) : cpu_cold_freqs;
if (cpu_warm == before_clk_update) {
int ret = tegra_dvfs_alt_freqs_set(cpu_dvfs, alt_freqs);
- WARN_ONCE(ret, "tegra dvfs: failed to set CPU alternative"
- " frequency limits for cold temeperature\n");
+ WARN_ONCE(ret, "tegra dvfs: failed to update CPU alternative"
+ " frequency limits\n");
}
}