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.

Dependency Surface

Detected Declarations

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

Implementation Notes