drivers/opp/of.c
Source file repositories/reference/linux-study-clean/drivers/opp/of.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/opp/of.c- Extension
.c- Size
- 40677 bytes
- Lines
- 1599
- Domain
- Driver Families
- Bucket
- drivers/opp
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/cpu.hlinux/errno.hlinux/device.hlinux/of.hlinux/pm_domain.hlinux/slab.hlinux/export.hlinux/energy_model.hopp.h
Detected Declarations
function of_node_putfunction list_for_each_entryfunction list_for_each_entryfunction list_for_each_entryfunction _opp_table_free_required_tablesfunction _opp_table_alloc_required_tablesfunction _of_init_opp_tablefunction _of_clear_opp_tablefunction _of_opp_alloc_required_oppsfunction _of_clear_oppfunction _link_required_oppsfunction _of_opp_alloc_required_oppsfunction lazy_link_required_oppsfunction list_for_each_entryfunction lazy_link_required_opp_tablefunction list_for_each_entry_safefunction _bandwidth_supportedfunction dev_pm_opp_of_find_icc_pathsfunction _opp_is_supportedfunction opp_parse_suppliesfunction dev_pm_opp_of_remove_tablefunction _read_ratefunction _read_bwfunction _read_opp_keyfunction _opp_add_static_v2function _of_add_opp_table_v2function _of_add_opp_table_v1function scoped_guardfunction _of_add_table_indexedfunction devm_pm_opp_of_table_releasefunction _devm_of_add_table_indexedfunction devm_pm_opp_of_add_tablefunction dev_pm_opp_of_add_tablefunction dev_pm_opp_of_add_table_indexedfunction devm_pm_opp_of_add_table_indexedfunction dev_pm_opp_of_cpumask_remove_tablefunction dev_pm_opp_of_cpumask_add_tablefunction for_each_cpufunction dev_pm_opp_of_get_sharing_cpusfunction for_each_possible_cpufunction of_get_required_opp_performance_statefunction dev_pm_opp_of_has_required_oppfunction dev_pm_opp_get_of_nodefunction _get_dt_powerfunction dev_pm_opp_calc_powerfunction _of_has_opp_microwatt_propertyfunction dev_pm_opp_of_register_emexport dev_pm_opp_of_get_opp_desc_node
Annotated Snippet
if (opp_table->np == np) {
/*
* Multiple devices can point to the same OPP table and
* so will have same node-pointer, np.
*
* But the OPPs will be considered as shared only if the
* OPP table contains a "opp-shared" property.
*/
if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED)
managed_table = dev_pm_opp_get_opp_table_ref(opp_table);
break;
}
}
return managed_table;
}
/* The caller must call dev_pm_opp_put() after the OPP is used */
static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table,
struct device_node *opp_np)
{
struct dev_pm_opp *opp;
guard(mutex)(&opp_table->lock);
list_for_each_entry(opp, &opp_table->opp_list, node) {
if (opp->np == opp_np)
return dev_pm_opp_get(opp);
}
return NULL;
}
static struct device_node *of_parse_required_opp(struct device_node *np,
int index)
{
return of_parse_phandle(np, "required-opps", index);
}
/* The caller must call dev_pm_opp_put_opp_table() after the table is used */
static struct opp_table *_find_table_of_opp_np(struct device_node *opp_np)
{
struct opp_table *opp_table;
struct device_node *opp_table_np __free(device_node) =
of_get_parent(opp_np);
if (!opp_table_np)
return ERR_PTR(-ENODEV);
guard(mutex)(&opp_table_lock);
list_for_each_entry(opp_table, &opp_tables, node) {
if (opp_table_np == opp_table->np)
return dev_pm_opp_get_opp_table_ref(opp_table);
}
return ERR_PTR(-ENODEV);
}
/* Free resources previously acquired by _opp_table_alloc_required_tables() */
static void _opp_table_free_required_tables(struct opp_table *opp_table)
{
struct opp_table **required_opp_tables = opp_table->required_opp_tables;
int i;
if (!required_opp_tables)
return;
for (i = 0; i < opp_table->required_opp_count; i++) {
if (IS_ERR_OR_NULL(required_opp_tables[i]))
continue;
dev_pm_opp_put_opp_table(required_opp_tables[i]);
}
kfree(required_opp_tables);
opp_table->required_opp_count = 0;
opp_table->required_opp_tables = NULL;
guard(mutex)(&opp_table_lock);
list_del(&opp_table->lazy);
}
/*
* Populate all devices and opp tables which are part of "required-opps" list.
* Checking only the first OPP node should be enough.
*/
Annotation
- Immediate include surface: `linux/cpu.h`, `linux/errno.h`, `linux/device.h`, `linux/of.h`, `linux/pm_domain.h`, `linux/slab.h`, `linux/export.h`, `linux/energy_model.h`.
- Detected declarations: `function of_node_put`, `function list_for_each_entry`, `function list_for_each_entry`, `function list_for_each_entry`, `function _opp_table_free_required_tables`, `function _opp_table_alloc_required_tables`, `function _of_init_opp_table`, `function _of_clear_opp_table`, `function _of_opp_alloc_required_opps`, `function _of_clear_opp`.
- Atlas domain: Driver Families / drivers/opp.
- Implementation status: integration implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.