ARM: tegra: dvfs: Add targeted predict millivolts APIs
Alex Frid [Sun, 4 Nov 2012 02:20:47 +0000 (19:20 -0700)]
Implemented voltage prediction APIs that return expected voltage
for clock domain if pll or dfll clock source is used, regardless
of the actual source selection (in addition to existing API that
predicts voltage for current clock source selection). Made sure
dfll mode can not be enabled for clock domains that do not have
dfll support.

Change-Id: I6bb0b7ab5fa60bc6633ebb207f3fc6e52844f770
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/161078
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Tested-by: Diwakar Tundlam <dtundlam@nvidia.com>

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

index 92f923f..7702dfe 100644 (file)
@@ -431,18 +431,13 @@ int tegra_dvfs_alt_freqs_set(struct dvfs *d, unsigned long *alt_freqs)
        return ret;
 }
 
-int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
+static int predict_millivolts(struct clk *c, const int *millivolts,
+                             unsigned long rate)
 {
        int i;
-       const int *millivolts;
-
-       if (!rate || !c->dvfs)
-               return 0;
 
-       millivolts = dvfs_get_millivolts(c->dvfs, rate);
        if (!millivolts)
                return -ENODEV;
-
        /*
         * Predicted voltage can not be used across the switch to alternative
         * frequency limits. For now, just fail the call for clock that has
@@ -462,6 +457,39 @@ int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
        return millivolts[i];
 }
 
+int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
+{
+       const int *millivolts;
+
+       if (!rate || !c->dvfs)
+               return 0;
+
+       millivolts = dvfs_get_millivolts(c->dvfs, rate);
+       return predict_millivolts(c, millivolts, rate);
+}
+
+int tegra_dvfs_predict_millivolts_pll(struct clk *c, unsigned long rate)
+{
+       const int *millivolts;
+
+       if (!rate || !c->dvfs)
+               return 0;
+
+       millivolts = c->dvfs->millivolts;
+       return predict_millivolts(c, millivolts, rate);
+}
+
+int tegra_dvfs_predict_millivolts_dfll(struct clk *c, unsigned long rate)
+{
+       const int *millivolts;
+
+       if (!rate || !c->dvfs)
+               return 0;
+
+       millivolts = c->dvfs->dfll_millivolts;
+       return predict_millivolts(c, millivolts, rate);
+}
+
 int tegra_dvfs_set_rate(struct clk *c, unsigned long rate)
 {
        int ret;
index d426295..e06509a 100644 (file)
@@ -179,6 +179,8 @@ void tegra_dvfs_rail_on(struct dvfs_rail *rail, ktime_t now);
 void tegra_dvfs_rail_pause(struct dvfs_rail *rail, ktime_t delta, bool on);
 struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id);
 int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate);
+int tegra_dvfs_predict_millivolts_pll(struct clk *c, unsigned long rate);
+int tegra_dvfs_predict_millivolts_dfll(struct clk *c, unsigned long rate);
 void tegra_dvfs_core_cap_enable(bool enable);
 void tegra_dvfs_core_cap_level_set(int level);
 int tegra_dvfs_alt_freqs_set(struct dvfs *d, unsigned long *alt_freqs);
@@ -216,6 +218,9 @@ static inline bool tegra_dvfs_is_dfll_range(struct dvfs *d, unsigned long rate)
 }
 static inline int tegra_dvfs_set_dfll_range(struct dvfs *d, int range)
 {
+       if (!d->dfll_millivolts)
+               return -ENOSYS;
+
        if ((range < DFLL_RANGE_NONE) || (range > DFLL_RANGE_HIGH_RATES))
                return -EINVAL;