opp_table
struct opp_table *opp_table,
*opp_table = &freq_table[0];
struct cpufreq_frequency_table **opp_table)
struct cpufreq_frequency_table **opp_table)
*opp_table = &freq_table[0];
if (devfreq->opp_table)
dev_pm_opp_put_opp_table(devfreq->opp_table);
devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
if (IS_ERR(devfreq->opp_table))
devfreq->opp_table = NULL;
parent_cpu_data->opp_table,
devfreq->opp_table, &cpu_cur);
parent_devfreq->opp_table,
devfreq->opp_table, freq);
struct opp_table *opp_table = NULL;
opp_table = dev_pm_opp_get_opp_table(cpu_dev);
if (IS_ERR(opp_table)) {
ret = PTR_ERR(opp_table);
parent_cpu_data->opp_table = opp_table;
struct opp_table *opp_table;
if (parent_cpu_data->opp_table)
dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
struct opp_table *p_opp_table,
struct opp_table *opp_table,
if (!p_dev || !p_opp_table || !opp_table || !freq)
opp = dev_pm_opp_xlate_required_opp(p_opp_table, opp_table, p_opp);
struct opp_table *opp_table,
struct opp_table *table;
static bool assert_clk_index(struct opp_table *opp_table,
_opp_config_clk_single(struct device *dev, struct opp_table *opp_table,
return opp_table->clk_count > index;
ret = clk_set_rate(opp_table->clk, freq);
opp_table->current_rate_single_clk = freq;
struct opp_table *opp_table, struct dev_pm_opp *opp, void *data,
for (i = opp_table->clk_count - 1; i >= 0; i--) {
ret = clk_set_rate(opp_table->clks[i], opp->rates[i]);
for (i = 0; i < opp_table->clk_count; i++) {
ret = clk_set_rate(opp_table->clks[i], opp->rates[i]);
static bool assert_bandwidth_index(struct opp_table *opp_table,
if (unlikely(!new_opp->opp_table->enabled)) {
return opp_table->path_count > index;
static int _set_opp_bw(const struct opp_table *opp_table,
if (!opp_table->paths)
for (i = 0; i < opp_table->path_count; i++) {
ret = icc_set_bw(opp_table->paths[i], avg, peak);
static int _set_required_opps(struct device *dev, struct opp_table *opp_table,
struct device **devs = opp_table->required_devs;
if (lazy_linking_pending(opp_table))
target = opp_table->required_opp_count;
index = opp_table->required_opp_count - 1;
static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
if (!IS_ERR(opp_table->clk)) {
freq = clk_get_rate(opp_table->clk);
opp = _find_freq_ceil(opp_table, &freq);
guard(mutex)(&opp_table->lock);
opp = dev_pm_opp_get(list_first_entry(&opp_table->opp_list,
opp_table->current_opp = opp;
static int _disable_opp_table(struct device *dev, struct opp_table *opp_table)
if (!opp_table->enabled)
if (!_get_opp_count(opp_table))
ret = _set_opp_bw(opp_table, NULL, dev);
if (opp_table->regulators)
regulator_disable(opp_table->regulators[0]);
ret = _set_required_opps(dev, opp_table, NULL, false);
opp_table->enabled = false;
static int _set_opp(struct device *dev, struct opp_table *opp_table,
return _disable_opp_table(dev, opp_table);
if (unlikely(!opp_table->current_opp))
_find_current_opp(dev, opp_table);
old_opp = opp_table->current_opp;
if (!forced && old_opp == opp && opp_table->enabled) {
scaling_down = _opp_compare_key(opp_table, old_opp, opp);
ret = _set_required_opps(dev, opp_table, opp, true);
if (index >= opp->opp_table->path_count)
ret = _set_opp_bw(opp_table, opp, dev);
if (opp_table->config_regulators) {
ret = opp_table->config_regulators(dev, old_opp, opp,
opp_table->regulators,
opp_table->regulator_count);
if (opp_table->config_clks) {
ret = opp_table->config_clks(dev, opp_table, opp, clk_data, scaling_down);
if (opp_table->config_regulators) {
ret = opp_table->config_regulators(dev, old_opp, opp,
opp_table->regulators,
opp_table->regulator_count);
ret = _set_opp_bw(opp_table, opp, dev);
ret = _set_required_opps(dev, opp_table, opp, false);
opp_table->enabled = true;
opp_table->current_opp = dev_pm_opp_get(opp);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
return PTR_ERR(opp_table);
if (!_get_opp_count(opp_table)) {
return opp_table->config_clks(dev, opp_table, NULL,
freq = clk_round_rate(opp_table->clk, target_freq);
opp = _find_freq_ceil(opp_table, &temp_freq);
forced = opp_table->current_rate_single_clk != freq;
return _set_opp(dev, opp_table, opp, &freq, forced);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
return PTR_ERR(opp_table);
return _set_opp(dev, opp_table, opp, NULL, false);
struct opp_table *opp_table)
opp_debug_unregister(opp_dev, opp_table);
struct opp_table *opp_table)
scoped_guard(mutex, &opp_table->lock)
list_add(&opp_dev->node, &opp_table->dev_list);
opp_debug_register(opp_dev, opp_table);
static struct opp_table *_allocate_opp_table(struct device *dev, int index)
struct opp_table *opp_table;
opp_table = kzalloc_obj(*opp_table);
if (!opp_table)
mutex_init(&opp_table->lock);
INIT_LIST_HEAD(&opp_table->dev_list);
INIT_LIST_HEAD(&opp_table->lazy);
opp_table->clk = ERR_PTR(-ENODEV);
opp_table->regulator_count = -1;
opp_dev = _add_opp_dev(dev, opp_table);
_of_init_opp_table(opp_table, dev, index);
ret = dev_pm_opp_of_find_icc_paths(dev, opp_table);
BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
INIT_LIST_HEAD(&opp_table->opp_list);
kref_init(&opp_table->kref);
return opp_table;
_of_clear_opp_table(opp_table);
_remove_opp_dev(opp_dev, opp_table);
mutex_destroy(&opp_table->lock);
kfree(opp_table);
static struct opp_table *_update_opp_table_clk(struct device *dev,
struct opp_table *opp_table,
if (!getclk || IS_ERR(opp_table) || !IS_ERR(opp_table->clk) ||
opp_table->clks)
return opp_table;
opp_table->clk = clk_get(dev, NULL);
ret = PTR_ERR_OR_ZERO(opp_table->clk);
opp_table->config_clks = _opp_config_clk_single;
opp_table->clk_count = 1;
return opp_table;
opp_table->clk_count = 1;
return opp_table;
dev_pm_opp_put_opp_table(opp_table);
struct opp_table *_add_opp_table_indexed(struct device *dev, int index,
struct opp_table *opp_table;
opp_table = _find_opp_table_unlocked(dev);
if (!IS_ERR(opp_table))
opp_table = _managed_opp(dev, index);
if (opp_table) {
if (!_add_opp_dev(dev, opp_table)) {
dev_pm_opp_put_opp_table(opp_table);
opp_table = ERR_PTR(-ENOMEM);
opp_table = _allocate_opp_table(dev, index);
if (!IS_ERR(opp_table))
list_add(&opp_table->node, &opp_tables);
return _update_opp_table_clk(dev, opp_table, getclk);
static struct opp_table *_add_opp_table(struct device *dev, bool getclk)
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
struct opp_table *opp_table = container_of(kref, struct opp_table, kref);
list_del(&opp_table->node);
if (opp_table->current_opp)
dev_pm_opp_put(opp_table->current_opp);
_of_clear_opp_table(opp_table);
if (!IS_ERR(opp_table->clk))
clk_put(opp_table->clk);
if (opp_table->paths) {
for (i = 0; i < opp_table->path_count; i++)
icc_put(opp_table->paths[i]);
kfree(opp_table->paths);
WARN_ON(!list_empty(&opp_table->opp_list));
list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node)
_remove_opp_dev(opp_dev, opp_table);
mutex_destroy(&opp_table->lock);
kfree(opp_table);
struct opp_table *dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table)
kref_get(&opp_table->kref);
return opp_table;
void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
kref_put_mutex(&opp_table->kref, _opp_table_kref_release,
struct opp_table *opp_table = opp->opp_table;
mutex_unlock(&opp_table->lock);
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_REMOVE, opp);
_of_clear_opp(opp_table, opp);
kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
if (!assert_single_clk(opp_table, 0))
scoped_guard(mutex, &opp_table->lock) {
list_for_each_entry(iter, &opp_table->opp_list, node) {
dev_pm_opp_put_opp_table(opp_table);
sizeof(*supplies) * opp->opp_table->regulator_count);
static struct dev_pm_opp *_opp_get_next(struct opp_table *opp_table,
guard(mutex)(&opp_table->lock);
list_for_each_entry(opp, &opp_table->opp_list, node) {
static void _opp_remove_all(struct opp_table *opp_table, bool dynamic)
while ((opp = _opp_get_next(opp_table, dynamic))) {
dev_pm_opp_put_opp_table(opp_table);
bool _opp_remove_all_static(struct opp_table *opp_table)
scoped_guard(mutex, &opp_table->lock) {
if (!opp_table->parsed_static_opps)
if (--opp_table->parsed_static_opps)
_opp_remove_all(opp_table, false);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
_opp_remove_all(opp_table, true);
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table)
supply_count = opp_table->regulator_count > 0 ?
opp_table->regulator_count : 1;
clk_size = sizeof(*opp->rates) * opp_table->clk_count;
icc_size = sizeof(*opp->bandwidth) * opp_table->path_count;
opp->bandwidth = (struct dev_pm_opp_icc_bw *)(opp->rates + opp_table->clk_count);
struct opp_table *opp_table)
if (!opp_table->regulators)
for (i = 0; i < opp_table->regulator_count; i++) {
reg = opp_table->regulators[i];
static int _opp_compare_rate(struct opp_table *opp_table,
for (i = 0; i < opp_table->clk_count; i++) {
static int _opp_compare_bw(struct opp_table *opp_table, struct dev_pm_opp *opp1,
for (i = 0; i < opp_table->path_count; i++) {
int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1,
ret = _opp_compare_rate(opp_table, opp1, opp2);
ret = _opp_compare_bw(opp_table, opp1, opp2);
struct opp_table *opp_table,
list_for_each_entry(opp, &opp_table->opp_list, node) {
opp_cmp = _opp_compare_key(opp_table, new_opp, opp);
for (i = 0; i < opp->opp_table->regulator_count; i++)
struct opp_table *opp_table)
scoped_guard(mutex, &opp_table->lock) {
head = &opp_table->opp_list;
ret = _opp_is_duplicate(dev, new_opp, opp_table, &head);
new_opp->opp_table = opp_table;
opp_debug_create_one(new_opp, opp_table);
if (!_opp_supported_by_regulators(new_opp, opp_table)) {
if (lazy_linking_pending(opp_table))
_required_opps_available(new_opp, opp_table->required_opp_count);
int _opp_add_v1(struct opp_table *opp_table, struct device *dev,
if (!assert_single_clk(opp_table, 0))
new_opp = _opp_allocate(opp_table);
tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
ret = _opp_add(dev, new_opp, opp_table);
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADD, new_opp);
static int _opp_set_supported_hw(struct opp_table *opp_table,
if (opp_table->supported_hw)
opp_table->supported_hw = kmemdup_array(versions, count,
if (!opp_table->supported_hw)
opp_table->supported_hw_count = count;
static void _opp_put_supported_hw(struct opp_table *opp_table)
if (opp_table->supported_hw) {
kfree(opp_table->supported_hw);
opp_table->supported_hw = NULL;
opp_table->supported_hw_count = 0;
static int _opp_set_prop_name(struct opp_table *opp_table, const char *name)
if (!opp_table->prop_name) {
opp_table->prop_name = kstrdup(name, GFP_KERNEL);
if (!opp_table->prop_name)
static void _opp_put_prop_name(struct opp_table *opp_table)
if (opp_table->prop_name) {
kfree(opp_table->prop_name);
opp_table->prop_name = NULL;
if (IS_ERR_OR_NULL(opp) || index >= opp->opp_table->clk_count) {
static int _opp_set_regulators(struct opp_table *opp_table, struct device *dev,
if (opp_table->regulators)
opp_table->regulators = kmalloc_objs(*opp_table->regulators, count);
if (!opp_table->regulators)
opp_table->regulators[i] = reg;
opp_table->regulator_count = count;
opp_table->config_regulators = _opp_config_regulator_single;
regulator_put(opp_table->regulators[--i]);
kfree(opp_table->regulators);
opp_table->regulators = NULL;
opp_table->regulator_count = -1;
static void _opp_put_regulators(struct opp_table *opp_table)
if (!opp_table->regulators)
if (opp_table->enabled) {
for (i = opp_table->regulator_count - 1; i >= 0; i--)
regulator_disable(opp_table->regulators[i]);
for (i = opp_table->regulator_count - 1; i >= 0; i--)
regulator_put(opp_table->regulators[i]);
kfree(opp_table->regulators);
opp_table->regulators = NULL;
opp_table->regulator_count = -1;
static void _put_clks(struct opp_table *opp_table, int count)
clk_put(opp_table->clks[i]);
kfree(opp_table->clks);
opp_table->clks = NULL;
static int _opp_set_clknames(struct opp_table *opp_table, struct device *dev,
if (opp_table->clks)
opp_table->clks = kmalloc_objs(*opp_table->clks, count);
if (!opp_table->clks)
opp_table->clks[i] = clk;
opp_table->clk_count = count;
opp_table->config_clks = config_clks;
if (!opp_table->config_clks)
opp_table->config_clks = _opp_config_clk_single;
opp_table->clk = opp_table->clks[0];
_put_clks(opp_table, i);
static void _opp_put_clknames(struct opp_table *opp_table)
if (!opp_table->clks)
opp_table->config_clks = NULL;
opp_table->clk = ERR_PTR(-ENODEV);
_put_clks(opp_table, opp_table->clk_count);
static int _opp_set_config_regulators_helper(struct opp_table *opp_table,
if (!opp_table->config_regulators)
opp_table->config_regulators = config_regulators;
static void _opp_put_config_regulators_helper(struct opp_table *opp_table)
if (opp_table->config_regulators)
opp_table->config_regulators = NULL;
static int _opp_set_required_dev(struct opp_table *opp_table,
struct opp_table *required_table, *pd_table;
if (opp_table->is_genpd) {
if (index >= opp_table->required_opp_count) {
required_table = opp_table->required_opp_tables[index];
opp_table->required_opp_tables[index] = pd_table;
opp_table->required_devs[index] = required_dev;
static void _opp_put_required_dev(struct opp_table *opp_table,
opp_table->required_devs[index] = NULL;
_opp_put_required_dev(data->opp_table,
_opp_put_regulators(data->opp_table);
_opp_put_supported_hw(data->opp_table);
_opp_put_config_regulators_helper(data->opp_table);
_opp_put_prop_name(data->opp_table);
_opp_put_clknames(data->opp_table);
dev_pm_opp_put_opp_table(data->opp_table);
struct opp_table *opp_table;
opp_table = _add_opp_table(dev, false);
if (IS_ERR(opp_table)) {
return PTR_ERR(opp_table);
data->opp_table = opp_table;
if (WARN_ON(!list_empty(&opp_table->opp_list))) {
ret = _opp_set_clknames(opp_table, dev, config->clk_names,
ret = _opp_set_prop_name(opp_table, config->prop_name);
ret = _opp_set_config_regulators_helper(opp_table, dev,
ret = _opp_set_supported_hw(opp_table, config->supported_hw,
ret = _opp_set_regulators(opp_table, dev,
ret = _opp_set_required_dev(opp_table, dev,
index >= opp->opp_table->required_opp_count) {
if (lazy_linking_pending(opp->opp_table))
struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table,
struct opp_table *dst_table,
if (unlikely(!opp->opp_table->required_opp_tables[index]->is_genpd)) {
int dev_pm_opp_xlate_performance_state(struct opp_table *src_table,
struct opp_table *dst_table,
struct opp_table *opp_table;
opp_table = _add_opp_table(dev, true);
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
opp_table->regulator_count = 1;
ret = _opp_add_v1(opp_table, dev, data, true);
dev_pm_opp_put_opp_table(opp_table);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
PTR_ERR(opp_table));
return PTR_ERR(opp_table);
if (!assert_single_clk(opp_table, 0))
scoped_guard(mutex, &opp_table->lock) {
list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ENABLE,
blocking_notifier_call_chain(&opp_table->head,
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
r = PTR_ERR(opp_table);
if (!assert_single_clk(opp_table, 0))
scoped_guard(mutex, &opp_table->lock) {
list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE,
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
if (unlikely(!opp_table->regulators))
if (!opp_table->enabled)
for (i = 0; i < opp_table->regulator_count; i++) {
reg = opp_table->regulators[i];
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
return blocking_notifier_chain_register(&opp_table->head, nb);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
return blocking_notifier_chain_unregister(&opp_table->head, nb);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
int error = PTR_ERR(opp_table);
struct opp_table *opp_table __free(put_opp_table) =
if (_opp_remove_all_static(opp_table))
dev_pm_opp_put_opp_table(opp_table);
if (IS_ERR(opp_table))
return opp_table->clock_latency_ns_max;
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
if (!opp_table->regulators)
count = opp_table->regulator_count;
scoped_guard(mutex, &opp_table->lock) {
list_for_each_entry(opp, &opp_table->opp_list, node) {
reg = opp_table->regulators[i];
static bool _find_opp_dev(const struct device *dev, struct opp_table *opp_table)
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
if (opp_table->suspend_opp && opp_table->suspend_opp->available)
freq = dev_pm_opp_get_freq(opp_table->suspend_opp);
int _get_opp_count(struct opp_table *opp_table)
guard(mutex)(&opp_table->lock);
list_for_each_entry(opp, &opp_table->opp_list, node) {
guard(mutex)(&opp_table->lock);
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
__func__, PTR_ERR(opp_table));
return PTR_ERR(opp_table);
list_for_each_entry(opp_dev, &opp_table->dev_list, node)
return _get_opp_count(opp_table);
static struct opp_table *_find_opp_table_unlocked(struct device *dev)
static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table,
bool (*assert)(struct opp_table *opp_table, unsigned int index))
struct opp_table *opp_table;
if (assert && !assert(opp_table, index))
guard(mutex)(&opp_table->lock);
list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
list_for_each_entry(opp_table, &opp_tables, node) {
static struct dev_pm_opp *_opp_table_find_opp_key(struct opp_table *opp_table,
bool (*assert)(struct opp_table *opp_table, unsigned int index))
if (_find_opp_dev(dev, opp_table))
if (!assert(opp_table, 0))
guard(mutex)(&opp_table->lock);
list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
return dev_pm_opp_get_opp_table_ref(opp_table);
bool (*assert)(struct opp_table *opp_table, unsigned int index))
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
PTR_ERR(opp_table));
return ERR_CAST(opp_table);
return _opp_table_find_key(opp_table, key, index, available, read,
bool (*assert)(struct opp_table *opp_table, unsigned int index))
static struct dev_pm_opp *_opp_table_find_key_ceil(struct opp_table *opp_table,
bool (*assert)(struct opp_table *opp_table, unsigned int index))
return _opp_table_find_key(opp_table, key, index, available, read,
bool (*assert)(struct opp_table *opp_table, unsigned int index))
bool (*assert)(struct opp_table *opp_table, unsigned int index))
struct opp_table *opp_table __free(put_opp_table) = _find_opp_table(dev);
if (IS_ERR(opp_table)) {
PTR_ERR(opp_table));
return ERR_CAST(opp_table);
return _opp_table_find_opp_key(opp_table, key, available,
struct opp_table *_find_opp_table(struct device *dev)
static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table,
return _opp_table_find_key_ceil(opp_table, freq, 0, true, _read_freq,
static bool assert_single_clk(struct opp_table *opp_table,
return !WARN_ON(opp_table->clk_count > 1);
kfree(*opp_table);
*opp_table = NULL;
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
opp_dev = _add_opp_dev(dev, opp_table);
opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN)
if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) {
guard(mutex)(&opp_table->lock);
list_for_each_entry(opp_dev, &opp_table->dev_list, node)
struct cpufreq_frequency_table **opp_table)
*opp_table = &freq_table[0];
struct cpufreq_frequency_table **opp_table)
if (!opp_table)
for (i = 0; i < opp_table->regulator_count; i++) {
void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
struct dentry *pdentry = opp_table->dentry;
if (likely(opp_table->clk_count == 1 && opp->rates[0])) {
snprintf(name, sizeof(name), "opp:%u", _get_opp_count(opp_table));
opp_debug_create_clks(opp, opp_table, d);
opp_debug_create_supplies(opp, opp_table, d);
opp_debug_create_bw(opp, opp_table, d);
struct opp_table *opp_table)
opp_set_dev_name(dev, opp_table->dentry_name);
d = debugfs_create_dir(opp_table->dentry_name, rootdir);
opp_table->dentry = d;
struct opp_table *opp_table)
opp_table->dentry_name);
void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
if (opp_table->dentry)
opp_list_debug_create_link(opp_dev, opp_table);
opp_list_debug_create_dir(opp_dev, opp_table);
struct opp_table *opp_table)
list_for_each_entry(iter, &opp_table->dev_list, node)
opp_set_dev_name(dev, opp_table->dentry_name);
err = debugfs_change_name(opp_dev->dentry, "%s", opp_table->dentry_name);
new_dev->dentry = opp_table->dentry = opp_dev->dentry;
struct opp_table *opp_table)
if (opp_dev->dentry == opp_table->dentry) {
if (!list_is_singular(&opp_table->dev_list)) {
opp_migrate_dentry(opp_dev, opp_table);
opp_table->dentry = NULL;
struct opp_table *opp_table,
for (i = 0; i < opp_table->path_count; i++) {
debugfs_create_file("name", S_IRUGO, d, opp_table->paths[i],
struct opp_table *opp_table,
if (opp_table->clk_count == 1) {
for (i = 0; i < opp_table->clk_count; i++) {
struct opp_table *opp_table,
static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
scoped_guard(mutex, &opp_table->lock) {
if (opp_table->parsed_static_opps) {
opp_table->parsed_static_opps++;
opp_table->parsed_static_opps = 1;
ret = _opp_add_v1(opp_table, dev, &data, false);
_opp_remove_all_static(opp_table);
struct opp_table *opp_table;
opp_table = _add_opp_table_indexed(dev, index, true);
if (IS_ERR(opp_table))
return PTR_ERR(opp_table);
list_for_each_entry(opp_table, &opp_tables, node) {
if (opp_table->np)
ret = _of_add_opp_table_v2(dev, opp_table);
ret = _of_add_opp_table_v1(dev, opp_table);
dev_pm_opp_put_opp_table(opp_table);
if (opp_table_np == opp_table->np)
return dev_pm_opp_get_opp_table_ref(opp_table);
static void _opp_table_free_required_tables(struct opp_table *opp_table)
struct opp_table **required_opp_tables = opp_table->required_opp_tables;
for (i = 0; i < opp_table->required_opp_count; i++) {
struct opp_table *opp_table __free(put_opp_table) =
if (IS_ERR(opp_table)) {
__func__, np, PTR_ERR(opp_table));
opp_table->required_opp_count = 0;
return PTR_ERR(opp_table);
if (unlikely(!opp_table->is_genpd)) {
opp_table->required_opp_tables = NULL;
_find_opp_of_np(opp_table, required_np);
list_del(&opp_table->lazy);
static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
struct opp_table **required_opp_tables;
size = sizeof(*required_opp_tables) + sizeof(*opp_table->required_devs);
opp_table->required_opp_tables = required_opp_tables;
opp_table->required_devs = (void *)(required_opp_tables + count);
opp_table->required_opp_count = count;
_opp_table_free_required_tables(opp_table);
list_add(&opp_table->lazy, &lazy_opp_tables);
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev,
opp_table->clock_latency_ns_max = val;
&opp_table->voltage_tolerance_v1);
opp_table->is_genpd = true;
opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
opp_table->np = opp_np;
_opp_table_alloc_required_tables(opp_table, dev, opp_np);
void _of_clear_opp_table(struct opp_table *opp_table)
_opp_table_free_required_tables(opp_table);
of_node_put(opp_table->np);
static void _of_opp_free_required_opps(struct opp_table *opp_table,
for (i = 0; i < opp_table->required_opp_count; i++) {
void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp)
_of_opp_free_required_opps(opp_table, opp);
struct opp_table *required_table, int index)
static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
struct opp_table *required_table;
int i, ret, count = opp_table->required_opp_count;
required_table = opp_table->required_opp_tables[i];
_of_opp_free_required_opps(opp_table, opp);
static int lazy_link_required_opps(struct opp_table *opp_table,
struct opp_table *new_table, int index)
list_for_each_entry(opp, &opp_table->opp_list, node) {
static void lazy_link_required_opp_table(struct opp_table *new_table)
struct opp_table *opp_table, *temp, **required_opp_tables;
list_for_each_entry_safe(opp_table, temp, &lazy_opp_tables, lazy) {
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;
ret = lazy_link_required_opps(opp_table, new_table, i);
list_del_init(&opp_table->lazy);
list_for_each_entry(opp, &opp_table->opp_list, node)
_required_opps_available(opp, opp_table->required_opp_count);
static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table)
if (!opp_table) {
opp_np = of_node_get(opp_table->np);
struct opp_table *opp_table)
ret = _bandwidth_supported(dev, opp_table);
struct opp_table *_managed_opp(struct device *dev, int index)
struct opp_table *opp_table, *managed_table = NULL;
if (opp_table) {
opp_table->paths = paths;
opp_table->path_count = num_paths;
static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
unsigned int levels = opp_table->supported_hw_count;
if (!opp_table->supported_hw) {
if (!(val & opp_table->supported_hw[j])) {
list_for_each_entry(opp_table, &opp_tables, node) {
struct opp_table *opp_table,
if (opp_table->np == np) {
if (opp_table->prop_name) {
opp_table->prop_name);
if (unlikely(opp_table->regulator_count == -1))
opp_table->regulator_count = 1;
if (count != opp_table->regulator_count &&
(!triplet || count != opp_table->regulator_count * 3)) {
__func__, prop_type, count, opp_table->regulator_count);
*triplet = count != opp_table->regulator_count;
struct opp_table *opp_table, bool *triplet)
microvolt = _parse_named_prop(opp, dev, opp_table, "microvolt", triplet);
if (list_empty(&opp_table->opp_list) &&
opp_table->regulator_count > 0) {
if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED)
struct opp_table *opp_table)
managed_table = dev_pm_opp_get_opp_table_ref(opp_table);
microvolt = opp_parse_microvolt(opp, dev, opp_table, &triplet);
microamp = _parse_named_prop(opp, dev, opp_table, "microamp", NULL);
microwatt = _parse_named_prop(opp, dev, opp_table, "microwatt", NULL);
if (unlikely(opp_table->regulator_count == -1)) {
opp_table->regulator_count = 0;
for (i = 0, j = 0; i < opp_table->regulator_count; i++) {
static int _read_rate(struct dev_pm_opp *new_opp, struct opp_table *opp_table,
if (opp_table->clk_count != count) {
__func__, count, opp_table->clk_count);
static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table,
static int _read_bw(struct dev_pm_opp *new_opp, struct opp_table *opp_table,
if (opp_table->path_count != count) {
__func__, name, count, opp_table->path_count);
guard(mutex)(&opp_table->lock);
struct opp_table *opp_table, struct device_node *np)
ret = _read_rate(new_opp, opp_table, np);
list_for_each_entry(opp, &opp_table->opp_list, node) {
ret = _read_bw(new_opp, opp_table, np, true);
ret = _read_bw(new_opp, opp_table, np, false);
static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
new_opp = _opp_allocate(opp_table);
ret = _read_opp_key(new_opp, opp_table, np);
if (!_opp_is_supported(dev, opp_table, np)) {
ret = _of_opp_alloc_required_opps(opp_table, new_opp);
ret = opp_parse_supplies(new_opp, dev, opp_table);
ret = _opp_add(dev, new_opp, opp_table);
if (opp_table->suspend_opp) {
if (_opp_compare_key(opp_table, new_opp, opp_table->suspend_opp) == 1) {
opp_table->suspend_opp->suspend = false;
opp_table->suspend_opp = new_opp;
opp_table->suspend_opp = new_opp;
if (new_opp->clock_latency_ns > opp_table->clock_latency_ns_max)
opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADD, new_opp);
_of_opp_free_required_opps(opp_table, new_opp);
static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
scoped_guard(mutex, &opp_table->lock) {
if (opp_table->parsed_static_opps) {
opp_table->parsed_static_opps++;
static struct opp_table *_find_table_of_opp_np(struct device_node *opp_np)
opp_table->parsed_static_opps = 1;
for_each_available_child_of_node_scoped(opp_table->np, np) {
opp = _opp_add_static_v2(opp_table, dev, np);
struct opp_table *opp_table;
lazy_link_required_opp_table(opp_table);
_opp_remove_all_static(opp_table);
struct opp_table *opp_table;
struct opp_table **required_opp_tables;
bool _opp_remove_all_static(struct opp_table *opp_table);
int _get_opp_count(struct opp_table *opp_table);
struct opp_table *_find_opp_table(struct device *dev);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
int _opp_compare_key(struct opp_table *opp_table, 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);
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, struct dev_pm_opp_data *data, bool dynamic);
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
static inline bool lazy_linking_pending(struct opp_table *opp_table)
return unlikely(!list_empty(&opp_table->lazy));
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
void _of_clear_opp_table(struct opp_table *opp_table);
struct opp_table *_managed_opp(struct device *dev, int index);
void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp);
static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
static inline void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) {}
void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
struct opp_table *opp_table) { }
struct opp_table *opp_table) { }
struct opp_table *opp_table)
struct opp_table *opp_table;
genpd->opp_table = NULL;
genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev);
WARN_ON(IS_ERR(genpd->opp_table));
if (genpd->opp_table) {
dev_pm_opp_put_opp_table(genpd->opp_table);
genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev);
WARN_ON(IS_ERR(genpd->opp_table));
if (genpd->opp_table) {
dev_pm_opp_put_opp_table(genpd->opp_table);
if (gpd->opp_table) {
dev_pm_opp_put_opp_table(gpd->opp_table);
return dev_pm_opp_xlate_performance_state(genpd->opp_table,
parent->opp_table,
dev_pm_opp_put_opp_table(opp_table);
struct opp_table *last_opp_table = NULL;
struct opp_table *opp_table;
opp_table = dev_pm_opp_get_opp_table(cpu);
if (IS_ERR(opp_table))
if (!last_opp_table || opp_table != last_opp_table) {
last_opp_table = opp_table;
int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table,
struct opp_table *opp_table;
struct opp_table;
struct opp_table *opp_table; /* OPP table of the genpd */
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
struct opp_table *dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table);
void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
struct opp_table *opp_table, struct dev_pm_opp *opp, void *data,
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);
static inline struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
static inline struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index)
static inline struct opp_table *dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table)
return opp_table;
struct opp_table;
static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
struct opp_table *opp_table, struct dev_pm_opp *opp, void *data,
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)
static inline int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate)
int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_table *opp_table);
typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table,
static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_table *opp_table)
DEFINE_FREE(put_opp_table, struct opp_table *, if (!IS_ERR_OR_NULL(_T)) dev_pm_opp_put_opp_table(_T))
int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table,