drm/nouveau/clk/gk20a: abstract pl_to_div
pl_to_div may be done differently depending on the chip. Abstract this operation so the same logic can be reused for them as well. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
a04bc140aa
commit
195c113773
|
@ -93,7 +93,7 @@
|
||||||
#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
|
#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \
|
||||||
(0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
|
(0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT)
|
||||||
|
|
||||||
static const u8 pl_to_div[] = {
|
static const u8 _pl_to_div[] = {
|
||||||
/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */
|
/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */
|
||||||
/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
|
/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32,
|
||||||
};
|
};
|
||||||
|
@ -106,6 +106,25 @@ struct gk20a_clk_pllg_params {
|
||||||
u32 min_n, max_n;
|
u32 min_n, max_n;
|
||||||
u32 min_pl, max_pl;
|
u32 min_pl, max_pl;
|
||||||
};
|
};
|
||||||
|
static u32 pl_to_div(u32 pl)
|
||||||
|
{
|
||||||
|
if (pl >= ARRAY_SIZE(_pl_to_div))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return _pl_to_div[pl];
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 div_to_pl(u32 div)
|
||||||
|
{
|
||||||
|
u32 pl;
|
||||||
|
|
||||||
|
for (pl = 0; pl < ARRAY_SIZE(_pl_to_div) - 1; pl++) {
|
||||||
|
if (_pl_to_div[pl] >= div)
|
||||||
|
return pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ARRAY_SIZE(_pl_to_div) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
|
static const struct gk20a_clk_pllg_params gk20a_pllg_params = {
|
||||||
.min_vco = 1000000, .max_vco = 2064000,
|
.min_vco = 1000000, .max_vco = 2064000,
|
||||||
|
@ -126,6 +145,9 @@ struct gk20a_clk {
|
||||||
const struct gk20a_clk_pllg_params *params;
|
const struct gk20a_clk_pllg_params *params;
|
||||||
struct gk20a_pll pll;
|
struct gk20a_pll pll;
|
||||||
u32 parent_rate;
|
u32 parent_rate;
|
||||||
|
|
||||||
|
u32 (*div_to_pl)(u32);
|
||||||
|
u32 (*pl_to_div)(u32);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -147,7 +169,7 @@ gk20a_pllg_calc_rate(struct gk20a_clk *clk)
|
||||||
u32 divider;
|
u32 divider;
|
||||||
|
|
||||||
rate = clk->parent_rate * clk->pll.n;
|
rate = clk->parent_rate * clk->pll.n;
|
||||||
divider = clk->pll.m * pl_to_div[clk->pll.pl];
|
divider = clk->pll.m * clk->pl_to_div(clk->pll.pl);
|
||||||
|
|
||||||
return rate / divider / 2;
|
return rate / divider / 2;
|
||||||
}
|
}
|
||||||
|
@ -181,34 +203,23 @@ gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate)
|
||||||
high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
|
high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f;
|
||||||
high_pl = min(high_pl, clk->params->max_pl);
|
high_pl = min(high_pl, clk->params->max_pl);
|
||||||
high_pl = max(high_pl, clk->params->min_pl);
|
high_pl = max(high_pl, clk->params->min_pl);
|
||||||
|
high_pl = clk->div_to_pl(high_pl);
|
||||||
|
|
||||||
/* min_pl <= low_pl <= max_pl */
|
/* min_pl <= low_pl <= max_pl */
|
||||||
low_pl = min_vco_f / target_vco_f;
|
low_pl = min_vco_f / target_vco_f;
|
||||||
low_pl = min(low_pl, clk->params->max_pl);
|
low_pl = min(low_pl, clk->params->max_pl);
|
||||||
low_pl = max(low_pl, clk->params->min_pl);
|
low_pl = max(low_pl, clk->params->min_pl);
|
||||||
|
low_pl = clk->div_to_pl(low_pl);
|
||||||
/* Find Indices of high_pl and low_pl */
|
|
||||||
for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
|
|
||||||
if (pl_to_div[pl] >= low_pl) {
|
|
||||||
low_pl = pl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) {
|
|
||||||
if (pl_to_div[pl] >= high_pl) {
|
|
||||||
high_pl = pl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nvkm_debug(subdev, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
|
nvkm_debug(subdev, "low_PL %d(div%d), high_PL %d(div%d)", low_pl,
|
||||||
pl_to_div[low_pl], high_pl, pl_to_div[high_pl]);
|
clk->pl_to_div(low_pl), high_pl, clk->pl_to_div(high_pl));
|
||||||
|
|
||||||
/* Select lowest possible VCO */
|
/* Select lowest possible VCO */
|
||||||
for (pl = low_pl; pl <= high_pl; pl++) {
|
for (pl = low_pl; pl <= high_pl; pl++) {
|
||||||
u32 m, n, n2;
|
u32 m, n, n2;
|
||||||
|
|
||||||
target_vco_f = target_clk_f * pl_to_div[pl];
|
target_vco_f = target_clk_f * clk->pl_to_div(pl);
|
||||||
|
|
||||||
for (m = clk->params->min_m; m <= clk->params->max_m; m++) {
|
for (m = clk->params->min_m; m <= clk->params->max_m; m++) {
|
||||||
u32 u_f, vco_f;
|
u32 u_f, vco_f;
|
||||||
|
|
||||||
|
@ -236,8 +247,8 @@ gk20a_pllg_calc_mnp(struct gk20a_clk *clk, unsigned long rate)
|
||||||
if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
|
if (vco_f >= min_vco_f && vco_f <= max_vco_f) {
|
||||||
u32 delta, lwv;
|
u32 delta, lwv;
|
||||||
|
|
||||||
lwv = (vco_f + (pl_to_div[pl] / 2))
|
lwv = (vco_f + (clk->pl_to_div(pl) / 2))
|
||||||
/ pl_to_div[pl];
|
/ clk->pl_to_div(pl);
|
||||||
delta = abs(lwv - target_clk_f);
|
delta = abs(lwv - target_clk_f);
|
||||||
|
|
||||||
if (delta < best_delta) {
|
if (delta < best_delta) {
|
||||||
|
@ -271,7 +282,7 @@ found_match:
|
||||||
nvkm_debug(subdev,
|
nvkm_debug(subdev,
|
||||||
"actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n",
|
"actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n",
|
||||||
target_freq / MHZ, clk->pll.m, clk->pll.n, clk->pll.pl,
|
target_freq / MHZ, clk->pll.m, clk->pll.n, clk->pll.pl,
|
||||||
pl_to_div[clk->pll.pl]);
|
clk->pl_to_div(clk->pll.pl));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,5 +693,9 @@ gk20a_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
|
||||||
ret = nvkm_clk_ctor(&gk20a_clk, device, index, true, &clk->base);
|
ret = nvkm_clk_ctor(&gk20a_clk, device, index, true, &clk->base);
|
||||||
nvkm_debug(&clk->base.subdev, "parent clock rate: %d Khz\n",
|
nvkm_debug(&clk->base.subdev, "parent clock rate: %d Khz\n",
|
||||||
clk->parent_rate / KHZ);
|
clk->parent_rate / KHZ);
|
||||||
|
|
||||||
|
clk->pl_to_div = pl_to_div;
|
||||||
|
clk->div_to_pl = div_to_pl;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue