Linux CCF框架简要分析和API调用
来源:互联网 发布:淘宝代购衣服专柜真假 编辑:程序博客网 时间:2024/05/19 16:20
转自http://blog.csdn.net/lidroid/article/details/50292125
1. 前言
从Linux3.10内核开始就正式的使用CCF框架了,在以前Clock部分,虽然也提供了相应的API根据名字去获取Clock,设置频率,获取父时钟,设置父时钟的函数,但是这些API都是由每个SoC单独实现,导致了代码的差异很大,于是就引入了一个新的通用的时钟框架来解决这个问题。由TI的工程师Mike Turquette提供了Common Clock Framewrok,让具体SoC实现clk_ops成员函数并通过clk_register、clk_register_clkdev注册时钟源以及源与设备对应关系,具体的clock驱动都统一迁移到drivers/clk目录。因此现在的时钟框架就采用CCF方式,使用CCF前提是内核配置了CONFIG_COMMON_CLK。
2.CCF框架简介
Common Clock Framewrok(CCF)主要就是来管理上面这些Clock相关的器件。并且提供相应的API给driver调用,屏蔽掉其中的硬件特性。
而且从上面这段话就可以大概猜测下,Linux内核支持多种平台(简单来说就是芯片),也就意味着最底层的操作,不同的平台的操作方式肯定不同,那么对于整个CCF框架大概可以猜测到的也分为三层:
实现Soc的底层操作,比如选择哪个时钟源,比如输出的频率等。
实现中间层,向上提供统一的操作接口,向下提供Soc底层操作的接口。
实现通用的上层操作接口,也就是driver调用的API。
以下是CCF的框架图:
3. 硬件时钟种类简介
3.1. 时钟的基本种类
1)提供基础时钟的时钟源,时钟振荡器(晶振)
2)用于倍频的锁相环(PLL)
3)用于多路选择的选择器(MUX)
4)用于分频的分频器(DIV)
5)用于时钟使能的门电路(GATE)
6)用于模块的时钟
对应上面的6类,咱们只需要了解前5类即可。为什么要讲上面这些呢?虽然每个SoC的时钟控制器寄存器的地址空间可能都不一样,但是时钟控制器的组成目前来说,基本都是这个样子的。那么CCF就可以把这些都抽象出来,定义不同的结构体,提供接口去分别实现上面的各个子组件。看起来是不是就简单多了。
事实上,从代码看来也是这样的,那么就来看下都定义了什么结构体?
3.2 时钟种类对应的结构体和函数
其中这些结构体都存放在linux-4.2.6\include\linux\clk-provider.h。顺便看下其对于的注册函数。额,为什么要有对应的注册函数?可以这样想下,咱们把一个完全的时钟域给拆了成一个一个的门、分频器、多路选择器、但是最终他们还是有依赖关系的。就像拼图一样,虽然买回来后拆了,但是拼好的时候得和谐或者完美,不然就搞笑了。废话不说,继续搬砖吧~
3.2.1 struct clk_gate
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3.2.2 struct clk_mux
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3.2.3 struct clk_hw
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
在上面讲到的不同的时钟类型,操作方式或者操作的地址也是不一样的,而这些操作都是底层的操作,在clk_hw结构体下面clk_init_data就提供了底层操作实现的接口,也就是说,不同种类的底层操作都可以通过设置clk_init_data的ops来实现不同种类的操作。
3.3 不同组件的注册和提供给用户的方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
上面的代码初始化完时钟名字、时钟父设备列表、时钟寄存器偏移地址等等,最终调用了clk_register()注册进去。那么来看下此函数做了什么?
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
从上面代码看来,注册过程中,把数据填充到clk_hw中的core成员进去,把时钟名字,父时钟等等到填充到这里,最终创建 __clk_create_clk把时钟放入哈希表中。其中API就是通过core来调用到对应Soc实现的底层操作。
好了,不说上面的,现在都说主要看气质,哪咱们主要看操作集合,init.ops = &clk_mux_ops;
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
同理,其他两个的注册也一样,这里就直接给出操作集合。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
因此,上面分析的看来,想要添加自己的时钟还是比较简单的,因为各种时钟的ops已经自带了。所以只需要:
1、创建时钟(一般包括gate mux div三个种类,如果是PLL时钟就另外咯)
2、初始化clk_hw中的struct clk_init_data
i.主要初始化时钟名字
ii.此时钟所在的寄存器
iii.设置此时钟相应的位置和位宽
3、注册gate/div/mux等
好,那么接下直接来看下为driver提供的API,我觉得嘛,看不懂里面的实现,至少得会用会抄,在谈深入比较好。
4.CCF提供的API
说得那么玄,其实不然把API一打开一看,还是一样的包装,还是熟悉的味道,只不过额外又加了几个包装,那么继续搬砖吧。
函数 功能
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
好了,那么在driver中就可以调用上面的函数去操作时钟了。看下例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
其中,clk_enable的调用过程:clk_enable(clk)—–>clk_core_enable(clk->core)—–>core->ops->enable(core->hw);
- Linux CCF框架简要分析和API调用
- Linux CCF框架简要分析和API调用
- linux系统调用简要分析
- HM框架简要分析
- Android源代码框架简要分析
- Executor框架的简要分析
- linux 通用时钟框架CCF
- linux 通用时钟框架CCF
- 【Java】Java集合框架源码和数据结构简要分析——Set和Map
- 从源码角度简要分析ActionBar框架
- 从源码角度简要分析ActionBar框架
- Android 的网络管理框架简要分析
- OkHttp 3.x框架简要分析
- Java NIO框架简要设计分析
- Replugin插件化框架简要分析
- 【Java】Java集合框架源码和数据结构简要分析——List
- 【Java】Java集合框架源码和数据结构简要分析——List
- Linux Shell函数调用简要介绍
- Spring mvc
- java设计模式之单例模式
- 未能从程序集“System.ServiceModel, Version=3.0.0.0..."中加载类型“System.ServiceModel.Activation.HttpModule”
- MYSQL常用操作
- Android定时发送短信功能实现
- Linux CCF框架简要分析和API调用
- iOS开发之Block详解
- P2P中NAT之间的打洞可能性
- scsi、cifs、nfs在存储上的区别
- Oracle字符串操作 、 Oracle数值操作 、 Oracle日期操作 、 空值操作
- Java中关键字continue、break和return的区别
- 策略模式(转)
- 安装Django后,执行django-admin.py无法创建工程的解决办法
- sChart.js:一个小型简单的图表库