@@ -729,6 +729,126 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
729
729
}
730
730
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_ceil_by_volt );
731
731
732
+ /**
733
+ * dev_pm_opp_find_bw_ceil() - Search for a rounded ceil bandwidth
734
+ * @dev: device for which we do this operation
735
+ * @freq: start bandwidth
736
+ * @index: which bandwidth to compare, in case of OPPs with several values
737
+ *
738
+ * Search for the matching floor *available* OPP from a starting bandwidth
739
+ * for a device.
740
+ *
741
+ * Return: matching *opp and refreshes *bw accordingly, else returns
742
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
743
+ * values can be:
744
+ * EINVAL: for bad pointer
745
+ * ERANGE: no match found for search
746
+ * ENODEV: if device not found in list of registered devices
747
+ *
748
+ * The callers are required to call dev_pm_opp_put() for the returned OPP after
749
+ * use.
750
+ */
751
+ struct dev_pm_opp * dev_pm_opp_find_bw_ceil (struct device * dev ,
752
+ unsigned int * bw , int index )
753
+ {
754
+ struct opp_table * opp_table ;
755
+ struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
756
+
757
+ if (!dev || !bw ) {
758
+ dev_err (dev , "%s: Invalid argument bw=%p\n" , __func__ , bw );
759
+ return ERR_PTR (- EINVAL );
760
+ }
761
+
762
+ opp_table = _find_opp_table (dev );
763
+ if (IS_ERR (opp_table ))
764
+ return ERR_CAST (opp_table );
765
+
766
+ if (index >= opp_table -> path_count )
767
+ return ERR_PTR (- EINVAL );
768
+
769
+ mutex_lock (& opp_table -> lock );
770
+
771
+ list_for_each_entry (temp_opp , & opp_table -> opp_list , node ) {
772
+ if (temp_opp -> available && temp_opp -> bandwidth ) {
773
+ if (temp_opp -> bandwidth [index ].peak >= * bw ) {
774
+ opp = temp_opp ;
775
+ * bw = opp -> bandwidth [index ].peak ;
776
+
777
+ /* Increment the reference count of OPP */
778
+ dev_pm_opp_get (opp );
779
+ break ;
780
+ }
781
+ }
782
+ }
783
+
784
+ mutex_unlock (& opp_table -> lock );
785
+ dev_pm_opp_put_opp_table (opp_table );
786
+
787
+ return opp ;
788
+ }
789
+ EXPORT_SYMBOL_GPL (dev_pm_opp_find_bw_ceil );
790
+
791
+ /**
792
+ * dev_pm_opp_find_bw_floor() - Search for a rounded floor bandwidth
793
+ * @dev: device for which we do this operation
794
+ * @freq: start bandwidth
795
+ * @index: which bandwidth to compare, in case of OPPs with several values
796
+ *
797
+ * Search for the matching floor *available* OPP from a starting bandwidth
798
+ * for a device.
799
+ *
800
+ * Return: matching *opp and refreshes *bw accordingly, else returns
801
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
802
+ * values can be:
803
+ * EINVAL: for bad pointer
804
+ * ERANGE: no match found for search
805
+ * ENODEV: if device not found in list of registered devices
806
+ *
807
+ * The callers are required to call dev_pm_opp_put() for the returned OPP after
808
+ * use.
809
+ */
810
+ struct dev_pm_opp * dev_pm_opp_find_bw_floor (struct device * dev ,
811
+ unsigned int * bw , int index )
812
+ {
813
+ struct opp_table * opp_table ;
814
+ struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
815
+
816
+ if (!dev || !bw ) {
817
+ dev_err (dev , "%s: Invalid argument bw=%p\n" , __func__ , bw );
818
+ return ERR_PTR (- EINVAL );
819
+ }
820
+
821
+ opp_table = _find_opp_table (dev );
822
+ if (IS_ERR (opp_table ))
823
+ return ERR_CAST (opp_table );
824
+
825
+ if (index >= opp_table -> path_count )
826
+ return ERR_PTR (- EINVAL );
827
+
828
+ mutex_lock (& opp_table -> lock );
829
+
830
+ list_for_each_entry (temp_opp , & opp_table -> opp_list , node ) {
831
+ if (temp_opp -> available && temp_opp -> bandwidth ) {
832
+ /* go to the next node, before choosing prev */
833
+ if (temp_opp -> bandwidth [index ].peak > * bw )
834
+ break ;
835
+ opp = temp_opp ;
836
+ }
837
+ }
838
+
839
+ /* Increment the reference count of OPP */
840
+ if (!IS_ERR (opp ))
841
+ dev_pm_opp_get (opp );
842
+ mutex_unlock (& opp_table -> lock );
843
+ dev_pm_opp_put_opp_table (opp_table );
844
+
845
+ if (!IS_ERR (opp ))
846
+ * bw = opp -> bandwidth [index ].peak ;
847
+
848
+ return opp ;
849
+ }
850
+ EXPORT_SYMBOL_GPL (dev_pm_opp_find_bw_floor );
851
+
732
852
static int _set_opp_voltage (struct device * dev , struct regulator * reg ,
733
853
struct dev_pm_opp_supply * supply )
734
854
{
0 commit comments