gpu: nvgpu: Add GPCPLL DVFS state to debug prints
[linux-3.10.git] / drivers / gpu / nvgpu / gm20b / clk_gm20b.c
index 7229e16..759f9f2 100644 (file)
@@ -31,8 +31,6 @@
 #include "hw_fuse_gm20b.h"
 #include "clk_gm20b.h"
 
-#define ALLOW_NON_CALIBRATED_NA_MODE   1
-
 #define gk20a_dbg_clk(fmt, arg...) \
        gk20a_dbg(gpu_dbg_clk, fmt, ##arg)
 
@@ -921,8 +919,9 @@ static void clk_config_pll_safe_dvfs(struct gk20a *g, struct pll *gpll)
        gpll->N = nsafe;
        clk_config_dvfs_ndiv(gpll->dvfs.mv, gpll->N, &gpll->dvfs);
 
-       gk20a_dbg_clk("safe freq %d kHz, M %d, N %d, PL %d(div%d)",
-               gpll->freq, gpll->M, gpll->N, gpll->PL, pl_to_div(gpll->PL));
+       gk20a_dbg_clk("safe freq %d kHz, M %d, N %d, PL %d(div%d), mV(cal) %d(%d), DC %d",
+               gpll->freq, gpll->M, gpll->N, gpll->PL, pl_to_div(gpll->PL),
+               gpll->dvfs.mv, gpll->dvfs.uv_cal / 1000, gpll->dvfs.dfs_coeff);
 }
 
 /* Change GPCPLL frequency and DVFS detection settings in DVFS mode */
@@ -995,6 +994,12 @@ static int clk_program_na_gpc_pll(struct gk20a *g, struct pll *gpll_new,
        clk_set_dfs_ext_cal(g, gpll_new->dvfs.dfs_ext_cal);
        clk_set_dfs_coeff(g, gpll_new->dvfs.dfs_coeff);
 
+       gk20a_dbg_clk("config_pll  %d kHz, M %d, N %d, PL %d(div%d), mV(cal) %d(%d), DC %d",
+               gpll_new->freq, gpll_new->M, gpll_new->N, gpll_new->PL,
+               pl_to_div(gpll_new->PL),
+               max(gpll_new->dvfs.mv, gpll_old->dvfs.mv),
+               gpll_new->dvfs.uv_cal / 1000, gpll_new->dvfs.dfs_coeff);
+
        /* Finally set target rate (with DVFS detection settings already new) */
        return clk_program_gpc_pll(g, gpll_new, 1);
 }
@@ -1069,7 +1074,6 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
        struct clk_gk20a *clk = &g->clk;
        unsigned long safe_rate;
        struct clk *ref;
-       bool calibrated;
 
        gk20a_dbg_fn("");
 
@@ -1109,10 +1113,10 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
                clk_get_parent(clk->tegra_clk));
        safe_rate = safe_rate * (100 - DVFS_SAFE_MARGIN) / 100;
        dvfs_safe_max_freq = rate_gpu_to_gpc2clk(safe_rate);
-       clk->gpc_pll.PL = DIV_ROUND_UP(gpc_pll_params.min_vco,
-                                      dvfs_safe_max_freq);
+       clk->gpc_pll.PL = (dvfs_safe_max_freq == 0) ? 0 :
+               DIV_ROUND_UP(gpc_pll_params.min_vco, dvfs_safe_max_freq);
 
-       /* Initial frequency: 1/3 VCO min (low enough to be safe at Vmin) */
+       /* Initial freq: low enough to be safe at Vmin (default 1/3 VCO min) */
        clk->gpc_pll.M = 1;
        clk->gpc_pll.N = DIV_ROUND_UP(gpc_pll_params.min_vco,
                                clk->gpc_pll.clk_in);
@@ -1120,14 +1124,20 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
        clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N;
        clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL);
 
-       calibrated = !clk_config_calibration_params(g);
+        /*
+         * All production parts should have ADC fuses burnt. Therefore, check
+         * ADC fuses always, regardless of whether NA mode is selected; and if
+         * NA mode is indeed selected, and part can support it, switch to NA
+         * mode even when ADC calibration is not fused; less accurate s/w
+         * self-calibration will be used for those parts.
+         */
+       clk_config_calibration_params(g);
 #ifdef CONFIG_TEGRA_USE_NA_GPCPLL
-       if (ALLOW_NON_CALIBRATED_NA_MODE || calibrated) {
+       if (tegra_fuse_can_use_na_gpcpll()) {
                /* NA mode is supported only at max update rate 38.4 MHz */
-               if (clk->gpc_pll.clk_in == gpc_pll_params.max_u) {
-                       clk->gpc_pll.mode = GPC_PLL_MODE_DVFS;
-                       gpc_pll_params.min_u = gpc_pll_params.max_u;
-               }
+               BUG_ON(clk->gpc_pll.clk_in != gpc_pll_params.max_u);
+               clk->gpc_pll.mode = GPC_PLL_MODE_DVFS;
+               gpc_pll_params.min_u = gpc_pll_params.max_u;
        }
 #endif
 
@@ -1136,7 +1146,7 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
        clk->sw_ready = true;
 
        gk20a_dbg_fn("done");
-       pr_info("GM20b GPCPLL initial settings:%s M=%u, N=%u, P=%u\n",
+       pr_info("gm20b gpu.0 GPCPLL initial settings:%s M=%u, N=%u, P=%u\n",
                clk->gpc_pll.mode == GPC_PLL_MODE_DVFS ? " NA mode," : "",
                clk->gpc_pll.M, clk->gpc_pll.N, clk->gpc_pll.PL);
        return 0;
@@ -1603,6 +1613,26 @@ static int monitor_get(void *data, u64 *val)
 }
 DEFINE_SIMPLE_ATTRIBUTE(monitor_fops, monitor_get, NULL, "%llu\n");
 
+static int pll_param_show(struct seq_file *s, void *data)
+{
+       seq_printf(s, "ADC offs = %d uV, ADC slope = %d uV, VCO ctrl = 0x%x\n",
+                  gpc_pll_params.uvdet_offs, gpc_pll_params.uvdet_slope,
+                  gpc_pll_params.vco_ctrl);
+       return 0;
+}
+
+static int pll_param_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pll_param_show, inode->i_private);
+}
+
+static const struct file_operations pll_param_fops = {
+       .open           = pll_param_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int clk_gm20b_debugfs_init(struct gk20a *g)
 {
        struct dentry *d;
@@ -1628,6 +1658,16 @@ static int clk_gm20b_debugfs_init(struct gk20a *g)
        if (!d)
                goto err_out;
 
+       d = debugfs_create_file(
+               "pll_param", S_IRUGO, platform->debugfs, g, &pll_param_fops);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_u32("pll_na_mode", S_IRUGO, platform->debugfs,
+                              (u32 *)&g->clk.gpc_pll.mode);
+       if (!d)
+               goto err_out;
+
        return 0;
 
 err_out: