iJoe's Blog
Published on

linux驱动学习-设备树03-clock系统

Authors

物理上的clock

clock是给数字电路提供时序基准,使内部逻辑按照一定节奏工作。但在实际物理电路中,并不是固定频率,或者是需要统一开关,所以就涉及到一套流程。

主要的物理模块

clock source
    ↓
PLL (它在其他之前是因为,需要先将源低频时钟,变成一个更适合系统的高频时钟,而放在后面意义不大)
    ↓
mux / divider / gate
    ↓
consumer

其中:

provider 是 Linux Clock Framework 中“提供 clock”的角色,不是 PLL/gate 一类物理模块。

pll是将频率按倍率增加的

gate是控制clock开关的

mux是多对一,将多个选择其中一个作为输出的

divider是将频率进行分频的,比如:600 MHz / 2 = 300 MHz。和上面的pll相反。

consumer就是消费者,使用这些clock

provider

一个clock tree可能具有多个provider,比如:

osc24M
└── Provider A

controller

PLL
AHB
UART
└── Provider B

它是由外源提供的clock,因此controller并不能操作osc24M,但把它当作了输入源。所以,一个 Clock provider 自己也可以同时是另一个 Clock 的 consumer。

比如下面设备树,也直观表示controller:

osc24m: oscillator {
    compatible = "fixed-clock";
    #clock-cells = <0>;
    clock-frequency = <24000000>;
};

ccu: clock-controller@30000000 {
    clocks = <&osc24m>;
};

clock controller

和前面的gpio一样,它也有一个controller,同时这里也间接对前面gpio补充。clock controller实际是一个物理硬件模块,相当于一个device,它也有对应的driver,而上层还有一个子系统(subsystem)来调用driver来操作这个控制器,再由控制器间接操作实际clock。即:

consumer driver
      ↓
Clock Framework
      ↓
clock provider driver
      ↓
PLL / mux / divider / gate 等 clock hardware
      ↓
clock signal
      ↓
设备硬件

这条流程对应上面相反,是从上到下的。

软件上的clock

要从具体的consumer去操作这个clock,那么就要涉及对应关系,而前面也说明了流程,下面提供一些数据结构等

主要数据结构

有两个数据结构,很容易混淆,clk和clk_hw。

其中struct clk 是 consumer 一侧获取并使用的 clock 句柄。同一条底层 clock 可以被多个 consumer 使用,各 consumer 可以持有自己的 struct clk。

而clk_hw 是 provider 一侧用于描述具体硬件 clock 及其底层实现的信息。比如 gate 如何开关、mux 如何选择 parent、divider 如何分频。

而其他api或者数据结构,暂不再深入讨论

整体流程

实际上某个设备需要调用clock时,只是在软件层面去操作,最后再硬件层面返回。

             软件
────────────────────────────

UART driver
    │
    │ clk_prepare_enable()
    ↓
Clock Framework
    ↓
clock provider driver
    │
    │ 写寄存器
    ↓

────────────────────────────
             硬件

Clock Controller
    │
    │ clock signal
    ↓
UART Controller

参考文档

[1] The Common Clk Framework
[2] Clock子系统