Files
rt-thread/documentation/6.components/device-driver/clk/fixed.md
T
GuEe-GUI cfda3b3d1a
doc_doxygen / doxygen_doc generate (push) Has been cancelled
doc_doxygen / deploy (push) Has been cancelled
[docs] device-driver: add DM subsystem docs and expand INDEX
Add Doxygen pages for RT-Thread device-model drivers: platform/OFW,
DM core (bus, dm, power), clk/regulator/reset/power-domain, PCI/PIC,
Phye, DMA/hwcache, block/SCSI/ATA/NVMe/UFS/SDIO, SCMI, RPMsg,
mailbox, NVMem, NUMA, syscon, thermal, input/LED/IIO/graphic, and
related power/charger/supply docs.
Expand device-driver INDEX.md with ~90 @subpage entries so all new
pages appear in the driver chapter navigation.
Update existing UART/SPI/RTC/pin/framework/dtc pages: UART docs moved
from serial/ to uart/ (uart + uart_dm + uart_earlycon); SPI and RTC
gain DM companion pages; pin links to pin_dm; framework points at DM
topics.
Focus on registration/probe flow and in-tree APIs; no standalone
VirtIO subsystem page (transport code still incomplete).
Test plan: build Doxygen for documentation/ and verify device-driver
INDEX links resolve without missing @ref/@subpage warnings.

Signed-off-by: GuEe-GUI <2991707448@qq.com>
2026-05-28 16:09:55 +08:00

3.5 KiB
Executable File

@page page_device_clk_fixed Fixed clock provider

fixed-clock platform driver

Implementation: components/drivers/clk/clk-fixed-rate.c. Driver name: clk-fixed-rate. Overview: @ref page_device_clk.

Registers a constant-frequency, always-on clock with no gate, parent, or rate programming — the leaf most SoC trees hang PLLs from.


Device tree

osc24m: fixed-clock {
    compatible = "fixed-clock";
    #clock-cells = <0>;
    clock-frequency = <24000000>;
    clock-accuracy = <0>;          /* optional, ppb */
    clock-output-names = "osc24m"; /* optional; becomes cell name */
};

Consumers:

uart0: serial@40000000 {
    clocks = <&osc24m>;
    /* clock-names optional when only one clock */
};

With #clock-cells = <0>, the specifier in clocks = <&osc24m> has no extra integers (implicit index 0).


Probe flow

  1. rt_platform_driver_register via INIT_SUBSYS_EXPORT(fixed_clk_drv_register) — early registration so crystal nodes probe before CCM consumers.
  2. fixed_clk_probe: rt_calloc struct clk_fixed (embeds rt_clk_node + one rt_clk_fixed_rate).
  3. rt_dm_dev_prop_read_u32(dev, "clock-frequency", &val)required; probe fails without it.
  4. Optional clock-accuracy, clock-output-namesfcell.cell.name.
  5. Wire cells[0], fixed_clk_ops (only .recalc_rate).
  6. rt_clk_register(&cf->parent) — may run rt_ofw_clk_set_defaults if the fixed-clock node has assigned-clocks* (unusual on leaf osc).

Data structures

struct clk_fixed {
    struct rt_clk_node parent;
    struct rt_clk_fixed_rate fcell;
    struct rt_clk_cell *cells[1];
};

struct rt_clk_fixed_rate {
    struct rt_clk_cell cell;
    rt_ubase_t fixed_rate;
    rt_ubase_t fixed_accuracy;
};
Member Role
fixed_rate Hz from clock-frequency
fixed_accuracy Optional ppb from DT
cell.ops->recalc_rate Returns fixed_rate; ignores parent

No enable/disable/prepare — enabling is a no-op at ops level; framework refcount still works for consumers.


OFW matching

static const struct rt_ofw_node_id fixed_clk_ofw_ids[] = {
    { .compatible = "fixed-clock" },
    { /* sentinel */ }
};

Linux-compatible binding; same node can be shared across BSP DTS and upstream dt-bindings.


When to use vs SoC CCM

Use fixed-clock Use SoC driver (e.g. rockchip,*-cru)
Crystal, RC oscillator, external clock input PLL, mux, divider, gate
Rate fixed at boot DVFS, dynamic reparent
No MMIO (or MMIO not managed here) Large clock controller IP

Consumer example

struct rt_clk *clk = rt_clk_get_by_name(dev, "uart_clk");
/* or index 0 if no clock-names */
rt_err_t err = rt_clk_prepare_enable(clk);
rt_ubase_t hz = rt_clk_get_rate(clk);

Fixed clocks rarely need rt_clk_set_rate — rate is fixed; rt_clk_get_rate reads recalc_rate.


Pitfalls

  • Missing clock-frequency — probe fails, phandle resolution returns NULL for consumers.
  • Wrong Hz in DT — all derived PLL math wrong; UART baud, SDIO timing, etc. break silently.
  • Using fixed-clock for gated peripherals — use a gate driver cell instead.
  • Name collisionsclock-output-names should be unique enough for rt_clk_get_by_name fallback lookup.

See also

  • @ref page_device_clk
  • components/drivers/clk/clk-fixed-rate.c
  • components/drivers/include/drivers/clk.h