0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "priv.h"
0026 #include "gk20a.h"
0027
0028 #include <core/tegra.h>
0029 #include <subdev/timer.h>
0030
0031 static const u8 _pl_to_div[] = {
0032
0033 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
0034 };
0035
0036 static u32 pl_to_div(u32 pl)
0037 {
0038 if (pl >= ARRAY_SIZE(_pl_to_div))
0039 return 1;
0040
0041 return _pl_to_div[pl];
0042 }
0043
0044 static u32 div_to_pl(u32 div)
0045 {
0046 u32 pl;
0047
0048 for (pl = 0; pl < ARRAY_SIZE(_pl_to_div) - 1; pl++) {
0049 if (_pl_to_div[pl] >= div)
0050 return pl;
0051 }
0052
0053 return ARRAY_SIZE(_pl_to_div) - 1;
0054 }
0055
0056 static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
0057 .min_vco = 1000000, .max_vco = 2064000,
0058 .min_u = 12000, .max_u = 38000,
0059 .min_m = 1, .max_m = 255,
0060 .min_n = 8, .max_n = 255,
0061 .min_pl = 1, .max_pl = 32,
0062 };
0063
0064 void
0065 gk20a_pllg_read_mnp(struct gk20a_clk *clk, struct gk20a_pll *pll)
0066 {
0067 struct nvkm_device *device = clk->base.subdev.device;
0068 u32 val;
0069
0070 val = nvkm_rd32(device, GPCPLL_COEFF);
0071 pll->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH);
0072 pll->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH);
0073 pll->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH);
0074 }
0075
0076 void
0077 gk20a_pllg_write_mnp(struct gk20a_clk *clk, const struct gk20a_pll *pll)
0078 {
0079 struct nvkm_device *device = clk->base.subdev.device;
0080 u32 val;
0081
0082 val = (pll->m & MASK(GPCPLL_COEFF_M_WIDTH)) << GPCPLL_COEFF_M_SHIFT;
0083 val |= (pll->n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT;
0084 val |= (pll->pl & MASK(GPCPLL_COEFF_P_WIDTH)) << GPCPLL_COEFF_P_SHIFT;
0085 nvkm_wr32(device, GPCPLL_COEFF, val);
0086 }
0087
0088 u32
0089 gk20a_pllg_calc_rate(struct gk20a_clk *clk, struct gk20a_pll *pll)
0090 {
0091 u32 rate;
0092 u32 divider;
0093
0094 rate = clk->parent_rate * pll->n;
0095 divider = pll->m * clk->pl_to_div(pll->pl);
0096
0097 return rate / divider / 2;
0098 }
0099
0100 int
0101 gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate,
0102 struct gk20a_pll *pll)
0103 {
0104 struct nvkm_subdev *subdev = &clk->base.subdev;
0105 u32 target_clk_f, ref_clk_f, target_freq;
0106 u32 min_vco_f, max_vco_f;
0107 u32 low_pl, high_pl, best_pl;
0108 u32 target_vco_f;
0109 u32 best_m, best_n;
0110 u32 best_delta = ~0;
0111 u32 pl;
0112
0113 target_clk_f = rate * 2 / KHZ;
0114 ref_clk_f = clk->parent_rate / KHZ;
0115
0116 target_vco_f = target_clk_f + target_clk_f / 50;
0117 max_vco_f = max(clk->params->max_vco, target_vco_f);
0118 min_vco_f = clk->params->min_vco;
0119 best_m = clk->params->max_m;
0120 best_n = clk->params->min_n;
0121 best_pl = clk->params->min_pl;
0122
0123
0124 high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
0125 high_pl = min(high_pl, clk->params->max_pl);
0126 high_pl = max(high_pl, clk->params->min_pl);
0127 high_pl = clk->div_to_pl(high_pl);
0128
0129
0130 low_pl = min_vco_f / target_vco_f;
0131 low_pl = min(low_pl, clk->params->max_pl);
0132 low_pl = max(low_pl, clk->params->min_pl);
0133 low_pl = clk->div_to_pl(low_pl);
0134
0135 nvkm_debug(subdev, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
0136 clk->pl_to_div(low_pl), high_pl, clk->pl_to_div(high_pl));
0137
0138
0139 for (pl = low_pl; pl <= high_pl; pl++) {
0140 u32 m, n, n2;
0141
0142 target_vco_f = target_clk_f * clk->pl_to_div(pl);
0143
0144 for (m = clk->params->min_m; m <= clk->params->max_m; m++) {
0145 u32 u_f = ref_clk_f / m;
0146
0147 if (u_f < clk->params->min_u)
0148 break;
0149 if (u_f > clk->params->max_u)
0150 continue;
0151
0152 n = (target_vco_f * m) / ref_clk_f;
0153 n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f;
0154
0155 if (n > clk->params->max_n)
0156 break;
0157
0158 for (; n <= n2; n++) {
0159 u32 vco_f;
0160
0161 if (n < clk->params->min_n)
0162 continue;
0163 if (n > clk->params->max_n)
0164 break;
0165
0166 vco_f = ref_clk_f * n / m;
0167
0168 if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
0169 u32 delta, lwv;
0170
0171 lwv = (vco_f + (clk->pl_to_div(pl) / 2))
0172 / clk->pl_to_div(pl);
0173 delta = abs(lwv - target_clk_f);
0174
0175 if (delta < best_delta) {
0176 best_delta = delta;
0177 best_m = m;
0178 best_n = n;
0179 best_pl = pl;
0180
0181 if (best_delta == 0)
0182 goto found_match;
0183 }
0184 }
0185 }
0186 }
0187 }
0188
0189 found_match:
0190 WARN_ON(best_delta == ~0);
0191
0192 if (best_delta != 0)
0193 nvkm_debug(subdev,
0194 "no best match for target @ %dMHz on gpc_pll",
0195 target_clk_f / KHZ);
0196
0197 pll->m = best_m;
0198 pll->n = best_n;
0199 pll->pl = best_pl;
0200
0201 target_freq = gk20a_pllg_calc_rate(clk, pll);
0202
0203 nvkm_debug(subdev,
0204 "actual target freq %d KHz, M %d, N %d, PL %d(div%d)\n",
0205 target_freq / KHZ, pll->m, pll->n, pll->pl,
0206 clk->pl_to_div(pll->pl));
0207 return 0;
0208 }
0209
0210 static int
0211 gk20a_pllg_slide(struct gk20a_clk *clk, u32 n)
0212 {
0213 struct nvkm_subdev *subdev = &clk->base.subdev;
0214 struct nvkm_device *device = subdev->device;
0215 struct gk20a_pll pll;
0216 int ret = 0;
0217
0218
0219 gk20a_pllg_read_mnp(clk, &pll);
0220
0221 if (n == pll.n)
0222 return 0;
0223
0224
0225 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
0226 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
0227 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
0228
0229
0230 pll.n = n;
0231 udelay(1);
0232 gk20a_pllg_write_mnp(clk, &pll);
0233
0234
0235 udelay(1);
0236 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
0237 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT),
0238 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT));
0239
0240
0241 if (nvkm_wait_usec(device, 500, GPC_BCAST_NDIV_SLOWDOWN_DEBUG,
0242 GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK,
0243 GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK) < 0)
0244 ret = -ETIMEDOUT;
0245
0246
0247 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
0248 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) |
0249 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
0250 nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN);
0251
0252 return ret;
0253 }
0254
0255 static int
0256 gk20a_pllg_enable(struct gk20a_clk *clk)
0257 {
0258 struct nvkm_device *device = clk->base.subdev.device;
0259 u32 val;
0260
0261 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
0262 nvkm_rd32(device, GPCPLL_CFG);
0263
0264
0265 val = nvkm_rd32(device, GPCPLL_CFG);
0266 if (val & GPCPLL_CFG_LOCK_DET_OFF) {
0267 val &= ~GPCPLL_CFG_LOCK_DET_OFF;
0268 nvkm_wr32(device, GPCPLL_CFG, val);
0269 }
0270
0271
0272 if (nvkm_wait_usec(device, 300, GPCPLL_CFG, GPCPLL_CFG_LOCK,
0273 GPCPLL_CFG_LOCK) < 0)
0274 return -ETIMEDOUT;
0275
0276
0277 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT),
0278 BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
0279
0280 return 0;
0281 }
0282
0283 static void
0284 gk20a_pllg_disable(struct gk20a_clk *clk)
0285 {
0286 struct nvkm_device *device = clk->base.subdev.device;
0287
0288
0289 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
0290
0291 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
0292 nvkm_rd32(device, GPCPLL_CFG);
0293 }
0294
0295 static int
0296 gk20a_pllg_program_mnp(struct gk20a_clk *clk, const struct gk20a_pll *pll)
0297 {
0298 struct nvkm_subdev *subdev = &clk->base.subdev;
0299 struct nvkm_device *device = subdev->device;
0300 struct gk20a_pll cur_pll;
0301 int ret;
0302
0303 gk20a_pllg_read_mnp(clk, &cur_pll);
0304
0305
0306 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0307 GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
0308
0309 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0310 GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
0311 nvkm_rd32(device, GPC2CLK_OUT);
0312 udelay(2);
0313
0314 gk20a_pllg_disable(clk);
0315
0316 gk20a_pllg_write_mnp(clk, pll);
0317
0318 ret = gk20a_pllg_enable(clk);
0319 if (ret)
0320 return ret;
0321
0322
0323 udelay(2);
0324 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0325 GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
0326
0327 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0328 GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
0329 nvkm_rd32(device, GPC2CLK_OUT);
0330
0331 return 0;
0332 }
0333
0334 static int
0335 gk20a_pllg_program_mnp_slide(struct gk20a_clk *clk, const struct gk20a_pll *pll)
0336 {
0337 struct gk20a_pll cur_pll;
0338 int ret;
0339
0340 if (gk20a_pllg_is_enabled(clk)) {
0341 gk20a_pllg_read_mnp(clk, &cur_pll);
0342
0343
0344 if (pll->m == cur_pll.m && pll->pl == cur_pll.pl)
0345 return gk20a_pllg_slide(clk, pll->n);
0346
0347
0348 cur_pll.n = gk20a_pllg_n_lo(clk, &cur_pll);
0349 ret = gk20a_pllg_slide(clk, cur_pll.n);
0350 if (ret)
0351 return ret;
0352 }
0353
0354
0355 cur_pll = *pll;
0356 cur_pll.n = gk20a_pllg_n_lo(clk, &cur_pll);
0357 ret = gk20a_pllg_program_mnp(clk, &cur_pll);
0358 if (ret)
0359 return ret;
0360
0361
0362 return gk20a_pllg_slide(clk, pll->n);
0363 }
0364
0365 static struct nvkm_pstate
0366 gk20a_pstates[] = {
0367 {
0368 .base = {
0369 .domain[nv_clk_src_gpc] = 72000,
0370 .voltage = 0,
0371 },
0372 },
0373 {
0374 .base = {
0375 .domain[nv_clk_src_gpc] = 108000,
0376 .voltage = 1,
0377 },
0378 },
0379 {
0380 .base = {
0381 .domain[nv_clk_src_gpc] = 180000,
0382 .voltage = 2,
0383 },
0384 },
0385 {
0386 .base = {
0387 .domain[nv_clk_src_gpc] = 252000,
0388 .voltage = 3,
0389 },
0390 },
0391 {
0392 .base = {
0393 .domain[nv_clk_src_gpc] = 324000,
0394 .voltage = 4,
0395 },
0396 },
0397 {
0398 .base = {
0399 .domain[nv_clk_src_gpc] = 396000,
0400 .voltage = 5,
0401 },
0402 },
0403 {
0404 .base = {
0405 .domain[nv_clk_src_gpc] = 468000,
0406 .voltage = 6,
0407 },
0408 },
0409 {
0410 .base = {
0411 .domain[nv_clk_src_gpc] = 540000,
0412 .voltage = 7,
0413 },
0414 },
0415 {
0416 .base = {
0417 .domain[nv_clk_src_gpc] = 612000,
0418 .voltage = 8,
0419 },
0420 },
0421 {
0422 .base = {
0423 .domain[nv_clk_src_gpc] = 648000,
0424 .voltage = 9,
0425 },
0426 },
0427 {
0428 .base = {
0429 .domain[nv_clk_src_gpc] = 684000,
0430 .voltage = 10,
0431 },
0432 },
0433 {
0434 .base = {
0435 .domain[nv_clk_src_gpc] = 708000,
0436 .voltage = 11,
0437 },
0438 },
0439 {
0440 .base = {
0441 .domain[nv_clk_src_gpc] = 756000,
0442 .voltage = 12,
0443 },
0444 },
0445 {
0446 .base = {
0447 .domain[nv_clk_src_gpc] = 804000,
0448 .voltage = 13,
0449 },
0450 },
0451 {
0452 .base = {
0453 .domain[nv_clk_src_gpc] = 852000,
0454 .voltage = 14,
0455 },
0456 },
0457 };
0458
0459 int
0460 gk20a_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
0461 {
0462 struct gk20a_clk *clk = gk20a_clk(base);
0463 struct nvkm_subdev *subdev = &clk->base.subdev;
0464 struct nvkm_device *device = subdev->device;
0465 struct gk20a_pll pll;
0466
0467 switch (src) {
0468 case nv_clk_src_crystal:
0469 return device->crystal;
0470 case nv_clk_src_gpc:
0471 gk20a_pllg_read_mnp(clk, &pll);
0472 return gk20a_pllg_calc_rate(clk, &pll) / GK20A_CLK_GPC_MDIV;
0473 default:
0474 nvkm_error(subdev, "invalid clock source %d\n", src);
0475 return -EINVAL;
0476 }
0477 }
0478
0479 int
0480 gk20a_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
0481 {
0482 struct gk20a_clk *clk = gk20a_clk(base);
0483
0484 return gk20a_pllg_calc_mnp(clk, cstate->domain[nv_clk_src_gpc] *
0485 GK20A_CLK_GPC_MDIV, &clk->pll);
0486 }
0487
0488 int
0489 gk20a_clk_prog(struct nvkm_clk *base)
0490 {
0491 struct gk20a_clk *clk = gk20a_clk(base);
0492 int ret;
0493
0494 ret = gk20a_pllg_program_mnp_slide(clk, &clk->pll);
0495 if (ret)
0496 ret = gk20a_pllg_program_mnp(clk, &clk->pll);
0497
0498 return ret;
0499 }
0500
0501 void
0502 gk20a_clk_tidy(struct nvkm_clk *base)
0503 {
0504 }
0505
0506 int
0507 gk20a_clk_setup_slide(struct gk20a_clk *clk)
0508 {
0509 struct nvkm_subdev *subdev = &clk->base.subdev;
0510 struct nvkm_device *device = subdev->device;
0511 u32 step_a, step_b;
0512
0513 switch (clk->parent_rate) {
0514 case 12000000:
0515 case 12800000:
0516 case 13000000:
0517 step_a = 0x2b;
0518 step_b = 0x0b;
0519 break;
0520 case 19200000:
0521 step_a = 0x12;
0522 step_b = 0x08;
0523 break;
0524 case 38400000:
0525 step_a = 0x04;
0526 step_b = 0x05;
0527 break;
0528 default:
0529 nvkm_error(subdev, "invalid parent clock rate %u KHz",
0530 clk->parent_rate / KHZ);
0531 return -EINVAL;
0532 }
0533
0534 nvkm_mask(device, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT,
0535 step_a << GPCPLL_CFG2_PLL_STEPA_SHIFT);
0536 nvkm_mask(device, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT,
0537 step_b << GPCPLL_CFG3_PLL_STEPB_SHIFT);
0538
0539 return 0;
0540 }
0541
0542 void
0543 gk20a_clk_fini(struct nvkm_clk *base)
0544 {
0545 struct nvkm_device *device = base->subdev.device;
0546 struct gk20a_clk *clk = gk20a_clk(base);
0547
0548
0549 if (gk20a_pllg_is_enabled(clk)) {
0550 struct gk20a_pll pll;
0551 u32 n_lo;
0552
0553 gk20a_pllg_read_mnp(clk, &pll);
0554 n_lo = gk20a_pllg_n_lo(clk, &pll);
0555 gk20a_pllg_slide(clk, n_lo);
0556 }
0557
0558 gk20a_pllg_disable(clk);
0559
0560
0561 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 1);
0562 }
0563
0564 static int
0565 gk20a_clk_init(struct nvkm_clk *base)
0566 {
0567 struct gk20a_clk *clk = gk20a_clk(base);
0568 struct nvkm_subdev *subdev = &clk->base.subdev;
0569 struct nvkm_device *device = subdev->device;
0570 int ret;
0571
0572
0573 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 0);
0574 nvkm_rd32(device, GPCPLL_CFG);
0575 udelay(5);
0576
0577 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK,
0578 GPC2CLK_OUT_INIT_VAL);
0579
0580 ret = gk20a_clk_setup_slide(clk);
0581 if (ret)
0582 return ret;
0583
0584
0585 base->func->calc(base, &base->func->pstates[0].base);
0586 ret = base->func->prog(&clk->base);
0587 if (ret) {
0588 nvkm_error(subdev, "cannot initialize clock\n");
0589 return ret;
0590 }
0591
0592 return 0;
0593 }
0594
0595 static const struct nvkm_clk_func
0596 gk20a_clk = {
0597 .init = gk20a_clk_init,
0598 .fini = gk20a_clk_fini,
0599 .read = gk20a_clk_read,
0600 .calc = gk20a_clk_calc,
0601 .prog = gk20a_clk_prog,
0602 .tidy = gk20a_clk_tidy,
0603 .pstates = gk20a_pstates,
0604 .nr_pstates = ARRAY_SIZE(gk20a_pstates),
0605 .domains = {
0606 { nv_clk_src_crystal, 0xff },
0607 { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
0608 { nv_clk_src_max }
0609 }
0610 };
0611
0612 int
0613 gk20a_clk_ctor(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0614 const struct nvkm_clk_func *func, const struct gk20a_clk_pllg_params *params,
0615 struct gk20a_clk *clk)
0616 {
0617 struct nvkm_device_tegra *tdev = device->func->tegra(device);
0618 int ret;
0619 int i;
0620
0621
0622 for (i = 0; i < func->nr_pstates; i++) {
0623 INIT_LIST_HEAD(&func->pstates[i].list);
0624 func->pstates[i].pstate = i + 1;
0625 }
0626
0627 clk->params = params;
0628 clk->parent_rate = clk_get_rate(tdev->clk);
0629
0630 ret = nvkm_clk_ctor(func, device, type, inst, true, &clk->base);
0631 if (ret)
0632 return ret;
0633
0634 nvkm_debug(&clk->base.subdev, "parent clock rate: %d Khz\n",
0635 clk->parent_rate / KHZ);
0636
0637 return 0;
0638 }
0639
0640 int
0641 gk20a_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0642 struct nvkm_clk **pclk)
0643 {
0644 struct gk20a_clk *clk;
0645 int ret;
0646
0647 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0648 if (!clk)
0649 return -ENOMEM;
0650 *pclk = &clk->base;
0651
0652 ret = gk20a_clk_ctor(device, type, inst, &gk20a_clk, &gk20a_pllg_params, clk);
0653
0654 clk->pl_to_div = pl_to_div;
0655 clk->div_to_pl = div_to_pl;
0656 return ret;
0657 }