arm: t12: clock: Change use_dfll behaviour
sreenivasulu velpula [Fri, 18 Jul 2014 09:33:40 +0000 (14:33 +0530)]
- If CONFIG_TEGRA_USE_DFLL_RANGE is set to '3'

  then do not allow use_dfll sysfs to control
  dfll range.

  AND

  during kernel init also, by default dfll
  range becomes 0.

Bug 1563635

Change-Id: I886a6ca365a1ee0fd7619312eca1ccd17d73222b
Signed-off-by: sreenivasulu velpula <svelpula@nvidia.com>
Reviewed-on: http://git-master/r/439769
(cherry picked from commit ce3cd984f88d19f5d929c0acbe509486fddcb8bc)
Reviewed-on: http://git-master/r/559391
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>

arch/arm/mach-tegra/dvfs.h
arch/arm/mach-tegra/tegra12_clocks.c

index 16d705f..c891786 100644 (file)
@@ -124,12 +124,23 @@ struct dvfs_rail {
        const char *version;
 };
 
+/*
+ * dfll_range -
+ *     DFLL_RANGE_NONE       : DFLL is not used
+ *     DFLL_RANGE_ALL_RATES  : DFLL is is used for all CPU rates
+ *     DFLL_RANGE_HIGH_RATES : DFLL is used only for high rates
+ *                             above crossover with PLL dvfs curve
+ */
 enum dfll_range {
        DFLL_RANGE_NONE = 0,
        DFLL_RANGE_ALL_RATES,
        DFLL_RANGE_HIGH_RATES,
 };
 
+/* DFLL usage is under thermal cooling device control */
+#define TEGRA_USE_DFLL_CDEV_CNTRL 3
+
+/* DVFS settings specific for DFLL clock source */
 struct dvfs_dfll_data {
        u32             tune0;
        u32             tune0_high_mv;
@@ -279,6 +290,7 @@ int tegra_dvfs_replace_voltage_table(struct dvfs *d, const int *new_millivolts);
 
 int tegra_dvfs_dfll_mode_set(struct dvfs *d, unsigned long rate);
 int tegra_dvfs_dfll_mode_clear(struct dvfs *d, unsigned long rate);
+int tegra_clk_dfll_range_control(enum dfll_range use_dfll);
 
 struct tegra_cooling_device *tegra_dvfs_get_cpu_vmax_cdev(void);
 struct tegra_cooling_device *tegra_dvfs_get_cpu_vmin_cdev(void);
index 7a8d2be..647b07f 100644 (file)
@@ -4358,56 +4358,19 @@ static struct clk_ops tegra_dfll_ops = {
 static int tegra12_use_dfll_cb(const char *arg, const struct kernel_param *kp)
 {
        int ret = 0;
-       unsigned long c_flags, p_flags;
        unsigned int old_use_dfll;
-       struct clk *c = tegra_get_clock_by_name("cpu");
-       struct clk *dfll = tegra_get_clock_by_name("dfll_cpu");
-
-       if (!c->parent || !c->parent->dvfs || !dfll)
-               return -ENOSYS;
-
-       ret = tegra_cpu_reg_mode_force_normal(true);
-       if (ret) {
-               pr_err("%s: Failed to force regulator normal mode\n", __func__);
-               return ret;
-       }
-
-       clk_lock_save(c, &c_flags);
-       if (dfll->state == UNINITIALIZED) {
-               pr_err("%s: DFLL is not initialized\n", __func__);
-               clk_unlock_restore(c, &c_flags);
-               tegra_cpu_reg_mode_force_normal(false);
-               return -ENOSYS;
-       }
-       if (c->parent->u.cpu.mode == MODE_LP) {
-               pr_err("%s: DFLL is not used on LP CPU\n", __func__);
-               clk_unlock_restore(c, &c_flags);
-               tegra_cpu_reg_mode_force_normal(false);
-               return -ENOSYS;
-       }
-
-       clk_lock_save(c->parent, &p_flags);
-       old_use_dfll = use_dfll;
-       param_set_int(arg, kp);
-
-       if (use_dfll != old_use_dfll) {
-               ret = tegra_dvfs_set_dfll_range(c->parent->dvfs, use_dfll);
-               if (ret) {
+       if (CONFIG_TEGRA_USE_DFLL_RANGE != TEGRA_USE_DFLL_CDEV_CNTRL) {
+               old_use_dfll = use_dfll;
+               param_set_int(arg, kp);
+               ret =  tegra_clk_dfll_range_control(use_dfll);
+               if (ret)
                        use_dfll = old_use_dfll;
-               } else {
-                       ret = clk_set_rate_locked(c->parent,
-                               clk_get_rate_locked(c->parent));
-                       if (ret) {
-                               use_dfll = old_use_dfll;
-                               tegra_dvfs_set_dfll_range(
-                                       c->parent->dvfs, use_dfll);
-                       }
-               }
+               return ret;
+       } else {
+               pr_warn("\n%s: Failed to set use_dfll\n", __func__);
+               pr_warn("DFLL usage is under thermal cooling device control\n");
+               return -EACCES;
        }
-       clk_unlock_restore(c->parent, &p_flags);
-       clk_unlock_restore(c, &c_flags);
-       tegra_update_cpu_edp_limits();
-       return ret;
 }
 
 static struct kernel_param_ops tegra12_use_dfll_ops = {
@@ -8926,7 +8889,9 @@ static void __init tegra12_dfll_cpu_late_init(struct clk *c)
        if (!ret) {
                c->state = OFF;
                if (tegra_platform_is_silicon()) {
-                       use_dfll = CONFIG_TEGRA_USE_DFLL_RANGE;
+                       if (CONFIG_TEGRA_USE_DFLL_RANGE !=
+                                       TEGRA_USE_DFLL_CDEV_CNTRL)
+                               use_dfll = CONFIG_TEGRA_USE_DFLL_RANGE;
 #ifdef CONFIG_ARCH_TEGRA_13x_SOC
                        if (tegra_cpu_speedo_id() == 0)
                                use_dfll = 0;