ARM: tegra: dvfs: Update CPU thermal control in dfll mode
Alex Frid [Sun, 17 Feb 2013 06:22:34 +0000 (22:22 -0800)]
During CPU cluster switch set CPU rail cold temperature limit in dfll
mode before switching to G CPU. Thus, the limit may be set only if
temperature is already low (before this commit the limit was set when
switching to LP CPU, and as such must be set unconditionally for the
worst case of cold temperature).

Made sure dfll and pll mode cooling devices have the same trip-points,
and dfll cooling device is enabled only when cold temperature voltage
limit is below DFLL minimum voltage.

Change-Id: Ia26b6caf3fbbd56f723661513474babad64b5d97
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/201831
(cherry picked from commit 92de167904c19a9c353de0ed22a3422549effae8)
Reviewed-on: http://git-master/r/208920
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

arch/arm/mach-tegra/dvfs.c
arch/arm/mach-tegra/tegra11_clocks.c
arch/arm/mach-tegra/tegra11_dvfs.c

index e7ece7b..3274b2b 100644 (file)
@@ -65,6 +65,23 @@ void tegra_dvfs_add_relationships(struct dvfs_relationship *rels, int n)
        mutex_unlock(&dvfs_lock);
 }
 
+/*
+ * Make sure that DFLL and PLL mode cooling devices have identical set of
+ * trip-points (needed for DFLL/PLL auto-switch)
+ */
+static void dvfs_validate_cdevs(struct dvfs_rail *rail)
+{
+       if (rail->dfll_mode_cdev) {
+               if (!rail->pll_mode_cdev ||
+                   (rail->dfll_mode_cdev->trip_temperatures !=
+                    rail->pll_mode_cdev->trip_temperatures)) {
+                       rail->dfll_mode_cdev = NULL;
+                       WARN(1, "%s: not matching dfll/pll mode trip-points\n",
+                            rail->reg_id);
+               }
+       }
+}
+
 int tegra_dvfs_init_rails(struct dvfs_rail *rails[], int n)
 {
        int i;
@@ -82,6 +99,8 @@ int tegra_dvfs_init_rails(struct dvfs_rail *rails[], int n)
 
                list_add_tail(&rails[i]->node, &dvfs_rail_list);
 
+               dvfs_validate_cdevs(rails[i]);
+
                if (!strcmp("vdd_cpu", rails[i]->reg_id))
                        tegra_cpu_rail = rails[i];
                else if (!strcmp("vdd_core", rails[i]->reg_id))
@@ -921,11 +940,17 @@ int tegra_dvfs_rail_dfll_mode_set_cold(struct dvfs_rail *rail)
        int ret = 0;
 
 #ifdef CONFIG_THERMAL
-       if (!rail || !rail->dfll_mode_cdev || !rail->min_millivolts_cold)
+       /* No cooling in dfll mode - nothing to do */
+       if (!rail || !rail->dfll_mode_cdev)
                return ret;
 
+       /*
+        * Since cooling thresholds are the same in pll and dfll modes, pll mode
+        * thermal index can be used to decide if cold limit should be set in
+        * dfll mode.
+        */
        mutex_lock(&dvfs_lock);
-       if (rail->dfll_mode)
+       if (rail->dfll_mode && !rail->thermal_idx)
                ret = dvfs_rail_set_voltage_reg(
                        rail, rail->min_millivolts_cold);
        mutex_unlock(&dvfs_lock);
index b500f88..8e33a4a 100644 (file)
@@ -1430,10 +1430,6 @@ static int tegra11_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
                if (ret)
                        goto abort;
 
-               ret = tegra_dvfs_rail_dfll_mode_set_cold(tegra_cpu_rail);
-               if (ret)
-                       goto abort;
-
                p_source = rate <= p->u.cpu.backup_rate ?
                        p->u.cpu.backup : p->u.cpu.main;
                ret = clk_set_rate(p_source, rate);
@@ -1451,6 +1447,11 @@ static int tegra11_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
                        max(rate, p->dvfs->dfll_data.use_dfll_rate_min));
                if (ret)
                        goto abort;
+
+               ret = tegra_dvfs_rail_dfll_mode_set_cold(tegra_cpu_rail);
+               if (ret)
+                       goto abort;
+
        } else
                /* DFLL is not selected on either side of the switch:
                 * set target p_source equal to current clock source
index 0e5f358..c851468 100644 (file)
@@ -623,6 +623,10 @@ static int __init set_cpu_dvfs_data(
        cpu_dvfs->dfll_data.out_rate_min = fmax_at_vmin * d->freqs_mult;
        cpu_dvfs->dfll_data.use_dfll_rate_min = fmin_use_dfll * d->freqs_mult;
        cpu_dvfs->dfll_data.min_millivolts = min_dfll_mv;
+
+       /* Invalidate dfll cooling if cold minimum is below dfll minimum */
+       if (cpu_dvfs->dvfs_rail->min_millivolts_cold <= min_dfll_mv)
+               cpu_dvfs->dvfs_rail->dfll_mode_cdev = NULL;
        return 0;
 }