drivers/cpufreq/qcom-cpufreq-hw.c
Source file repositories/reference/linux-study-clean/drivers/cpufreq/qcom-cpufreq-hw.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/cpufreq/qcom-cpufreq-hw.c- Extension
.c- Size
- 20512 bytes
- Lines
- 778
- Domain
- Driver Families
- Bucket
- drivers/cpufreq
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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/bitfield.hlinux/clk-provider.hlinux/cpufreq.hlinux/init.hlinux/interconnect.hlinux/interrupt.hlinux/io.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_opp.hlinux/slab.hlinux/spinlock.hlinux/units.h
Detected Declarations
struct qcom_cpufreq_soc_datastruct qcom_cpufreq_datafunction qcom_cpufreq_set_bwfunction qcom_cpufreq_update_oppfunction qcom_cpufreq_hw_target_indexfunction qcom_lmh_get_throttle_freqfunction qcom_cpufreq_get_freqfunction __qcom_cpufreq_hw_getfunction qcom_cpufreq_hw_getfunction qcom_cpufreq_hw_fast_switchfunction qcom_cpufreq_hw_read_lutfunction qcom_get_related_cpusfunction for_each_present_cpufunction qcom_lmh_dcvs_notifyfunction qcom_lmh_dcvs_pollfunction qcom_lmh_dcvs_handle_irqfunction qcom_cpufreq_hw_lmh_initfunction qcom_cpufreq_hw_cpu_onlinefunction qcom_cpufreq_hw_cpu_offlinefunction qcom_cpufreq_hw_lmh_exitfunction qcom_cpufreq_hw_cpu_initfunction qcom_cpufreq_hw_cpu_exitfunction qcom_cpufreq_readyfunction qcom_cpufreq_hw_recalc_ratefunction clk_set_ratefunction qcom_cpufreq_hw_driver_probefunction qcom_cpufreq_hw_driver_removefunction qcom_cpufreq_hw_initfunction qcom_cpufreq_hw_exit
Annotated Snippet
struct qcom_cpufreq_soc_data {
u32 reg_enable;
u32 reg_domain_state;
u32 reg_dcvs_ctrl;
u32 reg_freq_lut;
u32 reg_volt_lut;
u32 reg_intr_clr;
u32 reg_current_vote;
u32 reg_perf_state;
u32 lut_max_entries;
u8 lut_row_size;
};
struct qcom_cpufreq_data {
void __iomem *base;
/*
* Mutex to synchronize between de-init sequence and re-starting LMh
* polling/interrupts
*/
struct mutex throttle_lock;
int throttle_irq;
char irq_name[15];
bool cancel_throttle;
struct delayed_work throttle_work;
struct cpufreq_policy *policy;
struct clk_hw cpu_clk;
bool per_core_dcvs;
};
static struct {
struct qcom_cpufreq_data *data;
const struct qcom_cpufreq_soc_data *soc_data;
} qcom_cpufreq;
static unsigned long cpu_hw_rate, xo_rate;
static bool icc_scaling_enabled;
static int qcom_cpufreq_set_bw(struct cpufreq_policy *policy,
unsigned long freq_khz)
{
unsigned long freq_hz = freq_khz * 1000;
struct dev_pm_opp *opp;
struct device *dev;
int ret;
dev = get_cpu_device(policy->cpu);
if (!dev)
return -ENODEV;
opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true);
if (IS_ERR(opp))
return PTR_ERR(opp);
ret = dev_pm_opp_set_opp(dev, opp);
dev_pm_opp_put(opp);
return ret;
}
static int qcom_cpufreq_update_opp(struct device *cpu_dev,
unsigned long freq_khz,
unsigned long volt)
{
unsigned long freq_hz = freq_khz * 1000;
int ret;
/* Skip voltage update if the opp table is not available */
if (!icc_scaling_enabled)
return dev_pm_opp_add(cpu_dev, freq_hz, volt);
ret = dev_pm_opp_adjust_voltage(cpu_dev, freq_hz, volt, volt, volt);
if (ret) {
dev_err(cpu_dev, "Voltage update failed freq=%ld\n", freq_khz);
return ret;
}
return dev_pm_opp_enable(cpu_dev, freq_hz);
}
static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
unsigned int index)
{
struct qcom_cpufreq_data *data = policy->driver_data;
const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
unsigned long freq = policy->freq_table[index].frequency;
unsigned int i;
writel_relaxed(index, data->base + soc_data->reg_perf_state);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk-provider.h`, `linux/cpufreq.h`, `linux/init.h`, `linux/interconnect.h`, `linux/interrupt.h`, `linux/io.h`, `linux/kernel.h`.
- Detected declarations: `struct qcom_cpufreq_soc_data`, `struct qcom_cpufreq_data`, `function qcom_cpufreq_set_bw`, `function qcom_cpufreq_update_opp`, `function qcom_cpufreq_hw_target_index`, `function qcom_lmh_get_throttle_freq`, `function qcom_cpufreq_get_freq`, `function __qcom_cpufreq_hw_get`, `function qcom_cpufreq_hw_get`, `function qcom_cpufreq_hw_fast_switch`.
- Atlas domain: Driver Families / drivers/cpufreq.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.