drivers/clk/zynqmp/divider.c
Source file repositories/reference/linux-study-clean/drivers/clk/zynqmp/divider.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/zynqmp/divider.c- Extension
.c- Size
- 8757 bytes
- Lines
- 325
- 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.hlinux/clk-provider.hlinux/slab.hclk-zynqmp.h
Detected Declarations
struct zynqmp_clk_dividerfunction zynqmp_divider_get_valfunction zynqmp_clk_divider_recalc_ratefunction zynqmp_clk_divider_determine_ratefunction zynqmp_clk_divider_set_ratefunction zynqmp_clk_get_max_divisorfunction zynqmp_clk_map_divider_ccf_flagsfunction zynqmp_clk_register_divider
Annotated Snippet
struct zynqmp_clk_divider {
struct clk_hw hw;
u8 flags;
bool is_frac;
u32 clk_id;
u32 div_type;
u16 max_div;
};
static inline int zynqmp_divider_get_val(unsigned long parent_rate,
unsigned long rate, u16 flags)
{
int up, down;
unsigned long up_rate, down_rate;
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
down = DIV_ROUND_DOWN_ULL((u64)parent_rate, rate);
up = __roundup_pow_of_two(up);
down = __rounddown_pow_of_two(down);
up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
return (rate - up_rate) <= (down_rate - rate) ? up : down;
} else {
return DIV_ROUND_CLOSEST(parent_rate, rate);
}
}
/**
* zynqmp_clk_divider_recalc_rate() - Recalc rate of divider clock
* @hw: handle between common and hardware-specific interfaces
* @parent_rate: rate of parent clock
*
* Return: 0 on success else error+reason
*/
static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw);
const char *clk_name = clk_hw_get_name(hw);
u32 clk_id = divider->clk_id;
u32 div_type = divider->div_type;
u32 div, value;
int ret;
ret = zynqmp_pm_clock_getdivider(clk_id, &div);
if (ret)
pr_debug("%s() get divider failed for %s, ret = %d\n",
__func__, clk_name, ret);
if (div_type == TYPE_DIV1)
value = div & 0xFFFF;
else
value = div >> 16;
if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
value = 1 << value;
if (!value) {
WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
clk_name);
return parent_rate;
}
return DIV_ROUND_UP_ULL(parent_rate, value);
}
/**
* zynqmp_clk_divider_determine_rate() - Determine rate of divider clock
* @hw: handle between common and hardware-specific interfaces
* @req: rate of clock to be set
*
* Return: 0 on success else error+reason
*/
static int zynqmp_clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw);
const char *clk_name = clk_hw_get_name(hw);
u32 clk_id = divider->clk_id;
u32 div_type = divider->div_type;
u32 bestdiv;
int ret;
u8 width;
Annotation
- Immediate include surface: `linux/clk.h`, `linux/clk-provider.h`, `linux/slab.h`, `clk-zynqmp.h`.
- Detected declarations: `struct zynqmp_clk_divider`, `function zynqmp_divider_get_val`, `function zynqmp_clk_divider_recalc_rate`, `function zynqmp_clk_divider_determine_rate`, `function zynqmp_clk_divider_set_rate`, `function zynqmp_clk_get_max_divisor`, `function zynqmp_clk_map_divider_ccf_flags`, `function zynqmp_clk_register_divider`.
- 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.