drivers/clk/berlin/berlin2-avpll.c
Source file repositories/reference/linux-study-clean/drivers/clk/berlin/berlin2-avpll.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/berlin/berlin2-avpll.c- Extension
.c- Size
- 10755 bytes
- Lines
- 383
- 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/clk-provider.hlinux/io.hlinux/kernel.hlinux/of.hlinux/of_address.hlinux/slab.hberlin2-avpll.h
Detected Declarations
struct berlin2_avpll_vcostruct berlin2_avpll_channelfunction berlin2_avpll_vco_is_enabledfunction berlin2_avpll_vco_enablefunction berlin2_avpll_vco_disablefunction berlin2_avpll_vco_recalc_ratefunction berlin2_avpll_vco_registerfunction berlin2_avpll_channel_is_enabledfunction berlin2_avpll_channel_enablefunction berlin2_avpll_channel_disablefunction berlin2_avpll_channel_recalc_ratefunction berlin2_avpll_channel_register
Annotated Snippet
struct berlin2_avpll_vco {
struct clk_hw hw;
void __iomem *base;
u8 flags;
};
#define to_avpll_vco(hw) container_of(hw, struct berlin2_avpll_vco, hw)
static int berlin2_avpll_vco_is_enabled(struct clk_hw *hw)
{
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg;
reg = readl_relaxed(vco->base + VCO_CTRL0);
if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
reg >>= 4;
return !!(reg & VCO_POWERUP);
}
static int berlin2_avpll_vco_enable(struct clk_hw *hw)
{
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg;
reg = readl_relaxed(vco->base + VCO_CTRL0);
if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
reg |= VCO_POWERUP << 4;
else
reg |= VCO_POWERUP;
writel_relaxed(reg, vco->base + VCO_CTRL0);
return 0;
}
static void berlin2_avpll_vco_disable(struct clk_hw *hw)
{
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg;
reg = readl_relaxed(vco->base + VCO_CTRL0);
if (vco->flags & BERLIN2_AVPLL_BIT_QUIRK)
reg &= ~(VCO_POWERUP << 4);
else
reg &= ~VCO_POWERUP;
writel_relaxed(reg, vco->base + VCO_CTRL0);
}
static u8 vco_refdiv[] = { 1, 2, 4, 3 };
static unsigned long
berlin2_avpll_vco_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct berlin2_avpll_vco *vco = to_avpll_vco(hw);
u32 reg, refdiv, fbdiv;
u64 freq = parent_rate;
/* AVPLL VCO frequency: Fvco = (Fref / refdiv) * fbdiv */
reg = readl_relaxed(vco->base + VCO_CTRL1);
refdiv = (reg & VCO_REFDIV_MASK) >> VCO_REFDIV_SHIFT;
refdiv = vco_refdiv[refdiv];
fbdiv = (reg & VCO_FBDIV_MASK) >> VCO_FBDIV_SHIFT;
freq *= fbdiv;
do_div(freq, refdiv);
return (unsigned long)freq;
}
static const struct clk_ops berlin2_avpll_vco_ops = {
.is_enabled = berlin2_avpll_vco_is_enabled,
.enable = berlin2_avpll_vco_enable,
.disable = berlin2_avpll_vco_disable,
.recalc_rate = berlin2_avpll_vco_recalc_rate,
};
int __init berlin2_avpll_vco_register(void __iomem *base,
const char *name, const char *parent_name,
u8 vco_flags, unsigned long flags)
{
struct berlin2_avpll_vco *vco;
struct clk_init_data init;
vco = kzalloc_obj(*vco);
if (!vco)
return -ENOMEM;
vco->base = base;
vco->flags = vco_flags;
vco->hw.init = &init;
init.name = name;
Annotation
- Immediate include surface: `linux/clk-provider.h`, `linux/io.h`, `linux/kernel.h`, `linux/of.h`, `linux/of_address.h`, `linux/slab.h`, `berlin2-avpll.h`.
- Detected declarations: `struct berlin2_avpll_vco`, `struct berlin2_avpll_channel`, `function berlin2_avpll_vco_is_enabled`, `function berlin2_avpll_vco_enable`, `function berlin2_avpll_vco_disable`, `function berlin2_avpll_vco_recalc_rate`, `function berlin2_avpll_vco_register`, `function berlin2_avpll_channel_is_enabled`, `function berlin2_avpll_channel_enable`, `function berlin2_avpll_channel_disable`.
- 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.