模块架构
clock
按照 CCF 框架,时钟分为六类:
-
fixed rate clock
-
gate clock
-
divider clock
-
mux clock
-
fixed clock
-
composite clock
时钟树中的每一个 divider、gate、mux 等都需要定义一个 hw 结构体。CMU 模块中有非常多的 gate 和 divider,所以为了代码的简洁性和易用性,CMU 的驱动并未严格按照 CCF 框架编写。CMU 驱动模块将时钟分为五种类型:
-
fixed rate clock
-
fixed parent module clock
-
multiple parent module clock
-
display module clock
-
pll clock
fixed rate clock 包含 M、RC1M、OSC32K 三个时钟,这种时钟频率固定,不能调节频率,不能打开或关闭(即底层 ops 无 enable 和 disable 函数)。
fixed parent module clock 实现只有一个父时钟源的时钟驱动,主要是各个外设模块的时钟,该类型时钟可以改变时钟频率,打开或关闭时钟,获取父时钟源参数,但不能设置或改变父时钟源。
multiple parent module clock 实现有多个父时钟源的时钟驱动,主要是各种总线时钟,该类型的时钟最为复杂,可以打开或关闭时钟,调节频率,获取或改变父时钟源。
display module clock 实现了几个与显示模块相关的时钟驱动,由于显示模块除了自身的模块时钟外,还有一个像素时钟,相应的底层寄存器的设计也不同,所以将显示相关的几个时钟重新设计了底层驱动。
pll clock 实现了 CMU 的 pll 时钟驱动。
在上述的几种分类中,每中分类都自定义了一个该类型的结构体,基于该结构体实现各种时钟操作。在 module 的结构体中,定义了模块的 gate 和 gate,以及该类型时钟的分频系数,相当于综合了 CCF 框架中的 gate 和 divider。multiple parent module 的结构体中定义了 gate,mux 以及分频系数,相当于综合了 CCF 框架中的 gate,divider 和 mux。几种类型的时钟支持的 API 接口如下:
类型 | fixed rate clock | fixed parent clock | multi parent clock | disp clock | pll clock |
---|---|---|---|---|---|
clk_prepare | √ | √ | √ | √ | |
clk_prepare_enable | |||||
clk_unprepare | √ | √ | √ | √ | |
clk_disable_unprepare | |||||
clk_set_rate | - | √ | √ | √ | √ |
clk_get_rate | √ | √ | √ | √ | √ |
clk_round_rate | - | √ | √ | √ | √ |
clk_set_parent | - | - | √ | - | - |
clk_get_parent | - | - | √ | - | - |
recalc_rate | √ | √ | √ | √ | √ |
时钟树框图
类型 | 时钟 |
---|---|
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_TWI0-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 |
reset
-
reset_controller_register
-
reset_controller_unregister
struct reset_controller_dev { const struct reset_control_ops *ops; struct module *owner; struct list_head list; struct list_head reset_control_head; struct device *dev; struct device_node *of_node; int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec); unsigned int nr_resets; };
驱动实现过程主要是对 ops 结构体中的函数指针进行填充,基本上是 reset 驱动的所有工作量。在 CMU 模块的 reset 驱动中,实现了对 assert 和 deassert 及 status 三个函数指针的填充。