@@ -101,11 +101,30 @@ struct opp_table *_find_opp_table(struct device *dev)
101
101
* representation in the OPP table and manage the clock configuration themselves
102
102
* in an platform specific way.
103
103
*/
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 )
105
106
{
106
107
return !WARN_ON (opp_table -> clk_count > 1 );
107
108
}
108
109
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
+
109
128
/**
110
129
* dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp
111
130
* @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,
499
518
unsigned long (* read )(struct dev_pm_opp * opp , int index ),
500
519
bool (* compare )(struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
501
520
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 ))
503
522
{
504
523
struct dev_pm_opp * temp_opp , * opp = ERR_PTR (- ERANGE );
505
524
506
525
/* Assert that the requirement is met */
507
- if (assert && !assert (opp_table ))
526
+ if (assert && !assert (opp_table , index ))
508
527
return ERR_PTR (- EINVAL );
509
528
510
529
mutex_lock (& opp_table -> lock );
@@ -532,7 +551,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
532
551
unsigned long (* read )(struct dev_pm_opp * opp , int index ),
533
552
bool (* compare )(struct dev_pm_opp * * opp , struct dev_pm_opp * temp_opp ,
534
553
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 ))
536
555
{
537
556
struct opp_table * opp_table ;
538
557
struct dev_pm_opp * opp ;
@@ -555,7 +574,7 @@ _find_key(struct device *dev, unsigned long *key, int index, bool available,
555
574
static struct dev_pm_opp * _find_key_exact (struct device * dev ,
556
575
unsigned long key , int index , bool available ,
557
576
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 ))
559
578
{
560
579
/*
561
580
* 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,
568
587
static struct dev_pm_opp * _opp_table_find_key_ceil (struct opp_table * opp_table ,
569
588
unsigned long * key , int index , bool available ,
570
589
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 ))
572
591
{
573
592
return _opp_table_find_key (opp_table , key , index , available , read ,
574
593
_compare_ceil , assert );
@@ -577,7 +596,7 @@ static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table,
577
596
static struct dev_pm_opp * _find_key_ceil (struct device * dev , unsigned long * key ,
578
597
int index , bool available ,
579
598
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 ))
581
600
{
582
601
return _find_key (dev , key , index , available , read , _compare_ceil ,
583
602
assert );
@@ -586,7 +605,7 @@ static struct dev_pm_opp *_find_key_ceil(struct device *dev, unsigned long *key,
586
605
static struct dev_pm_opp * _find_key_floor (struct device * dev ,
587
606
unsigned long * key , int index , bool available ,
588
607
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 ))
590
609
{
591
610
return _find_key (dev , key , index , available , read , _compare_floor ,
592
611
assert );
@@ -623,6 +642,35 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
623
642
}
624
643
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_exact );
625
644
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
+
626
674
static noinline struct dev_pm_opp * _find_freq_ceil (struct opp_table * opp_table ,
627
675
unsigned long * freq )
628
676
{
@@ -679,7 +727,8 @@ struct dev_pm_opp *
679
727
dev_pm_opp_find_freq_ceil_indexed (struct device * dev , unsigned long * freq ,
680
728
u32 index )
681
729
{
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 );
683
732
}
684
733
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_ceil_indexed );
685
734
@@ -732,7 +781,7 @@ struct dev_pm_opp *
732
781
dev_pm_opp_find_freq_floor_indexed (struct device * dev , unsigned long * freq ,
733
782
u32 index )
734
783
{
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 );
736
785
}
737
786
EXPORT_SYMBOL_GPL (dev_pm_opp_find_freq_floor_indexed );
738
787
@@ -850,7 +899,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, unsigned int *bw,
850
899
unsigned long temp = * bw ;
851
900
struct dev_pm_opp * opp ;
852
901
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 );
854
904
* bw = temp ;
855
905
return opp ;
856
906
}
@@ -881,7 +931,8 @@ struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
881
931
unsigned long temp = * bw ;
882
932
struct dev_pm_opp * opp ;
883
933
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 );
885
936
* bw = temp ;
886
937
return opp ;
887
938
}
@@ -1675,7 +1726,7 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
1675
1726
if (IS_ERR (opp_table ))
1676
1727
return ;
1677
1728
1678
- if (!assert_single_clk (opp_table ))
1729
+ if (!assert_single_clk (opp_table , 0 ))
1679
1730
goto put_table ;
1680
1731
1681
1732
mutex_lock (& opp_table -> lock );
@@ -2027,7 +2078,7 @@ int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
2027
2078
unsigned long tol , u_volt = data -> u_volt ;
2028
2079
int ret ;
2029
2080
2030
- if (!assert_single_clk (opp_table ))
2081
+ if (!assert_single_clk (opp_table , 0 ))
2031
2082
return - EINVAL ;
2032
2083
2033
2084
new_opp = _opp_allocate (opp_table );
@@ -2894,7 +2945,7 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
2894
2945
return r ;
2895
2946
}
2896
2947
2897
- if (!assert_single_clk (opp_table )) {
2948
+ if (!assert_single_clk (opp_table , 0 )) {
2898
2949
r = - EINVAL ;
2899
2950
goto put_table ;
2900
2951
}
@@ -2970,7 +3021,7 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
2970
3021
return r ;
2971
3022
}
2972
3023
2973
- if (!assert_single_clk (opp_table )) {
3024
+ if (!assert_single_clk (opp_table , 0 )) {
2974
3025
r = - EINVAL ;
2975
3026
goto put_table ;
2976
3027
}
0 commit comments