drivers/clk/microchip/clk-core.c
Source file repositories/reference/linux-study-clean/drivers/clk/microchip/clk-core.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/microchip/clk-core.c- Extension
.c- Size
- 25224 bytes
- Lines
- 1020
- 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/delay.hlinux/device.hlinux/interrupt.hlinux/io.hlinux/iopoll.hlinux/platform_data/pic32.hclk-core.h
Detected Declarations
struct pic32_periph_clkstruct pic32_ref_oscstruct pic32_sys_pllstruct pic32_sys_clkstruct pic32_sec_oscfunction pbclk_is_enabledfunction pbclk_enablefunction pbclk_disablefunction calc_best_divided_ratefunction pbclk_read_pbdivfunction pbclk_recalc_ratefunction pbclk_determine_ratefunction pbclk_set_ratefunction roclk_is_enabledfunction roclk_enablefunction roclk_disablefunction roclk_initfunction roclk_get_parentfunction roclk_calc_ratefunction roclk_calc_div_trimfunction roclk_recalc_ratefunction roclk_determine_ratefunction roclk_set_parentfunction roclk_set_rate_and_parentfunction roclk_set_ratefunction spll_odiv_to_dividerfunction spll_calc_mult_divfunction spll_clk_recalc_ratefunction spll_clk_determine_ratefunction spll_clk_set_ratefunction sclk_get_ratefunction sclk_set_ratefunction sclk_get_parentfunction sclk_set_parentfunction sclk_initfunction sosc_clk_enablefunction sosc_clk_disablefunction sosc_clk_is_enabledfunction sosc_clk_calc_rate
Annotated Snippet
struct pic32_periph_clk {
struct clk_hw hw;
void __iomem *ctrl_reg;
struct pic32_clk_common *core;
};
#define clkhw_to_pbclk(_hw) container_of(_hw, struct pic32_periph_clk, hw)
static int pbclk_is_enabled(struct clk_hw *hw)
{
struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
return readl(pb->ctrl_reg) & PB_DIV_ENABLE;
}
static int pbclk_enable(struct clk_hw *hw)
{
struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
writel(PB_DIV_ENABLE, PIC32_SET(pb->ctrl_reg));
return 0;
}
static void pbclk_disable(struct clk_hw *hw)
{
struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
writel(PB_DIV_ENABLE, PIC32_CLR(pb->ctrl_reg));
}
static unsigned long calc_best_divided_rate(unsigned long rate,
unsigned long parent_rate,
u32 divider_max,
u32 divider_min)
{
unsigned long divided_rate, divided_rate_down, best_rate;
unsigned long div, div_up;
/* eq. clk_rate = parent_rate / divider.
*
* Find best divider to produce closest of target divided rate.
*/
div = parent_rate / rate;
div = clamp_val(div, divider_min, divider_max);
div_up = clamp_val(div + 1, divider_min, divider_max);
divided_rate = parent_rate / div;
divided_rate_down = parent_rate / div_up;
if (abs(rate - divided_rate_down) < abs(rate - divided_rate))
best_rate = divided_rate_down;
else
best_rate = divided_rate;
return best_rate;
}
static inline u32 pbclk_read_pbdiv(struct pic32_periph_clk *pb)
{
return ((readl(pb->ctrl_reg) >> PB_DIV_SHIFT) & PB_DIV_MASK) + 1;
}
static unsigned long pbclk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
return parent_rate / pbclk_read_pbdiv(pb);
}
static int pbclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate,
PB_DIV_MAX, PB_DIV_MIN);
return 0;
}
static int pbclk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
unsigned long flags;
u32 v, div;
int err;
/* check & wait for DIV_READY */
err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY,
1, LOCK_TIMEOUT_US);
if (err)
Annotation
- Immediate include surface: `linux/clk-provider.h`, `linux/delay.h`, `linux/device.h`, `linux/interrupt.h`, `linux/io.h`, `linux/iopoll.h`, `linux/platform_data/pic32.h`, `clk-core.h`.
- Detected declarations: `struct pic32_periph_clk`, `struct pic32_ref_osc`, `struct pic32_sys_pll`, `struct pic32_sys_clk`, `struct pic32_sec_osc`, `function pbclk_is_enabled`, `function pbclk_enable`, `function pbclk_disable`, `function calc_best_divided_rate`, `function pbclk_read_pbdiv`.
- 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.