Keywords covered in this lecture
linux multiplexer clock driver
clk_hw get_parent set_parent
clk_ops checklist
free linux kernel development course
free embedded systems course
The previous lecture covered every callback in struct clk_ops one by one, but left
an important practical question unanswered: for the clock you are actually writing,
which of those callbacks are you required to implement? This lecture answers that
with a single reference table covering mandatory clk_ops by clock type
— gate clocks, rate-changing clocks, single-parent clocks, multiplexer clocks, and
root clocks — so you know exactly what your driver owes the framework before you
start writing it.
What You Will Learn
- Which clk_ops callbacks are mandatory for a gate-capable clock
- Which callbacks a rate-changing clock must supply
- Why single-parent and root clocks must not implement set_parent/get_parent
- Why multiplexer clocks are the one case where set_parent/get_parent are required
- Using this table as a pre-flight checklist before writing a new clock driver
Prerequisites
- CCF clk_ops callback reference guide (previous lecture)
- CCF base clock types overview
Mandatory clk_ops Callbacks By Clock Type
The table below groups clocks by hardware capability rather than by base type name,
since that is really what determines which callbacks the CCF expects from you. A
“root” clock here means a clock with no parent at all, such as an external oscillator.
| Callback | Gate | Change Rate | Single Parent | Multiplexer | Root |
|---|---|---|---|---|---|
| prepare / unprepare | optional | optional | optional | optional | optional |
| enable / disable / is_enabled | required | — | — | — | — |
| recalc_rate | — | required | — | — | — |
| round_rate / determine_rate | — | one required | — | — | — |
| set_rate | — | required | — | — | — |
| set_parent | — | — | must not implement | required | must not implement |
| get_parent | — | — | must not implement | required | must not implement |
| recalc_accuracy | optional | optional | optional | optional | optional |
| init | optional | optional | optional | optional | optional |
“one required” on the round_rate/determine_rate row means exactly
one of the two should be implemented, never both — see the previous lecture for
why determine_rate is the preferred choice in new drivers.
Reading the Table Column by Column
Gate
Any clock capable of being turned on or off must implement
enable/disable (or prepare/unprepare
for sleepable buses, per the previous lecture), plus is_enabled if you want
the CCF to query real hardware state instead of relying on its own internal counter.
Change Rate
Any clock that can change its output frequency must implement
recalc_rate so the CCF knows the current rate, exactly one of
round_rate/determine_rate so a requested rate can be validated,
and set_rate to actually apply it.
Single Parent and Root
A clock with exactly one possible parent, and a root clock with no parent at all,
must never implement set_parent or get_parent. There is
nothing to select between, so providing these callbacks would be meaningless and
could confuse the framework about how many parents the clock actually has.
Multiplexer
This is the one column where set_parent and get_parent
flip from forbidden to mandatory. A multiplexer clock, by definition, has two or more
possible parents, and the CCF needs both a way to change the active parent and a way to
ask the hardware which parent is currently selected.
Using the Table as a Pre-Flight Checklist
Here is an original, minimal example applying just the “Gate” column of the table
— a clock that can only turn on and off, with nothing else implemented, matching
exactly what the table says is required and nothing more:
/* ep_gate_only_clk.c - implements only what the Gate column requires */
#include <linux/clk-provider.h>
#include <linux/io.h>
struct ep_gate_only_hw {
struct clk_hw hw;
void __iomem *reg;
u32 enable_mask;
};
static inline struct ep_gate_only_hw *to_ep_gate_only(struct clk_hw *hw)
{
return container_of(hw, struct ep_gate_only_hw, hw);
}
static int ep_gate_only_enable(struct clk_hw *hw)
{
struct ep_gate_only_hw *eclk = to_ep_gate_only(hw);
u32 val = readl(eclk->reg);
writel(val | eclk->enable_mask, eclk->reg);
return 0;
}
static void ep_gate_only_disable(struct clk_hw *hw)
{
struct ep_gate_only_hw *eclk = to_ep_gate_only(hw);
u32 val = readl(eclk->reg);
writel(val & ~eclk->enable_mask, eclk->reg);
}
static int ep_gate_only_is_enabled(struct clk_hw *hw)
{
struct ep_gate_only_hw *eclk = to_ep_gate_only(hw);
return !!(readl(eclk->reg) & eclk->enable_mask);
}
static const struct clk_ops ep_gate_only_ops = {
.enable = ep_gate_only_enable,
.disable = ep_gate_only_disable,
.is_enabled = ep_gate_only_is_enabled,
/* no recalc_rate, no set_parent/get_parent - this clock only gates */
};
Notice that recalc_rate, set_rate, set_parent,
and get_parent are all absent, exactly as the “Gate” column of the table
says they should be for a clock that only ever turns on and off.
Common Mistakes
- Implementing get_parent on a clock that genuinely has only one parent
- Providing set_rate without recalc_rate, leaving the CCF unable to report the current rate
- Implementing set_parent without get_parent (or vice versa) on a mux clock
- Adding enable/disable to a pure divider or mux clock that cannot gate at all
Best Practices
- Check this table before writing a single line of a new clock driver
- Implement set_parent and get_parent as a pair, never just one
- Keep gate logic and rate-change logic in separate callbacks even on a composite clock
- Re-verify the table whenever you add a new capability to an existing clock driver
Summary and Key Takeaways
- Gate-capable clocks require enable/disable (or prepare/unprepare)
- Rate-changing clocks require recalc_rate, one of round_rate/determine_rate, and set_rate
- Single-parent and root clocks must never implement set_parent/get_parent
- Multiplexer clocks are the only case where set_parent/get_parent are mandatory
Frequently Asked Questions
What counts as a “root” clock?
A clock with no parent at all, such as an external crystal oscillator feeding the
rest of the clock tree.
Can a clock be both a gate and a multiplexer?
Yes, by implementing both the Gate column’s callbacks and the Multiplexer column’s
callbacks together, or more simply by using a composite clock as covered earlier in
this chapter.
What happens if I implement get_parent on a single-parent clock?
It is technically harmless if it always returns the same index, but it adds
unnecessary code and can mislead future maintainers into thinking the clock has more
than one parent.
Is recalc_accuracy ever mandatory?
No, it stays optional across every clock type in this table; omit it unless your
driver has meaningful accuracy information to report.
Do I need is_enabled if I already implement enable/disable?
It is optional; without it, the CCF tracks enable state through its own internal
counter instead of querying the hardware directly.
Suggested Images For This Lecture
- Table graphic: mandatory clk_ops callbacks by clock type
- Diagram: single-parent/root vs multiplexer set_parent/get_parent rule
- Checklist graphic: gate-only clock driver requirements
Continue This Free Linux Kernel Development Course
Next, we implement a complete gate clock driver from scratch, callback by callback,
and register it against real device tree data.
