drivers/clk/qcom/clk-cbf-8996.c
Source file repositories/reference/linux-study-clean/drivers/clk/qcom/clk-cbf-8996.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/qcom/clk-cbf-8996.c- Extension
.c- Size
- 9556 bytes
- Lines
- 371
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/clk-provider.hlinux/interconnect-clk.hlinux/interconnect-provider.hlinux/of.hlinux/module.hlinux/platform_device.hlinux/regmap.hdt-bindings/interconnect/qcom,msm8996-cbf.hclk-alpha-pll.hclk-regmap.h
Detected Declarations
struct clk_cbf_8996_muxfunction clk_cbf_8996_mux_get_parentfunction clk_cbf_8996_mux_set_parentfunction clk_cbf_8996_mux_determine_ratefunction cbf_clk_notifier_cbfunction qcom_msm8996_cbf_icc_registerfunction qcom_msm8996_cbf_icc_removefunction qcom_msm8996_cbf_icc_registerfunction qcom_msm8996_cbf_probefunction qcom_msm8996_cbf_removefunction qcom_msm8996_cbf_initfunction qcom_msm8996_cbf_exit
Annotated Snippet
struct clk_cbf_8996_mux {
u32 reg;
struct notifier_block nb;
struct clk_regmap clkr;
};
static struct clk_cbf_8996_mux *to_clk_cbf_8996_mux(struct clk_regmap *clkr)
{
return container_of(clkr, struct clk_cbf_8996_mux, clkr);
}
static int cbf_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data);
static u8 clk_cbf_8996_mux_get_parent(struct clk_hw *hw)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_cbf_8996_mux *mux = to_clk_cbf_8996_mux(clkr);
u32 val;
regmap_read(clkr->regmap, mux->reg, &val);
return FIELD_GET(CBF_MUX_PARENT_MASK, val);
}
static int clk_cbf_8996_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_cbf_8996_mux *mux = to_clk_cbf_8996_mux(clkr);
u32 val;
val = FIELD_PREP(CBF_MUX_PARENT_MASK, index);
return regmap_update_bits(clkr->regmap, mux->reg, CBF_MUX_PARENT_MASK, val);
}
static int clk_cbf_8996_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_hw *parent;
if (req->rate < (DIV_THRESHOLD / cbf_pll_postdiv.div))
return -EINVAL;
if (req->rate < DIV_THRESHOLD)
parent = clk_hw_get_parent_by_index(hw, CBF_DIV_INDEX);
else
parent = clk_hw_get_parent_by_index(hw, CBF_PLL_INDEX);
if (!parent)
return -EINVAL;
req->best_parent_rate = clk_hw_round_rate(parent, req->rate);
req->best_parent_hw = parent;
return 0;
}
static const struct clk_ops clk_cbf_8996_mux_ops = {
.set_parent = clk_cbf_8996_mux_set_parent,
.get_parent = clk_cbf_8996_mux_get_parent,
.determine_rate = clk_cbf_8996_mux_determine_rate,
};
static struct clk_cbf_8996_mux cbf_mux = {
.reg = CBF_MUX_OFFSET,
.nb.notifier_call = cbf_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "cbf_mux",
.parent_data = cbf_mux_parent_data,
.num_parents = ARRAY_SIZE(cbf_mux_parent_data),
.ops = &clk_cbf_8996_mux_ops,
/* CPU clock is critical and should never be gated */
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
},
};
static int cbf_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
void *data)
{
struct clk_notifier_data *cnd = data;
switch (event) {
case PRE_RATE_CHANGE:
/*
* Avoid overvolting. clk_core_set_rate_nolock() walks from top
* to bottom, so it will change the rate of the PLL before
* chaging the parent of PMUX. This can result in pmux getting
* clocked twice the expected rate.
*
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/clk-provider.h`, `linux/interconnect-clk.h`, `linux/interconnect-provider.h`, `linux/of.h`, `linux/module.h`, `linux/platform_device.h`.
- Detected declarations: `struct clk_cbf_8996_mux`, `function clk_cbf_8996_mux_get_parent`, `function clk_cbf_8996_mux_set_parent`, `function clk_cbf_8996_mux_determine_rate`, `function cbf_clk_notifier_cb`, `function qcom_msm8996_cbf_icc_register`, `function qcom_msm8996_cbf_icc_remove`, `function qcom_msm8996_cbf_icc_register`, `function qcom_msm8996_cbf_probe`, `function qcom_msm8996_cbf_remove`.
- Atlas domain: Driver Families / drivers/clk.
- Implementation status: integration 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.