Skip to content

Commit 00ce387

Browse files
krzkvireshk
authored andcommitted
opp: Add apis to retrieve opps with interconnect bandwidth
Add dev_pm_opp_find_bw_ceil and dev_pm_opp_find_bw_floor to retrieve opps based on interconnect associated with the opp and bandwidth. The index variable is the index of the interconnect as specified in the opp table in Devicetree. Co-developed-by: Thara Gopinath <[email protected]> Signed-off-by: Thara Gopinath <[email protected]> Signed-off-by: Krzysztof Kozlowski <[email protected]> Signed-off-by: Viresh Kumar <[email protected]>
1 parent 3e1fac9 commit 00ce387

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

drivers/opp/core.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,126 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
729729
}
730730
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_by_volt);
731731

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+
732852
static int _set_opp_voltage(struct device *dev, struct regulator *reg,
733853
struct dev_pm_opp_supply *supply)
734854
{

include/linux/pm_opp.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
129129

130130
struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
131131
unsigned long *freq);
132+
133+
struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev,
134+
unsigned int *bw, int index);
135+
136+
struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
137+
unsigned int *bw, int index);
138+
132139
void dev_pm_opp_put(struct dev_pm_opp *opp);
133140

134141
int dev_pm_opp_add(struct device *dev, unsigned long freq,
@@ -279,6 +286,18 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
279286
return ERR_PTR(-EOPNOTSUPP);
280287
}
281288

289+
static inline struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev,
290+
unsigned int *bw, int index)
291+
{
292+
return ERR_PTR(-EOPNOTSUPP);
293+
}
294+
295+
static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev,
296+
unsigned int *bw, int index)
297+
{
298+
return ERR_PTR(-EOPNOTSUPP);
299+
}
300+
282301
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
283302

284303
static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,

0 commit comments

Comments
 (0)