@@ -260,9 +260,18 @@ static void xvcu_write_field_reg(void __iomem *iomem, int offset,
260260 xvcu_write (iomem , offset , val );
261261}
262262
263- static int xvcu_pll_wait_for_lock (struct xvcu_device * xvcu )
263+ #define to_vcu_pll (_hw ) container_of(_hw, struct vcu_pll, hw)
264+
265+ struct vcu_pll {
266+ struct clk_hw hw ;
267+ void __iomem * reg_base ;
268+ unsigned long fvco_min ;
269+ unsigned long fvco_max ;
270+ };
271+
272+ static int xvcu_pll_wait_for_lock (struct vcu_pll * pll )
264273{
265- void __iomem * base = xvcu -> vcu_slcr_ba ;
274+ void __iomem * base = pll -> reg_base ;
266275 unsigned long timeout ;
267276 u32 lock_status ;
268277
@@ -311,9 +320,9 @@ static const struct xvcu_pll_cfg *xvcu_find_cfg(int div)
311320 return cfg ;
312321}
313322
314- static int xvcu_pll_set_div (struct xvcu_device * xvcu , int div )
323+ static int xvcu_pll_set_div (struct vcu_pll * pll , int div )
315324{
316- void __iomem * base = xvcu -> vcu_slcr_ba ;
325+ void __iomem * base = pll -> reg_base ;
317326 const struct xvcu_pll_cfg * cfg = NULL ;
318327 u32 vcu_pll_ctrl ;
319328 u32 cfg_val ;
@@ -338,24 +347,49 @@ static int xvcu_pll_set_div(struct xvcu_device *xvcu, int div)
338347 return 0 ;
339348}
340349
341- static int xvcu_pll_set_rate (struct xvcu_device * xvcu ,
350+ static long xvcu_pll_round_rate (struct clk_hw * hw ,
351+ unsigned long rate , unsigned long * parent_rate )
352+ {
353+ struct vcu_pll * pll = to_vcu_pll (hw );
354+ unsigned int feedback_div ;
355+
356+ rate = clamp_t (unsigned long , rate , pll -> fvco_min , pll -> fvco_max );
357+
358+ feedback_div = DIV_ROUND_CLOSEST_ULL (rate , * parent_rate );
359+ feedback_div = clamp_t (unsigned int , feedback_div , 25 , 125 );
360+
361+ return * parent_rate * feedback_div ;
362+ }
363+
364+ static unsigned long xvcu_pll_recalc_rate (struct clk_hw * hw ,
365+ unsigned long parent_rate )
366+ {
367+ struct vcu_pll * pll = to_vcu_pll (hw );
368+ void __iomem * base = pll -> reg_base ;
369+ unsigned int div ;
370+ u32 vcu_pll_ctrl ;
371+
372+ vcu_pll_ctrl = xvcu_read (base , VCU_PLL_CTRL );
373+ div = (vcu_pll_ctrl >> VCU_PLL_CTRL_FBDIV_SHIFT ) & VCU_PLL_CTRL_FBDIV_MASK ;
374+
375+ return div * parent_rate ;
376+ }
377+
378+ static int xvcu_pll_set_rate (struct clk_hw * hw ,
342379 unsigned long rate , unsigned long parent_rate )
343380{
344- return xvcu_pll_set_div (xvcu , rate / parent_rate );
381+ struct vcu_pll * pll = to_vcu_pll (hw );
382+
383+ return xvcu_pll_set_div (pll , rate / parent_rate );
345384}
346385
347- static int xvcu_pll_enable (struct xvcu_device * xvcu )
386+ static int xvcu_pll_enable (struct clk_hw * hw )
348387{
349- void __iomem * base = xvcu -> vcu_slcr_ba ;
388+ struct vcu_pll * pll = to_vcu_pll (hw );
389+ void __iomem * base = pll -> reg_base ;
350390 u32 vcu_pll_ctrl ;
351391 int ret ;
352392
353- ret = clk_prepare_enable (xvcu -> pll_ref );
354- if (ret ) {
355- dev_err (xvcu -> dev , "failed to enable pll_ref clock source\n" );
356- return ret ;
357- }
358-
359393 xvcu_write_field_reg (base , VCU_PLL_CTRL ,
360394 1 , VCU_PLL_CTRL_BYPASS_MASK ,
361395 VCU_PLL_CTRL_BYPASS_SHIFT );
@@ -375,25 +409,24 @@ static int xvcu_pll_enable(struct xvcu_device *xvcu)
375409 vcu_pll_ctrl |= (0 & VCU_PLL_CTRL_RESET_MASK ) << VCU_PLL_CTRL_RESET_SHIFT ;
376410 xvcu_write (base , VCU_PLL_CTRL , vcu_pll_ctrl );
377411
378- ret = xvcu_pll_wait_for_lock (xvcu );
412+ ret = xvcu_pll_wait_for_lock (pll );
379413 if (ret ) {
380- dev_err ( xvcu -> dev , " PLL is not locked\n" );
414+ pr_err ( "VCU PLL is not locked\n" );
381415 goto err ;
382416 }
383417
384418 xvcu_write_field_reg (base , VCU_PLL_CTRL ,
385419 0 , VCU_PLL_CTRL_BYPASS_MASK ,
386420 VCU_PLL_CTRL_BYPASS_SHIFT );
387421
388- return ret ;
389422err :
390- clk_disable_unprepare (xvcu -> pll_ref );
391423 return ret ;
392424}
393425
394- static void xvcu_pll_disable (struct xvcu_device * xvcu )
426+ static void xvcu_pll_disable (struct clk_hw * hw )
395427{
396- void __iomem * base = xvcu -> vcu_slcr_ba ;
428+ struct vcu_pll * pll = to_vcu_pll (hw );
429+ void __iomem * base = pll -> reg_base ;
397430 u32 vcu_pll_ctrl ;
398431
399432 vcu_pll_ctrl = xvcu_read (base , VCU_PLL_CTRL );
@@ -404,8 +437,49 @@ static void xvcu_pll_disable(struct xvcu_device *xvcu)
404437 vcu_pll_ctrl &= ~(VCU_PLL_CTRL_RESET_MASK << VCU_PLL_CTRL_RESET_SHIFT );
405438 vcu_pll_ctrl |= (1 & VCU_PLL_CTRL_RESET_MASK ) << VCU_PLL_CTRL_RESET_SHIFT ;
406439 xvcu_write (base , VCU_PLL_CTRL , vcu_pll_ctrl );
440+ }
441+
442+ static const struct clk_ops vcu_pll_ops = {
443+ .enable = xvcu_pll_enable ,
444+ .disable = xvcu_pll_disable ,
445+ .round_rate = xvcu_pll_round_rate ,
446+ .recalc_rate = xvcu_pll_recalc_rate ,
447+ .set_rate = xvcu_pll_set_rate ,
448+ };
407449
408- clk_disable_unprepare (xvcu -> pll_ref );
450+ static struct clk_hw * xvcu_register_pll (struct device * dev ,
451+ void __iomem * reg_base ,
452+ const char * name , const char * parent ,
453+ unsigned long flags )
454+ {
455+ struct vcu_pll * pll ;
456+ struct clk_hw * hw ;
457+ struct clk_init_data init ;
458+ int ret ;
459+
460+ init .name = name ;
461+ init .parent_names = & parent ;
462+ init .ops = & vcu_pll_ops ;
463+ init .num_parents = 1 ;
464+ init .flags = flags ;
465+
466+ pll = devm_kmalloc (dev , sizeof (* pll ), GFP_KERNEL );
467+ if (!pll )
468+ return ERR_PTR (- ENOMEM );
469+
470+ pll -> hw .init = & init ;
471+ pll -> reg_base = reg_base ;
472+ pll -> fvco_min = FVCO_MIN ;
473+ pll -> fvco_max = FVCO_MAX ;
474+
475+ hw = & pll -> hw ;
476+ ret = devm_clk_hw_register (dev , hw );
477+ if (ret )
478+ return ERR_PTR (ret );
479+
480+ clk_hw_set_rate_range (hw , pll -> fvco_min , pll -> fvco_max );
481+
482+ return hw ;
409483}
410484
411485/**
@@ -430,9 +504,7 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
430504 u32 pll_clk ;
431505 u32 mod ;
432506 int i ;
433- int ret ;
434507 const struct xvcu_pll_cfg * found = NULL ;
435- struct clk_hw * hw ;
436508
437509 regmap_read (xvcu -> logicore_reg_ba , VCU_PLL_CLK , & inte );
438510 regmap_read (xvcu -> logicore_reg_ba , VCU_PLL_CLK_DEC , & deci );
@@ -490,17 +562,6 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
490562 dev_dbg (xvcu -> dev , "Actual Core clock freq is %uHz\n" , coreclk );
491563 dev_dbg (xvcu -> dev , "Actual Mcu clock freq is %uHz\n" , mcuclk );
492564
493- ret = xvcu_pll_set_rate (xvcu , fvco , refclk );
494- if (ret )
495- return ret ;
496-
497- hw = clk_hw_register_fixed_rate (xvcu -> dev , "vcu_pll" ,
498- __clk_get_name (xvcu -> pll_ref ),
499- 0 , fvco );
500- if (IS_ERR (hw ))
501- return PTR_ERR (hw );
502- xvcu -> pll = hw ;
503-
504565 return 0 ;
505566}
506567
@@ -523,7 +584,7 @@ static int xvcu_set_pll(struct xvcu_device *xvcu)
523584 return ret ;
524585 }
525586
526- return xvcu_pll_enable ( xvcu ) ;
587+ return 0 ;
527588}
528589
529590static struct clk_hw * xvcu_clk_hw_register_leaf (struct device * dev ,
@@ -630,6 +691,13 @@ static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
630691
631692 xvcu -> clk_data = data ;
632693
694+ hw = xvcu_register_pll (dev , reg_base ,
695+ "vcu_pll" , __clk_get_name (xvcu -> pll_ref ),
696+ CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE );
697+ if (IS_ERR (hw ))
698+ return PTR_ERR (hw );
699+ xvcu -> pll = hw ;
700+
633701 hw = xvcu_register_pll_post (dev , "vcu_pll_post" , xvcu -> pll , reg_base );
634702 if (IS_ERR (hw ))
635703 return PTR_ERR (hw );
@@ -811,8 +879,6 @@ static int xvcu_remove(struct platform_device *pdev)
811879 /* Add the the Gasket isolation and put the VCU in reset. */
812880 regmap_write (xvcu -> logicore_reg_ba , VCU_GASKET_INIT , 0 );
813881
814- clk_hw_unregister_fixed_rate (xvcu -> pll );
815- xvcu_pll_disable (xvcu );
816882 clk_disable_unprepare (xvcu -> aclk );
817883
818884 return 0 ;
0 commit comments