Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0019  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0020  * DEALINGS IN THE SOFTWARE.
0021  *
0022  * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c
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 /* PL:   0, 1, 2, 3, 4, 5, 6,  7,  8,  9, 10, 11, 12, 13, 14 */
0033 /* p: */ 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     /* min_pl <= high_pl <= max_pl */
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     /* min_pl <= low_pl <= max_pl */
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     /* Select lowest possible VCO */
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     /* get old coefficients */
0219     gk20a_pllg_read_mnp(clk, &pll);
0220     /* do nothing if NDIV is the same */
0221     if (n == pll.n)
0222         return 0;
0223 
0224     /* pll slowdown mode */
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     /* new ndiv ready for ramp */
0230     pll.n = n;
0231     udelay(1);
0232     gk20a_pllg_write_mnp(clk, &pll);
0233 
0234     /* dynamic ramp to new ndiv */
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     /* wait for ramping to complete */
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     /* exit slowdown mode */
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     /* enable lock detection */
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     /* wait for lock */
0272     if (nvkm_wait_usec(device, 300, GPCPLL_CFG, GPCPLL_CFG_LOCK,
0273                GPCPLL_CFG_LOCK) < 0)
0274         return -ETIMEDOUT;
0275 
0276     /* switch to VCO mode */
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     /* put PLL in bypass before disabling it */
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     /* split VCO-to-bypass jump in half by setting out divider 1:2 */
0306     nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0307           GPC2CLK_OUT_VCODIV2 << GPC2CLK_OUT_VCODIV_SHIFT);
0308     /* Intentional 2nd write to assure linear divider operation */
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     /* restore out divider 1:1 */
0323     udelay(2);
0324     nvkm_mask(device, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK,
0325           GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT);
0326     /* Intentional 2nd write to assure linear divider operation */
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         /* just do NDIV slide if there is no change to M and PL */
0344         if (pll->m == cur_pll.m && pll->pl == cur_pll.pl)
0345             return gk20a_pllg_slide(clk, pll->n);
0346 
0347         /* slide down to current NDIV_LO */
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     /* program MNP with the new clock parameters and new NDIV_LO */
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     /* slide up to new NDIV */
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     /* slide to VCO min */
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     /* set IDDQ */
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     /* get out from IDDQ */
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     /* Start with lowest frequency */
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     /* Finish initializing the pstates */
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 }