drivers/clk/renesas/clk-div6.c
Source file repositories/reference/linux-study-clean/drivers/clk/renesas/clk-div6.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/renesas/clk-div6.c- Extension
.c- Size
- 9314 bytes
- Lines
- 371
- 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/bitfield.hlinux/clk-provider.hlinux/init.hlinux/io.hlinux/kernel.hlinux/notifier.hlinux/of.hlinux/of_address.hlinux/pm.hlinux/slab.hclk-div6.h
Detected Declarations
struct div6_clockfunction cpg_div6_clock_enablefunction cpg_div6_clock_disablefunction cpg_div6_clock_is_enabledfunction cpg_div6_clock_recalc_ratefunction cpg_div6_clock_calc_divfunction cpg_div6_clock_determine_ratefunction cpg_div6_clock_set_ratefunction cpg_div6_clock_get_parentfunction cpg_div6_clock_set_parentfunction cpg_div6_clock_notifier_callfunction cpg_div6_registerfunction cpg_div6_clock_init
Annotated Snippet
struct div6_clock {
struct clk_hw hw;
void __iomem *reg;
unsigned int div;
u32 src_mask;
struct notifier_block nb;
u8 parents[];
};
#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)
static int cpg_div6_clock_enable(struct clk_hw *hw)
{
struct div6_clock *clock = to_div6_clock(hw);
u32 val;
val = (readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP))
| CPG_DIV6_DIV(clock->div - 1);
writel(val, clock->reg);
return 0;
}
static void cpg_div6_clock_disable(struct clk_hw *hw)
{
struct div6_clock *clock = to_div6_clock(hw);
u32 val;
val = readl(clock->reg);
val |= CPG_DIV6_CKSTP;
/*
* DIV6 clocks require the divisor field to be non-zero when stopping
* the clock. However, some clocks (e.g. ZB on sh73a0) fail to be
* re-enabled later if the divisor field is changed when stopping the
* clock
*/
if (!(val & CPG_DIV6_DIV_MASK))
val |= CPG_DIV6_DIV_MASK;
writel(val, clock->reg);
}
static int cpg_div6_clock_is_enabled(struct clk_hw *hw)
{
struct div6_clock *clock = to_div6_clock(hw);
return !(readl(clock->reg) & CPG_DIV6_CKSTP);
}
static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct div6_clock *clock = to_div6_clock(hw);
return parent_rate / clock->div;
}
static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
unsigned long parent_rate)
{
unsigned int div;
if (!rate)
rate = 1;
div = DIV_ROUND_CLOSEST(parent_rate, rate);
return clamp(div, 1U, 64U);
}
static int cpg_div6_clock_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long prate, calc_rate, diff, best_rate, best_prate;
unsigned int num_parents = clk_hw_get_num_parents(hw);
struct clk_hw *parent, *best_parent = NULL;
unsigned int i, min_div, max_div, div;
unsigned long min_diff = ULONG_MAX;
for (i = 0; i < num_parents; i++) {
parent = clk_hw_get_parent_by_index(hw, i);
if (!parent)
continue;
prate = clk_hw_get_rate(parent);
if (!prate)
continue;
min_div = max(DIV_ROUND_UP(prate, req->max_rate), 1UL);
max_div = req->min_rate ? min(prate / req->min_rate, 64UL) : 64;
if (max_div < min_div)
continue;
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk-provider.h`, `linux/init.h`, `linux/io.h`, `linux/kernel.h`, `linux/notifier.h`, `linux/of.h`, `linux/of_address.h`.
- Detected declarations: `struct div6_clock`, `function cpg_div6_clock_enable`, `function cpg_div6_clock_disable`, `function cpg_div6_clock_is_enabled`, `function cpg_div6_clock_recalc_rate`, `function cpg_div6_clock_calc_div`, `function cpg_div6_clock_determine_rate`, `function cpg_div6_clock_set_rate`, `function cpg_div6_clock_get_parent`, `function cpg_div6_clock_set_parent`.
- 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.