Linux 内核学习(1) --- 时钟子系统

本文详细介绍了Linux时钟系统的结构,包括时钟树的构建、ClockProvider如何通过clk_hw和clk_ops提供和管理时钟,以及clock_consumer如何通过clk_get获取和操作时钟。重点阐述了clock_device的注册流程和clk_ops中的关键函数。

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

时钟系统说明

时钟就是 SoC 中的脉搏,由它来控制各个部件按各自的节奏跳动。比如CPU主频设置,串口的波特率设置,I2S的采样率设置,I2C的速率设置等等。这些不同的clock设置,都需要从某个或某几个时钟源头而来,最终开枝散叶,形成一棵时钟树

Linux的时钟子系统由CCF(common clock framework) 框架管理,CCF向上给其他使用时钟的 IP 提供了通用的时钟接口,向下给驱动开发者提供硬件操作的接口。

这个也是一个consumer、framework、provider的模式。
Provider 是时钟的模块的具体实现者,系统开机时,需要通过驱动的时钟框架向系统注册不同的时钟,其他需要时钟的模块通过通用接口获取,使能,设置时钟
Framework 是内核提供的一套通用时钟实现框架,包含了注册和使用的通用接口
Consumer 是时钟模块的使用者,比如上面提到的 I2C 模块,Uart 模块的等等

电源管理的两大主要方面就是时钟和电压

时钟树

SoC上的模块很多,为了适应不同模块的时钟要求,会形成一课时钟树,如下所示:

根节点一般是 Oscillator(有源振荡器)或者 Crystal(无源振荡器),表示从芯片外部输入的基准时钟,
中间节点有很多种,包括 PLL(锁相环,用于提升频率的),Divider(分频器,用于降频的),Mux(从多个clock path中选择一个),Gate(只能被控制ON/OFF的)。Soc 上的时钟树
根据不同时钟的特点,clock framework 将 clock 分为 Fixed rateGateDividerMuxFixed factorComposite六类,这六类的含义如下:

  • Fixed Rate clock
    固定频率时钟,提供恒定的时钟信号,适用于需要固定频率的硬件,如PWM(脉宽调制)或定时器。
  • Gated clock
    门控时钟,只可以被开启或关闭,适用于可以被动态开启或者关闭的硬件,以节约电源
  • Divider clock
    分频时钟,可以将输入的时钟信号分频,产生一个较低频率的时钟信号,适用于需要降低时钟频率适应设备需要的设备
  • Muxed clock:
    复用时钟,时钟信号可以选择不同的时钟源
  • Fixed factor clock
    固定系数时钟,可以将输入时钟信号乘以一个固定的系数,产生一个更高或者更低的时钟信号
  • Composite clock
  • 组合时钟,可以由多个时钟实体组成,每个时钟实体都有特定的功能,适用于复杂时钟控制策略的硬件,比如复杂时钟路径和时钟管理

Linux cat /sys/kernel/debug/clk/clk_summary 可以查看当前 Soc 的时钟树

Clock Provider

时钟通用数据结构

Linux 内核将上面六类设备特点抽象出来,用 struct clk_hw 表示

struct clk_hw {
   
  //指向CCF模块中对应 clock device 实例
 struct clk_core *core;
  //clk是访问clk_core的实例 每当consumer通过clk_get对CCF中的clock device(也就是clk_core)发起访问的时候都需要获取一个句柄,
  //也就是clk
 struct clk *clk;
  //clock provider driver初始化时的数据,数据被用来初始化clk_hw对应的clk_core数据结构
 const struct clk_init_data *init;
};

struct clk_init_data {
   
  //该clock设备的名字
 const char  *name;
  //clock provider driver 进行的具体的 HW 操作
 const struct clk_ops *ops;
  //描述该clk_hw的拓扑结构
 const char  * const *parent_names;
 const struct clk_parent_data *parent_data;
 const struct clk_hw  **parent_hws;
 u8   num_parents;
 unsigned long  flags;
};

Fixed rate clockgate clock 为例,它就包含一个 struct clk_hw 结构作为核心:

struct clk_fixed_rate {
   
	// 包含的 clk_hw 结构
	struct		clk_hw hw;
	unsigned long	fixed_rate;
	unsigned long	fixed_accuracy;
	u8		flags;
};

struct clk_gate {
   
	struct clk_hw hw;
	void __iomem	*reg;
	u8		bit_idx;
	u8		flags;
	spinlock_t	*lock;
};

由此可以知道:

  1. 每次注册进入内核的 clock device 设备,都会包含一个 struct clk_hw 结构
  2. strutc clk_hw 包含一个重要的结构体成员 const struct clk_init_data *init,里面包含了注册进入内核的时钟的具体操作方法

struct clk_init_data 包含一个重要成员 clk_ops,里面就是时钟设备的具体操作方法函数:

struct clk_ops {
   
	int		(*prepare)(struct clk_hw *hw);
	void		(*unprepare)(struct clk_hw *hw);
	int		(*is_prepared)(struct clk_hw *hw);
	void		(*unprepare_unused)(struct clk_hw *hw);
	int		(*enable)(struct clk_hw *hw);
	void		(*disable)(struct clk_hw *hw);
	int		(*is_enabled)(struct clk_hw *hw);
	void		(*disable_unused)(struct clk_hw *hw);
	unsigned long	(*recalc_rate)(struct clk_hw *hw,
					unsigned long parent_rate);
	long		(*round_rate)(struct clk_hw *hw, unsigned long rate,
					unsigned long *parent_r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值