drivers/clk/sophgo/clk-cv18xx-pll.c
Source file repositories/reference/linux-study-clean/drivers/clk/sophgo/clk-cv18xx-pll.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/sophgo/clk-cv18xx-pll.c- Extension
.c- Size
- 10331 bytes
- Lines
- 420
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk-provider.hlinux/io.hlinux/limits.hlinux/spinlock.hclk-cv18xx-pll.h
Detected Declarations
function Copyrightfunction ipll_calc_ratefunction ipll_recalc_ratefunction ipll_find_ratefunction for_each_pll_limit_rangefunction ipll_determine_ratefunction pll_get_mode_ctrlfunction for_each_pll_limit_rangefunction ipll_check_mode_ctrl_restrictfunction ipll_set_ratefunction pll_enablefunction pll_disablefunction pll_is_enablefunction fpll_is_factional_modefunction fpll_calc_ratefunction fpll_recalc_ratefunction fpll_find_synthesizerfunction fpll_find_ratefunction for_each_pll_limit_rangefunction fpll_determine_ratefunction fpll_check_mode_ctrl_restrictfunction fpll_set_ratefunction fpll_get_parentfunction fpll_set_parent
Annotated Snippet
for_each_pll_limit_range(div, &limit->div) {
for_each_pll_limit_range(post, &limit->post_div) {
tmp = ipll_calc_rate(prate, pre, div, post);
if (tmp > trate)
continue;
if ((trate - tmp) < (trate - best_rate)) {
best_rate = tmp;
pre_div_sel = pre;
div_sel = div;
post_div_sel = post;
}
}
}
}
if (best_rate) {
detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel);
detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel);
detected = PLL_SET_DIV_SEL(detected, div_sel);
*value = detected;
*rate = best_rate;
return 0;
}
return -EINVAL;
}
static int ipll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
u32 val;
struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
return ipll_find_rate(pll->pll_limit, req->best_parent_rate,
&req->rate, &val);
}
static void pll_get_mode_ctrl(unsigned long div_sel,
bool (*mode_ctrl_check)(unsigned long,
unsigned long,
unsigned long),
const struct cv1800_clk_pll_limit *limit,
u32 *value)
{
unsigned long ictrl = 0, mode = 0;
u32 detected = *value;
for_each_pll_limit_range(mode, &limit->mode) {
for_each_pll_limit_range(ictrl, &limit->ictrl) {
if (mode_ctrl_check(div_sel, ictrl, mode)) {
detected = PLL_SET_SEL_MODE(detected, mode);
detected = PLL_SET_ICTRL(detected, ictrl);
*value = detected;
return;
}
}
}
}
static bool ipll_check_mode_ctrl_restrict(unsigned long div_sel,
unsigned long ictrl,
unsigned long mode)
{
unsigned long left_rest = 20 * div_sel;
unsigned long right_rest = 35 * div_sel;
unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2;
return test > left_rest && test <= right_rest;
}
static int ipll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
u32 regval, detected = 0;
unsigned long flags;
struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
ipll_find_rate(pll->pll_limit, parent_rate, &rate, &detected);
pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected),
ipll_check_mode_ctrl_restrict,
pll->pll_limit, &detected);
spin_lock_irqsave(pll->common.lock, flags);
regval = readl(pll->common.base + pll->pll_reg);
regval = PLL_COPY_REG(regval, detected);
writel(regval, pll->common.base + pll->pll_reg);
Annotation
- Immediate include surface: `linux/clk-provider.h`, `linux/io.h`, `linux/limits.h`, `linux/spinlock.h`, `clk-cv18xx-pll.h`.
- Detected declarations: `function Copyright`, `function ipll_calc_rate`, `function ipll_recalc_rate`, `function ipll_find_rate`, `function for_each_pll_limit_range`, `function ipll_determine_rate`, `function pll_get_mode_ctrl`, `function for_each_pll_limit_range`, `function ipll_check_mode_ctrl_restrict`, `function ipll_set_rate`.
- 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.