]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
dvfs: tegra: Update conditions to skip DVFS enable
authorAlex Frid <afrid@nvidia.com>
Wed, 1 Apr 2015 23:37:33 +0000 (16:37 -0700)
committerAleksandr Frid <afrid@nvidia.com>
Thu, 2 Apr 2015 19:58:16 +0000 (12:58 -0700)
Moved check for conditions when DVFS table initialization on particular
clock can be skipped to a separate function. This function is checking
the following three conditions (each of them allows to skip):

a) clock can reach maximum rate at minimum voltage - same as before this
commit

b) UART clock has a flat DVFS table - DVFS rates in the entire voltage
range are the same. Before this commit the flat table condition was not
limited to UART. However, in general, it is covered by (a) when maximum
clock rate is at/below maximum DVFS rate. UART is a special case, since
UART driver may use its own baud rate divider directly, and apply baud
rate limits based on platform data transparently to DVFS.

c) single-voltage range (minimum and nominal DVFS rail voltages are the
same). This condition is applied to non-shared bus clock provided clock
maximum rate is at/below maximum DVFS rate (the shared bus exception is
added, because shared buses may need DVFS initialized to define possible
rates). It is a new condition introduced by this commit.

Bug 1602537
Bug 1625003

Change-Id: I8d40cabcf8dd233931e15ca95a52c7ef2df516a2
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/726568
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
drivers/platform/tegra/dvfs.c

index bb065902d55de81ed0816730fd1437706c8b614c..5cc8714235238cc6e2877552a24ec8673a46b5fc 100644 (file)
@@ -1682,9 +1682,40 @@ static bool __init can_update_max_rate(struct clk *c, struct dvfs *d)
        return true;
 }
 
+/* Check if no need to apply DVFS limits and DVFS installation can be skipped */
+static bool __init can_skip_dvfs_on_clk(struct clk *c, struct dvfs *d,
+       bool max_rate_updated, int max_freq_index)
+{
+       /* Skip for clock can reach max rate at min voltage */
+       if (d->freqs[0] * d->freqs_mult >= c->max_rate)
+               return true;
+
+       /*
+        * Skip for UART that must have flat DVFS table. UART is a special case,
+        * since UART driver may use its own baud rate divider directly, and
+        * apply baud rate limits based on platform DT transparently to DVFS.
+        */
+       if (c->flags & DIV_U151_UART) {
+               BUG_ON(d->freqs[0] != d->freqs[max_freq_index]);
+               return true;
+       }
+
+       /*
+        * Skip for single-voltage range provided DVFS limit was already applied
+        * to maximum rate, and it is not a shared bus (the latter condition is
+        * added, because shared buses may define possible rates based on DVFS)
+        */
+       if (!c->ops->shared_bus_update && max_rate_updated &&
+           (d->dvfs_rail->min_millivolts == d->dvfs_rail->nominal_millivolts))
+               return true;
+
+       return false;
+}
+
 void __init tegra_init_dvfs_one(struct dvfs *d, int max_freq_index)
 {
        int ret;
+       bool max_rate_updated = false;
        struct clk *c = tegra_get_clock_by_name(d->clk_name);
 
        if (!c) {
@@ -1697,18 +1728,15 @@ void __init tegra_init_dvfs_one(struct dvfs *d, int max_freq_index)
                BUG_ON(!d->freqs[max_freq_index]);
                tegra_init_max_rate(
                        c, d->freqs[max_freq_index] * d->freqs_mult);
+               max_rate_updated = true;
        }
        d->max_millivolts = d->dvfs_rail->nominal_millivolts;
 
-       /*
-        * No need to enable DVFS on clock reaching max rate at min voltage,
-        * or when same frequency limit is specified for the entire voltage
-        * range.
-        */
-       if ((d->freqs[0] * d->freqs_mult >= c->max_rate) ||
-           (d->freqs[0] == d->freqs[max_freq_index]))
+       /* Skip DVFS enable if no voltage dependency, or single-voltage range */
+       if (can_skip_dvfs_on_clk(c, d, max_rate_updated, max_freq_index))
                return;
 
+       /* Enable DVFS */
        ret = enable_dvfs_on_clk(c, d);
        if (ret)
                pr_err("tegra_dvfs: failed to enable dvfs on %s\n", c->name);