drivers/cpufreq/spear-cpufreq.c

Source file repositories/reference/linux-study-clean/drivers/cpufreq/spear-cpufreq.c

File Facts

System
Linux kernel
Corpus path
drivers/cpufreq/spear-cpufreq.c
Extension
.c
Size
5905 bytes
Lines
243
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 (IS_ERR(srcclk)) {
			pr_err("Failed to get src clk\n");
			return PTR_ERR(srcclk);
		}

		/* SPEAr1340: src clk is always 2 * intended cpu clk */
		mult = 2;
	} else {
		/*
		 * src clock to be altered is ancestor of cpu clock. Hence we
		 * can directly work on cpu clk
		 */
		srcclk = spear_cpufreq.clk;
	}

	newfreq = clk_round_rate(srcclk, newfreq * mult);
	if (newfreq <= 0) {
		pr_err("clk_round_rate failed for cpu src clock\n");
		return newfreq;
	}

	if (mult == 2)
		ret = spear1340_set_cpu_rate(srcclk, newfreq);
	else
		ret = clk_set_rate(spear_cpufreq.clk, newfreq);

	if (ret)
		pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);

	return ret;
}

static int spear_cpufreq_init(struct cpufreq_policy *policy)
{
	policy->clk = spear_cpufreq.clk;
	cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
			spear_cpufreq.transition_latency);
	return 0;
}

static struct cpufreq_driver spear_cpufreq_driver = {
	.name		= "cpufreq-spear",
	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK,
	.verify		= cpufreq_generic_frequency_table_verify,
	.target_index	= spear_cpufreq_target,
	.get		= cpufreq_generic_get,
	.init		= spear_cpufreq_init,
};

static int spear_cpufreq_probe(struct platform_device *pdev)
{
	struct device_node *np;
	struct cpufreq_frequency_table *freq_tbl;
	u32 val;
	int cnt, ret, i = 0;

	np = of_cpu_device_node_get(0);
	if (!np) {
		pr_err("No cpu node found\n");
		return -ENODEV;
	}

	if (of_property_read_u32(np, "clock-latency",
				&spear_cpufreq.transition_latency))
		spear_cpufreq.transition_latency = CPUFREQ_DEFAULT_TRANSITION_LATENCY_NS;

	cnt = of_property_count_u32_elems(np, "cpufreq_tbl");
	if (cnt <= 0) {
		pr_err("Invalid cpufreq_tbl\n");
		ret = -ENODEV;
		goto out_put_node;
	}

	freq_tbl = kzalloc_objs(*freq_tbl, cnt + 1);
	if (!freq_tbl) {
		ret = -ENOMEM;
		goto out_put_node;
	}

	of_property_for_each_u32(np, "cpufreq_tbl", val)
		freq_tbl[i++].frequency = val;

	freq_tbl[cnt].frequency = CPUFREQ_TABLE_END;

	spear_cpufreq.freq_tbl = freq_tbl;

	of_node_put(np);

	spear_cpufreq.clk = clk_get(NULL, "cpu_clk");
	if (IS_ERR(spear_cpufreq.clk)) {

Annotation

Implementation Notes