基于RK3399分析Linux系统下的CPU时钟管理 - 第1篇

本文详细介绍了ARM处理器平台中的时钟管理机制,特别是基于设备树(dts)的时钟树结构。时钟提供者(clockproviders)通过#clock-cells定义输出时钟的数量,clock-output-names指定时钟名称,而时钟使用者(clockconsumers)通过clocks引用时钟源,并通过clock-names进行解析。此外,文章还提到了assigned-clocks和assigned-clock-rates用于多路时钟管理和频率设定,以及clock-frequency用于单一时钟频率的定义。通过对rk3399平台的实例分析,展示了时钟配置的具体细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 背景介绍

绝大多数的电子器件都是由时钟驱动其工作的。而SoC芯片或电路板中的时钟以树状结构呈现,按时钟域进行划分,按照不同的时钟需求进行管理。
出于功耗和数据传输时序控制等目的,在内核代码中对时钟进行统一注册、统一管理。kernel代码中很早就出现了时钟管理机制,甚至早于git版本管控之前。

1. 时钟定义

ARM处理器平台中基于dts描述时钟树,包括时钟结构、时钟属性等信息。由时钟框架驱动和设备驱动解析dts中时钟树信息,完成时钟系统的初始化、管理、使用。在设备树中定义了时钟的providersconsumers。前者代表时钟提供者,通常是一个固定的PLL,后者代表时钟使用者,例如处理器核心以及各种外部设备等。

1.1 Clock providers

1. #clock-cells

时钟提供者输出的时钟路数,当#clock-cells为0时,代表仅输出1路时钟,若大于等于1,则代表输出多路时钟,Clock consumers通过编号索引使用。
下面的时钟结点clock-cells为0,代表仅能够输出1路时钟,这里面只提供了一路24MHz的固定时钟。

xin24m: xin24m {
  compatible = "fixed-clock";
  clock-frequency = <24000000>;
  clock-output-names = "xin24m";
  #clock-cells = <0>;
};

下面的时钟结点中clock-cells为1,代表能够输出多路时钟,这里面我们可以看出它提供了两路时钟分别是PLL_PPLLFCLK_CM0S_SRC_PMU,时钟频率分别是67.6MHz和97MHz。

pmucru: pmu-clock-controller@ff750000 {
...
		#clock-cells = <1>;
		#reset-cells = <1>;
		assigned-clocks = <&pmucru PLL_PPLL>, <&pmucru FCLK_CM0S_SRC_PMU>;
		assigned-clock-rates = <676000000>, <97000000>;
	};

2. clock-output-names
顾名思义,它定义了输出时钟的名字。当clock consumers使用这路时钟的时候,我们可以见名知意。从下面的clock-output-names可以清楚的直到,这是外部晶振提供的24MHz时钟。

xin24m: xin24m {
		compatible = "fixed-clock";
		clock-frequency = <24000000>;
		clock-output-names = "xin24m";
		#clock-cells = <0>;
	};

3. clock-indices
这并不是一个必选项,当然也不常见。当存在多路输出时钟时,clock consumerindex引用对应的时钟,默认不指定clock-indices且没有使用assigned-clocks时,index索引是线性增长的,像下面这样,ckil的index是0,而ckih的index就是1。

oscillator { #clock-cells = <1>;
    clock-output-names = "ckil", "ckih"; };

当定义了clock-indices之后,index的值由clock-indices决定,像下面这样:

oscillator { #clock-cells = <1>;
    clock-output-names = "ckil", "ckih"; };

4. assigned-clocks
当输出多路时钟时,为没路输出时钟进行编号,以phandle+specifier组合进行管理,像下面这样:

pmucru: pmu-clock-controller@ff750000 {
...
  assigned-clocks = <&pmucru PLL_PPLL>, <&pmucru FCLK_CM0S_SRC_PMU>;
  assigned-clock-rates = <676000000>, <97000000>;
};

PLL_PPLL代表了specifier,其定义位于头文件include/dt-bindings/clock/rk3399-cru.h中。需要说明的是,这个头文件很重要,所有的specifier都可以在这里找到对应的宏。

5. assigned-clock-rates
这个定义是和assigned-clocks成对使用的。它代表了assigned-clocks所对应的时钟频率,例如PLL_PPLL所对应的时钟频率是67.6MHz。

pmucru: pmu-clock-controller@ff750000 {
...
  assigned-clocks = <&pmucru PLL_PPLL>, <&pmucru FCLK_CM0S_SRC_PMU>;
  assigned-clock-rates = <676000000>, <97000000>;
};

6. clock-frequency
当不使用assigned-clock-rates为输出时钟指定大小时,可以利用clock-frequency进行指定。像下面这样,指定了osc的时钟频率为32.678Khz。

osc: oscillator { 
    compatible = "fixed-clock";
    #clock-cells = <1>;
    clock-frequency  = <32678>;
    clock-output-names = "osc"; };

1.2 Clock consumers

Clock consumers意为时钟使用者,通常是CPU核心部件或者其他外设。
我们以dsi为例说明Clock consumers设备树的组成。

	vopb: vop@ff900000 {
		compatible = "rockchip,rk3399-vop-big";
		reg = <0x0 0xff900000 0x0 0x600>,
			<0x0 0xff901c00 0x0 0x200>,
			<0x0 0xff902000 0x0 0x1000>;
		reg-names = "regs", "cabc_lut", "gamma_lut";
		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;
		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>, <&cru DCLK_VOP0_DIV>;
		clock-names = "aclk_vop", "dclk_vop", "hclk_vop", "dclk_source";
  ...
};

1. clocks
它代表了设备的时钟源,通常以phandle+specifier组合进行引用。例如本例中,aclk_vop时钟使用的是cru模块提供的ACLK_VOP0,它的时钟频率在cru结点中定义,大小是400000000

2. clock-names
这代表了Clock consumers中使用的时钟名字,方便设备驱动代码进行相应的时钟解析,例如:

static int vop_bind(struct device *dev, struct device *master, void *data)
{
...
	vop->aclk = devm_clk_get(vop->dev, "aclk_vop");
	if (IS_ERR(vop->aclk)) {
		dev_err(vop->dev, "failed to get aclk source\n");
		return PTR_ERR(vop->aclk);
	}
...
}

以上是ARM平台RK3399的软件时钟树定义方式,具体可查看rk3399.dtsi文件。除此之外,可参考如下内核文档做相关了解。

Documentation/evicetree/indings/lock/lock-bindings.txt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux与SoC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值