10361|1

9

帖子

107

TA的资源

一粒金砂(初级)

楼主
 

Linux Common Clock Framework (2) [复制链接]

1.clock providerDTS
我们知道,DTSDevice Tree Source)是用来描述设备信息的,那系统的clock资源,是什么设备呢?换句话,用什么设备表示呢?这决定了clock providerDTS怎么写。
通常有两种方式:
方式1,将系统所有的clock,抽象为一个虚拟的设备,用一个DTS node表示。这个虚拟的设备称作clock controller,参考如下例子:
/* arch/arm/boot/dts/exynos4210.dtsi */
clock: clock-controller@0x10030000 {
compatible= "samsung,exynos4210-clock";
reg =<0x10030000 0x20000>;
#clock-cells = <1>;
};
clock,该clock设备的名称,clock consumer可以根据该名称引用clock
#clock-cells,该clockcells1表示该clock有多个输出,clock consumer需要通过ID值指定所要使用的clock(很好理解,系统那么多clock,被抽象为1个设备,因而需要额外的ID标识)。
方式2,每一个可输出clock的器件,如OscillatorPLLMux等等,都是一个设备,用一个DTS node表示。每一个器件,即是clock provider,也是clock consumer(根节点除外,如OSC),因为它需要接受clock输入,经过处理后,输出clock。参考如下例子(如果能拿到对应的datasheet会更容易理解):
/*arch/arm/boot/dts/sun4i-a10.dtsi */
clocks {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;
    /*This is a dummy clock, to be used as placeholder on
     * other mux clocks when a specific parentclock is not
     * yet implemented. It should be droppedwhen the driver
     * is complete. */
    dummy: dummy {
        #clock-cells = <0>;
        compatible = "fixed-clock";
        clock-frequency = <0>;
    };
    osc24M: osc24M@01c20050 {
          #clock-cells = <0>;
          compatible = "allwinner,sun4i-osc-clk";
    reg = <0x01c20050 0x4>;
    clock-frequency = <24000000>;
   };
osc32k:osc32k {
    #clock-cells = <0>;
    compatible = "fixed-clock";
    clock-frequency = <32768>;
   };
  pll1: pll1@01c20000 {
    #clock-cells = <0>;
    compatible = "allwinner,sun4i-pll1-clk";
    reg = <0x01c20000 0x4>;
    clocks= <&osc24M>;
     };
    /*dummy is 200M */
    cpu: cpu@01c20054 {
        #clock-cells = <0>;
        compatible = "allwinner,sun4i-cpu-clk";
        reg = <0x01c20054 0x4>;
        clocks = <&osc32k>,<&osc24M>, <&pll1>, <&dummy>;
    };
   axi: axi@01c20054 {
        #clock-cells = <0>;
        compatible = "allwinner,sun4i-axi-clk";
        reg = <0x01c20054 0x4>;
        clocks = <&cpu>;
    };
    axi_gates: axi_gates@01c2005c {
        #clock-cells = <1>;
        compatible = "allwinner,sun4i-axi-gates-clk";
        reg = <0x01c2005c 0x4>;
        clocks = <&axi>;
        clock-output-names = "axi_dram";
    };
   ahb: ahb@01c20054 {
        #clock-cells = <0>;
        compatible = "allwinner,sun4i-ahb-clk";
        reg = <0x01c20054 0x4>;
        clocks = <&axi>;
    };
   ahb_gates: ahb_gates@01c20060 {
        #clock-cells = <1>;
        compatible = "allwinner,sun4i-ahb-gates-clk";
        reg = <0x01c20060 0x8>;
        clocks = <&ahb>;
        clock-output-names = "ahb_usb0", "ahb_ehci0",
            "ahb_ohci0", "ahb_ehci1", "ahb_ohci1", "ahb_ss",
            "ahb_dma", "ahb_bist", "ahb_mmc0", "ahb_mmc1",
            "ahb_mmc2", "ahb_mmc3", "ahb_ms", "ahb_nand",
            "ahb_sdram", "ahb_ace",    "ahb_emac", "ahb_ts",
            "ahb_spi0", "ahb_spi1", "ahb_spi2", "ahb_spi3",
            "ahb_pata", "ahb_sata", "ahb_gps", "ahb_ve",
            "ahb_tvd", "ahb_tve0", "ahb_tve1", "ahb_lcd0",
            "ahb_lcd1", "ahb_csi0", "ahb_csi1", "ahb_hdmi",
            "ahb_de_be0", "ahb_de_be1", "ahb_de_fe0",
            "ahb_de_fe1", "ahb_mp", "ahb_mali400";
    };
};
osc24Mosc32k是两个rootclock,因此只做clockprovider功能。它们的cells均为0,因为直接使用名字即可引用。另外,增加了“clock-frequency”自定义关键字,这样在板子使用的OSC频率改变时,如变为12M,不需要重新编译代码,只需更改DTS的频率即可(这不正是DeviceTree的核心思想吗!)。话说回来了,osc24M的命名不是很好,如果频率改变,名称也得改吧,clockconsumer的引用也得改吧;
pll1即是clockprovidercell0,直接用名字引用),也是clockconsumerclocks关键字,指定输入clock“osc24M”);
再看一个复杂一点的,ahb_gates,它是clockprovidsrcell1),通过clock-output-names关键字,描述所有的输出时钟。同时它也是clockconsumer(由clocks关键字可知输入clock“ahb”)。需要注意的是,clock-output-names关键字只为了方便clockprovider编程方便(后面会讲),clockconsumer不能使用(或者可理解为不可见);


