drivers/opp/core.c
Source file repositories/reference/linux-study-clean/drivers/opp/core.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/opp/core.c- Extension
.c- Size
- 86100 bytes
- Lines
- 3130
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/clk.hlinux/errno.hlinux/err.hlinux/device.hlinux/export.hlinux/pm_domain.hlinux/regulator/consumer.hlinux/slab.hlinux/xarray.hopp.h
Detected Declarations
function _find_opp_devfunction list_for_each_entryfunction _find_opp_tablefunction assert_single_clkfunction assert_clk_indexfunction assert_bandwidth_indexfunction dev_pm_opp_get_bwfunction dev_pm_opp_get_voltagefunction dev_pm_opp_get_suppliesfunction dev_pm_opp_get_powerfunction dev_pm_opp_get_freq_indexedfunction dev_pm_opp_get_levelfunction dev_pm_opp_get_required_pstatefunction dev_pm_opp_is_turbofunction dev_pm_opp_get_max_clock_latencyfunction dev_pm_opp_get_max_volt_latencyfunction scoped_guardfunction list_for_each_entryfunction dev_pm_opp_get_max_transition_latencyfunction dev_pm_opp_get_suspend_opp_freqfunction _get_opp_countfunction list_for_each_entryfunction dev_pm_opp_get_opp_countfunction _read_freqfunction _read_levelfunction _read_bwfunction _read_opp_keyfunction _compare_exactfunction _compare_ceilfunction _compare_floorfunction _compare_opp_key_exactfunction longfunction list_for_each_entryfunction longfunction list_for_each_entryfunction _find_keyfunction longfunction longfunction longfunction longfunction dev_pm_opp_find_freq_exactfunction dev_pm_opp_find_key_exactfunction dev_pm_opp_find_freq_exact_indexedfunction dev_pm_opp_find_freq_ceilfunction dev_pm_opp_find_freq_ceil_indexedfunction dev_pm_opp_find_freq_floorfunction dev_pm_opp_find_freq_floor_indexedfunction dev_pm_opp_find_level_exact
Annotated Snippet
list_for_each_entry(opp, &opp_table->opp_list, node) {
if (!opp->available)
continue;
if (opp->supplies[i].u_volt_min < uV[i].min)
uV[i].min = opp->supplies[i].u_volt_min;
if (opp->supplies[i].u_volt_max > uV[i].max)
uV[i].max = opp->supplies[i].u_volt_max;
}
}
}
/*
* The caller needs to ensure that opp_table (and hence the regulator)
* isn't freed, while we are executing this routine.
*/
for (i = 0; i < count; i++) {
reg = opp_table->regulators[i];
ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
if (ret > 0)
latency_ns += ret * 1000;
}
kfree(uV);
return latency_ns;
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_volt_latency);
/**
* dev_pm_opp_get_max_transition_latency() - Get max transition latency in
* nanoseconds
* @dev: device for which we do this operation
*
* Return: This function returns the max transition latency, in nanoseconds, to
* switch from one OPP to other.
*/
unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev)
{
return dev_pm_opp_get_max_volt_latency(dev) +
dev_pm_opp_get_max_clock_latency(dev);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_transition_latency);
/**
* dev_pm_opp_get_suspend_opp_freq() - Get frequency of suspend opp in Hz
* @dev: device for which we do this operation
*
* Return: This function returns the frequency of the OPP marked as suspend_opp
* if one is available, else returns 0;
*/
unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
{
unsigned long freq = 0;
struct opp_table *opp_table __free(put_opp_table) =
_find_opp_table(dev);
if (IS_ERR(opp_table))
return 0;
if (opp_table->suspend_opp && opp_table->suspend_opp->available)
freq = dev_pm_opp_get_freq(opp_table->suspend_opp);
return freq;
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq);
int _get_opp_count(struct opp_table *opp_table)
{
struct dev_pm_opp *opp;
int count = 0;
guard(mutex)(&opp_table->lock);
list_for_each_entry(opp, &opp_table->opp_list, node) {
if (opp->available)
count++;
}
return count;
}
/**
* dev_pm_opp_get_opp_count() - Get number of opps available in the opp table
* @dev: device for which we do this operation
*
* Return: This function returns the number of available opps if there are any,
* else returns 0 if none or the corresponding error value.
*/
Annotation
- Immediate include surface: `linux/clk.h`, `linux/errno.h`, `linux/err.h`, `linux/device.h`, `linux/export.h`, `linux/pm_domain.h`, `linux/regulator/consumer.h`, `linux/slab.h`.
- Detected declarations: `function _find_opp_dev`, `function list_for_each_entry`, `function _find_opp_table`, `function assert_single_clk`, `function assert_clk_index`, `function assert_bandwidth_index`, `function dev_pm_opp_get_bw`, `function dev_pm_opp_get_voltage`, `function dev_pm_opp_get_supplies`, `function dev_pm_opp_get_power`.
- Atlas domain: Driver Families / drivers/opp.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.