@@ -101,11 +101,30 @@ struct opp_table *_find_opp_table(struct device *dev)
101101 * representation in the OPP table and manage the clock configuration themselves
102102 * in an platform specific way.
103103 */
104- static bool assert_single_clk (struct opp_table * opp_table )
104+ static bool assert_single_clk (struct opp_table * opp_table ,
105+ unsigned int __always_unused index )
105106{
106107 return !WARN_ON (opp_table -> clk_count > 1 );
107108}
108109
110+ /*
111+ * Returns true if clock table is large enough to contain the clock index.
112+ */
113+ static bool assert_clk_index (struct opp_table * opp_table ,
114+ unsigned int index )
115+ {
116+ return opp_table -> clk_count > index ;
117+ }
118+
119+ /*
120+ * Returns true if bandwidth table is large enough to contain the bandwidth index.
121+ */
122+ static bool assert_bandwidth_index (struct opp_table * opp_table ,
123+ unsigned int index )
124+ {
125+ return opp_table -> path_count > index ;
126+ }
127+
109128/**
110129 * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp
111130 * @opp: opp for which voltage has to be returned for
@@ -499,12 +518,12 @@ static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table,
499518 unsigned long (* read )(struct dev_pm_opp * opp , int index ),
500519 bool (* compare )(struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
501520 unsigned long opp_key , unsigned long key ),
502- bool (* assert )(struct opp_table * opp_table ))
521+ bool (* assert )(struct opp_table * opp_table , unsigned int index ))
503522{
504523 struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
505524
506525 /* Assert that the requirement is met */
507- if (assert && !assert (opp_table ))
526+ if (assert && !assert (opp_table , index ))
508527 return ERR_PTR (- EINVAL );
509528
510529 mutex_lock (& opp_table -> lock );
@@ -532,7 +551,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
532551 unsigned long (* read )(struct dev_pm_opp * opp , int index ),
533552 bool (* compare )(struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
534553 unsigned long opp_key , unsigned long key ),
535- bool (* assert )(struct opp_table * opp_table ))
554+ bool (* assert )(struct opp_table * opp_table , unsigned int index ))
536555{
537556 struct opp_table * opp_table ;
538557 struct dev_pm_opp * opp ;
@@ -555,7 +574,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
555574static struct dev_pm_opp * _find_key_exact (struct device * dev ,
556575 unsigned long key , int index , bool available ,
557576 unsigned long (* read )(struct dev_pm_opp * opp , int index ),
558- bool (* assert )(struct opp_table * opp_table ))
577+ bool (* assert )(struct opp_table * opp_table , unsigned int index ))
559578{
560579 /*
561580 * The value of key will be updated here, but will be ignored as the
@@ -568,7 +587,7 @@ static struct dev_pm_opp *_find_key_exact(struct device *dev,
568587static struct dev_pm_opp * _opp_table_find_key_ceil (struct opp_table * opp_table ,
569588 unsigned long * key , int index , bool available ,
570589 unsigned long (* read )(struct dev_pm_opp * opp , int index ),
571- bool (* assert )(struct opp_table * opp_table ))
590+ bool (* assert )(struct opp_table * opp_table , unsigned int index ))
572591{
573592 return _opp_table_find_key (opp_table , key , index , available , read ,
574593 _compare_ceil , assert );
@@ -577,7 +596,7 @@ static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table,
577596static struct dev_pm_opp * _find_key_ceil (struct device * dev , unsigned long * key ,
578597 int index , bool available ,
579598 unsigned long (* read )(struct dev_pm_opp * opp , int index ),
580- bool (* assert )(struct opp_table * opp_table ))
599+ bool (* assert )(struct opp_table * opp_table , unsigned int index ))
581600{
582601 return _find_key (dev , key , index , available , read , _compare_ceil ,
583602 assert );
@@ -586,7 +605,7 @@ static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key,
586605static struct dev_pm_opp * _find_key_floor (struct device * dev ,
587606 unsigned long * key , int index , bool available ,
588607 unsigned long (* read )(struct dev_pm_opp * opp , int index ),
589- bool (* assert )(struct opp_table * opp_table ))
608+ bool (* assert )(struct opp_table * opp_table , unsigned int index ))
590609{
591610 return _find_key (dev , key , index , available , read , _compare_floor ,
592611 assert );
@@ -623,6 +642,35 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
623642}
624643EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_exact );
625644
645+ /**
646+ * dev_pm_opp_find_freq_exact_indexed() - Search for an exact freq for the
647+ * clock corresponding to the index
648+ * @dev: Device for which we do this operation
649+ * @freq: frequency to search for
650+ * @index: Clock index
651+ * @available: true/false - match for available opp
652+ *
653+ * Search for the matching exact OPP for the clock corresponding to the
654+ * specified index from a starting freq for a device.
655+ *
656+ * Return: matching *opp , else returns ERR_PTR in case of error and should be
657+ * handled using IS_ERR. Error return values can be:
658+ * EINVAL: for bad pointer
659+ * ERANGE: no match found for search
660+ * ENODEV: if device not found in list of registered devices
661+ *
662+ * The callers are required to call dev_pm_opp_put() for the returned OPP after
663+ * use.
664+ */
665+ struct dev_pm_opp *
666+ dev_pm_opp_find_freq_exact_indexed (struct device * dev , unsigned long freq ,
667+ u32 index , bool available )
668+ {
669+ return _find_key_exact (dev , freq , index , available , _read_freq ,
670+ assert_clk_index );
671+ }
672+ EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_exact_indexed );
673+
626674static noinline struct dev_pm_opp * _find_freq_ceil (struct opp_table * opp_table ,
627675 unsigned long * freq )
628676{
@@ -679,7 +727,8 @@ struct dev_pm_opp *
679727dev_pm_opp_find_freq_ceil_indexed (struct device * dev , unsigned long * freq ,
680728 u32 index )
681729{
682- return _find_key_ceil (dev , freq , index , true, _read_freq , NULL );
730+ return _find_key_ceil (dev , freq , index , true, _read_freq ,
731+ assert_clk_index );
683732}
684733EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_ceil_indexed );
685734
@@ -732,7 +781,7 @@ struct dev_pm_opp *
732781dev_pm_opp_find_freq_floor_indexed (struct device * dev , unsigned long * freq ,
733782 u32 index )
734783{
735- return _find_key_floor (dev , freq , index , true, _read_freq , NULL );
784+ return _find_key_floor (dev , freq , index , true, _read_freq , assert_clk_index );
736785}
737786EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_floor_indexed );
738787
@@ -850,7 +899,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, unsigned int *bw,
850899 unsigned long temp = * bw ;
851900 struct dev_pm_opp * opp ;
852901
853- opp = _find_key_ceil (dev , & temp , index , true, _read_bw , NULL );
902+ opp = _find_key_ceil (dev , & temp , index , true, _read_bw ,
903+ assert_bandwidth_index );
854904 * bw = temp ;
855905 return opp ;
856906}
@@ -881,7 +931,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
881931 unsigned long temp = * bw ;
882932 struct dev_pm_opp * opp ;
883933
884- opp = _find_key_floor (dev , & temp , index , true, _read_bw , NULL );
934+ opp = _find_key_floor (dev , & temp , index , true, _read_bw ,
935+ assert_bandwidth_index );
885936 * bw = temp ;
886937 return opp ;
887938}
@@ -1675,7 +1726,7 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
16751726 if (IS_ERR (opp_table ))
16761727 return ;
16771728
1678- if (!assert_single_clk (opp_table ))
1729+ if (!assert_single_clk (opp_table , 0 ))
16791730 goto put_table ;
16801731
16811732 mutex_lock (& opp_table -> lock );
@@ -2027,7 +2078,7 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
20272078 unsigned long tol , u_volt = data -> u_volt ;
20282079 int ret ;
20292080
2030- if (!assert_single_clk (opp_table ))
2081+ if (!assert_single_clk (opp_table , 0 ))
20312082 return - EINVAL ;
20322083
20332084 new_opp = _opp_allocate (opp_table );
@@ -2894,7 +2945,7 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
28942945 return r ;
28952946 }
28962947
2897- if (!assert_single_clk (opp_table )) {
2948+ if (!assert_single_clk (opp_table , 0 )) {
28982949 r = - EINVAL ;
28992950 goto put_table ;
29002951 }
@@ -2970,7 +3021,7 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
29703021 return r ;
29713022 }
29723023
2973- if (!assert_single_clk (opp_table )) {
3024+ if (!assert_single_clk (opp_table , 0 )) {
29743025 r = - EINVAL ;
29753026 goto put_table ;
29763027 }
0 commit comments