Keywords covered in this lecture
clk prepare vs enable
clk_hw recalc_rate
clk_hw set_rate round_rate
free linux kernel development course
free linux device drivers course
Every base clock type from the previous lecture is really just a pre-filled
struct clk_ops. The CCF itself never asks what “kind” of clock it is
talking to — it only ever looks at which function pointers are non-NULL inside
that struct. Understanding the full set of linux clk_ops callbacks,
what each one is responsible for, and which ones are allowed to sleep, is the single
most important reference you will come back to while writing any clock provider
driver.
What You Will Learn
- How the CCF infers a clock’s capabilities purely from clk_ops
- The full current struct clk_ops field list for kernel 6.x
- Why prepare/unprepare may sleep but enable/disable never can
- What each callback is responsible for, one by one
- Why SPI/I2C clock chips implement prepare/unprepare instead of enable/disable
Prerequisites
- CCF base clock types overview (previous lecture)
- struct clk_hw and the embedding pattern
- Basic kernel locking concepts: atomic context vs sleeping context
The CCF Only Ever Looks at clk_ops
When you call clk_hw_register(), you never tell the framework “this is a
gate clock” or “this is a divider clock.” The CCF has no concept of clock type at all.
All it does is look at clk_hw->init.ops and check which function pointers
are set. If .set_rate is present, the clock can change rate. If
.get_parent is present, the clock has more than one possible parent. The
“type” you think of as gate, divider, or mux is really just a convention for which
callbacks a given clk_ops struct fills in.
The Current struct clk_ops (Kernel 6.x)
Current mainline kernels have grown a few extra fields beyond what an older reference
might show — notably set_rate_and_parent, recalc_accuracy,
get_phase/set_phase, and debug_init:
struct clk_ops {
int (*prepare)(struct clk_hw *hw);
void (*unprepare)(struct clk_hw *hw);
int (*is_prepared)(struct clk_hw *hw);
void (*unprepare_unused)(struct clk_hw *hw);
int (*enable)(struct clk_hw *hw);
void (*disable)(struct clk_hw *hw);
int (*is_enabled)(struct clk_hw *hw);
void (*disable_unused)(struct clk_hw *hw);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
long (*round_rate)(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate);
int (*determine_rate)(struct clk_hw *hw,
struct clk_rate_request *req);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
int (*set_rate_and_parent)(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate,
u8 index);
unsigned long (*recalc_accuracy)(struct clk_hw *hw,
unsigned long parent_accuracy);
int (*get_phase)(struct clk_hw *hw);
int (*set_phase)(struct clk_hw *hw, int degrees);
void (*init)(struct clk_hw *hw);
void (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
};
Sleep-Capable vs Atomic Callbacks
This is the single most important rule in this lecture: prepare,
unprepare, and is_prepared are allowed to sleep, while
enable, disable, and is_enabled must never sleep,
because the CCF calls them with a spinlock held. Mixing these up is one of the most
common bugs in real clock drivers.
Callback-by-Callback Reference
- prepare/unprepare: optional; whatever prepare sets up, unprepare must undo
- is_prepared: optional; if omitted, the CCF tracks a prepare counter for you instead of querying hardware
- unprepare_unused/disable_unused: optional, called only by the late-boot clk_disable_unused() cleanup path
- enable/disable: must run atomically and never sleep; enable should return only once the clock signal is valid
- is_enabled: same fallback logic as is_prepared, but for the enable counter
- recalc_rate: optional; recomputes the clock’s rate from the parent rate (rate defaults to 0 if omitted)
- round_rate: given a target rate, returns the closest rate the hardware actually supports
- determine_rate: the modern replacement for round_rate, evaluated against a full clk_rate_request
- set_parent: changes which parent is active, given a parent index
- get_parent: mandatory for multi-parent clocks; reads hardware and returns the active parent’s index
- set_rate: applies a rate that was already validated through round_rate/determine_rate
- set_rate_and_parent: changes rate and parent together in one atomic step, when hardware allows it
- recalc_accuracy: recomputes clock accuracy in PPB from the parent’s accuracy
- get_phase/set_phase: read or adjust a clock’s output phase relative to its parent
- init: a platform-specific hook run once at clk_hw_register() time
- debug_init: lets a driver add its own debugfs entries under the clock’s clk_summary node
round_rate vs determine_rate
You do not need both. determine_rate is the newer, more capable
callback — it receives a full struct clk_rate_request and can
consider minimum/maximum rate constraints, while round_rate only receives
a single target rate. New drivers should implement determine_rate;
round_rate exists mainly for older drivers that have not been converted.
Choosing Between prepare/unprepare and enable/disable
Because enable/disable must never sleep, any clock whose
control path goes over a sleepable bus — SPI or I2C being the classic examples
— cannot safely implement those two callbacks. Such drivers implement
prepare/unprepare instead, since those are allowed to sleep.
On the consumer side, this is exactly why clk_enable() must always be
preceded by clk_prepare(), and clk_disable() must always be
followed by clk_unprepare() — the consumer API needs both stages
available regardless of which one a given provider actually implements.
| Clock Class | Typical Control Path | Recommended Callbacks |
|---|---|---|
| SoC-internal clocks | Simple MMIO register writes | enable / disable |
| Discrete SPI/I2C clock chips | Sleepable bus transactions | prepare / unprepare |
Common Mistakes
- Implementing an I2C register write inside .enable instead of .prepare
- Implementing both round_rate and determine_rate when only one is needed
- Forgetting get_parent on a clock that also implements set_parent
- Returning success from .enable before the clock signal is actually valid
Best Practices
- Only implement the callbacks your hardware actually needs; leave the rest NULL
- Use determine_rate over round_rate in new drivers
- Match enable/disable vs prepare/unprepare to whether your bus can sleep
- Keep set_parent/get_parent index values consistent with parent_names ordering
Summary and Key Takeaways
- The CCF infers clock capability purely from which clk_ops callbacks are set
- prepare/unprepare/is_prepared may sleep; enable/disable/is_enabled must not
- determine_rate is the modern replacement for round_rate
- SPI/I2C-based clock chips belong on prepare/unprepare, not enable/disable
Frequently Asked Questions
Do I have to implement every clk_ops callback?
No. Only implement the callbacks your hardware capability actually requires; any
callback left NULL simply means that capability is unavailable for that clock.
What happens if is_enabled is omitted?
The CCF falls back to an internal enable counter, incremented and decremented by the
consumer-facing clk_enable()/clk_disable() calls, instead of querying hardware.
Why can’t enable ever sleep?
Because the CCF calls it while holding an internal spinlock; sleeping while holding
a spinlock can deadlock or corrupt kernel state.
Is set_rate_and_parent required if I have both set_rate and set_parent?
No, it is optional. It exists purely as an optimization for hardware that can change
rate and parent together atomically in one operation.
What does debug_init let a driver do?
It lets a clock driver add its own custom debugfs files under that clock’s entry,
alongside the standard clk_summary information the CCF already exposes.
Suggested Images For This Lecture
- Diagram: clk_ops capability inference instead of a type field
- Diagram: sleep-capable vs atomic-only callback groups
- Table graphic: SoC-internal vs SPI/I2C clock callback choice
Continue This Free Linux Kernel Development Course
Next, we look at exactly which of these callbacks are mandatory for each clock
type, using a clear comparison table.
