Skip to content

Commit 354dcf7

Browse files
tretterbebarino
authored andcommitted
soc: xilinx: vcu: add helpers for configuring PLL
The xvcu_set_vcu_pll_info function sets the rate of the PLL and enables it, which makes it difficult to cleanly convert the driver to the common clock framework. Split the function and add separate functions for setting the rate, enabling the clock and disabling the clock. Also move the enable of the reference clock from probe to the helper that enables the PLL. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> Acked-by: Michal Simek <michal.simek@xilinx.com> Link: https://lore.kernel.org/r/20210121071659.1226489-6-m.tretter@pengutronix.de Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent a3ab984 commit 354dcf7

1 file changed

Lines changed: 104 additions & 67 deletions

File tree

drivers/soc/xilinx/xlnx_vcu.c

Lines changed: 104 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,105 @@ static int xvcu_pll_wait_for_lock(struct xvcu_device *xvcu)
272272
return -ETIMEDOUT;
273273
}
274274

275+
static const struct xvcu_pll_cfg *xvcu_find_cfg(int div)
276+
{
277+
const struct xvcu_pll_cfg *cfg = NULL;
278+
unsigned int i;
279+
280+
for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++)
281+
if (xvcu_pll_cfg[i].fbdiv == div)
282+
cfg = &xvcu_pll_cfg[i];
283+
284+
return cfg;
285+
}
286+
287+
static int xvcu_pll_set_div(struct xvcu_device *xvcu, int div)
288+
{
289+
void __iomem *base = xvcu->vcu_slcr_ba;
290+
const struct xvcu_pll_cfg *cfg = NULL;
291+
u32 vcu_pll_ctrl;
292+
u32 cfg_val;
293+
294+
cfg = xvcu_find_cfg(div);
295+
if (!cfg)
296+
return -EINVAL;
297+
298+
vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
299+
vcu_pll_ctrl &= ~(VCU_PLL_CTRL_FBDIV_MASK << VCU_PLL_CTRL_FBDIV_SHIFT);
300+
vcu_pll_ctrl |= (cfg->fbdiv & VCU_PLL_CTRL_FBDIV_MASK) <<
301+
VCU_PLL_CTRL_FBDIV_SHIFT;
302+
xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
303+
304+
cfg_val = (cfg->res << VCU_PLL_CFG_RES_SHIFT) |
305+
(cfg->cp << VCU_PLL_CFG_CP_SHIFT) |
306+
(cfg->lfhf << VCU_PLL_CFG_LFHF_SHIFT) |
307+
(cfg->lock_cnt << VCU_PLL_CFG_LOCK_CNT_SHIFT) |
308+
(cfg->lock_dly << VCU_PLL_CFG_LOCK_DLY_SHIFT);
309+
xvcu_write(base, VCU_PLL_CFG, cfg_val);
310+
311+
return 0;
312+
}
313+
314+
static int xvcu_pll_set_rate(struct xvcu_device *xvcu,
315+
unsigned long rate, unsigned long parent_rate)
316+
{
317+
return xvcu_pll_set_div(xvcu, rate / parent_rate);
318+
}
319+
320+
static int xvcu_pll_enable(struct xvcu_device *xvcu)
321+
{
322+
void __iomem *base = xvcu->vcu_slcr_ba;
323+
u32 vcu_pll_ctrl;
324+
int ret;
325+
326+
ret = clk_prepare_enable(xvcu->pll_ref);
327+
if (ret) {
328+
dev_err(xvcu->dev, "failed to enable pll_ref clock source\n");
329+
return ret;
330+
}
331+
332+
vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
333+
vcu_pll_ctrl &= ~(VCU_PLL_CTRL_POR_IN_MASK <<
334+
VCU_PLL_CTRL_POR_IN_SHIFT);
335+
vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_POR_IN_MASK) <<
336+
VCU_PLL_CTRL_POR_IN_SHIFT;
337+
vcu_pll_ctrl &= ~(VCU_PLL_CTRL_PWR_POR_MASK <<
338+
VCU_PLL_CTRL_PWR_POR_SHIFT);
339+
vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_PWR_POR_MASK) <<
340+
VCU_PLL_CTRL_PWR_POR_SHIFT;
341+
xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
342+
343+
xvcu_write_field_reg(base, VCU_PLL_CTRL,
344+
1, VCU_PLL_CTRL_BYPASS_MASK,
345+
VCU_PLL_CTRL_BYPASS_SHIFT);
346+
xvcu_write_field_reg(base, VCU_PLL_CTRL,
347+
1, VCU_PLL_CTRL_RESET_MASK,
348+
VCU_PLL_CTRL_RESET_SHIFT);
349+
xvcu_write_field_reg(base, VCU_PLL_CTRL,
350+
0, VCU_PLL_CTRL_RESET_MASK,
351+
VCU_PLL_CTRL_RESET_SHIFT);
352+
353+
ret = xvcu_pll_wait_for_lock(xvcu);
354+
if (ret) {
355+
dev_err(xvcu->dev, "PLL is not locked\n");
356+
goto err;
357+
}
358+
359+
xvcu_write_field_reg(base, VCU_PLL_CTRL,
360+
0, VCU_PLL_CTRL_BYPASS_MASK,
361+
VCU_PLL_CTRL_BYPASS_SHIFT);
362+
363+
return ret;
364+
err:
365+
clk_disable_unprepare(xvcu->pll_ref);
366+
return ret;
367+
}
368+
369+
static void xvcu_pll_disable(struct xvcu_device *xvcu)
370+
{
371+
clk_disable_unprepare(xvcu->pll_ref);
372+
}
373+
275374
/**
276375
* xvcu_set_vcu_pll_info - Set the VCU PLL info
277376
* @xvcu: Pointer to the xvcu_device structure
@@ -292,8 +391,8 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
292391
u32 refclk, coreclk, mcuclk, inte, deci;
293392
u32 divisor_mcu, divisor_core, fvco;
294393
u32 clkoutdiv, vcu_pll_ctrl, pll_clk;
295-
u32 cfg_val, mod, ctrl;
296-
int ret, i;
394+
u32 mod, ctrl;
395+
int i;
297396
const struct xvcu_pll_cfg *found = NULL;
298397

299398
regmap_read(xvcu->logicore_reg_ba, VCU_PLL_CLK, &inte);
@@ -312,19 +411,6 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
312411
dev_dbg(xvcu->dev, "Core clock from logicoreIP is %uHz\n", coreclk);
313412
dev_dbg(xvcu->dev, "Mcu clock from logicoreIP is %uHz\n", mcuclk);
314413

315-
clk_disable_unprepare(xvcu->pll_ref);
316-
ret = clk_set_rate(xvcu->pll_ref, refclk);
317-
if (ret)
318-
dev_warn(xvcu->dev, "failed to set logicoreIP refclk rate\n");
319-
320-
ret = clk_prepare_enable(xvcu->pll_ref);
321-
if (ret) {
322-
dev_err(xvcu->dev, "failed to enable pll_ref clock source\n");
323-
return ret;
324-
}
325-
326-
refclk = clk_get_rate(xvcu->pll_ref);
327-
328414
/*
329415
* The divide-by-2 should be always enabled (==1)
330416
* to meet the timing in the design.
@@ -378,19 +464,6 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
378464
dev_dbg(xvcu->dev, "Actual Core clock freq is %uHz\n", coreclk);
379465
dev_dbg(xvcu->dev, "Actual Mcu clock freq is %uHz\n", mcuclk);
380466

381-
vcu_pll_ctrl &= ~(VCU_PLL_CTRL_FBDIV_MASK << VCU_PLL_CTRL_FBDIV_SHIFT);
382-
vcu_pll_ctrl |= (found->fbdiv & VCU_PLL_CTRL_FBDIV_MASK) <<
383-
VCU_PLL_CTRL_FBDIV_SHIFT;
384-
vcu_pll_ctrl &= ~(VCU_PLL_CTRL_POR_IN_MASK <<
385-
VCU_PLL_CTRL_POR_IN_SHIFT);
386-
vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_POR_IN_MASK) <<
387-
VCU_PLL_CTRL_POR_IN_SHIFT;
388-
vcu_pll_ctrl &= ~(VCU_PLL_CTRL_PWR_POR_MASK <<
389-
VCU_PLL_CTRL_PWR_POR_SHIFT);
390-
vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_PWR_POR_MASK) <<
391-
VCU_PLL_CTRL_PWR_POR_SHIFT;
392-
xvcu_write(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, vcu_pll_ctrl);
393-
394467
/* Set divisor for the core and mcu clock */
395468
ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL);
396469
ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
@@ -422,15 +495,7 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
422495
ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
423496
xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL, ctrl);
424497

