设计说明
源码说明
内核的时钟驱动框架位于 linux-5.10/drivers/clk 目录下,CMU 的底层驱动位于/drivers/clk/artinchip/目录下。
ArtInChip 的目录结构如下图所示:
文件 |
说明 |
---|---|
clk-aic.h |
aic 公用头文件 |
clk-aic.c |
CMU 各个时钟的初始化,注册文件 |
clk-disp.c |
显示模块的时钟文件 |
clk-fixed-parent-mod.c |
只有一个父时钟源的时钟文件 |
clk-multi-parent-mod.c |
具有多个父时钟源的时钟文件 |
clk-pll.c |
PLL 时钟文件 |
时钟树

-
Fixed rate clock:具有固定的输出频率,通常用于驱动一些不需要动态调整频率的外设。时钟频率固定,不能调节频率,不能打开或关闭。固定频率时钟包括 OSC24M、RC1M 和 OSC32K。
-
Fixed parent module clock:从另一个时钟信号派生出来的时钟,其输出频率与父时钟信号的频率相同。该类型时钟可以实现只有一个父时钟源的时钟驱动,主要用于各个外设模块的时钟驱动。该类型时钟可以改变时钟频率,打开或关闭时钟,获取父时钟源参数,但不能设置或改变父时钟源。
-
Multiple parent module clock:可以从多个父时钟源中选择其中一个作为其输入,并根据需要调整输出频率。 该类型时钟可以实现有多个父时钟源的时钟驱动,主要用于各种总线时钟驱动,可以打开或关闭时钟,调节频率,获取或改变父时钟源。
-
Display module clock: 实现了几个与显示模块相关的时钟驱动,除了自身的模块时钟外,显示模块还有一个像素时钟,相应的底层寄存器的设计也不同,所以显示相关的几个时钟重新设计了底层驱动。
-
PLL clock:实现了 CMU 的 PLL 时钟驱动。PLL 是一种能够产生高频时钟信号的电路。PLL 可以将一个低频率的参考时钟信号乘以一个整数倍的频率因子,从而得到一个高频率的时钟信号。
类型 | 时钟 |
---|---|
Fixed rate clock | OSC24M |
OSC32K | |
RC1M | |
Fixed parent clock | CLK_DMA |
CLK_CE | |
CLK_USBD | |
CLK_USBH0-1 | |
CLK_USB_PHY0-1 | |
CLK_GMAC0-1 | |
CLK_SPI0-1 | |
CLK_SDMMC0-2 | |
CLK_SYSCON | |
CLK_RTC | |
CLK_I2S0-1 | |
CLK_ADDA | |
CLK_DE | |
CLK_GE | |
CLK_VE | |
CLK_WDOG | |
CLK_SID | |
CLK_GTC | |
CLK_GPIO | |
CLK_UART0-7 | |
CLK_I2C0-3 | |
CLK_CAN0-1 | |
CLK_PWM | |
CLK_ADCIM | |
CLK_GPADC | |
CLK_RTP | |
CLK_TSEN | |
CLK_CIR | |
CLK_RGB | |
CLK_LVDS | |
CLK_MIPIDSI | |
Multi parent clock | CLK_CPU |
CLK_AHB0 | |
CLK_APB0 | |
CLK_APB1 | |
CLK_AXI0 | |
CLK_OUT0 | |
CLK_OUT1 | |
CLK_OUT2 | |
CLK_OUT3 | |
PLL clock | CLK_PLL_INT0 |
CLK_PLL_INT1 | |
CLK_PLL_FRA0 | |
CLK_PLL_FRA1 | |
CLK_PLL_FRA2 | |
Disp clock | CLK_PIX |
CLK_SCLK |
关键流程设计
Clock 和 Reset 驱动初始化
- Clock 驱动初始化
通过 DECLARE 宏定义,CMU 的 clock 驱动会在__clock_of_table 段存放一个 id 类型的变量。在系统初始化内核时,调用 init 函数,在该函数中调用相应的时钟初始化函数。初始化流程如下:
- Reset 驱动初始化
通过 initcall 宏,将 reset 驱动存放到.initcall2.init 段中。在系统初始化内核时,调用 init 函数进行 reset controller 的初始化和注册。
数据结构设计
- fixed_parent_clk_cfg
struct fixed_parent_clk_cfg { //fixed parent clock 的配置结构体 u32 id; //fixed parent clock 的索引值,参考 3.2 节 CLK_xxx u16 type; u8 fact_mult; u8 fact_div; const char *name; //fixed parent clock 的名字 const char * const *parent_names; //父时钟的名字 int num_parents; //父时钟个数 u32 offset_reg; //时钟在 CMU 中的偏移地址 s8 bus_gate_bit; //总线使能位偏移 s8 mod_gate_bit; //模块使能位偏移 u8 div_bit; //分频系数偏移 u8 div_width; //分频系数所占位宽 struct clk_hw *(*func)(void __iomem *base, const struct fixed_parent_clk_cfg *cfg); //指向初始化和注册 parent 时钟的函数指针
- multi_parent_clk_cfg
struct multi_parent_clk_cfg { //multi parent clock 的配置结构体 u32 id; //multi parent clock 的索引值,参考 3.3 节 CLK_xxx const char *name; const char * const *parent_names; int num_parents; u32 offset_reg; s32 gate_bit; u8 mux_bit; //父时钟源选择位的 bit 偏移 u8 mux_width; //父时钟源选择位所占位宽 u8 div0_bit; //分频系数偏移 u8 div0_width; //分频系数所占位宽 struct clk_hw *(*func)(void __iomem *base, const struct multi_parent_clk_cfg *cfg); //指向初始化和注册 parent 时钟的函数指针 };
- pll_clk_cfg
struct pll_clk_cfg { //pll 时钟的配置结构体 u32 id; //pll 时钟的索引值,参考 3.4 节 CLK_xxx enum aic_pll_type type; //pll 时钟的类型,是整数分频还是小数分频 const char *name; const char * const *parent_names; int num_parents; u32 offset_int; //整数分频寄存器的偏移 u32 offset_fra; //小数分频寄存器的偏移 u32 offset_sdm; //展频寄存器的偏移 struct clk_hw *(*func)(void __iomem *base, const struct pll_clk_cfg *cfg); //指向初始化和注册 pll 时钟的函数指针 };
- disp_clk_cfg
struct disp_clk_cfg { //显示模块时钟配置的结构体 u32 id; //显示模块时钟的索引值,参考 3.5 节 CLK_xxx const char *name; const char * const *parent_names; int num_parents; u32 offset_reg; //显示模块时钟使能寄存器 s8 bus_gate_bit; //显示模块总线使能位偏移 s8 mod_gate_bit; //显示模块模块使能位偏移 u32 offset_div_reg; //显示模块分频寄存器偏移 u8 divn_bit; //分频系数 N 偏移 u8 divn_width; //分频系数 N 所占位宽 u8 divm_bit; //分频系数 M 偏移 u8 divm_width; //分频系数 M 所占位宽 u8 flag_bit; //分频系数 M 标志位 struct clk_hw *(*func)(void __iomem *base, const struct disp_clk_cfg *cfg); //指向初始化和注册显示模块时钟的函数指针 };
接口设计
函数原型 |
struct clk_hw *aic_clk_hw_fixed_parent(void __iomem *base, const struct fixed_parent_clk_cfg *cfg) |
---|---|
功能说明 |
初始化 clock,并对时钟进行注册。 |
参数定义 |
|
返回值 |
返回 struct clk_hw*类型的指针。 |
注意事项 |
- |
函数原型 |
struct clk_hw *aic_clk_hw_multi_parent(void __iomem *base, const struct multi_parent_clk_cfg *cfg) |
---|---|
功能说明 |
初始化 clock,并对时钟进行注册。 |
参数定义 |
|
返回值 |
返回 struct clk_hw*类型的指针。 |
注意事项 |
- |
函数原型 |
struct clk_hw *aic_clk_hw_pll(void __iomem *base, const struct pll_clk_cfg *cfg) |
---|---|
功能说明 |
初始化 clock,并对时钟进行注册。 |
参数定义 |
|
返回值 |
返回 struct clk_hw*类型的指针。 |
注意事项 |
- |
函数原型 |
struct clk_hw *aic_clk_hw_disp(void __iomem *base, const struct disp_clk_cfg *cfg) |
---|---|
功能说明 |
初始化 clock,并对时钟进行注册。 |
参数定义 |
|
返回值 |
返回 struct clk_hw*类型的指针。 |
注意事项 |
- |