ARM: tegra12: clock: Separate EMC DVFS voltage steps
Alex Frid [Sun, 29 Sep 2013 06:22:39 +0000 (23:22 -0700)]
Separated EMC DVFS voltage steps from all other VDD_CORE clock
domains, since EMC steps are, in fact, different, and can very for
different board and DDR manufacturer combinations.

Change-Id: I6f01e664ba70dbd105124e31dee8c805d3823217
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/289510
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Xue Dong <xdong@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

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

index 6596701..ac28068 100644 (file)
@@ -1953,32 +1953,41 @@ static int dvfs_table_show(struct seq_file *s, void *data)
        int i;
        struct dvfs *d;
        struct dvfs_rail *rail;
+       const int *v_pll, *last_v_pll = NULL;
+       const int *v_dfll, *last_v_dfll = NULL;
 
-       seq_printf(s, "DVFS tables: units mV/MHz\n\n");
+       seq_printf(s, "DVFS tables: units mV/MHz\n");
 
        mutex_lock(&dvfs_lock);
 
        list_for_each_entry(rail, &dvfs_rail_list, node) {
-               bool mv_done = false;
                list_for_each_entry(d, &rail->dvfs, reg_node) {
-                       if (!mv_done) {
-                               const int *m = tegra_dvfs_get_millivolts_pll(d);
-                               mv_done = true;
-                               seq_printf(s, "%-16s", rail->reg_id);
-                               for (i = 0; i < d->num_freqs; i++) {
-                                       int mv = m[i];
-                                       seq_printf(s, "%7d", mv);
+                       bool mv_done = false;
+                       v_pll = tegra_dvfs_get_millivolts_pll(d);
+                       v_dfll = d->dfll_millivolts;
+
+                       if (v_pll && (last_v_pll != v_pll)) {
+                               if (!mv_done) {
+                                       seq_printf(s, "\n");
+                                       mv_done = true;
                                }
+                               last_v_pll = v_pll;
+                               seq_printf(s, "%-16s", rail->reg_id);
+                               for (i = 0; i < d->num_freqs; i++)
+                                       seq_printf(s, "%7d", v_pll[i]);
                                seq_printf(s, "\n");
-                               if (d->dfll_millivolts) {
-                                       seq_printf(s, "%-8s (dfll) ",
-                                                  rail->reg_id);
-                                       for (i = 0; i < d->num_freqs; i++) {
-                                               int mv = d->dfll_millivolts[i];
-                                               seq_printf(s, "%7d", mv);
-                                       }
+                       }
+
+                       if (v_dfll && (last_v_dfll != v_dfll)) {
+                               if (!mv_done) {
                                        seq_printf(s, "\n");
+                                       mv_done = true;
                                }
+                               last_v_dfll = v_dfll;
+                               seq_printf(s, "%-8s (dfll) ", rail->reg_id);
+                               for (i = 0; i < d->num_freqs; i++)
+                                       seq_printf(s, "%7d", v_dfll[i]);
+                               seq_printf(s, "\n");
                        }
 
                        seq_printf(s, "%-16s", d->clk_name);
@@ -1988,7 +1997,6 @@ static int dvfs_table_show(struct seq_file *s, void *data)
                        }
                        seq_printf(s, "\n");
                }
-               seq_printf(s, "\n");
        }
 
        mutex_unlock(&dvfs_lock);
index cfb9ccb..77ca784 100644 (file)
@@ -1020,30 +1020,38 @@ static int find_matching_input(const struct tegra12_emc_table *table,
        return 0;
 }
 
+
+static int emc_core_millivolts[MAX_DVFS_FREQS];
+
 static void adjust_emc_dvfs_table(const struct tegra12_emc_table *table,
                                  int table_size)
 {
-       int i, j;
+       int i, j, mv;
        unsigned long rate;
 
-       for (i = 0; i < MAX_DVFS_FREQS; i++) {
-               int mv = emc->dvfs->millivolts[i];
-               if (!mv)
-                       break;
+       BUG_ON(table_size > MAX_DVFS_FREQS);
 
-               /* For each dvfs voltage find maximum supported rate;
-                  use 1MHz placeholder if not found */
-               for (rate = 1000, j = 0; j < table_size; j++) {
-                       if (tegra_emc_clk_sel[j].input == NULL)
-                               continue;       /* invalid entry */
+       for (i = 0, j = 0; j < table_size; j++) {
+               if (tegra_emc_clk_sel[j].input == NULL)
+                       continue;       /* invalid entry */
 
-                       if ((mv >= table[j].emc_min_mv) &&
-                           (rate < table[j].rate))
-                               rate = table[j].rate;
+               rate = table[j].rate * 1000;
+               mv = table[j].emc_min_mv;
+
+               if ((i == 0) || (mv > emc_core_millivolts[i-1])) {
+                       /* advance: either regular or ll voltage increased -
+                          assure the same set of dvfs freqs in both modes */
+                       emc->dvfs->freqs[i] = rate;
+                       emc_core_millivolts[i] = mv;
+                       i++;
+               } else {
+                       /* squash: voltage has not increased */
+                       emc->dvfs->freqs[i-1] = rate;
                }
-               /* Table entries specify rate in kHz */
-               emc->dvfs->freqs[i] = rate * 1000;
        }
+
+       emc->dvfs->millivolts = emc_core_millivolts;
+       emc->dvfs->num_freqs = i;
 }
 
 #ifdef CONFIG_TEGRA_PLLM_SCALED
@@ -1126,10 +1134,13 @@ static int init_emc_table(const struct tegra12_emc_table *table, int table_size)
        for (i = 0; i < tegra_emc_table_size; i++) {
                unsigned long table_rate = table[i].rate;
 
-               /* Skip "no-rate" entry, or entry violating ascending order */
-               if (!table_rate ||
-                   (i && (table_rate <= table[i-1].rate)))
-                       continue;
+               /* Stop: "no-rate" entry, or entry violating ascending order */
+               if (!table_rate || (i && ((table_rate <= table[i-1].rate) ||
+                       (table[i].emc_min_mv < table[i-1].emc_min_mv)))) {
+                       pr_warn("tegra: EMC rate entry %lu is not ascending\n",
+                               table_rate);
+                       break;
+               }
 
                BUG_ON(table[i].rev != table[0].rev);