@@ -529,6 +529,182 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
529529}
530530EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_floor );
531531
532+ /*
533+ * The caller needs to ensure that device_opp (and hence the clk) isn't freed,
534+ * while clk returned here is used.
535+ */
536+ static struct clk * _get_opp_clk (struct device * dev )
537+ {
538+ struct device_opp * dev_opp ;
539+ struct clk * clk ;
540+
541+ rcu_read_lock ();
542+
543+ dev_opp = _find_device_opp (dev );
544+ if (IS_ERR (dev_opp )) {
545+ dev_err (dev , "%s: device opp doesn't exist\n" , __func__ );
546+ clk = ERR_CAST (dev_opp );
547+ goto unlock ;
548+ }
549+
550+ clk = dev_opp -> clk ;
551+ if (IS_ERR (clk ))
552+ dev_err (dev , "%s: No clock available for the device\n" ,
553+ __func__ );
554+
555+ unlock :
556+ rcu_read_unlock ();
557+ return clk ;
558+ }
559+
560+ static int _set_opp_voltage (struct device * dev , struct regulator * reg ,
561+ unsigned long u_volt , unsigned long u_volt_min ,
562+ unsigned long u_volt_max )
563+ {
564+ int ret ;
565+
566+ /* Regulator not available for device */
567+ if (IS_ERR (reg )) {
568+ dev_dbg (dev , "%s: regulator not available: %ld\n" , __func__ ,
569+ PTR_ERR (reg ));
570+ return 0 ;
571+ }
572+
573+ dev_dbg (dev , "%s: voltages (mV): %lu %lu %lu\n" , __func__ , u_volt_min ,
574+ u_volt , u_volt_max );
575+
576+ ret = regulator_set_voltage_triplet (reg , u_volt_min , u_volt ,
577+ u_volt_max );
578+ if (ret )
579+ dev_err (dev , "%s: failed to set voltage (%lu %lu %lu mV): %d\n" ,
580+ __func__ , u_volt_min , u_volt , u_volt_max , ret );
581+
582+ return ret ;
583+ }
584+
585+ /**
586+ * dev_pm_opp_set_rate() - Configure new OPP based on frequency
587+ * @dev: device for which we do this operation
588+ * @target_freq: frequency to achieve
589+ *
590+ * This configures the power-supplies and clock source to the levels specified
591+ * by the OPP corresponding to the target_freq.
592+ *
593+ * Locking: This function takes rcu_read_lock().
594+ */
595+ int dev_pm_opp_set_rate (struct device * dev , unsigned long target_freq )
596+ {
597+ struct device_opp * dev_opp ;
598+ struct dev_pm_opp * old_opp , * opp ;
599+ struct regulator * reg ;
600+ struct clk * clk ;
601+ unsigned long freq , old_freq ;
602+ unsigned long u_volt , u_volt_min , u_volt_max ;
603+ unsigned long ou_volt , ou_volt_min , ou_volt_max ;
604+ int ret ;
605+
606+ if (unlikely (!target_freq )) {
607+ dev_err (dev , "%s: Invalid target frequency %lu\n" , __func__ ,
608+ target_freq );
609+ return - EINVAL ;
610+ }
611+
612+ clk = _get_opp_clk (dev );
613+ if (IS_ERR (clk ))
614+ return PTR_ERR (clk );
615+
616+ freq = clk_round_rate (clk , target_freq );
617+ if ((long )freq <= 0 )
618+ freq = target_freq ;
619+
620+ old_freq = clk_get_rate (clk );
621+
622+ /* Return early if nothing to do */
623+ if (old_freq == freq ) {
624+ dev_dbg (dev , "%s: old/new frequencies (%lu Hz) are same, nothing to do\n" ,
625+ __func__ , freq );
626+ return 0 ;
627+ }
628+
629+ rcu_read_lock ();
630+
631+ dev_opp = _find_device_opp (dev );
632+ if (IS_ERR (dev_opp )) {
633+ dev_err (dev , "%s: device opp doesn't exist\n" , __func__ );
634+ rcu_read_unlock ();
635+ return PTR_ERR (dev_opp );
636+ }
637+
638+ old_opp = dev_pm_opp_find_freq_ceil (dev , & old_freq );
639+ if (!IS_ERR (old_opp )) {
640+ ou_volt = old_opp -> u_volt ;
641+ ou_volt_min = old_opp -> u_volt_min ;
642+ ou_volt_max = old_opp -> u_volt_max ;
643+ } else {
644+ dev_err (dev , "%s: failed to find current OPP for freq %lu (%ld)\n" ,
645+ __func__ , old_freq , PTR_ERR (old_opp ));
646+ }
647+
648+ opp = dev_pm_opp_find_freq_ceil (dev , & freq );
649+ if (IS_ERR (opp )) {
650+ ret = PTR_ERR (opp );
651+ dev_err (dev , "%s: failed to find OPP for freq %lu (%d)\n" ,
652+ __func__ , freq , ret );
653+ rcu_read_unlock ();
654+ return ret ;
655+ }
656+
657+ u_volt = opp -> u_volt ;
658+ u_volt_min = opp -> u_volt_min ;
659+ u_volt_max = opp -> u_volt_max ;
660+
661+ reg = dev_opp -> regulator ;
662+
663+ rcu_read_unlock ();
664+
665+ /* Scaling up? Scale voltage before frequency */
666+ if (freq > old_freq ) {
667+ ret = _set_opp_voltage (dev , reg , u_volt , u_volt_min ,
668+ u_volt_max );
669+ if (ret )
670+ goto restore_voltage ;
671+ }
672+
673+ /* Change frequency */
674+
675+ dev_dbg (dev , "%s: switching OPP: %lu Hz --> %lu Hz\n" ,
676+ __func__ , old_freq , freq );
677+
678+ ret = clk_set_rate (clk , freq );
679+ if (ret ) {
680+ dev_err (dev , "%s: failed to set clock rate: %d\n" , __func__ ,
681+ ret );
682+ goto restore_voltage ;
683+ }
684+
685+ /* Scaling down? Scale voltage after frequency */
686+ if (freq < old_freq ) {
687+ ret = _set_opp_voltage (dev , reg , u_volt , u_volt_min ,
688+ u_volt_max );
689+ if (ret )
690+ goto restore_freq ;
691+ }
692+
693+ return 0 ;
694+
695+ restore_freq :
696+ if (clk_set_rate (clk , old_freq ))
697+ dev_err (dev , "%s: failed to restore old-freq (%lu Hz)\n" ,
698+ __func__ , old_freq );
699+ restore_voltage :
700+ /* This shouldn't harm even if the voltages weren't updated earlier */
701+ if (!IS_ERR (old_opp ))
702+ _set_opp_voltage (dev , reg , ou_volt , ou_volt_min , ou_volt_max );
703+
704+ return ret ;
705+ }
706+ EXPORT_SYMBOL_GPL (dev_pm_opp_set_rate );
707+
532708/* List-dev Helpers */
533709static void _kfree_list_dev_rcu (struct rcu_head * head )
534710{
0 commit comments