@@ -389,6 +389,159 @@ const struct clk_ops clk_stm32_divider_ops = {
389389 .set_rate = clk_stm32_divider_set_rate ,
390390};
391391
392+ static int clk_stm32_composite_set_rate (struct clk_hw * hw , unsigned long rate ,
393+ unsigned long parent_rate )
394+ {
395+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
396+ unsigned long flags = 0 ;
397+ int ret ;
398+
399+ if (composite -> div_id == NO_STM32_DIV )
400+ return rate ;
401+
402+ spin_lock_irqsave (composite -> lock , flags );
403+
404+ ret = stm32_divider_set_rate (composite -> base , composite -> clock_data ,
405+ composite -> div_id , rate , parent_rate );
406+
407+ spin_unlock_irqrestore (composite -> lock , flags );
408+
409+ return ret ;
410+ }
411+
412+ static unsigned long clk_stm32_composite_recalc_rate (struct clk_hw * hw ,
413+ unsigned long parent_rate )
414+ {
415+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
416+
417+ if (composite -> div_id == NO_STM32_DIV )
418+ return parent_rate ;
419+
420+ return stm32_divider_get_rate (composite -> base , composite -> clock_data ,
421+ composite -> div_id , parent_rate );
422+ }
423+
424+ static long clk_stm32_composite_round_rate (struct clk_hw * hw , unsigned long rate ,
425+ unsigned long * prate )
426+ {
427+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
428+
429+ const struct stm32_div_cfg * divider ;
430+
431+ if (composite -> div_id == NO_STM32_DIV )
432+ return rate ;
433+
434+ divider = & composite -> clock_data -> dividers [composite -> div_id ];
435+
436+ /* if read only, just return current value */
437+ if (divider -> flags & CLK_DIVIDER_READ_ONLY ) {
438+ u32 val ;
439+
440+ val = readl (composite -> base + divider -> offset ) >> divider -> shift ;
441+ val &= clk_div_mask (divider -> width );
442+
443+ return divider_ro_round_rate (hw , rate , prate , divider -> table ,
444+ divider -> width , divider -> flags ,
445+ val );
446+ }
447+
448+ return divider_round_rate_parent (hw , clk_hw_get_parent (hw ),
449+ rate , prate , divider -> table ,
450+ divider -> width , divider -> flags );
451+ }
452+
453+ static u8 clk_stm32_composite_get_parent (struct clk_hw * hw )
454+ {
455+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
456+
457+ return stm32_mux_get_parent (composite -> base , composite -> clock_data , composite -> mux_id );
458+ }
459+
460+ static int clk_stm32_composite_set_parent (struct clk_hw * hw , u8 index )
461+ {
462+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
463+ unsigned long flags = 0 ;
464+
465+ spin_lock_irqsave (composite -> lock , flags );
466+
467+ stm32_mux_set_parent (composite -> base , composite -> clock_data , composite -> mux_id , index );
468+
469+ spin_unlock_irqrestore (composite -> lock , flags );
470+
471+ return 0 ;
472+ }
473+
474+ static int clk_stm32_composite_is_enabled (struct clk_hw * hw )
475+ {
476+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
477+
478+ if (composite -> gate_id == NO_STM32_GATE )
479+ return (__clk_get_enable_count (hw -> clk ) > 0 );
480+
481+ return stm32_gate_is_enabled (composite -> base , composite -> clock_data , composite -> gate_id );
482+ }
483+
484+ static void clk_stm32_composite_gate_endisable (struct clk_hw * hw , int enable )
485+ {
486+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
487+ unsigned long flags = 0 ;
488+
489+ spin_lock_irqsave (composite -> lock , flags );
490+
491+ stm32_gate_endisable (composite -> base , composite -> clock_data , composite -> gate_id , enable );
492+
493+ spin_unlock_irqrestore (composite -> lock , flags );
494+ }
495+
496+ static int clk_stm32_composite_gate_enable (struct clk_hw * hw )
497+ {
498+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
499+
500+ if (composite -> gate_id == NO_STM32_GATE )
501+ return 0 ;
502+
503+ clk_stm32_composite_gate_endisable (hw , 1 );
504+
505+ return 0 ;
506+ }
507+
508+ static void clk_stm32_composite_gate_disable (struct clk_hw * hw )
509+ {
510+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
511+
512+ if (composite -> gate_id == NO_STM32_GATE )
513+ return ;
514+
515+ clk_stm32_composite_gate_endisable (hw , 0 );
516+ }
517+
518+ static void clk_stm32_composite_disable_unused (struct clk_hw * hw )
519+ {
520+ struct clk_stm32_composite * composite = to_clk_stm32_composite (hw );
521+ unsigned long flags = 0 ;
522+
523+ if (composite -> gate_id == NO_STM32_GATE )
524+ return ;
525+
526+ spin_lock_irqsave (composite -> lock , flags );
527+
528+ stm32_gate_disable_unused (composite -> base , composite -> clock_data , composite -> gate_id );
529+
530+ spin_unlock_irqrestore (composite -> lock , flags );
531+ }
532+
533+ const struct clk_ops clk_stm32_composite_ops = {
534+ .set_rate = clk_stm32_composite_set_rate ,
535+ .recalc_rate = clk_stm32_composite_recalc_rate ,
536+ .round_rate = clk_stm32_composite_round_rate ,
537+ .get_parent = clk_stm32_composite_get_parent ,
538+ .set_parent = clk_stm32_composite_set_parent ,
539+ .enable = clk_stm32_composite_gate_enable ,
540+ .disable = clk_stm32_composite_gate_disable ,
541+ .is_enabled = clk_stm32_composite_is_enabled ,
542+ .disable_unused = clk_stm32_composite_disable_unused ,
543+ };
544+
392545struct clk_hw * clk_stm32_mux_register (struct device * dev ,
393546 const struct stm32_rcc_match_data * data ,
394547 void __iomem * base ,
@@ -451,3 +604,24 @@ struct clk_hw *clk_stm32_div_register(struct device *dev,
451604
452605 return hw ;
453606}
607+
608+ struct clk_hw * clk_stm32_composite_register (struct device * dev ,
609+ const struct stm32_rcc_match_data * data ,
610+ void __iomem * base ,
611+ spinlock_t * lock ,
612+ const struct clock_config * cfg )
613+ {
614+ struct clk_stm32_composite * composite = cfg -> clock_cfg ;
615+ struct clk_hw * hw = & composite -> hw ;
616+ int err ;
617+
618+ composite -> base = base ;
619+ composite -> lock = lock ;
620+ composite -> clock_data = data -> clock_data ;
621+
622+ err = clk_hw_register (dev , hw );
623+ if (err )
624+ return ERR_PTR (err );
625+
626+ return hw ;
627+ }
0 commit comments