What is Linux Clock Flags Reference Guide in Linux Kernel

Linux Clock Flags Reference Guide-Free Linux Device Drivers Course
Free Linux Kernel Development Course · Common Clock Framework · Kernel 6.x
Chapter 4 · Lecture 14
Reading Time: 15 min
Level: Intermediate

Keywords covered in this lecture

linux clock flags CLK_SET_RATE_GATE
CLK_IGNORE_UNUSED
CLK_IS_CRITICAL
clk_hw init flags
free linux kernel development course
free linux device drivers course

Two clocks can implement the exact same clk_ops callbacks and still behave very
differently once registered, because of one field we have not looked at yet:
clk_hw->init.flags. These linux clock flags are
framework-level hints, defined in include/linux/clk-provider.h and
OR’d together, that change how the CCF itself behaves around rate changes,
re-parenting, and unused-clock cleanup — independent of anything your own
callbacks do.

What You Will Learn

  • Where clk_hw.init.flags lives and how flags are combined
  • What each CLK_* flag actually changes in framework behavior
  • Why CLK_SET_RATE_PARENT needs to be used with care
  • Which flag keeps a boot-critical clock from ever being gated
  • A flag that is now obsolete, and two newer ones added since this book was written

Prerequisites

  • Mandatory clk_ops by clock type (previous lecture)
  • CCF clk_ops callback reference guide
  • Basic bitfield/BIT() macro familiarity

Where Clock Flags Live

Every clock’s struct clk_init_data has a flags field, set
once at registration time and never changed afterward. Unlike clk_ops, which tells the
CCF what your hardware can do, these flags tell the CCF how to behave around
that hardware — whether a rate change must be gated first, whether an unused clock
should be left alone, and so on. Multiple flags are combined with a bitwise OR.

clk_ops vs Flags: Two Different Jobs
clk_ops
what the hardware can do
|
init.flags
how the framework should behave

Clock Flags Reference

CLK_SET_RATE_GATE

The clock must be gated (disabled) across any rate change. With this flag set, if the
clock has already been prepared, a clk_set_rate() call will fail outright
— this exists to protect against rate glitches reaching a running consumer.

CLK_SET_PARENT_GATE

The clock must be gated (disabled) across any re-parenting operation, for the same
glitch-protection reason as CLK_SET_RATE_GATE, but applied to parent switches instead of
rate changes.

CLK_SET_RATE_PARENT

This is the most involved flag, and the one you already saw used for parent chaining
in an earlier lecture. It has two separate effects:

  • If .round_rate is missing, a clk_round_rate() request is forwarded up to the parent instead of just returning the cached rate
  • Any clk_set_rate() request is forwarded upstream, letting a parent rate change stand in for a rate change the clock itself cannot perform

This flag is typically set on gate and mux clocks that have no rate-changing ability
of their own, and the book’s own advice still holds today: use it with care, since it
means a seemingly local rate change can ripple up and affect every other clock sharing
that same parent.

CLK_IGNORE_UNUSED

Tells the CCF to skip this specific clock during its late-boot “disable unused
clocks” pass. This is the per-clock equivalent of the clk_ignore_unused boot
parameter, and is mainly a bring-up and debug aid for clocks a bootloader leaves running
that no driver has claimed yet — it is not meant for normal production use.

CLK_GET_RATE_NOCACHE

Forces the CCF to recompute the clock’s rate every time instead of trusting its
cached value. This matters on hardware where the rate can change outside the kernel’s
knowledge — for example, a piece of firmware or another core adjusting a PLL
behind the kernel’s back.

CLK_SET_RATE_NO_REPARENT

Prevents the CCF from switching a mux clock’s parent as a side effect of trying to
satisfy a requested rate. Without this flag, a rate request that no current parent can
satisfy exactly might cause an automatic re-parent; this flag disables that behavior.

CLK_GET_ACCURACY_NOCACHE

The accuracy equivalent of CLK_GET_RATE_NOCACHE: it forces accuracy to be
recalculated on every query instead of using a cached parts-per-billion value.

CLK_RECALC_NEW_RATES

Tells the CCF to recalculate this clock’s rate whenever it receives a rate-change
notification, rather than assuming the rate is still whatever was last cached.

CLK_SET_RATE_UNGATE

Marks a clock that must actually be running (ungated) in order for a rate change to
be applied at all — some hardware simply cannot latch a new divider or PLL setting
while the clock signal is stopped.

CLK_IS_CRITICAL

Marks a clock that must never be gated, under any circumstances, even if the CCF
believes no consumer currently holds it. This is reserved for clocks whose loss would
crash the system outright, such as a clock feeding the CPU or system bus itself.

A flag that no longer exists, and two that are new

CLK_IS_BASIC, which older references may still list, has been removed and is no
longer used in current kernels — do not rely on it in new drivers. Since this
book’s era, mainline has also added CLK_OPS_PARENT_ENABLE (forces the
parent clock to be enabled during gate/ungate, set_rate, and re-parent operations)
and CLK_DUTY_CYCLE_PARENT (forwards duty-cycle queries to the parent
clock), verified against current kernel source.

Gated Means Disabled, Ungated Means Enabled

It is easy to trip over the terminology here: a gated clock is a
disabled clock, and an ungated clock is an enabled one. Several of the
flags above talk about gating specifically around rate changes and re-parenting, and
reading “gate” as “disable” makes every one of them much easier to reason about.

Original Demo: Applying CLK_IS_CRITICAL and CLK_SET_RATE_PARENT

Here is a short original example showing both flags at work: a bus clock that must
never be gated, and a gate clock beneath it that forwards any rate change request to
that same bus clock.

