代码编织梦想

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

前言

Linux Clock的框架图:

088b9f183e6d2734d33439d0787e1301.png

以上的框架图就能说明整个clock子系统的运作情况,从上往下看,clock consumer – clock core – clock provider,同时通过DTS来配置串接。大多数Linux子系统中都呈现这种分层式架构。

clock consumer :向其它driver提供操作clocks的通用API。

clock core:实现clock控制的通用逻辑,这部分和硬件无关。

clock provider:将和硬件相关的clock控制逻辑封装成操作函数集,交由底层的platform开发者实现,由通用逻辑调用。

硬件相关

那么板子上clock相关模块到底是如何分布和规划的?

e3346b36346a1bc099b33d3359986a49.png

上图从左往右看,最开始的源头产生:Oscillator –> 中间可能有倍频PLL、分频Divider、多路选择Mux、开关Gate –> clock使用的硬件模块。

也就是说,软件层面的架构 与 硬件层面的架构有一定程度的吻合。比如软件需要提供:1.Enable/Disable Clk;2. Set clk rate; 3. 选择clock的parent。

软件架构

主要是如何体现clock consumer clock core(CCF) clock provider。两个层面问题,一是clock provider是如何注册进CCF的,二是clock consumer如何从CCF通过相应API获取对应的Clock控制。

1.Clock provider注册进CCF

以Allwinner H5 Linux3.10为例,初始化的起点从start_kernel() 进入板级DT_MACHINE_START,如下:

linux-3.10archarmmach-sunxiSun50i.c1

2

3

4

5(SUNXI_DT, CONFIG_SUNXI_SOC_NAME)

.map_io= sunxi_map_io,

.init_time= sunxi_timer_init,

.dt_compat= sunxi_board_dt_compat,

MACHINE_END

从sunxi_timer_init – > of_clk_init –> __clk_of_table中所有需要注册的各种类型clock – > linux-3.10driversclksunxiclk-sun50iw2.c 中CLK_OF_DECLARE定义的初始化函数。

以上有两个问题阐释下,一是__clk_of_table从何而来,二是具体初始化哪些clock类型。

__clk_of_table是从所有CLK_OF_DECLARE定义而来,而初始化哪些clock则是由CLK_OF_DECLARE中的定义与Clock Provider DTS中的定义匹配而来,举个Fixed Clock的例子:

clk-sun50iw2.c中定义CLK_OF_DECLARE(sunxi_fixed_clk, "allwinner,fixed-clock",of_sunxi_fixed_clk_setup); ,而DTS(sun50iw1p1-clk.dtsi)中的定义:1

2

3

4

5

6

7

8

9

10

11

12

13

14clk_losc: losc {

#clock-cells = <0>;

compatible = "allwinner,fixed-clock";

clock-frequency= <32768>;

clock-output-names= "losc";

};

clk_hosc: hosc {

#clock-cells = <0>;

compatible = "allwinner,fixed-clock";

clock-frequency= <24000000>;

clock-output-names= "hosc";

};

从上面可以看到是通过allwinner,fixed-clock字段来匹配的,匹配之后最终通过clk_register/of_clk_add_provider添加到CCF中以供Clock Consumer使用。这只是其中一种clock类型,那么还有哪些类型呢?

根据clock的特点,clock framework将clock分为fixed rate、gate、devider、mux、fixed factor、composite六类,每一类clock都有相似的功能、相似的控制方式,因而可以使用相同的逻辑,统一处理,这充分体现了面向对象的思想。fixed rate clock:具有固定的频率,不能开关、不能调整频率、不能选择parent、不需要提供任何的clk_ops回调函数,是最简单的一类clock。

gate clock:只可开关,会提供.enable/.disable回调。

divider clock:可以设置分频值,因而会提供.recalc_rate/.set_rate/.round_rate回调。

mux clock:可以选择多个parent,因为会实现.get_parent/.set_parent/.recalc_rate回调。

fixed factor clock:具有固定的factor(即multiplier和divider),clock的频率是由parent clock的频率,乘以mul,除以div,多用于一些具有固定分频系数的clock。由于parent clock的频率可以改变,因而fix factor clock也可该改变频率,因此也会提供.recalc_rate/.set_rate/.round_rate等回调。

composite clock:顾名思义,就是mux、divider、gate等clock的组合。

2.Clock Consumer如何使用Clock

以Emmc模块为例,首先需要在DTS中EMMC相关部分配置,指明需要消费哪些Clock Provider中提供clock类型:1

2

3

4

5

6

7compatible = "allwinner,sun50i-sdmmc2";

~~~~~~

clocks = ,,,,;

clock-names = "osc24m","pll_periph","mmc","ahb","rst";

~~~~~~

};

如以上的clk_sdmmc2_mod、clk_sdmmc2_bus、clk_sdmmc2_rst就有在sun50iw1p1-clk.dtsi中定义。然后在emmc驱动相关代码中通过CCF提供的API取得相关clk并配置,如下(sunxi-mmc.c):1

2

3

4

5

6

7

8

9

10

11

