@@ -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
582621error_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