mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
Merge branch 'pm-opp' into pm
* pm-opp: (37 commits) PM / devfreq: Add required OPPs support to passive governor PM / devfreq: Cache OPP table reference in devfreq OPP: Add function to look up required OPP's for a given OPP opp: Replace ENOTSUPP with EOPNOTSUPP opp: Fix "foo * bar" should be "foo *bar" opp: Don't ignore clk_get() errors other than -ENOENT opp: Update bandwidth requirements based on scaling up/down opp: Allow lazy-linking of required-opps opp: Remove dev_pm_opp_set_bw() devfreq: tegra30: Migrate to dev_pm_opp_set_opp() drm: msm: Migrate to dev_pm_opp_set_opp() cpufreq: qcom: Migrate to dev_pm_opp_set_opp() opp: Implement dev_pm_opp_set_opp() opp: Update parameters of _set_opp_custom() opp: Allow _generic_set_opp_clk_only() to work for non-freq devices opp: Allow _generic_set_opp_regulator() to work for non-freq devices opp: Allow _set_opp() to work for non-freq devices opp: Split _set_opp() out of dev_pm_opp_set_rate() opp: Keep track of currently programmed OPP opp: No need to check clk for errors ...
This commit is contained in:
commit
f5c233c8fe
@ -54,7 +54,7 @@ static int qcom_cpufreq_set_bw(struct cpufreq_policy *policy,
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
|
||||
ret = dev_pm_opp_set_bw(dev, opp);
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
dev_pm_opp_put(opp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -757,6 +757,9 @@ static void devfreq_dev_release(struct device *dev)
|
||||
if (devfreq->profile->exit)
|
||||
devfreq->profile->exit(devfreq->dev.parent);
|
||||
|
||||
if (devfreq->opp_table)
|
||||
dev_pm_opp_put_opp_table(devfreq->opp_table);
|
||||
|
||||
mutex_destroy(&devfreq->lock);
|
||||
kfree(devfreq);
|
||||
}
|
||||
@ -844,6 +847,10 @@ struct devfreq *devfreq_add_device(struct device *dev,
|
||||
}
|
||||
|
||||
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
|
||||
devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
|
||||
if (IS_ERR(devfreq->opp_table))
|
||||
devfreq->opp_table = NULL;
|
||||
|
||||
atomic_set(&devfreq->suspend_count, 0);
|
||||
|
||||
dev_set_name(&devfreq->dev, "%s", dev_name(dev));
|
||||
|
@ -19,18 +19,16 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
|
||||
= (struct devfreq_passive_data *)devfreq->data;
|
||||
struct devfreq *parent_devfreq = (struct devfreq *)p_data->parent;
|
||||
unsigned long child_freq = ULONG_MAX;
|
||||
struct dev_pm_opp *opp;
|
||||
int i, count, ret = 0;
|
||||
struct dev_pm_opp *opp, *p_opp;
|
||||
int i, count;
|
||||
|
||||
/*
|
||||
* If the devfreq device with passive governor has the specific method
|
||||
* to determine the next frequency, should use the get_target_freq()
|
||||
* of struct devfreq_passive_data.
|
||||
*/
|
||||
if (p_data->get_target_freq) {
|
||||
ret = p_data->get_target_freq(devfreq, freq);
|
||||
goto out;
|
||||
}
|
||||
if (p_data->get_target_freq)
|
||||
return p_data->get_target_freq(devfreq, freq);
|
||||
|
||||
/*
|
||||
* If the parent and passive devfreq device uses the OPP table,
|
||||
@ -56,26 +54,35 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
|
||||
* list of parent device. Because in this case, *freq is temporary
|
||||
* value which is decided by ondemand governor.
|
||||
*/
|
||||
opp = devfreq_recommended_opp(parent_devfreq->dev.parent, freq, 0);
|
||||
if (IS_ERR(opp)) {
|
||||
ret = PTR_ERR(opp);
|
||||
goto out;
|
||||
if (devfreq->opp_table && parent_devfreq->opp_table) {
|
||||
p_opp = devfreq_recommended_opp(parent_devfreq->dev.parent,
|
||||
freq, 0);
|
||||
if (IS_ERR(p_opp))
|
||||
return PTR_ERR(p_opp);
|
||||
|
||||
opp = dev_pm_opp_xlate_required_opp(parent_devfreq->opp_table,
|
||||
devfreq->opp_table, p_opp);
|
||||
dev_pm_opp_put(p_opp);
|
||||
|
||||
if (IS_ERR(opp))
|
||||
return PTR_ERR(opp);
|
||||
|
||||
*freq = dev_pm_opp_get_freq(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/*
|
||||
* Get the OPP table's index of decided freqeuncy by governor
|
||||
* Get the OPP table's index of decided frequency by governor
|
||||
* of parent device.
|
||||
*/
|
||||
for (i = 0; i < parent_devfreq->profile->max_state; i++)
|
||||
if (parent_devfreq->profile->freq_table[i] == *freq)
|
||||
break;
|
||||
|
||||
if (i == parent_devfreq->profile->max_state) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (i == parent_devfreq->profile->max_state)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get the suitable frequency by using index of parent device. */
|
||||
if (i < devfreq->profile->max_state) {
|
||||
@ -88,8 +95,7 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
|
||||
/* Return the suitable frequency for passive device. */
|
||||
*freq = child_freq;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int devfreq_passive_notifier_call(struct notifier_block *nb,
|
||||
|
@ -647,7 +647,7 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
|
||||
ret = dev_pm_opp_set_bw(dev, opp);
|
||||
ret = dev_pm_opp_set_opp(dev, opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
return ret;
|
||||
@ -849,7 +849,7 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = dev_pm_opp_of_add_table(&pdev->dev);
|
||||
err = dev_pm_opp_of_add_table_noclk(&pdev->dev, 0);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to add OPP table: %d\n", err);
|
||||
goto put_hw;
|
||||
|
@ -134,7 +134,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp)
|
||||
|
||||
if (!gmu->legacy) {
|
||||
a6xx_hfi_set_freq(gmu, perf_index);
|
||||
dev_pm_opp_set_bw(&gpu->pdev->dev, opp);
|
||||
dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
|
||||
pm_runtime_put(gmu->dev);
|
||||
return;
|
||||
}
|
||||
@ -158,7 +158,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp)
|
||||
if (ret)
|
||||
dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
|
||||
|
||||
dev_pm_opp_set_bw(&gpu->pdev->dev, opp);
|
||||
dev_pm_opp_set_opp(&gpu->pdev->dev, opp);
|
||||
pm_runtime_put(gmu->dev);
|
||||
}
|
||||
|
||||
@ -866,7 +866,7 @@ static void a6xx_gmu_set_initial_bw(struct msm_gpu *gpu, struct a6xx_gmu *gmu)
|
||||
if (IS_ERR_OR_NULL(gpu_opp))
|
||||
return;
|
||||
|
||||
dev_pm_opp_set_bw(&gpu->pdev->dev, gpu_opp);
|
||||
dev_pm_opp_set_opp(&gpu->pdev->dev, gpu_opp);
|
||||
dev_pm_opp_put(gpu_opp);
|
||||
}
|
||||
|
||||
@ -1072,7 +1072,7 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
|
||||
a6xx_gmu_shutdown(gmu);
|
||||
|
||||
/* Remove the bus vote */
|
||||
dev_pm_opp_set_bw(&gpu->pdev->dev, NULL);
|
||||
dev_pm_opp_set_opp(&gpu->pdev->dev, NULL);
|
||||
|
||||
/*
|
||||
* Make sure the GX domain is off before turning off the GMU (CX)
|
||||
|
File diff suppressed because it is too large
Load Diff
240
drivers/opp/of.c
240
drivers/opp/of.c
@ -144,7 +144,7 @@ static void _opp_table_free_required_tables(struct opp_table *opp_table)
|
||||
|
||||
for (i = 0; i < opp_table->required_opp_count; i++) {
|
||||
if (IS_ERR_OR_NULL(required_opp_tables[i]))
|
||||
break;
|
||||
continue;
|
||||
|
||||
dev_pm_opp_put_opp_table(required_opp_tables[i]);
|
||||
}
|
||||
@ -153,6 +153,7 @@ static void _opp_table_free_required_tables(struct opp_table *opp_table)
|
||||
|
||||
opp_table->required_opp_count = 0;
|
||||
opp_table->required_opp_tables = NULL;
|
||||
list_del(&opp_table->lazy);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -165,6 +166,7 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
|
||||
{
|
||||
struct opp_table **required_opp_tables;
|
||||
struct device_node *required_np, *np;
|
||||
bool lazy = false;
|
||||
int count, i;
|
||||
|
||||
/* Traversing the first OPP node is all we need */
|
||||
@ -195,8 +197,10 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
|
||||
required_opp_tables[i] = _find_table_of_opp_np(required_np);
|
||||
of_node_put(required_np);
|
||||
|
||||
if (IS_ERR(required_opp_tables[i]))
|
||||
goto free_required_tables;
|
||||
if (IS_ERR(required_opp_tables[i])) {
|
||||
lazy = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We only support genpd's OPPs in the "required-opps" for now,
|
||||
@ -210,6 +214,10 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
|
||||
}
|
||||
}
|
||||
|
||||
/* Let's do the linking later on */
|
||||
if (lazy)
|
||||
list_add(&opp_table->lazy, &lazy_opp_tables);
|
||||
|
||||
goto put_np;
|
||||
|
||||
free_required_tables:
|
||||
@ -278,14 +286,14 @@ void _of_opp_free_required_opps(struct opp_table *opp_table,
|
||||
|
||||
for (i = 0; i < opp_table->required_opp_count; i++) {
|
||||
if (!required_opps[i])
|
||||
break;
|
||||
continue;
|
||||
|
||||
/* Put the reference back */
|
||||
dev_pm_opp_put(required_opps[i]);
|
||||
}
|
||||
|
||||
kfree(required_opps);
|
||||
opp->required_opps = NULL;
|
||||
kfree(required_opps);
|
||||
}
|
||||
|
||||
/* Populate all required OPPs which are part of "required-opps" list */
|
||||
@ -309,6 +317,10 @@ static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
|
||||
for (i = 0; i < count; i++) {
|
||||
required_table = opp_table->required_opp_tables[i];
|
||||
|
||||
/* Required table not added yet, we will link later */
|
||||
if (IS_ERR_OR_NULL(required_table))
|
||||
continue;
|
||||
|
||||
np = of_parse_required_opp(opp->np, i);
|
||||
if (unlikely(!np)) {
|
||||
ret = -ENODEV;
|
||||
@ -334,6 +346,104 @@ free_required_opps:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Link required OPPs for an individual OPP */
|
||||
static int lazy_link_required_opps(struct opp_table *opp_table,
|
||||
struct opp_table *new_table, int index)
|
||||
{
|
||||
struct device_node *required_np;
|
||||
struct dev_pm_opp *opp;
|
||||
|
||||
list_for_each_entry(opp, &opp_table->opp_list, node) {
|
||||
required_np = of_parse_required_opp(opp->np, index);
|
||||
if (unlikely(!required_np))
|
||||
return -ENODEV;
|
||||
|
||||
opp->required_opps[index] = _find_opp_of_np(new_table, required_np);
|
||||
of_node_put(required_np);
|
||||
|
||||
if (!opp->required_opps[index]) {
|
||||
pr_err("%s: Unable to find required OPP node: %pOF (%d)\n",
|
||||
__func__, opp->np, index);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Link required OPPs for all OPPs of the newly added OPP table */
|
||||
static void lazy_link_required_opp_table(struct opp_table *new_table)
|
||||
{
|
||||
struct opp_table *opp_table, *temp, **required_opp_tables;
|
||||
struct device_node *required_np, *opp_np, *required_table_np;
|
||||
struct dev_pm_opp *opp;
|
||||
int i, ret;
|
||||
|
||||
/*
|
||||
* We only support genpd's OPPs in the "required-opps" for now,
|
||||
* as we don't know much about other cases.
|
||||
*/
|
||||
if (!new_table->is_genpd)
|
||||
return;
|
||||
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
list_for_each_entry_safe(opp_table, temp, &lazy_opp_tables, lazy) {
|
||||
bool lazy = false;
|
||||
|
||||
/* opp_np can't be invalid here */
|
||||
opp_np = of_get_next_available_child(opp_table->np, NULL);
|
||||
|
||||
for (i = 0; i < opp_table->required_opp_count; i++) {
|
||||
required_opp_tables = opp_table->required_opp_tables;
|
||||
|
||||
/* Required opp-table is already parsed */
|
||||
if (!IS_ERR(required_opp_tables[i]))
|
||||
continue;
|
||||
|
||||
/* required_np can't be invalid here */
|
||||
required_np = of_parse_required_opp(opp_np, i);
|
||||
required_table_np = of_get_parent(required_np);
|
||||
|
||||
of_node_put(required_table_np);
|
||||
of_node_put(required_np);
|
||||
|
||||
/*
|
||||
* Newly added table isn't the required opp-table for
|
||||
* opp_table.
|
||||
*/
|
||||
if (required_table_np != new_table->np) {
|
||||
lazy = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
required_opp_tables[i] = new_table;
|
||||
_get_opp_table_kref(new_table);
|
||||
|
||||
/* Link OPPs now */
|
||||
ret = lazy_link_required_opps(opp_table, new_table, i);
|
||||
if (ret) {
|
||||
/* The OPPs will be marked unusable */
|
||||
lazy = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(opp_np);
|
||||
|
||||
/* All required opp-tables found, remove from lazy list */
|
||||
if (!lazy) {
|
||||
list_del(&opp_table->lazy);
|
||||
INIT_LIST_HEAD(&opp_table->lazy);
|
||||
|
||||
list_for_each_entry(opp, &opp_table->opp_list, node)
|
||||
_required_opps_available(opp, opp_table->required_opp_count);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&opp_table_lock);
|
||||
}
|
||||
|
||||
static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table)
|
||||
{
|
||||
struct device_node *np, *opp_np;
|
||||
@ -755,7 +865,6 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
||||
struct device *dev, struct device_node *np)
|
||||
{
|
||||
struct dev_pm_opp *new_opp;
|
||||
u64 rate = 0;
|
||||
u32 val;
|
||||
int ret;
|
||||
bool rate_not_available = false;
|
||||
@ -772,7 +881,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
||||
|
||||
/* Check if the OPP supports hardware's hierarchy of versions or not */
|
||||
if (!_opp_is_supported(dev, opp_table, np)) {
|
||||
dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
|
||||
dev_dbg(dev, "OPP not supported by hardware: %lu\n",
|
||||
new_opp->rate);
|
||||
goto free_opp;
|
||||
}
|
||||
|
||||
@ -822,10 +932,11 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
||||
if (new_opp->clock_latency_ns > opp_table->clock_latency_ns_max)
|
||||
opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
|
||||
|
||||
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
|
||||
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu level:%u\n",
|
||||
__func__, new_opp->turbo, new_opp->rate,
|
||||
new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
|
||||
new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns);
|
||||
new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns,
|
||||
new_opp->level);
|
||||
|
||||
/*
|
||||
* Notify the changes in the availability of the operable
|
||||
@ -888,6 +999,8 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
|
||||
}
|
||||
}
|
||||
|
||||
lazy_link_required_opp_table(opp_table);
|
||||
|
||||
return 0;
|
||||
|
||||
remove_static_opp:
|
||||
@ -956,6 +1069,41 @@ remove_static_opp:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _of_add_table_indexed(struct device *dev, int index, bool getclk)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
int ret, count;
|
||||
|
||||
if (index) {
|
||||
/*
|
||||
* If only one phandle is present, then the same OPP table
|
||||
* applies for all index requests.
|
||||
*/
|
||||
count = of_count_phandle_with_args(dev->of_node,
|
||||
"operating-points-v2", NULL);
|
||||
if (count == 1)
|
||||
index = 0;
|
||||
}
|
||||
|
||||
opp_table = _add_opp_table_indexed(dev, index, getclk);
|
||||
if (IS_ERR(opp_table))
|
||||
return PTR_ERR(opp_table);
|
||||
|
||||
/*
|
||||
* OPPs have two version of bindings now. Also try the old (v1)
|
||||
* bindings for backward compatibility with older dtbs.
|
||||
*/
|
||||
if (opp_table->np)
|
||||
ret = _of_add_opp_table_v2(dev, opp_table);
|
||||
else
|
||||
ret = _of_add_opp_table_v1(dev, opp_table);
|
||||
|
||||
if (ret)
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_pm_opp_of_add_table() - Initialize opp table from device tree
|
||||
* @dev: device pointer used to lookup OPP table.
|
||||
@ -975,26 +1123,7 @@ remove_static_opp:
|
||||
*/
|
||||
int dev_pm_opp_of_add_table(struct device *dev)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
int ret;
|
||||
|
||||
opp_table = _add_opp_table_indexed(dev, 0);
|
||||
if (IS_ERR(opp_table))
|
||||
return PTR_ERR(opp_table);
|
||||
|
||||
/*
|
||||
* OPPs have two version of bindings now. Also try the old (v1)
|
||||
* bindings for backward compatibility with older dtbs.
|
||||
*/
|
||||
if (opp_table->np)
|
||||
ret = _of_add_opp_table_v2(dev, opp_table);
|
||||
else
|
||||
ret = _of_add_opp_table_v1(dev, opp_table);
|
||||
|
||||
if (ret)
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ret;
|
||||
return _of_add_table_indexed(dev, 0, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
|
||||
|
||||
@ -1006,45 +1135,32 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
|
||||
* Register the initial OPP table with the OPP library for given device only
|
||||
* using the "operating-points-v2" property.
|
||||
*
|
||||
* Return:
|
||||
* 0 On success OR
|
||||
* Duplicate OPPs (both freq and volt are same) and opp->available
|
||||
* -EEXIST Freq are same and volt are different OR
|
||||
* Duplicate OPPs (both freq and volt are same) and !opp->available
|
||||
* -ENOMEM Memory allocation failure
|
||||
* -ENODEV when 'operating-points' property is not found or is invalid data
|
||||
* in device node.
|
||||
* -ENODATA when empty 'operating-points' property is found
|
||||
* -EINVAL when invalid entries are found in opp-v2 table
|
||||
* Return: Refer to dev_pm_opp_of_add_table() for return values.
|
||||
*/
|
||||
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
int ret, count;
|
||||
|
||||
if (index) {
|
||||
/*
|
||||
* If only one phandle is present, then the same OPP table
|
||||
* applies for all index requests.
|
||||
*/
|
||||
count = of_count_phandle_with_args(dev->of_node,
|
||||
"operating-points-v2", NULL);
|
||||
if (count == 1)
|
||||
index = 0;
|
||||
}
|
||||
|
||||
opp_table = _add_opp_table_indexed(dev, index);
|
||||
if (IS_ERR(opp_table))
|
||||
return PTR_ERR(opp_table);
|
||||
|
||||
ret = _of_add_opp_table_v2(dev, opp_table);
|
||||
if (ret)
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ret;
|
||||
return _of_add_table_indexed(dev, index, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed);
|
||||
|
||||
/**
|
||||
* dev_pm_opp_of_add_table_noclk() - Initialize indexed opp table from device
|
||||
* tree without getting clk for device.
|
||||
* @dev: device pointer used to lookup OPP table.
|
||||
* @index: Index number.
|
||||
*
|
||||
* Register the initial OPP table with the OPP library for given device only
|
||||
* using the "operating-points-v2" property. Do not try to get the clk for the
|
||||
* device.
|
||||
*
|
||||
* Return: Refer to dev_pm_opp_of_add_table() for return values.
|
||||
*/
|
||||
int dev_pm_opp_of_add_table_noclk(struct device *dev, int index)
|
||||
{
|
||||
return _of_add_table_indexed(dev, index, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_noclk);
|
||||
|
||||
/* CPU device specific helpers */
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ struct regulator;
|
||||
/* Lock to allow exclusive modification to the device and opp lists */
|
||||
extern struct mutex opp_table_lock;
|
||||
|
||||
extern struct list_head opp_tables;
|
||||
extern struct list_head opp_tables, lazy_opp_tables;
|
||||
|
||||
/*
|
||||
* Internal data structure organization with the OPP layer library is as
|
||||
@ -135,6 +135,7 @@ enum opp_table_access {
|
||||
* @clock_latency_ns_max: Max clock latency in nanoseconds.
|
||||
* @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
|
||||
* @shared_opp: OPP is shared between multiple devices.
|
||||
* @current_opp: Currently configured OPP for the table.
|
||||
* @suspend_opp: Pointer to OPP to be used during device suspend.
|
||||
* @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
|
||||
* @genpd_virt_devs: List of virtual devices for multiple genpd support.
|
||||
@ -155,6 +156,7 @@ enum opp_table_access {
|
||||
* @genpd_performance_state: Device's power domain support performance state.
|
||||
* @is_genpd: Marks if the OPP table belongs to a genpd.
|
||||
* @set_opp: Platform specific set_opp callback
|
||||
* @sod_supplies: Set opp data supplies
|
||||
* @set_opp_data: Data to be passed to set_opp callback
|
||||
* @dentry: debugfs dentry pointer of the real device directory (not links).
|
||||
* @dentry_name: Name of the real dentry.
|
||||
@ -166,7 +168,7 @@ enum opp_table_access {
|
||||
* meant for book keeping and private to OPP library.
|
||||
*/
|
||||
struct opp_table {
|
||||
struct list_head node;
|
||||
struct list_head node, lazy;
|
||||
|
||||
struct blocking_notifier_head head;
|
||||
struct list_head dev_list;
|
||||
@ -182,6 +184,7 @@ struct opp_table {
|
||||
|
||||
unsigned int parsed_static_opps;
|
||||
enum opp_table_access shared_opp;
|
||||
struct dev_pm_opp *current_opp;
|
||||
struct dev_pm_opp *suspend_opp;
|
||||
|
||||
struct mutex genpd_virt_dev_lock;
|
||||
@ -202,6 +205,7 @@ struct opp_table {
|
||||
bool is_genpd;
|
||||
|
||||
int (*set_opp)(struct dev_pm_set_opp_data *data);
|
||||
struct dev_pm_opp_supply *sod_supplies;
|
||||
struct dev_pm_set_opp_data *set_opp_data;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@ -223,9 +227,14 @@ int _opp_compare_key(struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
|
||||
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available);
|
||||
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
|
||||
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
|
||||
struct opp_table *_add_opp_table(struct device *dev);
|
||||
struct opp_table *_add_opp_table_indexed(struct device *dev, int index);
|
||||
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
|
||||
void _put_opp_list_kref(struct opp_table *opp_table);
|
||||
void _required_opps_available(struct dev_pm_opp *opp, int count);
|
||||
|
||||
static inline bool lazy_linking_pending(struct opp_table *opp_table)
|
||||
{
|
||||
return unlikely(!list_empty(&opp_table->lazy));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
|
||||
|
@ -137,6 +137,7 @@ struct devfreq_stats {
|
||||
* using devfreq.
|
||||
* @profile: device-specific devfreq profile
|
||||
* @governor: method how to choose frequency based on the usage.
|
||||
* @opp_table: Reference to OPP table of dev.parent, if one exists.
|
||||
* @nb: notifier block used to notify devfreq object that it should
|
||||
* reevaluate operable frequencies. Devfreq users may use
|
||||
* devfreq.nb to the corresponding register notifier call chain.
|
||||
@ -173,6 +174,7 @@ struct devfreq {
|
||||
struct device dev;
|
||||
struct devfreq_dev_profile *profile;
|
||||
const struct devfreq_governor *governor;
|
||||
struct opp_table *opp_table;
|
||||
struct notifier_block nb;
|
||||
struct delayed_work work;
|
||||
|
||||
|
@ -98,6 +98,9 @@ unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
|
||||
|
||||
unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp);
|
||||
|
||||
unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp,
|
||||
unsigned int index);
|
||||
|
||||
bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
|
||||
|
||||
int dev_pm_opp_get_opp_count(struct device *dev);
|
||||
@ -111,6 +114,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
|
||||
bool available);
|
||||
struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev,
|
||||
unsigned int level);
|
||||
struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev,
|
||||
unsigned int *level);
|
||||
|
||||
struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
|
||||
unsigned long *freq);
|
||||
@ -143,28 +148,32 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
||||
void dev_pm_opp_put_prop_name(struct opp_table *opp_table);
|
||||
struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
|
||||
void dev_pm_opp_put_regulators(struct opp_table *opp_table);
|
||||
struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name);
|
||||
struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name);
|
||||
void dev_pm_opp_put_clkname(struct opp_table *opp_table);
|
||||
struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
|
||||
void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table);
|
||||
struct opp_table *devm_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
|
||||
struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs);
|
||||
void dev_pm_opp_detach_genpd(struct opp_table *opp_table);
|
||||
struct opp_table *devm_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs);
|
||||
struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp);
|
||||
int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);
|
||||
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
|
||||
int dev_pm_opp_set_bw(struct device *dev, struct dev_pm_opp *opp);
|
||||
int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp);
|
||||
int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask);
|
||||
int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask);
|
||||
void dev_pm_opp_remove_table(struct device *dev);
|
||||
void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask);
|
||||
int dev_pm_opp_sync_regulators(struct device *dev);
|
||||
#else
|
||||
static inline struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
|
||||
@ -184,6 +193,13 @@ static inline unsigned int dev_pm_opp_get_level(struct dev_pm_opp *opp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp,
|
||||
unsigned int index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp)
|
||||
{
|
||||
return false;
|
||||
@ -217,31 +233,37 @@ static inline unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
|
||||
unsigned long freq, bool available)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev,
|
||||
unsigned int level)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev,
|
||||
unsigned int *level)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
|
||||
unsigned long *freq)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
|
||||
unsigned long u_volt)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
|
||||
unsigned long *freq)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
|
||||
@ -249,7 +271,7 @@ static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {}
|
||||
static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,
|
||||
unsigned long u_volt)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_remove(struct device *dev, unsigned long freq)
|
||||
@ -280,19 +302,19 @@ static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq)
|
||||
|
||||
static inline int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
|
||||
const u32 *versions,
|
||||
unsigned int count)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_supported_hw(struct opp_table *opp_table) {}
|
||||
@ -300,57 +322,76 @@ static inline void dev_pm_opp_put_supported_hw(struct opp_table *opp_table) {}
|
||||
static inline struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
|
||||
int (*set_opp)(struct dev_pm_set_opp_data *data))
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *
|
||||
devm_pm_opp_register_set_opp_helper(struct device *dev,
|
||||
int (*set_opp)(struct dev_pm_set_opp_data *data))
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_prop_name(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name)
|
||||
static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_detach_genpd(struct opp_table *opp_table) {}
|
||||
|
||||
static inline struct opp_table *devm_pm_opp_attach_genpd(struct device *dev,
|
||||
const char **names, struct device ***virt_devs)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table,
|
||||
struct opp_table *dst_table, struct dev_pm_opp *src_opp)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_set_bw(struct device *dev, struct dev_pm_opp *opp)
|
||||
static inline int dev_pm_opp_set_opp(struct device *dev, struct dev_pm_opp *opp)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
||||
@ -366,11 +407,17 @@ static inline void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask
|
||||
{
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_sync_regulators(struct device *dev)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM_OPP */
|
||||
|
||||
#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
|
||||
int dev_pm_opp_of_add_table(struct device *dev);
|
||||
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index);
|
||||
int dev_pm_opp_of_add_table_noclk(struct device *dev, int index);
|
||||
void dev_pm_opp_of_remove_table(struct device *dev);
|
||||
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask);
|
||||
void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask);
|
||||
@ -387,12 +434,17 @@ static inline void dev_pm_opp_of_unregister_em(struct device *dev)
|
||||
#else
|
||||
static inline int dev_pm_opp_of_add_table(struct device *dev)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_of_add_table_noclk(struct device *dev, int index)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_of_remove_table(struct device *dev)
|
||||
@ -401,7 +453,7 @@ static inline void dev_pm_opp_of_remove_table(struct device *dev)
|
||||
|
||||
static inline int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask)
|
||||
@ -410,7 +462,7 @@ static inline void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpum
|
||||
|
||||
static inline int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
|
||||
@ -426,7 +478,7 @@ static inline struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp)
|
||||
static inline int dev_pm_opp_of_register_em(struct device *dev,
|
||||
struct cpumask *cpus)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void dev_pm_opp_of_unregister_em(struct device *dev)
|
||||
@ -435,12 +487,12 @@ static inline void dev_pm_opp_of_unregister_em(struct device *dev)
|
||||
|
||||
static inline int of_get_required_opp_performance_state(struct device_node *np, int index)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_table *opp_table)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user