/* ep_flagged_clk_tree.c - demonstrating CLK_IS_CRITICAL and CLK_SET_RATE_PARENT */
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/spinlock.h>

struct ep_flagged_data {
    void __iomem *base;
    spinlock_t lock;
    struct clk_hw *bus_hw;
    struct clk_hw *periph_hw;
};

static int ep_flagged_probe(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct ep_flagged_data *data;

    data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    spin_lock_init(&data->lock);

    data->base = devm_platform_ioremap_resource(pdev, 0);
    if (IS_ERR(data->base))
        return PTR_ERR(data->base);

    /* the shared bus clock must never be gated, even if unused */
    data->bus_hw = devm_clk_hw_register_fixed_rate(dev, "ep_bus_clk", NULL,
                                                    CLK_IS_CRITICAL, 100000000);
    if (IS_ERR(data->bus_hw))
        return PTR_ERR(data->bus_hw);

    /* a peripheral gate that forwards rate requests up to ep_bus_clk */
    data->periph_hw = devm_clk_hw_register_gate(dev, "ep_periph_clk", "ep_bus_clk",
                                                 CLK_SET_RATE_PARENT,
                                                 data->base, 0, 0, &data->lock);
    if (IS_ERR(data->periph_hw))
        return PTR_ERR(data->periph_hw);

    return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, data->periph_hw);
}

static const struct of_device_id ep_flagged_of_match[] = {
    { .compatible = "ep,clk-flags-demo" },
    { }
};
MODULE_DEVICE_TABLE(of, ep_flagged_of_match);

static struct platform_driver ep_flagged_driver = {
    .probe = ep_flagged_probe,
    .driver = {
        .name = "ep_clk_flags_demo",
        .of_match_table = ep_flagged_of_match,
    },
};
module_platform_driver(ep_flagged_driver);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("EmbeddedPathashala clock flags demo");

Because ep_bus_clk carries CLK_IS_CRITICAL, the late-boot
unused-clock cleanup pass will never disable it, even though nothing directly consumes
it in this demo. Because ep_periph_clk carries
CLK_SET_RATE_PARENT, any clk_set_rate() call against it is
forwarded to ep_bus_clk instead of failing outright.

Clock Flags at a Glance

Flag Affects
CLK_SET_RATE_GATE Forces gating across rate changes
CLK_SET_PARENT_GATE Forces gating across re-parenting
CLK_SET_RATE_PARENT Forwards round_rate/set_rate to the parent
CLK_IGNORE_UNUSED Skips this clock during unused-clock cleanup
CLK_GET_RATE_NOCACHE Recomputes rate on every query
CLK_SET_RATE_NO_REPARENT Blocks automatic re-parenting on rate change
CLK_GET_ACCURACY_NOCACHE Recomputes accuracy on every query
CLK_RECALC_NEW_RATES Recalculates rate on notification
CLK_SET_RATE_UNGATE Requires the clock to be running to set rate
CLK_IS_CRITICAL Never gates this clock, ever
CLK_OPS_PARENT_ENABLE Requires parent enabled during gate/rate/reparent ops
CLK_DUTY_CYCLE_PARENT Forwards duty-cycle queries to the parent

Common Mistakes

  • Relying on CLK_IS_BASIC, which no longer exists in current kernels
  • Setting CLK_SET_RATE_PARENT without understanding it can change sibling clocks’ rates too
  • Using CLK_IGNORE_UNUSED as a permanent fix instead of a bring-up debug aid
  • Marking a non-essential clock CLK_IS_CRITICAL, wasting power for no real benefit

Best Practices

  • Reserve CLK_IS_CRITICAL for clocks whose loss would crash the system
  • Document why CLK_SET_RATE_PARENT is set whenever you use it
  • Treat CLK_IGNORE_UNUSED as temporary bring-up scaffolding, not a permanent flag
  • Combine flags with a plain bitwise OR and keep the combination readable

Summary and Key Takeaways

  • Flags live in clk_init_data.flags and change framework behavior, not hardware capability
  • CLK_SET_RATE_PARENT and CLK_IS_CRITICAL are the two flags worth the most care
  • CLK_IS_BASIC is obsolete; CLK_OPS_PARENT_ENABLE and CLK_DUTY_CYCLE_PARENT are newer additions
  • “Gated” always means disabled, and “ungated” always means enabled

Frequently Asked Questions

Can I combine multiple clock flags?

Yes, they are simple bit values meant to be combined with a bitwise OR in
clk_init_data.flags.

Is CLK_IS_BASIC safe to use in a new driver?

No, it is no longer used by current kernels and should not appear in new driver
code.

Does CLK_IGNORE_UNUSED replace proper clock claiming?

No, it is meant as a bring-up and debug aid for clocks left on by a bootloader, not
a substitute for a driver correctly calling clk_get()/clk_prepare_enable().

What is the risk of CLK_SET_RATE_PARENT?

A rate change on the clock carrying this flag can propagate up and change the
parent’s rate, which may also affect every sibling clock sharing that same parent.

When would I use CLK_GET_RATE_NOCACHE?

When hardware or firmware outside the kernel’s control can change a clock’s rate,
so the cached value the CCF would otherwise trust could go stale.

Suggested Images For This Lecture

  • Diagram: clk_ops vs init.flags responsibility split
  • Diagram: CLK_SET_RATE_PARENT forwarding a rate request upstream
  • Table graphic: all current CLK_* flags at a glance

Continue This Free Linux Kernel Development Course

Next, we start our first full clock-type case study: the fixed-rate clock, its
struct clk_fixed_rate wrapper, and how to register one from scratch.

Leave a Reply

Your email address will not be published. Required fields are marked *