CPM 时钟电源复位接口

模块功能介绍

CPM模块用于管理时钟和电源。包括:时钟控制,pll控制,电源控制,复位控制。

CPM驱动主要负责系统和模块的时钟电源管理,包括倍频,分频,时钟开关, 时钟源选择。

驱动位置

驱动源码所在位置:

module_drivers/drivers/clk/ingenic-v2

├── clk-bus.c
├── clk-bus.h
├── clk.c
├── clk-div.c
├── clk-div.h
├── clk.h
├── clk-m300.c
├── clk-pll.c(kernel4.4.94没有该文件)
├── clk-pll.h
├── clk-pll-v1.c
├── clk-pll-v1.h
├── clk-pll-v2.c
├── clk-pll-v2.h
├── clk-x1600.c
├── clk-x2000.c
├── clk-x2500.c
├── Kconfig
├── Makefile
├── power-gate.c
└── power-gate.h

设备树配置

设备树所在位置:

kernel内核(version <= 5.10)dts文件路径:

module_driver/dts-stage/x2000/x2000.dtsi

kernel内核(version > 5.10)dts文件路径:

module_driver/dts/x2000/x2000.dtsi

CPM控制器描述:

clock: clock-controller@0x10000000 {

 compatible = "ingenic,x2000-clocks";

 reg = <0x10000000 0x100>;

 clocks = <&extclk>, <&rtcclk>;

 clock-names = "ext", "rtc_ext";

 #clock-cells = <1>;

 little-endian;

};

extclk: extclk {

 compatible = "ingenic,fixed-clock";

 clock-output-names ="ext";

 #clock-cells = <0>;

 clock-frequency = <24000000>;

};

rtcclk: rtcclk {

 compatible = "ingenic,fixed-clock";

 clock-output-names ="rtc_ext";

 #clock-cells = <0>;

 clock-frequency = <32768>;

};

设备树默认配置

设备树默认编译会产生clock,extclk,rtcclk设备,配置extclk频率为24Mhz:

extclk: extclk {

 clock-frequency = <24000000>;

};

设备树自定义配置

内核编译配置

内核默认编译配置

使用cpm驱动内核不需要添加特殊配置,只依赖soc的配置选项CONFIG_SOC_X2000,相关代码在:module_drivers/drivers/clk/ingenic-v2/

内核自定义编译配置

设备节点生成

1. 生成的设备节点在

/sys/devices/platform/apb/10000000.clock-controller

2. 挂载debugfs到/mnt,/mnt/clk下面的节点可以查看各个时钟的频率和状态

  1.  cat clk_summary可以查看所以时钟的父子关系,使能状态,频率等:

    img_01.png

2. /mnt/clk下,每个文件夹代表一个时钟,其中mux_xxx控制时钟源选择,div_xxx控制时钟分频, gate_xxx控制时钟的开关。pd_mem_xxx控制每个模块memory的电源开关状态。power_xxx控制模块的电源开关状态。

img_02.png

3. 进入到某一个时钟的文件夹内,cat clk_rate可以查看时钟频率

img_03.png

应用程序使用说明

时钟的使用

在SDK的module_drivers/drivers/clk/ingenic-v2路径下已经定义好了时钟的信息,在内核启动后,会将时钟信息以树的形式进行关联,用户在使用时可以通过以下方式(以cim为例)。

在module_drivers/dts-stage/x2000/x2000.dtsi或module_drivers/dts/x2000/x2000.dtsi中cim节点的描述为:

cim: cim@0x13060000 {

 compatible = "ingenic,x2000-cim";

 reg = <0x13060000 0x10000>;

 interrupt-parent = <&core_intc>;

 interrupts = <IRQ_CIM>;

 clocks = <&clock CLK_DIV_CIM>, <&clock CLK_GATE_CIM>, <&clock CLK_GATE_MIPI_CSI>, <&clock CLK_GATE_CIM_MCLK>;

 clock-names = "div_cim", "gate_cim", "gate_mipi", "gate_cim_mclk";

 status = "disable";

 };

其中“clocks”和“clock-name”为内核关键字,用于获取时钟信息使用。

cim的probe函数会获取cim的时钟信息,用于控制cim设备时钟的开关。

/*get cim clk*/

pcdev->clk = of_clk_get(pdev->dev.of_node, 1);

if (pcdev->clk == NULL) {

 err = PTR_ERR(pcdev->clk);

 dev_err(&pdev->dev, "%s:can't get clk %s\n", \__func__, "cim");

 goto err_clk_get_cim;

}

如需修改cim的设备时钟频率需进行以下操作:

1. 获取div_cim的时钟信息

clk = clk_get(dev, “div_cim”)

2. 设置cim频率为24MHz(需要先关闭cim的gate时钟)

clk_set_rate(clk, 24000000);