drivers/clk/mvebu/clk-cpu.c
Source file repositories/reference/linux-study-clean/drivers/clk/mvebu/clk-cpu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/mvebu/clk-cpu.c- Extension
.c- Size
- 6530 bytes
- Lines
- 248
- Domain
- Driver Families
- Bucket
- drivers/clk
- 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.
- 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/kernel.hlinux/slab.hlinux/clk.hlinux/clk-provider.hlinux/of_address.hlinux/io.hlinux/of.hlinux/delay.hlinux/mvebu-pmsu.hasm/smp_plat.h
Detected Declarations
struct cpu_clkfunction clk_cpu_recalc_ratefunction clk_cpu_determine_ratefunction clk_cpu_off_set_ratefunction clk_cpu_on_set_ratefunction clk_cpu_set_ratefunction of_cpu_clk_setupfunction for_each_possible_cpufunction of_mv98dx3236_cpu_clk_setup
Annotated Snippet
struct cpu_clk {
struct clk_hw hw;
int cpu;
const char *clk_name;
const char *parent_name;
void __iomem *reg_base;
void __iomem *pmu_dfs;
};
static struct clk **clks;
static struct clk_onecell_data clk_data;
#define to_cpu_clk(p) container_of(p, struct cpu_clk, hw)
static unsigned long clk_cpu_recalc_rate(struct clk_hw *hwclk,
unsigned long parent_rate)
{
struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
u32 reg, div;
reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
div = (reg >> (cpuclk->cpu * 8)) & SYS_CTRL_CLK_DIVIDER_MASK;
return parent_rate / div;
}
static int clk_cpu_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/* Valid ratio are 1:1, 1:2 and 1:3 */
u32 div;
div = req->best_parent_rate / req->rate;
if (div == 0)
div = 1;
else if (div > 3)
div = 3;
req->rate = req->best_parent_rate / div;
return 0;
}
static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
unsigned long parent_rate)
{
struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
u32 reg, div;
u32 reload_mask;
div = parent_rate / rate;
reg = (readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET)
& (~(SYS_CTRL_CLK_DIVIDER_MASK << (cpuclk->cpu * 8))))
| (div << (cpuclk->cpu * 8));
writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET);
/* Set clock divider reload smooth bit mask */
reload_mask = 1 << (20 + cpuclk->cpu);
reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
| reload_mask;
writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
/* Now trigger the clock update */
reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET)
| 1 << 24;
writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
/* Wait for clocks to settle down then clear reload request */
udelay(1000);
reg &= ~(reload_mask | 1 << 24);
writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
udelay(1000);
return 0;
}
static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
unsigned long parent_rate)
{
u32 reg;
unsigned long fabric_div, target_div, cur_rate;
struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
/*
* PMU DFS registers are not mapped, Device Tree does not
* describes them. We cannot change the frequency dynamically.
*/
if (!cpuclk->pmu_dfs)
return -ENODEV;
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/slab.h`, `linux/clk.h`, `linux/clk-provider.h`, `linux/of_address.h`, `linux/io.h`, `linux/of.h`, `linux/delay.h`.
- Detected declarations: `struct cpu_clk`, `function clk_cpu_recalc_rate`, `function clk_cpu_determine_rate`, `function clk_cpu_off_set_rate`, `function clk_cpu_on_set_rate`, `function clk_cpu_set_rate`, `function of_cpu_clk_setup`, `function for_each_possible_cpu`, `function of_mv98dx3236_cpu_clk_setup`.
- Atlas domain: Driver Families / drivers/clk.
- Implementation status: source implementation candidate.
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.