drivers/clk/clk-fractional-divider.c
Source file repositories/reference/linux-study-clean/drivers/clk/clk-fractional-divider.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/clk-fractional-divider.c- Extension
.c- Size
- 8158 bytes
- Lines
- 333
- Domain
- Driver Families
- Bucket
- drivers/clk
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- 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/debugfs.hlinux/device.hlinux/io.hlinux/math.hlinux/module.hlinux/rational.hlinux/slab.hlinux/clk-provider.hclk-fractional-divider.h
Detected Declarations
function Copyrightfunction clk_fd_writelfunction clk_fd_get_divfunction clk_fd_recalc_ratefunction clk_fractional_divider_general_approximationfunction byfunction clk_fd_determine_ratefunction clk_fd_set_ratefunction clk_fd_numerator_getfunction clk_fd_denominator_getfunction clk_fd_debug_initfunction clk_hw_unregister_fractional_dividerexport clk_fractional_divider_general_approximationexport clk_fractional_divider_opsexport clk_hw_register_fractional_dividerexport clk_register_fractional_divider
Annotated Snippet
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2014 Intel Corporation
*
* Adjustable fractional divider clock implementation.
* Uses rational best approximation algorithm.
*
* Output is calculated as
*
* rate = (m / n) * parent_rate (1)
*
* This is useful when we have a prescaler block which asks for
* m (numerator) and n (denominator) values to be provided to satisfy
* the (1) as much as possible.
*
* Since m and n have the limitation by a range, e.g.
*
* n >= 1, n < N_width, where N_width = 2^nwidth (2)
*
* for some cases the output may be saturated. Hence, from (1) and (2),
* assuming the worst case when m = 1, the inequality
*
* floor(log2(parent_rate / rate)) <= nwidth (3)
*
* may be derived. Thus, in cases when
*
* (parent_rate / rate) >> N_width (4)
*
* we might scale up the rate by 2^scale (see the description of
* CLK_FRAC_DIVIDER_POWER_OF_TWO_PS for additional information), where
*
* scale = floor(log2(parent_rate / rate)) - nwidth (5)
*
* and assume that the IP, that needs m and n, has also its own
* prescaler, which is capable to divide by 2^scale. In this way
* we get the denominator to satisfy the desired range (2) and
* at the same time a much better result of m and n than simple
* saturated values.
*/
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/rational.h>
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include "clk-fractional-divider.h"
static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
{
if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
return ioread32be(fd->reg);
return readl(fd->reg);
}
static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
{
if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
iowrite32be(val, fd->reg);
else
writel(val, fd->reg);
}
static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
unsigned long m, n;
u32 mmask, nmask;
u32 val;
if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
else
__acquire(fd->lock);
val = clk_fd_readl(fd);
if (fd->lock)
spin_unlock_irqrestore(fd->lock, flags);
else
__release(fd->lock);
mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift;
nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift;
Annotation
- Immediate include surface: `linux/debugfs.h`, `linux/device.h`, `linux/io.h`, `linux/math.h`, `linux/module.h`, `linux/rational.h`, `linux/slab.h`, `linux/clk-provider.h`.
- Detected declarations: `function Copyright`, `function clk_fd_writel`, `function clk_fd_get_div`, `function clk_fd_recalc_rate`, `function clk_fractional_divider_general_approximation`, `function by`, `function clk_fd_determine_rate`, `function clk_fd_set_rate`, `function clk_fd_numerator_get`, `function clk_fd_denominator_get`.
- Atlas domain: Driver Families / drivers/clk.
- Implementation status: integration 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.