drivers/clk/sunxi/clk-factors.c
Source file repositories/reference/linux-study-clean/drivers/clk/sunxi/clk-factors.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/sunxi/clk-factors.c- Extension
.c- Size
- 7829 bytes
- Lines
- 305
- 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/err.hlinux/io.hlinux/of_address.hlinux/slab.hlinux/string.hclk-factors.h
Detected Declarations
function Copyrightfunction clk_factors_determine_ratefunction clk_factors_set_ratefunction sunxi_factors_unregister
Annotated Snippet
if (child_rate <= req->rate && child_rate > best_child_rate) {
best_parent = parent;
best = parent_rate;
best_child_rate = child_rate;
}
}
if (!best_parent)
return -EINVAL;
req->best_parent_hw = best_parent;
req->best_parent_rate = best;
req->rate = best_child_rate;
return 0;
}
static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct factors_request req = {
.rate = rate,
.parent_rate = parent_rate,
};
u32 reg;
struct clk_factors *factors = to_clk_factors(hw);
const struct clk_factors_config *config = factors->config;
unsigned long flags = 0;
factors->get_factors(&req);
if (factors->lock)
spin_lock_irqsave(factors->lock, flags);
/* Fetch the register value */
reg = readl(factors->reg);
/* Set up the new factors - macros do not do anything if width is 0 */
reg = FACTOR_SET(config->nshift, config->nwidth, reg, req.n);
reg = FACTOR_SET(config->kshift, config->kwidth, reg, req.k);
reg = FACTOR_SET(config->mshift, config->mwidth, reg, req.m);
reg = FACTOR_SET(config->pshift, config->pwidth, reg, req.p);
/* Apply them now */
writel(reg, factors->reg);
/* delay 500us so pll stabilizes */
__delay((rate >> 20) * 500 / 2);
if (factors->lock)
spin_unlock_irqrestore(factors->lock, flags);
return 0;
}
static const struct clk_ops clk_factors_ops = {
.determine_rate = clk_factors_determine_rate,
.recalc_rate = clk_factors_recalc_rate,
.set_rate = clk_factors_set_rate,
};
static struct clk *__sunxi_factors_register(struct device_node *node,
const struct factors_data *data,
spinlock_t *lock, void __iomem *reg,
unsigned long flags)
{
struct clk *clk;
struct clk_factors *factors;
struct clk_gate *gate = NULL;
struct clk_mux *mux = NULL;
struct clk_hw *gate_hw = NULL;
struct clk_hw *mux_hw = NULL;
const char *clk_name = node->name;
const char *parents[FACTORS_MAX_PARENTS];
int ret, i = 0;
/* if we have a mux, we will have >1 parents */
i = of_clk_parent_fill(node, parents, FACTORS_MAX_PARENTS);
/*
* some factor clocks, such as pll5 and pll6, may have multiple
* outputs, and have their name designated in factors_data
*/
if (data->name)
clk_name = data->name;
else
of_property_read_string(node, "clock-output-names", &clk_name);
factors = kzalloc_obj(struct clk_factors);
if (!factors)
Annotation
- Immediate include surface: `linux/clk-provider.h`, `linux/delay.h`, `linux/err.h`, `linux/io.h`, `linux/of_address.h`, `linux/slab.h`, `linux/string.h`, `clk-factors.h`.
- Detected declarations: `function Copyright`, `function clk_factors_determine_rate`, `function clk_factors_set_rate`, `function sunxi_factors_unregister`.
- 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.