drivers/clk/rockchip/clk.c
Source file repositories/reference/linux-study-clean/drivers/clk/rockchip/clk.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/rockchip/clk.c- Extension
.c- Size
- 21441 bytes
- Lines
- 797
- 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/slab.hlinux/clk.hlinux/clk-provider.hlinux/io.hlinux/mfd/syscon.hlinux/platform_device.hlinux/regmap.hlinux/reboot.h../clk-fractional-divider.hclk.h
Detected Declarations
struct rockchip_clk_fracfunction Copyrightfunction container_offunction rockchip_fractional_approximationfunction rockchip_clk_finalizefunction rockchip_clk_of_add_providerfunction rockchip_clk_register_pllsfunction rockchip_clk_find_max_clk_idfunction rockchip_clk_register_branchesfunction rockchip_clk_register_late_branchesfunction rockchip_clk_register_armclkfunction rockchip_clk_register_armclk_multi_pllfunction rockchip_clk_protect_criticalfunction rockchip_restart_notifyfunction rockchip_register_restart_notifierexport rockchip_clk_initexport rockchip_clk_init_earlyexport rockchip_clk_finalizeexport rockchip_clk_of_add_providerexport rockchip_clk_register_pllsexport rockchip_clk_find_max_clk_idexport rockchip_clk_register_branchesexport rockchip_clk_register_late_branchesexport rockchip_clk_register_armclkexport rockchip_clk_register_armclk_multi_pllexport rockchip_clk_protect_criticalexport rockchip_register_restart_notifier
Annotated Snippet
struct rockchip_clk_frac {
struct notifier_block clk_nb;
struct clk_fractional_divider div;
struct clk_gate gate;
struct clk_mux mux;
const struct clk_ops *mux_ops;
int mux_frac_idx;
bool rate_change_remuxed;
int rate_change_idx;
};
#define to_rockchip_clk_frac_nb(nb) \
container_of(nb, struct rockchip_clk_frac, clk_nb)
static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
struct clk_notifier_data *ndata = data;
struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
struct clk_mux *frac_mux = &frac->mux;
int ret = 0;
pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
__func__, event, ndata->old_rate, ndata->new_rate);
if (event == PRE_RATE_CHANGE) {
frac->rate_change_idx =
frac->mux_ops->get_parent(&frac_mux->hw);
if (frac->rate_change_idx != frac->mux_frac_idx) {
frac->mux_ops->set_parent(&frac_mux->hw,
frac->mux_frac_idx);
frac->rate_change_remuxed = 1;
}
} else if (event == POST_RATE_CHANGE) {
/*
* The POST_RATE_CHANGE notifier runs directly after the
* divider clock is set in clk_change_rate, so we'll have
* remuxed back to the original parent before clk_change_rate
* reaches the mux itself.
*/
if (frac->rate_change_remuxed) {
frac->mux_ops->set_parent(&frac_mux->hw,
frac->rate_change_idx);
frac->rate_change_remuxed = 0;
}
}
return notifier_from_errno(ret);
}
/*
* fractional divider must set that denominator is 20 times larger than
* numerator to generate precise clock frequency.
*/
static void rockchip_fractional_approximation(struct clk_hw *hw,
unsigned long rate, unsigned long *parent_rate,
unsigned long *m, unsigned long *n)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long p_rate, p_parent_rate;
struct clk_hw *p_parent;
p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
p_parent_rate = clk_hw_get_rate(p_parent);
*parent_rate = p_parent_rate;
}
fd->flags |= CLK_FRAC_DIVIDER_POWER_OF_TWO_PS;
clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
}
static struct clk *rockchip_clk_register_frac_branch(
struct rockchip_clk_provider *ctx, const char *name,
const char *const *parent_names, u8 num_parents,
void __iomem *base, int muxdiv_offset, u8 div_flags,
int gate_offset, u8 gate_shift, u8 gate_flags,
unsigned long flags, struct rockchip_clk_branch *child,
spinlock_t *lock)
{
struct clk_hw *hw;
struct rockchip_clk_frac *frac;
struct clk_gate *gate = NULL;
struct clk_fractional_divider *div = NULL;
const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
if (muxdiv_offset < 0)
Annotation
- Immediate include surface: `linux/slab.h`, `linux/clk.h`, `linux/clk-provider.h`, `linux/io.h`, `linux/mfd/syscon.h`, `linux/platform_device.h`, `linux/regmap.h`, `linux/reboot.h`.
- Detected declarations: `struct rockchip_clk_frac`, `function Copyright`, `function container_of`, `function rockchip_fractional_approximation`, `function rockchip_clk_finalize`, `function rockchip_clk_of_add_provider`, `function rockchip_clk_register_plls`, `function rockchip_clk_find_max_clk_id`, `function rockchip_clk_register_branches`, `function rockchip_clk_register_late_branches`.
- 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.