summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gm20b/clk_gm20b.c63
1 files changed, 29 insertions, 34 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
index 8e37047e..7fc4b8fb 100644
--- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c
@@ -33,27 +33,34 @@
33 33
34/* from vbios PLL info table */ 34/* from vbios PLL info table */
35static struct pll_parms gpc_pll_params = { 35static struct pll_parms gpc_pll_params = {
36 144000, 2064000, /* freq */ 36 128000, 2600000, /* freq */
37 1000000, 2064000, /* vco */ 37 1300000, 2600000, /* vco */
38 12000, 38000, /* u */ 38 12000, 38400, /* u */
39 1, 255, /* M */ 39 1, 255, /* M */
40 8, 255, /* N */ 40 8, 255, /* N */
41 1, 32, /* PL */ 41 1, 31, /* PL */
42}; 42};
43 43
44#ifdef CONFIG_DEBUG_FS 44#ifdef CONFIG_DEBUG_FS
45static int clk_gm20b_debugfs_init(struct gk20a *g); 45static int clk_gm20b_debugfs_init(struct gk20a *g);
46#endif 46#endif
47 47
48static u8 pl_to_div[] = { 48/* 1:1 match between post divider settings and divisor value */
49/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ 49static inline u32 pl_to_div(u32 pl)
50/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32 }; 50{
51 return pl;
52}
53
54static inline u32 div_to_pl(u32 div)
55{
56 return div;
57}
51 58
52/* Calculate and update M/N/PL as well as pll->freq 59/* Calculate and update M/N/PL as well as pll->freq
53 ref_clk_f = clk_in_f / src_div = clk_in_f; (src_div = 1 on gk20a) 60 ref_clk_f = clk_in_f;
54 u_f = ref_clk_f / M; 61 u_f = ref_clk_f / M;
55 PLL output = vco_f = u_f * N = ref_clk_f * N / M; 62 vco_f = u_f * N = ref_clk_f * N / M;
56 gpc2clk = target clock frequency = vco_f / PL; 63 PLL output = gpc2clk = target clock frequency = vco_f / pl_to_pdiv(PL);
57 gpcclk = gpc2clk / 2; */ 64 gpcclk = gpc2clk / 2; */
58static int clk_config_pll(struct clk_gk20a *clk, struct pll *pll, 65static int clk_config_pll(struct clk_gk20a *clk, struct pll *pll,
59 struct pll_parms *pll_params, u32 *target_freq, bool best_fit) 66 struct pll_parms *pll_params, u32 *target_freq, bool best_fit)
@@ -65,7 +72,7 @@ static int clk_config_pll(struct clk_gk20a *clk, struct pll *pll,
65 u32 target_vco_f, vco_f; 72 u32 target_vco_f, vco_f;
66 u32 ref_clk_f, target_clk_f, u_f; 73 u32 ref_clk_f, target_clk_f, u_f;
67 u32 delta, lwv, best_delta = ~0; 74 u32 delta, lwv, best_delta = ~0;
68 int pl; 75 u32 pl;
69 76
70 BUG_ON(target_freq == NULL); 77 BUG_ON(target_freq == NULL);
71 78
@@ -83,32 +90,20 @@ static int clk_config_pll(struct clk_gk20a *clk, struct pll *pll,
83 if (max_vco_f < target_vco_f) 90 if (max_vco_f < target_vco_f)
84 max_vco_f = target_vco_f; 91 max_vco_f = target_vco_f;
85 92
86 high_PL = (max_vco_f + target_vco_f - 1) / target_vco_f; 93 /* Set PL search boundaries. */
94 high_PL = div_to_pl((max_vco_f + target_vco_f - 1) / target_vco_f);
87 high_PL = min(high_PL, pll_params->max_PL); 95 high_PL = min(high_PL, pll_params->max_PL);
88 high_PL = max(high_PL, pll_params->min_PL); 96 high_PL = max(high_PL, pll_params->min_PL);
89 97
90 low_PL = min_vco_f / target_vco_f; 98 low_PL = div_to_pl(min_vco_f / target_vco_f);
91 low_PL = min(low_PL, pll_params->max_PL); 99 low_PL = min(low_PL, pll_params->max_PL);
92 low_PL = max(low_PL, pll_params->min_PL); 100 low_PL = max(low_PL, pll_params->min_PL);
93 101
94 /* Find Indices of high_PL and low_PL */
95 for (pl = 0; pl < 14; pl++) {
96 if (pl_to_div[pl] >= low_PL) {
97 low_PL = pl;
98 break;
99 }
100 }
101 for (pl = 0; pl < 14; pl++) {
102 if (pl_to_div[pl] >= high_PL) {
103 high_PL = pl;
104 break;
105 }
106 }
107 gk20a_dbg_info("low_PL %d(div%d), high_PL %d(div%d)", 102 gk20a_dbg_info("low_PL %d(div%d), high_PL %d(div%d)",
108 low_PL, pl_to_div[low_PL], high_PL, pl_to_div[high_PL]); 103 low_PL, pl_to_div(low_PL), high_PL, pl_to_div(high_PL));
109 104
110 for (pl = low_PL; pl <= high_PL; pl++) { 105 for (pl = low_PL; pl <= high_PL; pl++) {
111 target_vco_f = target_clk_f * pl_to_div[pl]; 106 target_vco_f = target_clk_f * pl_to_div(pl);
112 107
113 for (m = pll_params->min_M; m <= pll_params->max_M; m++) { 108 for (m = pll_params->min_M; m <= pll_params->max_M; m++) {
114 u_f = ref_clk_f / m; 109 u_f = ref_clk_f / m;
@@ -133,8 +128,8 @@ static int clk_config_pll(struct clk_gk20a *clk, struct pll *pll,
133 vco_f = ref_clk_f * n / m; 128 vco_f = ref_clk_f * n / m;
134 129
135 if (vco_f >= min_vco_f && vco_f <= max_vco_f) { 130 if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
136 lwv = (vco_f + (pl_to_div[pl] / 2)) 131 lwv = (vco_f + (pl_to_div(pl) / 2))
137 / pl_to_div[pl]; 132 / pl_to_div(pl);
138 delta = abs(lwv - target_clk_f); 133 delta = abs(lwv - target_clk_f);
139 134
140 if (delta < best_delta) { 135 if (delta < best_delta) {
@@ -169,12 +164,12 @@ found_match:
169 pll->PL = best_PL; 164 pll->PL = best_PL;
170 165
171 /* save current frequency */ 166 /* save current frequency */
172 pll->freq = ref_clk_f * pll->N / (pll->M * pl_to_div[pll->PL]); 167 pll->freq = ref_clk_f * pll->N / (pll->M * pl_to_div(pll->PL));
173 168
174 *target_freq = pll->freq; 169 *target_freq = pll->freq;
175 170
176 gk20a_dbg_clk("actual target freq %d MHz, M %d, N %d, PL %d(div%d)", 171 gk20a_dbg_clk("actual target freq %d MHz, M %d, N %d, PL %d(div%d)",
177 *target_freq, pll->M, pll->N, pll->PL, pl_to_div[pll->PL]); 172 *target_freq, pll->M, pll->N, pll->PL, pl_to_div(pll->PL));
178 173
179 gk20a_dbg_fn("done"); 174 gk20a_dbg_fn("done");
180 175
@@ -465,7 +460,7 @@ static int gm20b_init_clk_setup_sw(struct gk20a *g)
465 clk->gpc_pll.clk_in); 460 clk->gpc_pll.clk_in);
466 clk->gpc_pll.PL = 3; 461 clk->gpc_pll.PL = 3;
467 clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N; 462 clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N;
468 clk->gpc_pll.freq /= pl_to_div[clk->gpc_pll.PL]; 463 clk->gpc_pll.freq /= pl_to_div(clk->gpc_pll.PL);
469 } 464 }
470 465
471 mutex_init(&clk->clk_mutex); 466 mutex_init(&clk->clk_mutex);
@@ -744,7 +739,7 @@ static int pll_reg_show(struct seq_file *s, void *data)
744 m = trim_sys_gpcpll_coeff_mdiv_v(reg); 739 m = trim_sys_gpcpll_coeff_mdiv_v(reg);
745 n = trim_sys_gpcpll_coeff_ndiv_v(reg); 740 n = trim_sys_gpcpll_coeff_ndiv_v(reg);
746 pl = trim_sys_gpcpll_coeff_pldiv_v(reg); 741 pl = trim_sys_gpcpll_coeff_pldiv_v(reg);
747 f = g->clk.gpc_pll.clk_in * n / (m * pl_to_div[pl]); 742 f = g->clk.gpc_pll.clk_in * n / (m * pl_to_div(pl));
748 seq_printf(s, "coef = 0x%x : m = %u : n = %u : pl = %u", reg, m, n, pl); 743 seq_printf(s, "coef = 0x%x : m = %u : n = %u : pl = %u", reg, m, n, pl);
749 seq_printf(s, " : pll_f(gpu_f) = %u(%u) kHz\n", f, f/2); 744 seq_printf(s, " : pll_f(gpu_f) = %u(%u) kHz\n", f, f/2);
750 mutex_unlock(&g->clk.clk_mutex); 745 mutex_unlock(&g->clk.clk_mutex);