12host->clk_mmc = devm_clk_get(&pdev->dev, "mmc"); -- 取得clk

if (IS_ERR(host->clk_mmc)) {

dev_err(&pdev->dev, "Could not get mmc clockn");

ret = PTR_ERR(host->clk_mmc);

goto error_disable_regulator;

}

ret = clk_prepare_enable(host->clk_mmc); -- 使能clk

if (ret) {

dev_err(&pdev->dev, "Enable mmc clk err %dn", ret);

goto error_disable_clk_ahb;

}

除了devm_clk_get/clk_prepare_enable外还有一些clock操作的API:clk_enable/clk_disable,启动/停止clock。不会睡眠。

clk_prepare/clk_unprepare,启动clock前的准备工作/停止clock后的善后工作。可能会睡眠。

clk_get_rate/clk_set_rate/clk_round_rate,clock频率的获取和设置,其中clk_set_rate可能会不成功(例如没有对应的分频比),此时会返回错误。如果要确保设置成功,则需要先调用clk_round_rate接口,得到和需要设置的rate比较接近的那个值。

获取/选择clock的parent clock。

clk_prepare_enable,将clk_prepare和clk_enable组合起来,一起调用。clk_disable_unprepare,将clk_disable和clk_unprepare组合起来,一起调用。

更详细的解读可参考如下。

ref

linux common clock framework(1)-爱代码爱编程

原文地址 http://www.wowotech.net/linux_kenrel/clk_overview.html Linux common clock framework(1)_概述 作者:蜗蜗 发布于:2014-10-20 23:06 分类:Linux内核分析 1. 前言 common clock framework是用来管理系统clo

linux common clock framework(2)-爱代码爱编程

原文地址 http://www.wowotech.net/linux_kenrel/clock_provider.html Linux common clock framework(2)_clock provider 作者:蜗蜗 发布于:2014-10-23 23:49 分类:Linux内核分析 1. 前言 本文接上篇文章,从clock dri

全志h3平台clock简析-爱代码爱编程

1 概要 时钟管理模块是linux系统为统一管理各硬件的时钟而实现管理框架,负责所有模块的时钟调节和电源管理。 1.1 模块功能介绍 时钟管理模块主要负责处理各硬件模块的工作频率调节及电源切换管理。一个硬件模块要正常工作,必须先配置好硬件的工作频率、打开电源开关、总线访问开关等操作,时钟管理模块为设备驱动提供统一的操作接口,使驱动不用关心时钟硬件实现

linux clock-爱代码爱编程

linux kernel在3.4之后加入了CCF(common clock framework)来统一管理clock,对外提供了统一的接口供其它驱动模块调用,对内封装了clock驱动。linux的clock是基于provid

嵌入式linux驱动笔记(十四)------详解clock时钟(ccf)框架及clk_get函数_风筝丶的博客-爱代码爱编程

你好!这里是风筝的博客, 欢迎和我一起交流。 我在找资料的时候,发现网上大部分文章都是说: 在s3c244x_init_clocks函数里: void __init s3c244x_init_clocks(int x

clk子系统 - 驱动框架_鸭蛋西红柿的博客-爱代码爱编程_clk结构体

clk子系统负责为整个系统硬件提供时钟信号,这个要和linux的时钟系统区别开来;现在的ASoC上包含许多clk模块,比如晶振,pll,divider等,那么clk子系统就把这些模块抽象出来,并形成一个驱动框架,这样对

linux驱动开发09:【设备树】nanopi的led驱动_卡咖喱的博客-爱代码爱编程

介绍 这节通过在nanopi的设备树中添加LED子节点,来实现一个LED驱动。由于linux内核支持LED驱动框架并且有通用的LED驱动,因此这里只需按照驱动要求添加设备树节点就可以了,不用我们自己重写LED驱动。这一节先

Linux CommonClock Framework子系统分析之一 系统概述-爱代码爱编程

  本专栏主要介绍linux的ccf子系统,主要用于系统clock的管理等操作。本专栏我们大概分为如下几章进行学习: 一、CCF子系统概述   二、CCF子系统数据结构分析及关联说明   三、CCF子系统的clk注册与注销接口实现分析   四、虚拟的clk设备驱动实现

Linux CommonClock Framework分析之三 驱动开发流程说明-爱代码爱编程

         在上两篇文章中,我们简要介绍了CCF子系统内部的设计,并说明了CCF子系统内部数据结构的定义及关联。本篇文章主要介绍CCF子系统下驱动程序的开发,本章涉及如下三个方面的内容: 一、clk注册与注销接口说明   二、clk驱动开发流程   三、clk使用流程  

设备树与驱动的关系_Linux CommonClock Framework分析之三 驱动开发流程说明-爱代码爱编程

在上两篇文章中,我们简要介绍了CCF子系统内部的设计,并说明了CCF子系统内部数据结构的定义及关联。本篇文章主要介绍CCF子系统下驱动程序的开发,本章涉及如下三个方面的内容: 一、clk注册与注销接口说明 二、clk驱动开发流程 三、clk使用流程 四、依据clk provider用途封装的注册接口 一、clk注册与注销接口说明 clk