转载需声明出处: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驱动框架,详细分析。敬请关注!

LINUX kernel clock系统,基于内核4.4相关推荐

  1. Linux kernel pwn notes(内核漏洞利用学习)

    前言 对这段时间学习的 linux 内核中的一些简单的利用技术做一个记录,如有差错,请见谅. 相关的文件 https://gitee.com/hac425/kernel_ctf 相关引用已在文中进行了 ...

  2. Linux Kernel系列 - 黄牛X内核代码凝视

    Hanks.Wang - 专注于操作系统与移动安全研究.Linux-Kernel/SELinux/SEAndroid/TrustZone/Encription/MDM    Mail - byhank ...

  3. linux透明加密系统,基于Linux的透明加密系统的设计与实现

    摘要: 随着互联网时代的到来,人们用于接触事物的方式不仅仅局限于简单的通讯工具了,如:口语交流,书信传递等等,现在已经越来越多地通过手机,电脑,平板等电子设备进行信息的交流和信息的存储.但是在我们享受 ...

  4. linux点餐系统,基于Linux的智能点餐系统

    基于Linux的智能点餐系统 摘要:当今这个快节奏的社会,效率这个词被提升到了一个很重要的地位,不管工作上,还是生活上.饮食方面也是一个很重要的部分,尤其是在上班日,每个餐厅的人员都爆满,传统的现金付 ...

  5. 镜像安装linux选择内核版本,在CentOS和Ubuntu中安装Linux Kernel 4.13.10

    Linus Torvalds 在 10 月 17 日星期五正式发布了稳定版 Linux Kernel 4.13.10,这个最新版本发布了新功能,进行了诸多修复和问题改进.下面将向大家介绍在 CentO ...

  6. linux内核多大 4.17.8,Linux Kernel 4.17结束支持,请升级到Linux 4.18内核

    Linux Kernel 4.17最后一个更新是Linux Kernel 4.17.19内核,该系列内核版本将结束支持,它不会再得到新的更新,请用户把Linux内核升级到4.18版本,这样能避免安全漏 ...

  7. linux最新内核4.19,Linux Kernel 4.19内核为长期支持版本,有诸多新功能及改进

    Linux Kernel开发者与维护总负责人Greg Kroah-Hartman宣布Linux Kernel 4.19内核将是长期支持版本,即用户使用该内核可得到长期的补丁支持,包括修复重要的漏洞.目 ...

  8. linux 嵌入式 快照_基于Linux的嵌入式启动优化的研究

    基于Linux的嵌入式启动优化的研究 论文 开题分析 周报 启动 基于Linux嵌入式系统启动加速的研究 一. 所选课题的目的和意义 随着科学技术的蓬勃发展,计算机被更多的人使用,并与人类对额生活结合 ...

  9. Linux kernel中断子系统之(五):驱动申请中断API【转】

    转自:http://www.wowotech.net/linux_kenrel/request_threaded_irq.html 一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的 ...

最新文章

  1. 组合恒等式3 母函数与形式幂级数的运算
  2. 【Linux】普通用户修改 root 权限文件,没有权限;sudo: 没有终端存在,且未指定 askpass 程序
  3. @override报错_C++ 多态性:C++11:override 与 final(学习笔记:第8章 09)
  4. Addr、@运算符与Pointer类型
  5. Unity3D获取Andorid设备返回键,主页键等功能
  6. 什么是安斯库姆四重奏?为什么统计分析之前必须要作图?
  7. 记录一次es商品模糊查询
  8. Visual Assist X破解版安装(vs2010助手)
  9. HTML5期末大作业:仿华为手机商城网站设计——仿华为手机电子商城 (1页) HTML+CSS+JavaScript html网页制作期末大作业成品_网页设计期末作业
  10. 网游实时对战同步技术三篇
  11. MySQL源代码的海洋中游弋 初探MySQL之SQL执行过程 [转]
  12. 【Java】并发模式
  13. layui 怎么设置点击图片放大_layui图片如何放大
  14. 将favdb转换成html,360浏览器收藏夹使用小记
  15. ##MYfirstLog
  16. unbuntu下 sudo apt-get update 更新软件源列表
  17. Spark性能优化--如何解决数据倾斜
  18. BPM 工作流 activiti 资料总结
  19. mysql使用联结的好处_Mysql-联结
  20. 一段Python代码自动出20以内的加减算术题

热门文章

  1. this和super
  2. Lucene 2.2.0发布自带的HTMLParser的使用
  3. HTML 制作简单的导航栏
  4. 致同助力国企改革不断迈出实质性步伐
  5. 一个三流学校程序员的奋斗
  6. Image Projection Network: 3D to 2D ImageSegmentation in OCTA Images 论文阅读笔记
  7. 虚电路和数据报的区别以及应用
  8. 雷林鹏分享:Ruby 字符串(String)
  9. ts 的class和interface的区别
  10. dockerfile编写之恋爱初体验~~~