What is Fixed and PWM Clock Bindings in Linux Kernel-Free Linux Device Drivers Course

Fixed and PWM Clock Bindings-Free Linux Device Drivers Course
Free Linux Kernel Development Course · Common Clock Framework · Kernel 6.x
Chapter 4 · Lecture 17
Reading Time: 13 min
Level: Intermediate

Keywords covered in this lecture

linux fixed clock device tree
pwm-clock device tree binding
dummy clock no driver
clock-frequency clock-output-names
free linux kernel development course
free embedded systems course

Every clock driver in this chapter so far has needed a probe function. This lecture
covers two clock types that need none at all. A linux fixed clock device
tree
node and a PWM-backed clock node are both parsed and registered
automatically by the CCF’s own core code the moment the device tree is loaded —
no compatible-matched platform driver required on your part.

What You Will Learn

  • Registering a fixed-rate clock purely through DTS with compatible = “fixed-clock”
  • Why this exists mainly to describe dummy/external reference clocks
  • Using a PWM output pad as a clock source with compatible = “pwm-clock”
  • Why pwm-clock is classified as a fixed-rate clock type
  • When to reach for a DT-only clock instead of a full provider driver

Prerequisites

  • Fixed-rate clock case study (struct clk_fixed_rate, clk_fixed_rate_ops)
  • Clock consumer device tree binding (#clock-cells, clocks/clock-names)
  • Basic PWM binding familiarity (pwms property) is helpful but not required

The fixed-clock Compatible: Zero-Driver Fixed Rate Clocks

A node with compatible = "fixed-clock" is read directly by the CCF’s own
device tree bootstrap code, without any platform_driver ever matching against it. This
exists mainly to describe dummy clocks — external crystals or reference sources
that a peripheral needs to know the frequency of, but which have no register interface
of their own to control. A classic example is an SPI-attached controller chip that needs
to be told what frequency its external crystal runs at, purely so its own internal PLL
math comes out correct.

clocks {
    ep_ext_osc: clk@1 {
        compatible = "fixed-clock";
        reg = <0>;
        #clock-cells = <0>;
        clock-frequency = <8000000>;
        clock-output-names = "ep_ext_osc";
    };
};

/* consumer: an SPI-attached controller that needs to know its crystal's rate */
ep_spi_ctrl: controller@0 {
    compatible = "ep,fake-spi-ctrl";
    reg = <0>;
    spi-max-frequency = <10000000>;
    clocks = <&ep_ext_osc>;
};

#clock-cells is 0 here because a fixed-clock node only ever
exposes a single output line — the specifier a consumer needs is nothing more than
the phandle of the provider, with no index argument at all. No probe function, no
compatible-matched platform driver, and no clk_ops anywhere in your own code are
required; the CCF parses clock-frequency and registers the clock for you
automatically.

Verifying a fixed-clock Node

Since there is no driver to build, verification happens entirely through the running
system:

cat /sys/kernel/debug/clk/clk_summary | grep ep_ext_osc

Expected output, showing the clock already registered before any of your own drivers
even probed:

ep_ext_osc                1        1        0     8000000          0

The pwm-clock Alternative

Some boards simply do not route a dedicated clock output pad to a given component,
but do have a spare PWM output available. Since a PWM signal is just a fixed-period
square wave, board designers sometimes repurpose a PWM channel as a stand-in clock
source. Because the period has to be fixed at binding time, pwm-clock is
classified as a fixed-rate clock type, backed by the driver at
drivers/clk/clk-pwm.c.

ep_pwm_clk: ep_pwm_clk {
    compatible = "pwm-clock";
    #clock-cells = <0>;
    clock-frequency = <22000000>;
    clock-output-names = "ep_pwm_clk";
    pwms = <&pwm2 0 45>;   /* 1 / 45ns ≈ 22 MHz */
    status = "okay";
};

/* consumer: an external sensor clocked from the PWM pad */
ep_sensor: sensor@40 {
    compatible = "ep,fake-sensor";
    reg = <0x40>;
    clocks = <&ep_pwm_clk>;
    clock-names = "xclk";
};

Just like fixed-clock, #clock-cells is 0 and no
compatible-matched platform driver of your own is needed — the existing
clk-pwm.c driver in the kernel tree already handles this compatible string.
Your job is only to describe the PWM channel and the resulting frequency correctly in
the device tree.

Three Ways to Get a Fixed-Rate Clock Into the System

Approach Driver Code Needed? Typical Use
compatible = “fixed-clock” None Dummy/external reference clocks with no registers
compatible = “pwm-clock” None (kernel already ships clk-pwm.c) Boards reusing a PWM pad as a clock source
clk_hw_register_fixed_rate() in a platform driver Yes, a probe function A real clock-controller chip your own driver manages

Common Mistakes

  • Writing a platform driver for a fixed-clock or pwm-clock node that the CCF core already handles
  • Setting #clock-cells to anything other than 0 on these single-output node types
  • Forgetting clock-frequency, without which the CCF has nothing to register
  • Miscalculating a PWM-derived frequency from its period argument

Best Practices

  • Use fixed-clock for any dummy/reference clock with no register interface
  • Reserve pwm-clock for boards genuinely lacking a dedicated clock pad
  • Give every DT-only clock node a clock-output-names entry for clean clk_summary naming
  • Reach for a real driver only once the clock genuinely needs software control (gating, rate changes, muxing)

Summary and Key Takeaways

  • fixed-clock and pwm-clock nodes are parsed and registered by the CCF core with zero driver code
  • Both use #clock-cells = 0, since each node exposes exactly one output line
  • pwm-clock is classified as a fixed-rate type because its period is fixed at binding time
  • Reach for a real platform driver only when the clock needs actual runtime control

Frequently Asked Questions

Do I need to write a compatible-matched driver for a fixed-clock node?

No. The CCF’s own device tree bootstrap code parses and registers it automatically;
no platform_driver of yours ever needs to match against it.

Why is pwm-clock treated as a fixed-rate clock?

Because the PWM binding requires specifying a fixed period up front, so the
resulting clock frequency cannot change at runtime, matching the fixed-rate category.

Can a fixed-clock node expose more than one output?

No, it always exposes exactly one, which is why #clock-cells is always 0 for this
compatible string.

What driver actually handles compatible = “pwm-clock” in the kernel?

drivers/clk/clk-pwm.c, which already ships in mainline and requires no additional
driver code from you.

When should I write a real clock provider driver instead?

Once the clock needs actual software control — gating, changeable rate,
parent switching — rather than simply describing a fixed external frequency.

Suggested Images For This Lecture

  • Diagram: fixed-clock DT node parsed directly by CCF core, no driver box in the flow
  • Diagram: PWM pad repurposed as a clock source feeding a sensor
  • Table graphic: three ways to get a fixed-rate clock into the system

Continue This Free Linux Kernel Development Course

Next, we look at the fixed-factor clock type — a fixed multiplier/divider on
top of a parent clock — and its own DT-only binding option.

Leave a Reply

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