LINUX kernel clock系统,基于内核4.4

转载需声明出处:https://blog.csdn.net/chenjiebing2016/article/details/83058816

内核把驱动分为三部分,分别为为框架实现层(与具体soc平台相关)、框架层(内核自身)、驱动层(调用框架提供的api)

今天,我们将建立在这个框架思想上来分析时钟系统使用过程

以rk3399上的rk808 pmic为例

为什么要选用这个?

rk808 pmic上有两个clock输出,其中一路提供给蓝牙模块,由于没有具体的soc datasheet,只能以这个来分析。具体流程框架都是一样的,只是涉及的具体平台的操作实现内容不一样。

由于是内核4.4,插讲device tree

这里只是再分析框架的同时需要我们要理解设备树的简单知识,设备树并不是很难,我们只是学习怎么使用设备树,不必深入分析

    wireless-bluetooth {
        compatible = "bluetooth-platdata";
        clocks = <&rk808 1>;
        clock-names = "ext_clock";

        //wifi-bt-power-toggle;
        uart_rts_gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; /* GPIO2_C3 */
        pinctrl-names = "default", "rts_gpio";
        pinctrl-0 = <&uart0_rts>;
        pinctrl-1 = <&uart0_gpios>;
        //BT,power_gpio  = <&gpio3 19 GPIO_ACTIVE_HIGH>; /* GPIOx_xx */
        BT,reset_gpio    = <&gpio0 9 GPIO_ACTIVE_HIGH>; /* GPIO0_B1 */
        BT,wake_gpio     = <&gpio2 26 GPIO_ACTIVE_HIGH>; /* GPIO2_D2 */
        BT,wake_host_irq = <&gpio0 4 GPIO_ACTIVE_HIGH>; /* GPIO0_A4 */
        status = "okay";
    };

我们只分析红色部分,其他部分大家可以上谷歌百度查阅资料,或者发邮件到我的个人邮箱咨询 jiebing2016@163.com

关于红色部分怎么在内核驱动里面使用

内核有一套完整的of开头api来解析,建议多看源码,加深对device tree的理解。

以下分析使用:

我们在设备驱动代码中仅使用以下两个api即打开了对应的时钟

data->ext_clk = devm_clk_get(dev, "ext_clock");
    if (IS_ERR(data->ext_clk)) {
        LOG("%s: clk_get failed!!!.\n", __func__);
    } else {
        clk_prepare_enable(data->ext_clk);
    }

我们解析来分析它的流程

"ext_clock"为设备树中 clock-names = "ext_clock";

继续追源码

dev_id为设备的名称,对应设备树节点的 wireless-bluetooth

con_id为“ext_clock”

我们继续分析__of_clk_get_by_name

of_property_match_string查找ext_clock是否在clock-names的属性中,我们从设备树中看出 clock-names的属性值为“ext_clock”

结果返回0,即index为0

index是什么意思?

它代表的是属性值的编号。

比如clock-names=“ext_clock”,"xxxx";

其中index 0为“ext_clock, index 1 为“xxxx”

继续分析__of_clk_get

这个api很重要,为什么说很重要,很多人在学习设备设备树的时候不知道

 clocks = <&rk808 1>;

这个尖括号里面代表的意思

我们一起分析,第一个参数是device_node,第二个参数是设备树中的clocks ,那#clock-cells是啥?

这个是另一节点里面的属性

 

为什么会扯到这个节点。这就是这个api的重要性,我简单解释下这个api的作用:

 clocks = <&rk808 1>;

&rk808引用的是rk808这个节点,如上图

其中#clock-cells是用来表示 clocks 这个属性参数的个数

#clock-cells=<1>;表示参数只有一个

参数值为1

那么解析出来的参数又存在哪里?

struct of_phandle_args clkspec;

struct of_phandle_args {
    struct device_node *np;   //引用到的节点
    int args_count;   //参数数量
    uint32_t args[MAX_PHANDLE_ARGS];参数
};

这个参数很重要,我们暂且记住,后面时钟用到了再说

__of_clk_get_from_provider(&clkspec, dev_id, con_id, true);

继续分析

遍历of_clk_providers链表

获得struct of_clk_provider *provider;

这结构体是用来干嘛的

重点,函数指针,获得clk结构体的函数,分析到现在,终于知道了clk是怎么来的,那么,这个函数指针又是在哪被赋值的呢?

既然有遍历,就有add链表。

我们追到了这个api,这个非常关键,它将由具体平台的实现框架进行调用。

这个api即为刚才那个函数指针

我们注意到了idx,这个就是我们提到的参数

struct clk_onecell_data {
    struct clk **clks;
    unsigned int clk_num;
};

最后返回一个clk_data->clks[idx];,这代表是什么意思?

从函数看出它应该是一个存放clk指针的数组,取参数对应的clk

函数指针通过一下api传入

注意:回调函数由内核框架提供,固定。所以,这个of_clk_add_provider的最后一个参数void*data只能为struct clk_onecell_data 类型

clk设备注册流程:

 devm_clk_register

              clk_register

                              core->ops = hw->init->ops;  //时钟操作函数赋值
                               hw->core = core;

                               clk_hw_create_clk

 

简单说下:

创建clk,并对其中成员进行赋值

其中的core里面的    const struct clk_ops    *ops;即为时钟操作函数

讲了这里,基本结束

总结框架:

devm_clk_register返回一个时钟指针

struct clk_onecell_data {
    struct clk **clks;
    unsigned int clk_num;
};
返回的clk指针存放在这个结构体,设备树的参数代表取得是哪一个clk

devm_clk_get获得对应的clk,clk_prepare_enable调用对应的硬件操作函数,

具体的代码,大家可以结合自己的平台分析,框架不变。

 

接下来将发布:linux audio驱动框架,详细分析。敬请关注!

 

 

 

 

 

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Linux默认内核是由Linus Torvalds开发的Linux内核。要进行内核配置,可以使用make menuconfig或make config命令进行交互式配置,也可以使用make defconfig命令使用默认配置。以下是更详细的步骤: 1. 下载Linux内核源代码,并解压缩。 2. 进入内核源代码目录,运行make menuconfig命令,进入交互式配置界面。 3. 在界面中,可以选择不同的内核配置选项。例如,选择“General setup”选项,可以配置内核的基本设置,如内核版本号、支持的处理器架构、系统时间等。 4. 选择“Processor type and features”选项,可以配置内核的处理器类型和特性,如是否支持超线程、是否支持SSE指令集等。 5. 选择“Networking support”选项,可以配置内核对网络的支持,如是否启用IPv6、是否支持网络设备驱动等。 6. 选择“File systems”选项,可以配置内核对文件系统的支持,如是否支持ext4、NTFS等。 7. 配置完成后,可以保存配置并退出。此时,内核配置文件会被保存为.config文件。 8. 运行make命令,编译内核。编译完成后,会生成一个内核镜像文件。 9. 将内核镜像文件拷贝到/boot目录下。 10. 配置引导程序,使其启动新的内核。具体步骤因引导程序而异,这里不再赘述。 以上是Linux内核配置的基本步骤。需要注意的是,配置内核时需要根据实际需求进行选择,不要选择过多或不必要的功能,以免浪费系统资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值