drivers/cpufreq/vexpress-spc-cpufreq.c
Source file repositories/reference/linux-study-clean/drivers/cpufreq/vexpress-spc-cpufreq.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/cpufreq/vexpress-spc-cpufreq.c- Extension
.c- Size
- 14404 bytes
- Lines
- 576
- Domain
- Driver Families
- Bucket
- drivers/cpufreq
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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/cpu.hlinux/cpufreq.hlinux/cpumask.hlinux/device.hlinux/module.hlinux/mutex.hlinux/platform_device.hlinux/pm_opp.hlinux/slab.hlinux/topology.hlinux/types.hasm/bL_switcher.h
Detected Declarations
function raw_cpu_to_clusterfunction cpu_to_clusterfunction find_cluster_maxfreqfunction for_each_online_cpufunction clk_get_cpu_ratefunction ve_spc_cpufreq_get_ratefunction ve_spc_cpufreq_set_ratefunction ve_spc_cpufreq_set_targetfunction get_table_countfunction get_table_minfunction get_table_maxfunction search_frequencyfunction merge_cluster_tablesfunction _put_cluster_clk_and_freq_tablefunction put_cluster_clk_and_freq_tablefunction for_each_present_cpufunction _get_cluster_clk_and_freq_tablefunction get_cluster_clk_and_freq_tablefunction ve_spc_cpufreq_initfunction ve_spc_cpufreq_exitfunction bL_cpufreq_switcher_notifierfunction __bLs_register_notifierfunction __bLs_unregister_notifierfunction __bLs_register_notifierfunction __bLs_unregister_notifierfunction ve_spc_cpufreq_probefunction ve_spc_cpufreq_remove
Annotated Snippet
if (bLs) {
per_cpu(cpu_last_req_freq, cpu) = prev_rate;
per_cpu(physical_cluster, cpu) = old_cluster;
}
mutex_unlock(&cluster_lock[new_cluster]);
return ret;
}
mutex_unlock(&cluster_lock[new_cluster]);
/* Recalc freq for old cluster when switching clusters */
if (old_cluster != new_cluster) {
/* Switch cluster */
bL_switch_request(cpu, new_cluster);
mutex_lock(&cluster_lock[old_cluster]);
/* Set freq of old cluster if there are cpus left on it */
new_rate = find_cluster_maxfreq(old_cluster);
new_rate = ACTUAL_FREQ(old_cluster, new_rate);
if (new_rate &&
clk_set_rate(clk[old_cluster], new_rate * 1000)) {
pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n",
__func__, ret, old_cluster);
}
mutex_unlock(&cluster_lock[old_cluster]);
}
return 0;
}
/* Set clock frequency */
static int ve_spc_cpufreq_set_target(struct cpufreq_policy *policy,
unsigned int index)
{
u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster;
unsigned int freqs_new;
cur_cluster = cpu_to_cluster(cpu);
new_cluster = actual_cluster = per_cpu(physical_cluster, cpu);
freqs_new = freq_table[cur_cluster][index].frequency;
if (is_bL_switching_enabled()) {
if (actual_cluster == A15_CLUSTER && freqs_new < clk_big_min)
new_cluster = A7_CLUSTER;
else if (actual_cluster == A7_CLUSTER &&
freqs_new > clk_little_max)
new_cluster = A15_CLUSTER;
}
return ve_spc_cpufreq_set_rate(cpu, actual_cluster, new_cluster,
freqs_new);
}
static inline u32 get_table_count(struct cpufreq_frequency_table *table)
{
int count;
for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
;
return count;
}
/* get the minimum frequency in the cpufreq_frequency_table */
static inline u32 get_table_min(struct cpufreq_frequency_table *table)
{
struct cpufreq_frequency_table *pos;
u32 min_freq = ~0;
cpufreq_for_each_entry(pos, table)
if (pos->frequency < min_freq)
min_freq = pos->frequency;
return min_freq;
}
/* get the maximum frequency in the cpufreq_frequency_table */
static inline u32 get_table_max(struct cpufreq_frequency_table *table)
{
struct cpufreq_frequency_table *pos;
u32 max_freq = 0;
cpufreq_for_each_entry(pos, table)
if (pos->frequency > max_freq)
max_freq = pos->frequency;
return max_freq;
Annotation
- Immediate include surface: `linux/clk.h`, `linux/cpu.h`, `linux/cpufreq.h`, `linux/cpumask.h`, `linux/device.h`, `linux/module.h`, `linux/mutex.h`, `linux/platform_device.h`.
- Detected declarations: `function raw_cpu_to_cluster`, `function cpu_to_cluster`, `function find_cluster_maxfreq`, `function for_each_online_cpu`, `function clk_get_cpu_rate`, `function ve_spc_cpufreq_get_rate`, `function ve_spc_cpufreq_set_rate`, `function ve_spc_cpufreq_set_target`, `function get_table_count`, `function get_table_min`.
- Atlas domain: Driver Families / drivers/cpufreq.
- Implementation status: source 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.