aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c394
1 files changed, 179 insertions, 215 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c
index 5f0ee24e31b8..218893e3e5f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk20a.c
@@ -28,69 +28,6 @@
28#include <core/tegra.h> 28#include <core/tegra.h>
29#include <subdev/timer.h> 29#include <subdev/timer.h>
30 30
31#define KHZ (1000)
32#define MHZ (KHZ * 1000)
33
34#define MASK(w) ((1 << w) - 1)
35
36#define GPCPLL_CFG (SYS_GPCPLL_CFG_BASE + 0)
37#define GPCPLL_CFG_ENABLE BIT(0)
38#define GPCPLL_CFG_IDDQ BIT(1)
39#define GPCPLL_CFG_LOCK_DET_OFF BIT(4)
40#define GPCPLL_CFG_LOCK BIT(17)
41
42#define GPCPLL_COEFF (SYS_GPCPLL_CFG_BASE + 4)
43#define GPCPLL_COEFF_M_SHIFT 0
44#define GPCPLL_COEFF_M_WIDTH 8
45#define GPCPLL_COEFF_N_SHIFT 8
46#define GPCPLL_COEFF_N_WIDTH 8
47#define GPCPLL_COEFF_P_SHIFT 16
48#define GPCPLL_COEFF_P_WIDTH 6
49
50#define GPCPLL_CFG2 (SYS_GPCPLL_CFG_BASE + 0xc)
51#define GPCPLL_CFG2_SETUP2_SHIFT 16
52#define GPCPLL_CFG2_PLL_STEPA_SHIFT 24
53
54#define GPCPLL_CFG3 (SYS_GPCPLL_CFG_BASE + 0x18)
55#define GPCPLL_CFG3_PLL_STEPB_SHIFT 16
56
57#define GPC_BCASE_GPCPLL_CFG_BASE 0x00132800
58#define GPCPLL_NDIV_SLOWDOWN (SYS_GPCPLL_CFG_BASE + 0x1c)
59#define GPCPLL_NDIV_SLOWDOWN_NDIV_LO_SHIFT 0
60#define GPCPLL_NDIV_SLOWDOWN_NDIV_MID_SHIFT 8
61#define GPCPLL_NDIV_SLOWDOWN_STEP_SIZE_LO2MID_SHIFT 16
62#define GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT 22
63#define GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT 31
64
65#define SEL_VCO (SYS_GPCPLL_CFG_BASE + 0x100)
66#define SEL_VCO_GPC2CLK_OUT_SHIFT 0
67
68#define GPC2CLK_OUT (SYS_GPCPLL_CFG_BASE + 0x250)
69#define GPC2CLK_OUT_SDIV14_INDIV4_WIDTH 1
70#define GPC2CLK_OUT_SDIV14_INDIV4_SHIFT 31
71#define GPC2CLK_OUT_SDIV14_INDIV4_MODE 1
72#define GPC2CLK_OUT_VCODIV_WIDTH 6
73#define GPC2CLK_OUT_VCODIV_SHIFT 8
74#define GPC2CLK_OUT_VCODIV1 0
75#define GPC2CLK_OUT_VCODIV_MASK (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << \
76 GPC2CLK_OUT_VCODIV_SHIFT)
77#define GPC2CLK_OUT_BYPDIV_WIDTH 6
78#define GPC2CLK_OUT_BYPDIV_SHIFT 0
79#define GPC2CLK_OUT_BYPDIV31 0x3c
80#define GPC2CLK_OUT_INIT_MASK ((MASK(GPC2CLK_OUT_SDIV14_INDIV4_WIDTH) << \
81 GPC2CLK_OUT_SDIV14_INDIV4_SHIFT)\
82 | (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << GPC2CLK_OUT_VCODIV_SHIFT)\
83 | (MASK(GPC2CLK_OUT_BYPDIV_WIDTH) << GPC2CLK_OUT_BYPDIV_SHIFT))
84#define GPC2CLK_OUT_INIT_VAL ((GPC2CLK_OUT_SDIV14_INDIV4_MODE << \
85 GPC2CLK_OUT_SDIV14_INDIV4_SHIFT) \
86 | (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT) \
87 | (GPC2CLK_OUT_BYPDIV31 << GPC2CLK_OUT_BYPDIV_SHIFT))
88
89#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG (GPC_BCASE_GPCPLL_CFG_BASE + 0xa0)
90#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT 24
91#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
92 (0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
93
94static const u8 _pl_to_div[] = { 31static const u8 _pl_to_div[] = {
95/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ 32/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */
96/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32, 33/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
@@ -124,7 +61,7 @@ static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
124 .min_pl = 1, .max_pl = 32, 61 .min_pl = 1, .max_pl = 32,
125}; 62};
126 63
127static void 64void
128gk20a_pllg_read_mnp(struct gk20a_clk *clk, struct gk20a_pll *pll) 65gk20a_pllg_read_mnp(struct gk20a_clk *clk, struct gk20a_pll *pll)
129{ 66{
130 struct nvkm_device *device = clk->base.subdev.device; 67 struct nvkm_device *device = clk->base.subdev.device;
@@ -136,20 +73,33 @@ gk20a_pllg_read_mnp(struct gk20a_clk *clk, struct gk20a_pll *pll)
136 pll->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH); 73 pll->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
137} 74}
138 75
139static u32 76void
140gk20a_pllg_calc_rate(struct gk20a_clk *clk) 77gk20a_pllg_write_mnp(struct gk20a_clk *clk, const struct gk20a_pll *pll)
78{
79 struct nvkm_device *device = clk->base.subdev.device;
80 u32 val;
81
82 val = (pll->m & MASK(GPCPLL_COEFF_M_WIDTH)) << GPCPLL_COEFF_M_SHIFT;
83 val |= (pll->n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
84 val |= (pll->pl & MASK(GPCPLL_COEFF_P_WIDTH)) << GPCPLL_COEFF_P_SHIFT;
85 nvkm_wr32(device, GPCPLL_COEFF, val);
86}
87
88u32
89gk20a_pllg_calc_rate(struct gk20a_clk *clk, struct gk20a_pll *pll)
141{ 90{
142 u32 rate; 91 u32 rate;
143 u32 divider; 92 u32 divider;
144 93
145 rate = clk->parent_rate * clk->pll.n; 94 rate = clk->parent_rate * pll->n;
146 divider = clk->pll.m * clk->pl_to_div(clk->pll.pl); 95 divider = pll->m * clk->pl_to_div(pll->pl);
147 96
148 return rate / divider / 2; 97 return rate / divider / 2;
149} 98}
150 99
151static int 100int
152gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate) 101gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate,
102 struct gk20a_pll *pll)
153{ 103{
154 struct nvkm_subdev *subdev = &clk->base.subdev; 104 struct nvkm_subdev *subdev = &clk->base.subdev;
155 u32 target_clk_f, ref_clk_f, target_freq; 105 u32 target_clk_f, ref_clk_f, target_freq;
@@ -163,16 +113,13 @@ gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate)
163 target_clk_f = rate * 2 / KHZ; 113 target_clk_f = rate * 2 / KHZ;
164 ref_clk_f = clk->parent_rate / KHZ; 114 ref_clk_f = clk->parent_rate / KHZ;
165 115
166 max_vco_f = clk->params->max_vco; 116 target_vco_f = target_clk_f + target_clk_f / 50;
117 max_vco_f = max(clk->params->max_vco, target_vco_f);
167 min_vco_f = clk->params->min_vco; 118 min_vco_f = clk->params->min_vco;
168 best_m = clk->params->max_m; 119 best_m = clk->params->max_m;
169 best_n = clk->params->min_n; 120 best_n = clk->params->min_n;
170 best_pl = clk->params->min_pl; 121 best_pl = clk->params->min_pl;
171 122
172 target_vco_f = target_clk_f + target_clk_f / 50;
173 if (max_vco_f < target_vco_f)
174 max_vco_f = target_vco_f;
175
176 /* min_pl <= high_pl <= max_pl */ 123 /* min_pl <= high_pl <= max_pl */
177 high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f; 124 high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
178 high_pl = min(high_pl, clk->params->max_pl); 125 high_pl = min(high_pl, clk->params->max_pl);
@@ -195,9 +142,7 @@ gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate)
195 target_vco_f = target_clk_f * clk->pl_to_div(pl); 142 target_vco_f = target_clk_f * clk->pl_to_div(pl);
196 143
197 for (m = clk->params->min_m; m <= clk->params->max_m; m++) { 144 for (m = clk->params->min_m; m <= clk->params->max_m; m++) {
198 u32 u_f, vco_f; 145 u32 u_f = ref_clk_f / m;
199
200 u_f = ref_clk_f / m;
201 146
202 if (u_f < clk->params->min_u) 147 if (u_f < clk->params->min_u)
203 break; 148 break;
@@ -211,6 +156,8 @@ gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate)
211 break; 156 break;
212 157
213 for (; n <= n2; n++) { 158 for (; n <= n2; n++) {
159 u32 vco_f;
160
214 if (n < clk->params->min_n) 161 if (n < clk->params->min_n)
215 continue; 162 continue;
216 if (n > clk->params->max_n) 163 if (n > clk->params->max_n)
@@ -247,16 +194,16 @@ found_match:
247 "no best match for target @ %dMHz on gpc_pll", 194 "no best match for target @ %dMHz on gpc_pll",
248 target_clk_f / KHZ); 195 target_clk_f / KHZ);
249 196
250 clk->pll.m = best_m; 197 pll->m = best_m;
251 clk->pll.n = best_n; 198 pll->n = best_n;
252 clk->pll.pl = best_pl; 199 pll->pl = best_pl;
253 200
254 target_freq = gk20a_pllg_calc_rate(clk); 201 target_freq = gk20a_pllg_calc_rate(clk, pll);
255 202
256 nvkm_debug(subdev, 203 nvkm_debug(subdev,
257 "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n", 204 "actual target freq %d KHz, M %d, N %d, PL %d(div%d)\n",
258 target_freq / MHZ, clk->pll.m, clk->pll.n, clk->pll.pl, 205 target_freq / KHZ, pll->m, pll->n, pll->pl,
259 clk->pl_to_div(clk->pll.pl)); 206 clk->pl_to_div(pll->pl));
260 return 0; 207 return 0;
261} 208}
262 209
@@ -265,45 +212,36 @@ gk20a_pllg_slide(struct gk20a_clk *clk, u32 n)
265{ 212{
266 struct nvkm_subdev *subdev = &clk->base.subdev; 213 struct nvkm_subdev *subdev = &clk->base.subdev;
267 struct nvkm_device *device = subdev->device; 214 struct nvkm_device *device = subdev->device;
268 u32 val; 215 struct gk20a_pll pll;
269 int ramp_timeout; 216 int ret = 0;
270 217
271 /* get old coefficients */ 218 /* get old coefficients */
272 val = nvkm_rd32(device, GPCPLL_COEFF); 219 gk20a_pllg_read_mnp(clk, &pll);
273 /* do nothing if NDIV is the same */ 220 /* do nothing if NDIV is the same */
274 if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH))) 221 if (n == pll.n)
275 return 0; 222 return 0;
276 223
277 /* setup */
278 nvkm_mask(device, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
279 0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT);
280 nvkm_mask(device, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
281 0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT);
282
283 /* pll slowdown mode */ 224 /* pll slowdown mode */
284 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN, 225 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
285 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT), 226 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
286 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT)); 227 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
287 228
288 /* new ndiv ready for ramp */ 229 /* new ndiv ready for ramp */
289 val = nvkm_rd32(device, GPCPLL_COEFF); 230 pll.n = n;
290 val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT);
291 val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
292 udelay(1); 231 udelay(1);
293 nvkm_wr32(device, GPCPLL_COEFF, val); 232 gk20a_pllg_write_mnp(clk, &pll);
294 233
295 /* dynamic ramp to new ndiv */ 234 /* dynamic ramp to new ndiv */
296 val = nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN);
297 val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT;
298 udelay(1); 235 udelay(1);
299 nvkm_wr32(device, GPCPLL_NDIV_SLOWDOWN, val); 236 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
237 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT),
238 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT));
300 239
301 for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) { 240 /* wait for ramping to complete */
302 udelay(1); 241 if (nvkm_wait_usec(device, 500, GPC_BCAST_NDIV_SLOWDOWN_DEBUG,
303 val = nvkm_rd32(device, GPC_BCAST_NDIV_SLOWDOWN_DEBUG); 242 GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK,
304 if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK) 243 GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK) < 0)
305 break; 244 ret = -ETIMEDOUT;
306 }
307 245
308 /* exit slowdown mode */ 246 /* exit slowdown mode */
309 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN, 247 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
@@ -311,21 +249,35 @@ gk20a_pllg_slide(struct gk20a_clk *clk, u32 n)
311 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0); 249 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
312 nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN); 250 nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN);
313 251
314 if (ramp_timeout <= 0) { 252 return ret;
315 nvkm_error(subdev, "gpcpll dynamic ramp timeout\n");
316 return -ETIMEDOUT;
317 }
318
319 return 0;
320} 253}
321 254
322static void 255static int
323gk20a_pllg_enable(struct gk20a_clk *clk) 256gk20a_pllg_enable(struct gk20a_clk *clk)
324{ 257{
325 struct nvkm_device *device = clk->base.subdev.device; 258 struct nvkm_device *device = clk->base.subdev.device;
259 u32 val;
326 260
327 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE); 261 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
328 nvkm_rd32(device, GPCPLL_CFG); 262 nvkm_rd32(device, GPCPLL_CFG);
263
264 /* enable lock detection */
265 val = nvkm_rd32(device, GPCPLL_CFG);
266 if (val & GPCPLL_CFG_LOCK_DET_OFF) {
267 val &= ~GPCPLL_CFG_LOCK_DET_OFF;
268 nvkm_wr32(device, GPCPLL_CFG, val);
269 }
270
271 /* wait for lock */
272 if (nvkm_wait_usec(device, 300, GPCPLL_CFG, GPCPLL_CFG_LOCK,
273 GPCPLL_CFG_LOCK) < 0)
274 return -ETIMEDOUT;
275
276 /* switch to VCO mode */
277 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT),
278 BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
279
280 return 0;
329} 281}
330 282
331static void 283static void
@@ -333,117 +285,81 @@ gk20a_pllg_disable(struct gk20a_clk *clk)
333{ 285{
334 struct nvkm_device *device = clk->base.subdev.device; 286 struct nvkm_device *device = clk->base.subdev.device;
335 287
288 /* put PLL in bypass before disabling it */
289 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
290
336 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0); 291 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
337 nvkm_rd32(device, GPCPLL_CFG); 292 nvkm_rd32(device, GPCPLL_CFG);
338} 293}
339 294
340static int 295static int
341_gk20a_pllg_program_mnp(struct gk20a_clk *clk, bool allow_slide) 296gk20a_pllg_program_mnp(struct gk20a_clk *clk, const struct gk20a_pll *pll)
342{ 297{
343 struct nvkm_subdev *subdev = &clk->base.subdev; 298 struct nvkm_subdev *subdev = &clk->base.subdev;
344 struct nvkm_device *device = subdev->device; 299 struct nvkm_device *device = subdev->device;
345 u32 val, cfg; 300 struct gk20a_pll cur_pll;
346 struct gk20a_pll old_pll; 301 int ret;
347 u32 n_lo;
348
349 /* get old coefficients */
350 gk20a_pllg_read_mnp(clk, &old_pll);
351
352 /* do NDIV slide if there is no change in M and PL */
353 cfg = nvkm_rd32(device, GPCPLL_CFG);
354 if (allow_slide && clk->pll.m == old_pll.m &&
355 clk->pll.pl == old_pll.pl && (cfg & GPCPLL_CFG_ENABLE)) {
356 return gk20a_pllg_slide(clk, clk->pll.n);
357 }
358
359 /* slide down to NDIV_LO */
360 if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) {
361 int ret;
362
363 n_lo = DIV_ROUND_UP(old_pll.m * clk->params->min_vco,
364 clk->parent_rate / KHZ);
365 ret = gk20a_pllg_slide(clk, n_lo);
366 302
367 if (ret) 303 gk20a_pllg_read_mnp(clk, &cur_pll);
368 return ret;
369 }
370 304
371 /* split FO-to-bypass jump in halfs by setting out divider 1:2 */ 305 /* split VCO-to-bypass jump in half by setting out divider 1:2 */
372 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK, 306 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
373 0x2 << GPC2CLK_OUT_VCODIV_SHIFT); 307 GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
374 308 /* Intentional 2nd write to assure linear divider operation */
375 /* put PLL in bypass before programming it */ 309 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
376 val = nvkm_rd32(device, SEL_VCO); 310 GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
377 val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT)); 311 nvkm_rd32(device, GPC2CLK_OUT);
378 udelay(2); 312 udelay(2);
379 nvkm_wr32(device, SEL_VCO, val);
380
381 /* get out from IDDQ */
382 val = nvkm_rd32(device, GPCPLL_CFG);
383 if (val & GPCPLL_CFG_IDDQ) {
384 val &= ~GPCPLL_CFG_IDDQ;
385 nvkm_wr32(device, GPCPLL_CFG, val);
386 nvkm_rd32(device, GPCPLL_CFG);
387 udelay(2);
388 }
389 313
390 gk20a_pllg_disable(clk); 314 gk20a_pllg_disable(clk);
391 315
392 nvkm_debug(subdev, "%s: m=%d n=%d pl=%d\n", __func__, 316 gk20a_pllg_write_mnp(clk, pll);
393 clk->pll.m, clk->pll.n, clk->pll.pl);
394
395 n_lo = DIV_ROUND_UP(clk->pll.m * clk->params->min_vco,
396 clk->parent_rate / KHZ);
397 val = clk->pll.m << GPCPLL_COEFF_M_SHIFT;
398 val |= (allow_slide ? n_lo : clk->pll.n) << GPCPLL_COEFF_N_SHIFT;
399 val |= clk->pll.pl << GPCPLL_COEFF_P_SHIFT;
400 nvkm_wr32(device, GPCPLL_COEFF, val);
401 317
402 gk20a_pllg_enable(clk); 318 ret = gk20a_pllg_enable(clk);
403 319 if (ret)
404 val = nvkm_rd32(device, GPCPLL_CFG); 320 return ret;
405 if (val & GPCPLL_CFG_LOCK_DET_OFF) {
406 val &= ~GPCPLL_CFG_LOCK_DET_OFF;
407 nvkm_wr32(device, GPCPLL_CFG, val);
408 }
409
410 if (nvkm_usec(device, 300,
411 if (nvkm_rd32(device, GPCPLL_CFG) & GPCPLL_CFG_LOCK)
412 break;
413 ) < 0)
414 return -ETIMEDOUT;
415
416 /* switch to VCO mode */
417 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT),
418 BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
419 321
420 /* restore out divider 1:1 */ 322 /* restore out divider 1:1 */
421 val = nvkm_rd32(device, GPC2CLK_OUT); 323 udelay(2);
422 if ((val & GPC2CLK_OUT_VCODIV_MASK) != 324 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
423 (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT)) { 325 GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
424 val &= ~GPC2CLK_OUT_VCODIV_MASK; 326 /* Intentional 2nd write to assure linear divider operation */
425 val |= GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT; 327 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
426 udelay(2); 328 GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
427 nvkm_wr32(device, GPC2CLK_OUT, val); 329 nvkm_rd32(device, GPC2CLK_OUT);
428 /* Intentional 2nd write to assure linear divider operation */
429 nvkm_wr32(device, GPC2CLK_OUT, val);
430 nvkm_rd32(device, GPC2CLK_OUT);
431 }
432 330
433 /* slide up to new NDIV */ 331 return 0;
434 return allow_slide ? gk20a_pllg_slide(clk, clk->pll.n) : 0;
435} 332}
436 333
437static int 334static int
438gk20a_pllg_program_mnp(struct gk20a_clk *clk) 335gk20a_pllg_program_mnp_slide(struct gk20a_clk *clk, const struct gk20a_pll *pll)
439{ 336{
440 int err; 337 struct gk20a_pll cur_pll;
338 int ret;
441 339
442 err = _gk20a_pllg_program_mnp(clk, true); 340 if (gk20a_pllg_is_enabled(clk)) {
443 if (err) 341 gk20a_pllg_read_mnp(clk, &cur_pll);
444 err = _gk20a_pllg_program_mnp(clk, false); 342
343 /* just do NDIV slide if there is no change to M and PL */
344 if (pll->m == cur_pll.m && pll->pl == cur_pll.pl)
345 return gk20a_pllg_slide(clk, pll->n);
346
347 /* slide down to current NDIV_LO */
348 cur_pll.n = gk20a_pllg_n_lo(clk, &cur_pll);
349 ret = gk20a_pllg_slide(clk, cur_pll.n);
350 if (ret)
351 return ret;
352 }
353
354 /* program MNP with the new clock parameters and new NDIV_LO */
355 cur_pll = *pll;
356 cur_pll.n = gk20a_pllg_n_lo(clk, &cur_pll);
357 ret = gk20a_pllg_program_mnp(clk, &cur_pll);
358 if (ret)
359 return ret;
445 360
446 return err; 361 /* slide up to new NDIV */
362 return gk20a_pllg_slide(clk, pll->n);
447} 363}
448 364
449static struct nvkm_pstate 365static struct nvkm_pstate
@@ -546,13 +462,14 @@ gk20a_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
546 struct gk20a_clk *clk = gk20a_clk(base); 462 struct gk20a_clk *clk = gk20a_clk(base);
547 struct nvkm_subdev *subdev = &clk->base.subdev; 463 struct nvkm_subdev *subdev = &clk->base.subdev;
548 struct nvkm_device *device = subdev->device; 464 struct nvkm_device *device = subdev->device;
465 struct gk20a_pll pll;
549 466
550 switch (src) { 467 switch (src) {
551 case nv_clk_src_crystal: 468 case nv_clk_src_crystal:
552 return device->crystal; 469 return device->crystal;
553 case nv_clk_src_gpc: 470 case nv_clk_src_gpc:
554 gk20a_pllg_read_mnp(clk, &clk->pll); 471 gk20a_pllg_read_mnp(clk, &pll);
555 return gk20a_pllg_calc_rate(clk) / GK20A_CLK_GPC_MDIV; 472 return gk20a_pllg_calc_rate(clk, &pll) / GK20A_CLK_GPC_MDIV;
556 default: 473 default:
557 nvkm_error(subdev, "invalid clock source %d\n", src); 474 nvkm_error(subdev, "invalid clock source %d\n", src);
558 return -EINVAL; 475 return -EINVAL;
@@ -565,15 +482,20 @@ gk20a_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
565 struct gk20a_clk *clk = gk20a_clk(base); 482 struct gk20a_clk *clk = gk20a_clk(base);
566 483
567 return gk20a_pllg_calc_mnp(clk, cstate->domain[nv_clk_src_gpc] * 484 return gk20a_pllg_calc_mnp(clk, cstate->domain[nv_clk_src_gpc] *
568 GK20A_CLK_GPC_MDIV); 485 GK20A_CLK_GPC_MDIV, &clk->pll);
569} 486}
570 487
571int 488int
572gk20a_clk_prog(struct nvkm_clk *base) 489gk20a_clk_prog(struct nvkm_clk *base)
573{ 490{
574 struct gk20a_clk *clk = gk20a_clk(base); 491 struct gk20a_clk *clk = gk20a_clk(base);
492 int ret;
493
494 ret = gk20a_pllg_program_mnp_slide(clk, &clk->pll);
495 if (ret)
496 ret = gk20a_pllg_program_mnp(clk, &clk->pll);
575 497
576 return gk20a_pllg_program_mnp(clk); 498 return ret;
577} 499}
578 500
579void 501void
@@ -581,29 +503,62 @@ gk20a_clk_tidy(struct nvkm_clk *base)
581{ 503{
582} 504}
583 505
506int
507gk20a_clk_setup_slide(struct gk20a_clk *clk)
508{
509 struct nvkm_subdev *subdev = &clk->base.subdev;
510 struct nvkm_device *device = subdev->device;
511 u32 step_a, step_b;
512
513 switch (clk->parent_rate) {
514 case 12000000:
515 case 12800000:
516 case 13000000:
517 step_a = 0x2b;
518 step_b = 0x0b;
519 break;
520 case 19200000:
521 step_a = 0x12;
522 step_b = 0x08;
523 break;
524 case 38400000:
525 step_a = 0x04;
526 step_b = 0x05;
527 break;
528 default:
529 nvkm_error(subdev, "invalid parent clock rate %u KHz",
530 clk->parent_rate / KHZ);
531 return -EINVAL;
532 }
533
534 nvkm_mask(device, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
535 step_a << GPCPLL_CFG2_PLL_STEPA_SHIFT);
536 nvkm_mask(device, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
537 step_b << GPCPLL_CFG3_PLL_STEPB_SHIFT);
538
539 return 0;
540}
541
584void 542void
585gk20a_clk_fini(struct nvkm_clk *base) 543gk20a_clk_fini(struct nvkm_clk *base)
586{ 544{
587 struct nvkm_device *device = base->subdev.device; 545 struct nvkm_device *device = base->subdev.device;
588 struct gk20a_clk *clk = gk20a_clk(base); 546 struct gk20a_clk *clk = gk20a_clk(base);
589 u32 val;
590 547
591 /* slide to VCO min */ 548 /* slide to VCO min */
592 val = nvkm_rd32(device, GPCPLL_CFG); 549 if (gk20a_pllg_is_enabled(clk)) {
593 if (val & GPCPLL_CFG_ENABLE) {
594 struct gk20a_pll pll; 550 struct gk20a_pll pll;
595 u32 n_lo; 551 u32 n_lo;
596 552
597 gk20a_pllg_read_mnp(clk, &pll); 553 gk20a_pllg_read_mnp(clk, &pll);
598 n_lo = DIV_ROUND_UP(pll.m * clk->params->min_vco, 554 n_lo = gk20a_pllg_n_lo(clk, &pll);
599 clk->parent_rate / KHZ);
600 gk20a_pllg_slide(clk, n_lo); 555 gk20a_pllg_slide(clk, n_lo);
601 } 556 }
602 557
603 /* put PLL in bypass before disabling it */
604 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
605
606 gk20a_pllg_disable(clk); 558 gk20a_pllg_disable(clk);
559
560 /* set IDDQ */
561 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 1);
607} 562}
608 563
609static int 564static int
@@ -614,9 +569,18 @@ gk20a_clk_init(struct nvkm_clk *base)
614 struct nvkm_device *device = subdev->device; 569 struct nvkm_device *device = subdev->device;
615 int ret; 570 int ret;
616 571
572 /* get out from IDDQ */
573 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 0);
574 nvkm_rd32(device, GPCPLL_CFG);
575 udelay(5);
576
617 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, 577 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK,
618 GPC2CLK_OUT_INIT_VAL); 578 GPC2CLK_OUT_INIT_VAL);
619 579
580 ret = gk20a_clk_setup_slide(clk);
581 if (ret)
582 return ret;
583
620 /* Start with lowest frequency */ 584 /* Start with lowest frequency */
621 base->func->calc(base, &base->func->pstates[0].base); 585 base->func->calc(base, &base->func->pstates[0].base);
622 ret = base->func->prog(&clk->base); 586 ret = base->func->prog(&clk->base);
@@ -646,7 +610,7 @@ gk20a_clk = {
646}; 610};
647 611
648int 612int
649_gk20a_clk_ctor(struct nvkm_device *device, int index, 613gk20a_clk_ctor(struct nvkm_device *device, int index,
650 const struct nvkm_clk_func *func, 614 const struct nvkm_clk_func *func,
651 const struct gk20a_clk_pllg_params *params, 615 const struct gk20a_clk_pllg_params *params,
652 struct gk20a_clk *clk) 616 struct gk20a_clk *clk)
@@ -685,7 +649,7 @@ gk20a_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
685 return -ENOMEM; 649 return -ENOMEM;
686 *pclk = &clk->base; 650 *pclk = &clk->base;
687 651
688 ret = _gk20a_clk_ctor(device, index, &gk20a_clk, &gk20a_pllg_params, 652 ret = gk20a_clk_ctor(device, index, &gk20a_clk, &gk20a_pllg_params,
689 clk); 653 clk);
690 654
691 clk->pl_to_div = pl_to_div; 655 clk->pl_to_div = pl_to_div;