2.clock consumerDTS
例子1(对应方式1):
   /*arch/arm/boot/dts/exynos4210.dtsi */
   mct@10050000 {
           compatible = "samsung,exynos4210-mct";
           ...
           clocks = <&clock3>, <&clock 344>;
           clock-names = "fin_pll", "mct";
           ...
   };
clocks,指明该设备的clock列表,clk_get时,会以它为关键字,去device_node中搜索,以得到对应的structclk指针;
clocks需要指明的信息,由clockprovider“#clock-cells”规定:为0时,只需要提供一个clockprovider name(称作phandle);为1时,表示phandle有多个输出,则需要额外提供一个ID,指明具体需要使用那个输出。这个例子直接用立即数表示,更好的做法是,将系统所有clockID,定义在一个头文件中,而DTS可以包含这个头文件,如“clocks= <&clock CLK_SPI0>”
clock-names,为clocks指定的那些clock分配一些易于使用的名字,driver可以直接以名字为参数,getclock的句柄(具体可参考Linuxcommon clock framework(1)clk_get相关的接口描述)。
例子2,如果clockprovider“#clock-cells”0,可直接引用该clockprovider的名字,具体可参考方式2
例子3,方式2有一个clockprovider的名字为apb0_gates,它的“#clock-cells”1,并通过clock-output-names指定了所有的输出clock,那么,clockconsumer怎么引用呢?如下(2.1中的方式2,来自同一个DTS文件):
  /*arch/arm/boot/dts/sun4i-a10.dtsi */
  soc@01c20000 {
          compatible = "simple-bus";
          ...
  
          pio: pinctrl@01c20800 {
                  compatible = "allwinner,sun4i-a10-pinctrl";
                  reg = <0x01c208000x400>;
                  clocks =<&apb0_gates 5>;
                  ...
          }
  }
和例子1一样,指定phandle“aph0_gates”ID5
3. 使用clock framework编写clock驱动的步骤
编写clockdriver的步骤大概如下:
1)分析硬件的clocktree,按照上面所描述的分类,讲这些clock分类。
2)将clocktreeDTS中描述出来,需要注意以下几2点:
a)对于fixedrate clocks.compatible固定填充"fixed-clock",并提供"clock-frequency""clock-output-names"关键字。之后不需要再driver中做任何处理,clockframework core会帮我们搞定一切。
b)同样,对于fixedfactor clock.compatible"fixed-factor-clock",并提供"clock-div""clock-mult""clock-output-names"关键字。clockframework core会帮我们搞定一切。
切记,尽量利用kernel已有资源,不要多写一行代码,简洁的就是美的!
3)对于不能由clockframework core处理的clock,需要在driver中使用structof_device_id进行匹配,并在初始化时,调用OF模块,查找所有的DTS匹配项,并执行合适的regitser接口,注册clock
4)注册clock的同时,将返回的structclk指针,保存在一个数组中,并调用of_clk_add_provider接口,告知clockframework core
5)最后,也是最重要的一点,多看kernel源代码,多模仿,多抄几遍,什么都熟悉了!

最新回复

谢谢分享   详情 回复 发表于 2021-3-26 15:25
点赞 关注

回复
举报

661

帖子

0

TA的资源

纯净的硅(初级)

沙发
 

谢谢分享

 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表