0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <subdev/clk.h>
0024 #include <subdev/volt.h>
0025 #include <subdev/timer.h>
0026 #include <core/device.h>
0027 #include <core/tegra.h>
0028
0029 #include "priv.h"
0030 #include "gk20a.h"
0031
0032 #define GPCPLL_CFG_SYNC_MODE BIT(2)
0033
0034 #define BYPASSCTRL_SYS (SYS_GPCPLL_CFG_BASE + 0x340)
0035 #define BYPASSCTRL_SYS_GPCPLL_SHIFT 0
0036 #define BYPASSCTRL_SYS_GPCPLL_WIDTH 1
0037
0038 #define GPCPLL_CFG2_SDM_DIN_SHIFT 0
0039 #define GPCPLL_CFG2_SDM_DIN_WIDTH 8
0040 #define GPCPLL_CFG2_SDM_DIN_MASK \
0041 (MASK(GPCPLL_CFG2_SDM_DIN_WIDTH) << GPCPLL_CFG2_SDM_DIN_SHIFT)
0042 #define GPCPLL_CFG2_SDM_DIN_NEW_SHIFT 8
0043 #define GPCPLL_CFG2_SDM_DIN_NEW_WIDTH 15
0044 #define GPCPLL_CFG2_SDM_DIN_NEW_MASK \
0045 (MASK(GPCPLL_CFG2_SDM_DIN_NEW_WIDTH) << GPCPLL_CFG2_SDM_DIN_NEW_SHIFT)
0046 #define GPCPLL_CFG2_SETUP2_SHIFT 16
0047 #define GPCPLL_CFG2_PLL_STEPA_SHIFT 24
0048
0049 #define GPCPLL_DVFS0 (SYS_GPCPLL_CFG_BASE + 0x10)
0050 #define GPCPLL_DVFS0_DFS_COEFF_SHIFT 0
0051 #define GPCPLL_DVFS0_DFS_COEFF_WIDTH 7
0052 #define GPCPLL_DVFS0_DFS_COEFF_MASK \
0053 (MASK(GPCPLL_DVFS0_DFS_COEFF_WIDTH) << GPCPLL_DVFS0_DFS_COEFF_SHIFT)
0054 #define GPCPLL_DVFS0_DFS_DET_MAX_SHIFT 8
0055 #define GPCPLL_DVFS0_DFS_DET_MAX_WIDTH 7
0056 #define GPCPLL_DVFS0_DFS_DET_MAX_MASK \
0057 (MASK(GPCPLL_DVFS0_DFS_DET_MAX_WIDTH) << GPCPLL_DVFS0_DFS_DET_MAX_SHIFT)
0058
0059 #define GPCPLL_DVFS1 (SYS_GPCPLL_CFG_BASE + 0x14)
0060 #define GPCPLL_DVFS1_DFS_EXT_DET_SHIFT 0
0061 #define GPCPLL_DVFS1_DFS_EXT_DET_WIDTH 7
0062 #define GPCPLL_DVFS1_DFS_EXT_STRB_SHIFT 7
0063 #define GPCPLL_DVFS1_DFS_EXT_STRB_WIDTH 1
0064 #define GPCPLL_DVFS1_DFS_EXT_CAL_SHIFT 8
0065 #define GPCPLL_DVFS1_DFS_EXT_CAL_WIDTH 7
0066 #define GPCPLL_DVFS1_DFS_EXT_SEL_SHIFT 15
0067 #define GPCPLL_DVFS1_DFS_EXT_SEL_WIDTH 1
0068 #define GPCPLL_DVFS1_DFS_CTRL_SHIFT 16
0069 #define GPCPLL_DVFS1_DFS_CTRL_WIDTH 12
0070 #define GPCPLL_DVFS1_EN_SDM_SHIFT 28
0071 #define GPCPLL_DVFS1_EN_SDM_WIDTH 1
0072 #define GPCPLL_DVFS1_EN_SDM_BIT BIT(28)
0073 #define GPCPLL_DVFS1_EN_DFS_SHIFT 29
0074 #define GPCPLL_DVFS1_EN_DFS_WIDTH 1
0075 #define GPCPLL_DVFS1_EN_DFS_BIT BIT(29)
0076 #define GPCPLL_DVFS1_EN_DFS_CAL_SHIFT 30
0077 #define GPCPLL_DVFS1_EN_DFS_CAL_WIDTH 1
0078 #define GPCPLL_DVFS1_EN_DFS_CAL_BIT BIT(30)
0079 #define GPCPLL_DVFS1_DFS_CAL_DONE_SHIFT 31
0080 #define GPCPLL_DVFS1_DFS_CAL_DONE_WIDTH 1
0081 #define GPCPLL_DVFS1_DFS_CAL_DONE_BIT BIT(31)
0082
0083 #define GPC_BCAST_GPCPLL_DVFS2 (GPC_BCAST_GPCPLL_CFG_BASE + 0x20)
0084 #define GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT BIT(16)
0085
0086 #define GPCPLL_CFG3_PLL_DFS_TESTOUT_SHIFT 24
0087 #define GPCPLL_CFG3_PLL_DFS_TESTOUT_WIDTH 7
0088
0089 #define DFS_DET_RANGE 6
0090 #define SDM_DIN_RANGE 12
0091
0092 struct gm20b_clk_dvfs_params {
0093 s32 coeff_slope;
0094 s32 coeff_offs;
0095 u32 vco_ctrl;
0096 };
0097
0098 static const struct gm20b_clk_dvfs_params gm20b_dvfs_params = {
0099 .coeff_slope = -165230,
0100 .coeff_offs = 214007,
0101 .vco_ctrl = 0x7 << 3,
0102 };
0103
0104
0105
0106
0107
0108 struct gm20b_pll {
0109 struct gk20a_pll base;
0110 u32 sdm_din;
0111 };
0112
0113 struct gm20b_clk_dvfs {
0114 u32 dfs_coeff;
0115 s32 dfs_det_max;
0116 s32 dfs_ext_cal;
0117 };
0118
0119 struct gm20b_clk {
0120
0121 struct gk20a_clk base;
0122 struct gm20b_clk_dvfs dvfs;
0123 u32 uv;
0124
0125
0126 struct gk20a_pll new_pll;
0127 struct gm20b_clk_dvfs new_dvfs;
0128 u32 new_uv;
0129
0130 const struct gm20b_clk_dvfs_params *dvfs_params;
0131
0132
0133 s32 uvdet_slope;
0134 s32 uvdet_offs;
0135
0136
0137 u32 safe_fmax_vmin;
0138 };
0139 #define gm20b_clk(p) container_of((gk20a_clk(p)), struct gm20b_clk, base)
0140
0141 static u32 pl_to_div(u32 pl)
0142 {
0143 return pl;
0144 }
0145
0146 static u32 div_to_pl(u32 div)
0147 {
0148 return div;
0149 }
0150
0151 static const struct gk20a_clk_pllg_params gm20b_pllg_params = {
0152 .min_vco = 1300000, .max_vco = 2600000,
0153 .min_u = 12000, .max_u = 38400,
0154 .min_m = 1, .max_m = 255,
0155 .min_n = 8, .max_n = 255,
0156 .min_pl = 1, .max_pl = 31,
0157 };
0158
0159 static void
0160 gm20b_pllg_read_mnp(struct gm20b_clk *clk, struct gm20b_pll *pll)
0161 {
0162 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0163 struct nvkm_device *device = subdev->device;
0164 u32 val;
0165
0166 gk20a_pllg_read_mnp(&clk->base, &pll->base);
0167 val = nvkm_rd32(device, GPCPLL_CFG2);
0168 pll->sdm_din = (val >> GPCPLL_CFG2_SDM_DIN_SHIFT) &
0169 MASK(GPCPLL_CFG2_SDM_DIN_WIDTH);
0170 }
0171
0172 static void
0173 gm20b_pllg_write_mnp(struct gm20b_clk *clk, const struct gm20b_pll *pll)
0174 {
0175 struct nvkm_device *device = clk->base.base.subdev.device;
0176
0177 nvkm_mask(device, GPCPLL_CFG2, GPCPLL_CFG2_SDM_DIN_MASK,
0178 pll->sdm_din << GPCPLL_CFG2_SDM_DIN_SHIFT);
0179 gk20a_pllg_write_mnp(&clk->base, &pll->base);
0180 }
0181
0182
0183
0184
0185
0186
0187
0188 static void
0189 gm20b_dvfs_calc_det_coeff(struct gm20b_clk *clk, s32 uv,
0190 struct gm20b_clk_dvfs *dvfs)
0191 {
0192 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0193 const struct gm20b_clk_dvfs_params *p = clk->dvfs_params;
0194 u32 coeff;
0195
0196 s32 mv = DIV_ROUND_CLOSEST(uv, 1000);
0197
0198
0199 coeff = DIV_ROUND_CLOSEST(mv * p->coeff_slope, 1000) + p->coeff_offs;
0200 coeff = DIV_ROUND_CLOSEST(coeff, 1000);
0201 dvfs->dfs_coeff = min_t(u32, coeff, MASK(GPCPLL_DVFS0_DFS_COEFF_WIDTH));
0202
0203 dvfs->dfs_ext_cal = DIV_ROUND_CLOSEST(uv - clk->uvdet_offs,
0204 clk->uvdet_slope);
0205
0206 if (abs(dvfs->dfs_ext_cal) >= BIT(DFS_DET_RANGE))
0207 nvkm_error(subdev, "dfs_ext_cal overflow!\n");
0208
0209 dvfs->dfs_det_max = 0;
0210
0211 nvkm_debug(subdev, "%s uv: %d coeff: %x, ext_cal: %d, det_max: %d\n",
0212 __func__, uv, dvfs->dfs_coeff, dvfs->dfs_ext_cal,
0213 dvfs->dfs_det_max);
0214 }
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 static void
0225 gm20b_dvfs_calc_ndiv(struct gm20b_clk *clk, u32 n_eff, u32 *n_int, u32 *sdm_din)
0226 {
0227 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0228 const struct gk20a_clk_pllg_params *p = clk->base.params;
0229 u32 n;
0230 s32 det_delta;
0231 u32 rem, rem_range;
0232
0233
0234 det_delta = DIV_ROUND_CLOSEST(((s32)clk->uv) - clk->uvdet_offs,
0235 clk->uvdet_slope);
0236 det_delta -= clk->dvfs.dfs_ext_cal;
0237 det_delta = min(det_delta, clk->dvfs.dfs_det_max);
0238 det_delta *= clk->dvfs.dfs_coeff;
0239
0240
0241 n = (n_eff << DFS_DET_RANGE) - det_delta;
0242
0243 if (n <= 0) {
0244 nvkm_error(subdev, "ndiv <= 0 - setting to 1...\n");
0245 n = 1 << DFS_DET_RANGE;
0246 }
0247 if (n >> DFS_DET_RANGE > p->max_n) {
0248 nvkm_error(subdev, "ndiv > max_n - setting to max_n...\n");
0249 n = p->max_n << DFS_DET_RANGE;
0250 }
0251 *n_int = n >> DFS_DET_RANGE;
0252
0253
0254 rem = ((u32)n) & MASK(DFS_DET_RANGE);
0255 rem_range = SDM_DIN_RANGE + 1 - DFS_DET_RANGE;
0256
0257 rem = (rem << rem_range) - BIT(SDM_DIN_RANGE);
0258
0259 *sdm_din = (rem >> BITS_PER_BYTE) & MASK(GPCPLL_CFG2_SDM_DIN_WIDTH);
0260
0261 nvkm_debug(subdev, "%s n_eff: %d, n_int: %d, sdm_din: %d\n", __func__,
0262 n_eff, *n_int, *sdm_din);
0263 }
0264
0265 static int
0266 gm20b_pllg_slide(struct gm20b_clk *clk, u32 n)
0267 {
0268 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0269 struct nvkm_device *device = subdev->device;
0270 struct gm20b_pll pll;
0271 u32 n_int, sdm_din;
0272 int ret = 0;
0273
0274
0275 gm20b_dvfs_calc_ndiv(clk, n, &n_int, &sdm_din);
0276
0277
0278 gm20b_pllg_read_mnp(clk, &pll);
0279
0280 if (n_int == pll.base.n && sdm_din == pll.sdm_din)
0281 return 0;
0282
0283
0284 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
0285 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT),
0286 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT));
0287
0288
0289
0290 nvkm_mask(device, GPCPLL_CFG2, GPCPLL_CFG2_SDM_DIN_NEW_MASK,
0291 sdm_din << GPCPLL_CFG2_SDM_DIN_NEW_SHIFT);
0292 pll.base.n = n_int;
0293 udelay(1);
0294 gk20a_pllg_write_mnp(&clk->base, &pll.base);
0295
0296
0297 udelay(1);
0298 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
0299 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT),
0300 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT));
0301
0302
0303 if (nvkm_wait_usec(device, 500, GPC_BCAST_NDIV_SLOWDOWN_DEBUG,
0304 GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK,
0305 GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK) < 0)
0306 ret = -ETIMEDOUT;
0307
0308
0309 nvkm_mask(device, GPCPLL_CFG2, GPCPLL_CFG2_SDM_DIN_MASK,
0310 sdm_din << GPCPLL_CFG2_SDM_DIN_SHIFT);
0311
0312
0313 nvkm_mask(device, GPCPLL_NDIV_SLOWDOWN,
0314 BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) |
0315 BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0);
0316 nvkm_rd32(device, GPCPLL_NDIV_SLOWDOWN);
0317
0318 return ret;
0319 }
0320
0321 static int
0322 gm20b_pllg_enable(struct gm20b_clk *clk)
0323 {
0324 struct nvkm_device *device = clk->base.base.subdev.device;
0325
0326 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE);
0327 nvkm_rd32(device, GPCPLL_CFG);
0328
0329
0330 udelay(40);
0331
0332
0333 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_SYNC_MODE,
0334 GPCPLL_CFG_SYNC_MODE);
0335 nvkm_rd32(device, GPCPLL_CFG);
0336
0337
0338 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT),
0339 BIT(SEL_VCO_GPC2CLK_OUT_SHIFT));
0340
0341 return 0;
0342 }
0343
0344 static void
0345 gm20b_pllg_disable(struct gm20b_clk *clk)
0346 {
0347 struct nvkm_device *device = clk->base.base.subdev.device;
0348
0349
0350 nvkm_mask(device, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0);
0351
0352
0353 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_SYNC_MODE, 0);
0354
0355 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
0356 nvkm_rd32(device, GPCPLL_CFG);
0357 }
0358
0359 static int
0360 gm20b_pllg_program_mnp(struct gm20b_clk *clk, const struct gk20a_pll *pll)
0361 {
0362 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0363 struct nvkm_device *device = subdev->device;
0364 struct gm20b_pll cur_pll;
0365 u32 n_int, sdm_din;
0366
0367 bool pdiv_only;
0368 int ret;
0369
0370 gm20b_dvfs_calc_ndiv(clk, pll->n, &n_int, &sdm_din);
0371 gm20b_pllg_read_mnp(clk, &cur_pll);
0372 pdiv_only = cur_pll.base.n == n_int && cur_pll.sdm_din == sdm_din &&
0373 cur_pll.base.m == pll->m;
0374
0375
0376 if (!gk20a_pllg_is_enabled(&clk->base))
0377 pdiv_only = false;
0378
0379
0380 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0381 GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
0382
0383 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0384 GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
0385 nvkm_rd32(device, GPC2CLK_OUT);
0386 udelay(2);
0387
0388 if (pdiv_only) {
0389 u32 old = cur_pll.base.pl;
0390 u32 new = pll->pl;
0391
0392
0393
0394
0395
0396
0397
0398 if ((old & new) == 0) {
0399 cur_pll.base.pl = min(old | BIT(ffs(new) - 1),
0400 new | BIT(ffs(old) - 1));
0401 gk20a_pllg_write_mnp(&clk->base, &cur_pll.base);
0402 }
0403
0404 cur_pll.base.pl = new;
0405 gk20a_pllg_write_mnp(&clk->base, &cur_pll.base);
0406 } else {
0407
0408 gm20b_pllg_disable(clk);
0409
0410 cur_pll.base = *pll;
0411 cur_pll.base.n = n_int;
0412 cur_pll.sdm_din = sdm_din;
0413 gm20b_pllg_write_mnp(clk, &cur_pll);
0414
0415 ret = gm20b_pllg_enable(clk);
0416 if (ret)
0417 return ret;
0418 }
0419
0420
0421 udelay(2);
0422 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0423 GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
0424
0425 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0426 GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
0427 nvkm_rd32(device, GPC2CLK_OUT);
0428
0429 return 0;
0430 }
0431
0432 static int
0433 gm20b_pllg_program_mnp_slide(struct gm20b_clk *clk, const struct gk20a_pll *pll)
0434 {
0435 struct gk20a_pll cur_pll;
0436 int ret;
0437
0438 if (gk20a_pllg_is_enabled(&clk->base)) {
0439 gk20a_pllg_read_mnp(&clk->base, &cur_pll);
0440
0441
0442 if (pll->m == cur_pll.m && pll->pl == cur_pll.pl)
0443 return gm20b_pllg_slide(clk, pll->n);
0444
0445
0446 cur_pll.n = gk20a_pllg_n_lo(&clk->base, &cur_pll);
0447 ret = gm20b_pllg_slide(clk, cur_pll.n);
0448 if (ret)
0449 return ret;
0450 }
0451
0452
0453 cur_pll = *pll;
0454 cur_pll.n = gk20a_pllg_n_lo(&clk->base, &cur_pll);
0455 ret = gm20b_pllg_program_mnp(clk, &cur_pll);
0456 if (ret)
0457 return ret;
0458
0459
0460 return gm20b_pllg_slide(clk, pll->n);
0461 }
0462
0463 static int
0464 gm20b_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
0465 {
0466 struct gm20b_clk *clk = gm20b_clk(base);
0467 struct nvkm_subdev *subdev = &base->subdev;
0468 struct nvkm_volt *volt = base->subdev.device->volt;
0469 int ret;
0470
0471 ret = gk20a_pllg_calc_mnp(&clk->base, cstate->domain[nv_clk_src_gpc] *
0472 GK20A_CLK_GPC_MDIV, &clk->new_pll);
0473 if (ret)
0474 return ret;
0475
0476 clk->new_uv = volt->vid[cstate->voltage].uv;
0477 gm20b_dvfs_calc_det_coeff(clk, clk->new_uv, &clk->new_dvfs);
0478
0479 nvkm_debug(subdev, "%s uv: %d uv\n", __func__, clk->new_uv);
0480
0481 return 0;
0482 }
0483
0484
0485
0486
0487 static void
0488 gm20b_dvfs_calc_safe_pll(struct gm20b_clk *clk, struct gk20a_pll *pll)
0489 {
0490 u32 rate = gk20a_pllg_calc_rate(&clk->base, pll) / KHZ;
0491 u32 parent_rate = clk->base.parent_rate / KHZ;
0492 u32 nmin, nsafe;
0493
0494
0495 if (rate > clk->safe_fmax_vmin)
0496 rate = rate * (100 - 10) / 100;
0497
0498
0499 rate *= 2;
0500
0501 nmin = DIV_ROUND_UP(pll->m * clk->base.params->min_vco, parent_rate);
0502 nsafe = pll->m * rate / (clk->base.parent_rate);
0503
0504 if (nsafe < nmin) {
0505 pll->pl = DIV_ROUND_UP(nmin * parent_rate, pll->m * rate);
0506 nsafe = nmin;
0507 }
0508
0509 pll->n = nsafe;
0510 }
0511
0512 static void
0513 gm20b_dvfs_program_coeff(struct gm20b_clk *clk, u32 coeff)
0514 {
0515 struct nvkm_device *device = clk->base.base.subdev.device;
0516
0517
0518 nvkm_mask(device, GPC_BCAST_GPCPLL_DVFS2,
0519 GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT,
0520 GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT);
0521
0522 nvkm_mask(device, GPCPLL_DVFS0, GPCPLL_DVFS0_DFS_COEFF_MASK,
0523 coeff << GPCPLL_DVFS0_DFS_COEFF_SHIFT);
0524
0525 udelay(1);
0526 nvkm_mask(device, GPC_BCAST_GPCPLL_DVFS2,
0527 GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT, 0);
0528 }
0529
0530 static void
0531 gm20b_dvfs_program_ext_cal(struct gm20b_clk *clk, u32 dfs_det_cal)
0532 {
0533 struct nvkm_device *device = clk->base.base.subdev.device;
0534 u32 val;
0535
0536 nvkm_mask(device, GPC_BCAST_GPCPLL_DVFS2, MASK(DFS_DET_RANGE + 1),
0537 dfs_det_cal);
0538 udelay(1);
0539
0540 val = nvkm_rd32(device, GPCPLL_DVFS1);
0541 if (!(val & BIT(25))) {
0542
0543 val |= BIT(25) | BIT(16);
0544 nvkm_wr32(device, GPCPLL_DVFS1, val);
0545 }
0546 }
0547
0548 static void
0549 gm20b_dvfs_program_dfs_detection(struct gm20b_clk *clk,
0550 struct gm20b_clk_dvfs *dvfs)
0551 {
0552 struct nvkm_device *device = clk->base.base.subdev.device;
0553
0554
0555 nvkm_mask(device, GPC_BCAST_GPCPLL_DVFS2,
0556 GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT,
0557 GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT);
0558
0559 nvkm_mask(device, GPCPLL_DVFS0,
0560 GPCPLL_DVFS0_DFS_COEFF_MASK | GPCPLL_DVFS0_DFS_DET_MAX_MASK,
0561 dvfs->dfs_coeff << GPCPLL_DVFS0_DFS_COEFF_SHIFT |
0562 dvfs->dfs_det_max << GPCPLL_DVFS0_DFS_DET_MAX_SHIFT);
0563
0564 udelay(1);
0565 nvkm_mask(device, GPC_BCAST_GPCPLL_DVFS2,
0566 GPC_BCAST_GPCPLL_DVFS2_DFS_EXT_STROBE_BIT, 0);
0567
0568 gm20b_dvfs_program_ext_cal(clk, dvfs->dfs_ext_cal);
0569 }
0570
0571 static int
0572 gm20b_clk_prog(struct nvkm_clk *base)
0573 {
0574 struct gm20b_clk *clk = gm20b_clk(base);
0575 u32 cur_freq;
0576 int ret;
0577
0578
0579 if (clk->uv == clk->new_uv)
0580 goto prog;
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601 cur_freq = nvkm_clk_read(&clk->base.base, nv_clk_src_gpc);
0602 if (cur_freq > clk->safe_fmax_vmin) {
0603 struct gk20a_pll pll_safe;
0604
0605 if (clk->uv < clk->new_uv)
0606
0607 pll_safe = clk->base.pll;
0608 else
0609
0610 pll_safe = clk->new_pll;
0611
0612 gm20b_dvfs_calc_safe_pll(clk, &pll_safe);
0613 ret = gm20b_pllg_program_mnp_slide(clk, &pll_safe);
0614 if (ret)
0615 return ret;
0616 }
0617
0618
0619
0620
0621
0622
0623
0624 gm20b_dvfs_program_coeff(clk, 0);
0625 gm20b_dvfs_program_ext_cal(clk, clk->new_dvfs.dfs_ext_cal);
0626 gm20b_dvfs_program_coeff(clk, clk->new_dvfs.dfs_coeff);
0627 gm20b_dvfs_program_dfs_detection(clk, &clk->new_dvfs);
0628
0629 prog:
0630 clk->uv = clk->new_uv;
0631 clk->dvfs = clk->new_dvfs;
0632 clk->base.pll = clk->new_pll;
0633
0634 return gm20b_pllg_program_mnp_slide(clk, &clk->base.pll);
0635 }
0636
0637 static struct nvkm_pstate
0638 gm20b_pstates[] = {
0639 {
0640 .base = {
0641 .domain[nv_clk_src_gpc] = 76800,
0642 .voltage = 0,
0643 },
0644 },
0645 {
0646 .base = {
0647 .domain[nv_clk_src_gpc] = 153600,
0648 .voltage = 1,
0649 },
0650 },
0651 {
0652 .base = {
0653 .domain[nv_clk_src_gpc] = 230400,
0654 .voltage = 2,
0655 },
0656 },
0657 {
0658 .base = {
0659 .domain[nv_clk_src_gpc] = 307200,
0660 .voltage = 3,
0661 },
0662 },
0663 {
0664 .base = {
0665 .domain[nv_clk_src_gpc] = 384000,
0666 .voltage = 4,
0667 },
0668 },
0669 {
0670 .base = {
0671 .domain[nv_clk_src_gpc] = 460800,
0672 .voltage = 5,
0673 },
0674 },
0675 {
0676 .base = {
0677 .domain[nv_clk_src_gpc] = 537600,
0678 .voltage = 6,
0679 },
0680 },
0681 {
0682 .base = {
0683 .domain[nv_clk_src_gpc] = 614400,
0684 .voltage = 7,
0685 },
0686 },
0687 {
0688 .base = {
0689 .domain[nv_clk_src_gpc] = 691200,
0690 .voltage = 8,
0691 },
0692 },
0693 {
0694 .base = {
0695 .domain[nv_clk_src_gpc] = 768000,
0696 .voltage = 9,
0697 },
0698 },
0699 {
0700 .base = {
0701 .domain[nv_clk_src_gpc] = 844800,
0702 .voltage = 10,
0703 },
0704 },
0705 {
0706 .base = {
0707 .domain[nv_clk_src_gpc] = 921600,
0708 .voltage = 11,
0709 },
0710 },
0711 {
0712 .base = {
0713 .domain[nv_clk_src_gpc] = 998400,
0714 .voltage = 12,
0715 },
0716 },
0717 };
0718
0719 static void
0720 gm20b_clk_fini(struct nvkm_clk *base)
0721 {
0722 struct nvkm_device *device = base->subdev.device;
0723 struct gm20b_clk *clk = gm20b_clk(base);
0724
0725
0726 if (gk20a_pllg_is_enabled(&clk->base)) {
0727 struct gk20a_pll pll;
0728 u32 n_lo;
0729
0730 gk20a_pllg_read_mnp(&clk->base, &pll);
0731 n_lo = gk20a_pllg_n_lo(&clk->base, &pll);
0732 gm20b_pllg_slide(clk, n_lo);
0733 }
0734
0735 gm20b_pllg_disable(clk);
0736
0737
0738 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 1);
0739 }
0740
0741 static int
0742 gm20b_clk_init_dvfs(struct gm20b_clk *clk)
0743 {
0744 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0745 struct nvkm_device *device = subdev->device;
0746 bool fused = clk->uvdet_offs && clk->uvdet_slope;
0747 static const s32 ADC_SLOPE_UV = 10000;
0748 u32 data;
0749 int ret;
0750
0751
0752 nvkm_mask(device, GPCPLL_DVFS1, GPCPLL_DVFS1_EN_DFS_BIT,
0753 GPCPLL_DVFS1_EN_DFS_BIT);
0754
0755
0756 if (clk->dvfs_params->vco_ctrl)
0757 nvkm_mask(device, GPCPLL_CFG3, GPCPLL_CFG3_VCO_CTRL_MASK,
0758 clk->dvfs_params->vco_ctrl << GPCPLL_CFG3_VCO_CTRL_SHIFT);
0759
0760 if (fused) {
0761
0762 nvkm_mask(device, GPCPLL_DVFS1, GPCPLL_DVFS1_EN_DFS_CAL_BIT,
0763 GPCPLL_DVFS1_EN_DFS_CAL_BIT);
0764
0765
0766 goto calibrated;
0767 }
0768
0769
0770
0771
0772
0773
0774 nvkm_mask(device, GPCPLL_DVFS1, GPCPLL_DVFS1_EN_DFS_CAL_BIT,
0775 GPCPLL_DVFS1_EN_DFS_CAL_BIT);
0776
0777
0778 ret = nvkm_wait_usec(device, 10, GPCPLL_DVFS1,
0779 GPCPLL_DVFS1_DFS_CAL_DONE_BIT,
0780 GPCPLL_DVFS1_DFS_CAL_DONE_BIT);
0781 if (ret < 0) {
0782 nvkm_error(subdev, "GPCPLL calibration timeout\n");
0783 return -ETIMEDOUT;
0784 }
0785
0786 data = nvkm_rd32(device, GPCPLL_CFG3) >>
0787 GPCPLL_CFG3_PLL_DFS_TESTOUT_SHIFT;
0788 data &= MASK(GPCPLL_CFG3_PLL_DFS_TESTOUT_WIDTH);
0789
0790 clk->uvdet_slope = ADC_SLOPE_UV;
0791 clk->uvdet_offs = ((s32)clk->uv) - data * ADC_SLOPE_UV;
0792
0793 nvkm_debug(subdev, "calibrated DVFS parameters: offs %d, slope %d\n",
0794 clk->uvdet_offs, clk->uvdet_slope);
0795
0796 calibrated:
0797
0798 gm20b_dvfs_calc_det_coeff(clk, clk->uv, &clk->dvfs);
0799 gm20b_dvfs_program_coeff(clk, 0);
0800 gm20b_dvfs_program_ext_cal(clk, clk->dvfs.dfs_ext_cal);
0801 gm20b_dvfs_program_coeff(clk, clk->dvfs.dfs_coeff);
0802 gm20b_dvfs_program_dfs_detection(clk, &clk->new_dvfs);
0803
0804 return 0;
0805 }
0806
0807
0808 static const struct nvkm_clk_func gm20b_clk;
0809
0810 static int
0811 gm20b_clk_init(struct nvkm_clk *base)
0812 {
0813 struct gk20a_clk *clk = gk20a_clk(base);
0814 struct nvkm_subdev *subdev = &clk->base.subdev;
0815 struct nvkm_device *device = subdev->device;
0816 int ret;
0817 u32 data;
0818
0819
0820 nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_IDDQ, 0);
0821 nvkm_rd32(device, GPCPLL_CFG);
0822 udelay(5);
0823
0824 nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK,
0825 GPC2CLK_OUT_INIT_VAL);
0826
0827
0828 nvkm_mask(device, BYPASSCTRL_SYS,
0829 MASK(BYPASSCTRL_SYS_GPCPLL_WIDTH) << BYPASSCTRL_SYS_GPCPLL_SHIFT,
0830 0);
0831
0832 ret = gk20a_clk_setup_slide(clk);
0833 if (ret)
0834 return ret;
0835
0836
0837 data = nvkm_rd32(device, 0x021944);
0838 if (!(data & 0x3)) {
0839 data |= 0x2;
0840 nvkm_wr32(device, 0x021944, data);
0841
0842 data = nvkm_rd32(device, 0x021948);
0843 data |= 0x1;
0844 nvkm_wr32(device, 0x021948, data);
0845 }
0846
0847
0848 nvkm_mask(device, 0x20160, 0x003f0000, 0x0);
0849
0850
0851 if (clk->base.func == &gm20b_clk) {
0852 struct gm20b_clk *_clk = gm20b_clk(base);
0853 struct nvkm_volt *volt = device->volt;
0854
0855
0856 _clk->uv = nvkm_volt_get(volt);
0857
0858
0859 ret = gm20b_clk_init_dvfs(_clk);
0860 if (ret)
0861 return ret;
0862 }
0863
0864
0865 base->func->calc(base, &base->func->pstates[0].base);
0866 ret = base->func->prog(base);
0867 if (ret) {
0868 nvkm_error(subdev, "cannot initialize clock\n");
0869 return ret;
0870 }
0871
0872 return 0;
0873 }
0874
0875 static const struct nvkm_clk_func
0876 gm20b_clk_speedo0 = {
0877 .init = gm20b_clk_init,
0878 .fini = gk20a_clk_fini,
0879 .read = gk20a_clk_read,
0880 .calc = gk20a_clk_calc,
0881 .prog = gk20a_clk_prog,
0882 .tidy = gk20a_clk_tidy,
0883 .pstates = gm20b_pstates,
0884
0885 .nr_pstates = ARRAY_SIZE(gm20b_pstates) - 1,
0886 .domains = {
0887 { nv_clk_src_crystal, 0xff },
0888 { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
0889 { nv_clk_src_max },
0890 },
0891 };
0892
0893 static const struct nvkm_clk_func
0894 gm20b_clk = {
0895 .init = gm20b_clk_init,
0896 .fini = gm20b_clk_fini,
0897 .read = gk20a_clk_read,
0898 .calc = gm20b_clk_calc,
0899 .prog = gm20b_clk_prog,
0900 .tidy = gk20a_clk_tidy,
0901 .pstates = gm20b_pstates,
0902 .nr_pstates = ARRAY_SIZE(gm20b_pstates),
0903 .domains = {
0904 { nv_clk_src_crystal, 0xff },
0905 { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
0906 { nv_clk_src_max },
0907 },
0908 };
0909
0910 static int
0911 gm20b_clk_new_speedo0(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0912 struct nvkm_clk **pclk)
0913 {
0914 struct gk20a_clk *clk;
0915 int ret;
0916
0917 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0918 if (!clk)
0919 return -ENOMEM;
0920 *pclk = &clk->base;
0921
0922 ret = gk20a_clk_ctor(device, type, inst, &gm20b_clk_speedo0, &gm20b_pllg_params, clk);
0923 clk->pl_to_div = pl_to_div;
0924 clk->div_to_pl = div_to_pl;
0925 return ret;
0926 }
0927
0928
0929 #define FUSE_RESERVED_CALIB0 0x204
0930 #define FUSE_RESERVED_CALIB0_INTERCEPT_FRAC_SHIFT 0
0931 #define FUSE_RESERVED_CALIB0_INTERCEPT_FRAC_WIDTH 4
0932 #define FUSE_RESERVED_CALIB0_INTERCEPT_INT_SHIFT 4
0933 #define FUSE_RESERVED_CALIB0_INTERCEPT_INT_WIDTH 10
0934 #define FUSE_RESERVED_CALIB0_SLOPE_FRAC_SHIFT 14
0935 #define FUSE_RESERVED_CALIB0_SLOPE_FRAC_WIDTH 10
0936 #define FUSE_RESERVED_CALIB0_SLOPE_INT_SHIFT 24
0937 #define FUSE_RESERVED_CALIB0_SLOPE_INT_WIDTH 6
0938 #define FUSE_RESERVED_CALIB0_FUSE_REV_SHIFT 30
0939 #define FUSE_RESERVED_CALIB0_FUSE_REV_WIDTH 2
0940
0941 static int
0942 gm20b_clk_init_fused_params(struct gm20b_clk *clk)
0943 {
0944 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0945 u32 val = 0;
0946 u32 rev = 0;
0947
0948 #if IS_ENABLED(CONFIG_ARCH_TEGRA)
0949 tegra_fuse_readl(FUSE_RESERVED_CALIB0, &val);
0950 rev = (val >> FUSE_RESERVED_CALIB0_FUSE_REV_SHIFT) &
0951 MASK(FUSE_RESERVED_CALIB0_FUSE_REV_WIDTH);
0952 #endif
0953
0954
0955 if (rev == 0)
0956 return -EINVAL;
0957
0958
0959 clk->uvdet_slope = ((val >> FUSE_RESERVED_CALIB0_SLOPE_INT_SHIFT) &
0960 MASK(FUSE_RESERVED_CALIB0_SLOPE_INT_WIDTH)) * 1000 +
0961 ((val >> FUSE_RESERVED_CALIB0_SLOPE_FRAC_SHIFT) &
0962 MASK(FUSE_RESERVED_CALIB0_SLOPE_FRAC_WIDTH));
0963
0964
0965 clk->uvdet_offs = ((val >> FUSE_RESERVED_CALIB0_INTERCEPT_INT_SHIFT) &
0966 MASK(FUSE_RESERVED_CALIB0_INTERCEPT_INT_WIDTH)) * 1000 +
0967 ((val >> FUSE_RESERVED_CALIB0_INTERCEPT_FRAC_SHIFT) &
0968 MASK(FUSE_RESERVED_CALIB0_INTERCEPT_FRAC_WIDTH)) * 100;
0969
0970 nvkm_debug(subdev, "fused calibration data: slope %d, offs %d\n",
0971 clk->uvdet_slope, clk->uvdet_offs);
0972 return 0;
0973 }
0974
0975 static int
0976 gm20b_clk_init_safe_fmax(struct gm20b_clk *clk)
0977 {
0978 struct nvkm_subdev *subdev = &clk->base.base.subdev;
0979 struct nvkm_volt *volt = subdev->device->volt;
0980 struct nvkm_pstate *pstates = clk->base.base.func->pstates;
0981 int nr_pstates = clk->base.base.func->nr_pstates;
0982 int vmin, id = 0;
0983 u32 fmax = 0;
0984 int i;
0985
0986
0987 vmin = volt->vid[0].uv;
0988 for (i = 1; i < volt->vid_nr; i++) {
0989 if (volt->vid[i].uv <= vmin) {
0990 vmin = volt->vid[i].uv;
0991 id = volt->vid[i].vid;
0992 }
0993 }
0994
0995
0996 for (i = 0; i < nr_pstates; i++)
0997 if (pstates[i].base.voltage == id)
0998 fmax = max(fmax,
0999 pstates[i].base.domain[nv_clk_src_gpc]);
1000
1001 if (!fmax) {
1002 nvkm_error(subdev, "failed to evaluate safe fmax\n");
1003 return -EINVAL;
1004 }
1005
1006
1007 clk->safe_fmax_vmin = fmax * (100 - 10) / 100;
1008 nvkm_debug(subdev, "safe fmax @ vmin = %u Khz\n", clk->safe_fmax_vmin);
1009
1010 return 0;
1011 }
1012
1013 int
1014 gm20b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
1015 struct nvkm_clk **pclk)
1016 {
1017 struct nvkm_device_tegra *tdev = device->func->tegra(device);
1018 struct gm20b_clk *clk;
1019 struct nvkm_subdev *subdev;
1020 struct gk20a_clk_pllg_params *clk_params;
1021 int ret;
1022
1023
1024 if (tdev->gpu_speedo_id == 0)
1025 return gm20b_clk_new_speedo0(device, type, inst, pclk);
1026
1027
1028 clk = kzalloc(sizeof(*clk) + sizeof(*clk_params), GFP_KERNEL);
1029 if (!clk)
1030 return -ENOMEM;
1031 *pclk = &clk->base.base;
1032 subdev = &clk->base.base.subdev;
1033
1034
1035 clk_params = (void *) (clk + 1);
1036 *clk_params = gm20b_pllg_params;
1037 ret = gk20a_clk_ctor(device, type, inst, &gm20b_clk, clk_params, &clk->base);
1038 if (ret)
1039 return ret;
1040
1041
1042
1043
1044
1045 clk_params->max_m = clk_params->min_m = DIV_ROUND_UP(clk_params->max_u,
1046 (clk->base.parent_rate / KHZ));
1047 if (clk_params->max_m == 0) {
1048 nvkm_warn(subdev, "cannot use NAPLL, using legacy clock...\n");
1049 kfree(clk);
1050 return gm20b_clk_new_speedo0(device, type, inst, pclk);
1051 }
1052
1053 clk->base.pl_to_div = pl_to_div;
1054 clk->base.div_to_pl = div_to_pl;
1055
1056 clk->dvfs_params = &gm20b_dvfs_params;
1057
1058 ret = gm20b_clk_init_fused_params(clk);
1059
1060
1061
1062
1063 if (ret)
1064 nvkm_warn(subdev, "no fused calibration parameters\n");
1065
1066 ret = gm20b_clk_init_safe_fmax(clk);
1067 if (ret)
1068 return ret;
1069
1070 return 0;
1071 }