drivers/clk/bcm/clk-kona.c
Source file repositories/reference/linux-study-clean/drivers/clk/bcm/clk-kona.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/bcm/clk-kona.c- Extension
.c- Size
- 33179 bytes
- Lines
- 1254
- 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
clk-kona.hlinux/delay.hlinux/io.hlinux/kernel.hlinux/clk-provider.hlinux/string_choices.h
Detected Declarations
function Copyrightfunction bitfield_extractfunction bitfield_replacefunction scaled_div_valuefunction scaled_div_minfunction scaled_div_maxfunction dividerfunction scale_ratefunction __ccu_readfunction __ccu_writefunction ccu_lockfunction ccu_unlockfunction __ccu_write_enablefunction __ccu_write_disablefunction __ccu_wait_bitfunction __ccu_policy_engine_startfunction __ccu_policy_engine_stopfunction conditionsfunction __is_clk_gate_enabledfunction is_clk_gate_enabledfunction __gate_commitfunction gate_initfunction __clk_gatefunction clk_gatefunction hyst_initfunction __clk_triggerfunction divider_read_scaledfunction __div_commitfunction div_initfunction divider_writefunction clk_recalc_ratefunction thefunction selectorfunction selector_read_indexfunction __sel_commitfunction sel_initfunction selector_writefunction kona_peri_clk_enablefunction kona_peri_clk_disablefunction kona_peri_clk_is_enabledfunction kona_peri_clk_recalc_ratefunction kona_peri_clk_round_ratefunction kona_peri_clk_determine_ratefunction kona_peri_clk_set_parentfunction kona_peri_clk_get_parentfunction kona_peri_clk_set_ratefunction __peri_clk_initfunction __kona_clk_init
Annotated Snippet
if (delta < best_delta) {
best_delta = delta;
best_rate = other_rate;
req->best_parent_hw = parent;
req->best_parent_rate = parent_rate;
}
}
req->rate = best_rate;
return 0;
}
static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->u.peri;
struct bcm_clk_sel *sel = &data->sel;
struct bcm_clk_trig *trig;
int ret;
BUG_ON(index >= sel->parent_count);
/* If there's only one parent we don't require a selector */
if (!selector_exists(sel))
return 0;
/*
* The regular trigger is used by default, but if there's a
* pre-trigger we want to use that instead.
*/
trig = trigger_exists(&data->pre_trig) ? &data->pre_trig
: &data->trig;
ret = selector_write(bcm_clk->ccu, &data->gate, sel, trig, index);
if (ret == -ENXIO) {
pr_err("%s: gating failure for %s\n", __func__,
bcm_clk->init_data.name);
ret = -EIO; /* Don't proliferate weird errors */
} else if (ret == -EIO) {
pr_err("%s: %strigger failed for %s\n", __func__,
trig == &data->pre_trig ? "pre-" : "",
bcm_clk->init_data.name);
}
return ret;
}
static u8 kona_peri_clk_get_parent(struct clk_hw *hw)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->u.peri;
u8 index;
index = selector_read_index(bcm_clk->ccu, &data->sel);
/* Not all callers would handle an out-of-range value gracefully */
return index == BAD_CLK_INDEX ? 0 : index;
}
static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct kona_clk *bcm_clk = to_kona_clk(hw);
struct peri_clk_data *data = bcm_clk->u.peri;
struct bcm_clk_div *div = &data->div;
u64 scaled_div = 0;
int ret;
if (parent_rate > (unsigned long)LONG_MAX)
return -EINVAL;
if (rate == clk_hw_get_rate(hw))
return 0;
if (!divider_exists(div))
return rate == parent_rate ? 0 : -EINVAL;
/*
* A fixed divider can't be changed. (Nor can a fixed
* pre-divider be, but for now we never actually try to
* change that.) Tolerate a request for a no-op change.
*/
if (divider_is_fixed(&data->div))
return rate == parent_rate ? 0 : -EINVAL;
/*
* Get the scaled divisor value needed to achieve a clock
* rate as close as possible to what was requested, given
* the parent clock rate supplied.
*/
Annotation
- Immediate include surface: `clk-kona.h`, `linux/delay.h`, `linux/io.h`, `linux/kernel.h`, `linux/clk-provider.h`, `linux/string_choices.h`.
- Detected declarations: `function Copyright`, `function bitfield_extract`, `function bitfield_replace`, `function scaled_div_value`, `function scaled_div_min`, `function scaled_div_max`, `function divider`, `function scale_rate`, `function __ccu_read`, `function __ccu_write`.
- 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.