drivers/clk/renesas/rcar-gen4-cpg.c
Source file repositories/reference/linux-study-clean/drivers/clk/renesas/rcar-gen4-cpg.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/renesas/rcar-gen4-cpg.c- Extension
.c- Size
- 14823 bytes
- Lines
- 547
- 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.hlinux/clk-provider.hlinux/device.hlinux/err.hlinux/init.hlinux/io.hlinux/iopoll.hlinux/slab.hrenesas-cpg-mssr.hrcar-gen4-cpg.hrcar-cpg-lib.h
Detected Declarations
struct cpg_pll_clkstruct cpg_z_clkfunction cpg_pll_8_25_clk_recalc_ratefunction cpg_pll_8_25_clk_determine_ratefunction cpg_pll_8_25_clk_set_ratefunction cpg_pll_9_24_clk_recalc_ratefunction cpg_pll_clk_registerfunction cpg_z_clk_recalc_ratefunction cpg_z_clk_determine_ratefunction cpg_z_clk_set_ratefunction cpg_z_clk_registerfunction rcar_gen4_cpg_clk_registerfunction rcar_gen4_cpg_init
Annotated Snippet
struct cpg_pll_clk {
struct clk_hw hw;
void __iomem *pllcr0_reg;
void __iomem *pllcr1_reg;
void __iomem *pllecr_reg;
u32 pllecr_pllst_mask;
};
#define to_pll_clk(_hw) container_of(_hw, struct cpg_pll_clk, hw)
static unsigned long cpg_pll_8_25_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
u32 cr0 = readl(pll_clk->pllcr0_reg);
unsigned int ni, nf;
unsigned long rate;
ni = (FIELD_GET(CPG_PLLxCR0_NI8, cr0) + 1) * 2;
rate = parent_rate * ni;
if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
nf = FIELD_GET(CPG_PLLxCR1_NF25, readl(pll_clk->pllcr1_reg));
rate += mul_u64_u32_shr(parent_rate, nf, 24);
}
return rate;
}
static int cpg_pll_8_25_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
unsigned int min_mult, max_mult, ni, nf;
u32 cr0 = readl(pll_clk->pllcr0_reg);
unsigned long prate;
prate = req->best_parent_rate * 2;
min_mult = max(div64_ul(req->min_rate, prate), 1ULL);
max_mult = min(div64_ul(req->max_rate, prate), 256ULL);
if (max_mult < min_mult)
return -EINVAL;
if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
ni = div64_ul(req->rate, prate);
if (ni < min_mult) {
ni = min_mult;
nf = 0;
} else {
ni = min(ni, max_mult);
nf = div64_ul((u64)(req->rate - prate * ni) << 24,
req->best_parent_rate);
}
} else {
ni = DIV_ROUND_CLOSEST_ULL(req->rate, prate);
ni = clamp(ni, min_mult, max_mult);
nf = 0;
}
req->rate = prate * ni + mul_u64_u32_shr(req->best_parent_rate, nf, 24);
return 0;
}
static int cpg_pll_8_25_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct cpg_pll_clk *pll_clk = to_pll_clk(hw);
unsigned long prate = parent_rate * 2;
u32 cr0 = readl(pll_clk->pllcr0_reg);
unsigned int ni, nf;
u32 val;
if (cr0 & CPG_PLLxCR0_SSMODE_FM) {
ni = div64_ul(rate, prate);
if (ni < 1) {
ni = 1;
nf = 0;
} else {
ni = min(ni, 256U);
nf = div64_ul((u64)(rate - prate * ni) << 24,
parent_rate);
}
} else {
ni = DIV_ROUND_CLOSEST_ULL(rate, prate);
ni = clamp(ni, 1U, 256U);
}
if (readl(pll_clk->pllcr0_reg) & CPG_PLLxCR0_KICK)
return -EBUSY;
cpg_reg_modify(pll_clk->pllcr0_reg, CPG_PLLxCR0_NI8,
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/clk-provider.h`, `linux/device.h`, `linux/err.h`, `linux/init.h`, `linux/io.h`, `linux/iopoll.h`.
- Detected declarations: `struct cpg_pll_clk`, `struct cpg_z_clk`, `function cpg_pll_8_25_clk_recalc_rate`, `function cpg_pll_8_25_clk_determine_rate`, `function cpg_pll_8_25_clk_set_rate`, `function cpg_pll_9_24_clk_recalc_rate`, `function cpg_pll_clk_register`, `function cpg_z_clk_recalc_rate`, `function cpg_z_clk_determine_rate`, `function cpg_z_clk_set_rate`.
- 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.