drivers/clk/bcm/clk-bcm2835.c
Source file repositories/reference/linux-study-clean/drivers/clk/bcm/clk-bcm2835.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/bcm/clk-bcm2835.c- Extension
.c- Size
- 61501 bytes
- Lines
- 2358
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/clkdev.hlinux/clk.hlinux/debugfs.hlinux/delay.hlinux/io.hlinux/math.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/slab.hdt-bindings/clock/bcm2835.h
Detected Declarations
struct bcm2835_cprmanstruct cprman_plat_datastruct bcm2835_pll_datastruct bcm2835_pll_ana_bitsstruct bcm2835_pll_divider_datastruct bcm2835_clock_datastruct bcm2835_gate_datastruct bcm2835_pllstruct bcm2835_pll_dividerstruct bcm2835_clockstruct bcm2835_clk_descfunction cprman_writefunction cprman_readfunction bcm2835_measure_tcnt_muxfunction bcm2835_debugfs_regsetfunction bcm2835_pll_is_onfunction bcm2835_pll_get_prediv_maskfunction bcm2835_pll_choose_ndiv_and_fdivfunction bcm2835_pll_rate_from_divisorsfunction bcm2835_pll_determine_ratefunction bcm2835_pll_get_ratefunction bcm2835_pll_offfunction bcm2835_pll_onfunction bcm2835_pll_write_anafunction bcm2835_pll_set_ratefunction bcm2835_pll_debug_initfunction bcm2835_pll_divider_from_hwfunction bcm2835_pll_divider_is_onfunction bcm2835_pll_divider_determine_ratefunction bcm2835_pll_divider_get_ratefunction bcm2835_pll_divider_offfunction bcm2835_pll_divider_onfunction bcm2835_pll_divider_set_ratefunction bcm2835_pll_divider_debug_initfunction bcm2835_clock_is_onfunction bcm2835_clock_choose_divfunction bcm2835_clock_rate_from_divisorfunction bcm2835_round_ratefunction bcm2835_clock_get_ratefunction bcm2835_clock_wait_busyfunction bcm2835_clock_offfunction bcm2835_clock_onfunction bcm2835_clock_set_ratefunction bcm2835_clk_is_pllcfunction bcm2835_clock_choose_div_and_pratefunction bcm2835_clock_determine_ratefunction bcm2835_clock_set_parentfunction bcm2835_clock_get_parent
Annotated Snippet
struct bcm2835_cprman {
struct device *dev;
void __iomem *regs;
spinlock_t regs_lock; /* spinlock for all clocks */
unsigned int soc;
/*
* Real names of cprman clock parents looked up through
* of_clk_get_parent_name(), which will be used in the
* parent_names[] arrays for clock registration.
*/
const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)];
/* Must be last */
struct clk_hw_onecell_data onecell;
};
struct cprman_plat_data {
unsigned int soc;
};
static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
{
writel(CM_PASSWORD | val, cprman->regs + reg);
}
static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg)
{
return readl(cprman->regs + reg);
}
/* Does a cycle of measuring a clock through the TCNT clock, which may
* source from many other clocks in the system.
*/
static unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman,
u32 tcnt_mux)
{
u32 osccount = 19200; /* 1ms */
u32 count;
ktime_t timeout;
spin_lock(&cprman->regs_lock);
cprman_write(cprman, CM_TCNTCTL, CM_KILL);
cprman_write(cprman, CM_TCNTCTL,
(tcnt_mux & CM_SRC_MASK) |
(tcnt_mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT);
cprman_write(cprman, CM_OSCCOUNT, osccount);
/* do a kind delay at the start */
mdelay(1);
/* Finish off whatever is left of OSCCOUNT */
timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
while (cprman_read(cprman, CM_OSCCOUNT)) {
if (ktime_after(ktime_get(), timeout)) {
dev_err(cprman->dev, "timeout waiting for OSCCOUNT\n");
count = 0;
goto out;
}
cpu_relax();
}
/* Wait for BUSY to clear. */
timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
while (cprman_read(cprman, CM_TCNTCTL) & CM_BUSY) {
if (ktime_after(ktime_get(), timeout)) {
dev_err(cprman->dev, "timeout waiting for !BUSY\n");
count = 0;
goto out;
}
cpu_relax();
}
count = cprman_read(cprman, CM_TCNTCNT);
cprman_write(cprman, CM_TCNTCTL, 0);
out:
spin_unlock(&cprman->regs_lock);
return count * 1000;
}
static void bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
const struct debugfs_reg32 *regs,
size_t nregs, struct dentry *dentry)
{
Annotation
- Immediate include surface: `linux/clk-provider.h`, `linux/clkdev.h`, `linux/clk.h`, `linux/debugfs.h`, `linux/delay.h`, `linux/io.h`, `linux/math.h`, `linux/module.h`.
- Detected declarations: `struct bcm2835_cprman`, `struct cprman_plat_data`, `struct bcm2835_pll_data`, `struct bcm2835_pll_ana_bits`, `struct bcm2835_pll_divider_data`, `struct bcm2835_clock_data`, `struct bcm2835_gate_data`, `struct bcm2835_pll`, `struct bcm2835_pll_divider`, `struct bcm2835_clock`.
- Atlas domain: Driver Families / drivers/clk.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.