425-
/* Set RES, CP, LFHF, LOCK_CNT and LOCK_DLY cfg values */
426-
cfg_val = (found->res << VCU_PLL_CFG_RES_SHIFT) |
427-
(found->cp << VCU_PLL_CFG_CP_SHIFT) |
428-
(found->lfhf << VCU_PLL_CFG_LFHF_SHIFT) |
429-
(found->lock_cnt << VCU_PLL_CFG_LOCK_CNT_SHIFT) |
430-
(found->lock_dly << VCU_PLL_CFG_LOCK_DLY_SHIFT);
431-
xvcu_write(xvcu->vcu_slcr_ba, VCU_PLL_CFG, cfg_val);
432-
433-
return 0;
498+
return xvcu_pll_set_rate(xvcu, fvco, refclk);
434499
}
435500

436501
/**
@@ -452,27 +517,7 @@ static int xvcu_set_pll(struct xvcu_device *xvcu)
452517
return ret;
453518
}
454519

455-
xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL,
456-
1, VCU_PLL_CTRL_BYPASS_MASK,
457-
VCU_PLL_CTRL_BYPASS_SHIFT);
458-
xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL,
459-
1, VCU_PLL_CTRL_RESET_MASK,
460-
VCU_PLL_CTRL_RESET_SHIFT);
461-
xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL,
462-
0, VCU_PLL_CTRL_RESET_MASK,
463-
VCU_PLL_CTRL_RESET_SHIFT);
464-
465-
ret = xvcu_pll_wait_for_lock(xvcu);
466-
if (ret) {
467-
dev_err(xvcu->dev, "PLL is not locked\n");
468-
return ret;
469-
}
470-
471-
xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL,
472-
0, VCU_PLL_CTRL_BYPASS_MASK,
473-
VCU_PLL_CTRL_BYPASS_SHIFT);
474-
475-
return ret;
520+
return xvcu_pll_enable(xvcu);
476521
}
477522

478523
/**
@@ -555,12 +600,6 @@ static int xvcu_probe(struct platform_device *pdev)
555600
return ret;
556601
}
557602

558-
ret = clk_prepare_enable(xvcu->pll_ref);
559-
if (ret) {
560-
dev_err(&pdev->dev, "pll_ref clock enable failed\n");
561-
goto error_aclk;
562-
}
563-
564603
/*
565604
* Do the Gasket isolation and put the VCU out of reset
566605
* Bit 0 : Gasket isolation
@@ -580,8 +619,6 @@ static int xvcu_probe(struct platform_device *pdev)
580619
return 0;
581620

582621
error_pll_ref:
583-
clk_disable_unprepare(xvcu->pll_ref);
584-
error_aclk:
585622
clk_disable_unprepare(xvcu->aclk);
586623
return ret;
587624
}
@@ -605,7 +642,7 @@ static int xvcu_remove(struct platform_device *pdev)
605642
/* Add the the Gasket isolation and put the VCU in reset. */
606643
regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
607644

608-
clk_disable_unprepare(xvcu->pll_ref);
645+
xvcu_pll_disable(xvcu);
609646
clk_disable_unprepare(xvcu->aclk);
610647

611648
return 0;

0 commit comments

Comments
 (0)