工作中接触到的clock代码的学习和总结。clock子系统。阅读了工作中的代码,参考了http://www.wowotech.net/tag/clock 里的一系列文章。

clock设备,包括root clock,如外部晶振;PLL,倍频; divider, 分频; gate , 只有开和关两种,还有mux,从多个上级clock输入中选择其中一种。

工作代码,clock设备没有放在dts中,只是把两个clock的基地址放在了dts里,clock的配置信息以结构体数组的table形式,放在了源代码中。

在项目自己的clk.c文件中,
有一个static struct clk **clk_table; 
clock系统初始化时
clk_data.clks = clk_table;
clk_data.clk_num = nr_clks;
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
会把这个clk_table注册为clock provider
每初始化一个clock,会把这个clock加入到clk_table中:
void XXX_clk_add_lookup(struct clk *clk, unsigned int id)
{
if (clk_table && id)
clk_table[id] = clk;
}

clock初始化,包括了 fixed root clock, pll, mux, divider, gate 的初始化,每种clock基本上是一张表,表中的每一项就是一个clock的配置信息。比如fixed root clock的表中:
FRATE(CLK_XTAL, "xtal", NULL, CLK_IS_ROOT, 24000000),
FRATE(0, "32Khz", NULL, CLK_IS_ROOT, 32000),
FRATE(CLK_81, "clk81", NULL, CLK_IS_ROOT, 166666666),
FRATE(CLK_FIXED_PLL, "fixed_pll", NULL, CLK_IS_ROOT, 2000000000),
FRATE(CLK_FPLL_DIV2, "fclk_div2", NULL, CLK_IS_ROOT, 1000000000),
FRATE(CLK_FPLL_DIV3, "fclk_div3", NULL, CLK_IS_ROOT,  666666666),
FRATE(CLK_FPLL_DIV4, "fclk_div4", NULL, CLK_IS_ROOT,  500000000),
FRATE(CLK_FPLL_DIV5, "fclk_div5", NULL, CLK_IS_ROOT,  400000000),
FRATE(CLK_FPLL_DIV7, "fclk_div7", NULL, CLK_IS_ROOT,  285714285),
通过for循环,分别读取这些配置信息,每读取一项,就调用一次clk_register.
register 过程:
实现每个clock的ops回调函数,如recalc_rate, enable, disable,把回调函数赋值到ops域,填充初始化结构体,比如前面说的ops域, parent_names, num_parents, 然后调用clk_register,参数是struct clk_hw, 初始化需要用到的信息都放在这个结构体参数重。在clk_register中,又调用了int __clk_init(struct device *dev, struct clk *clk)
, 在__clk_init中,首先检查clk结构体中的各个域是否合法,如果已注册的clock中有待注册的clock的parent, 则建立parent child关联,如果没有parent,并且是root,就加入到clk_root_list链表中,如果既没有parent,也不是root, 就加入到clk_orphan_list中。如果clock实现了clk->ops->recalc_rate这个回调函数,则调用这个函数计算clock rate,并且把rate保存在clk->rate中,如果没有实现clk->ops->recalc_rate,就以该clock的parent clock->rate作为该clock的clock->rate. 遍历clk_orphan_list,调用list中的clk的get_parent回调,确认待注册的clock是否为orphan clock的parent, 如果是,则调用__clk_parent,建立关系。完成clk_register之后。clk_table[id] = clk;把这个clock保存到项目的静态的数据表格中。调用ret = clk_register_clkdev(clk, list->name, NULL);用于之后获取clock。clk_register_clkdev已经过时了,我们的项目中还没有使用dts来配置clock,是使用的静态数组,所以还需要调用这个函数。

fix rate clock, pll, mux, gate, 等类型的clock,都会调用到clk_register. 不同的是,每种类型的clock的ops不一样,像mux,主要是选择parent, 有get parent, set parent的ops, gate类型的,有enable, disable. 还有的clock有计算clock rate和set clock rate的回调函数。

recalc_rate回调函数:看了一个给cpu提供clock的ops, 主要是读取相关的寄存器,根据寄存器数值,进行倍频,分频,计算得到clock频率。
set_rate: 对于给cpu提供clock的clock,
irq_flags = arch_local_irq_save();
preempt_disable();
/*CPU switch to xtal*/
cpu clock rate有一个clock rate表格,如果目标rate小于最小rate,就按最小rate那一项来设置,如果目标rate大于表格中的最大rate,就按最大rate来设置。
查找到待设置的rate属于表格中的哪一项,按照表格中的配置项,配置pll,配置寄存器。
  /*cpu switch to sys pll*/
preempt_enable();
arch_local_irq_restore(irq_flags);
切换cpu频率之后,需要对LPJ loop_per_jiffiy 校准,用于udelay延时。

clock子系统的总结相关推荐

  1. Linux clock子系统【3】-i2c控制器打开时钟的流程分析(devm_clk_get)(consumer侧)

    文章目录 前言 一.硬件流程图 二.晶振设备树描述 三. I2CX时钟设备树描述 四.驱动中获得/使能时钟 4.1 流程源码分析 4.1.1 devm_clk_get(struct device *d ...

  2. Linux clock子系统【1】- 对clock时钟框架见解

    系列文章目录 Linux clock子系统[1]- 对clock时钟框架见解 Linux clock子系统[2]- 一文搞懂 | Linux 时钟子系统 Linux clock子系统[3]-i2c控制 ...

  3. Exynos4412的Linux5.4.174时钟驱动开发(四)——clk API的调用方法

    系列文章目录 Exynos4412的Linux时钟驱动开发(一)--Exynos4412的时钟管理单元CMU Exynos4412的Linux时钟驱动开发(二)--时钟驱动的初始化(CLK_OF_DE ...

  4. MSP430F5529输出PWM

    msp430f5529产生4路PWM波,改变占空比从而改变电机(直流减速电机)的速度.驱动电机必然会用到驱动模块,接下来就介绍一下驱动模块--L298N L298N驱动 若要对直流电机进行PWM调速, ...

  5. 详解sd协议以及裸机和u-boot中的sd卡驱动(2)

    3. sd卡驱动 3.1 引入 经过第2章我们知道,要想实现读写sd卡,需要按照sd协议规定的基本传输单位(命令.响应.数据)以及流程(初始化.读.写),向sd卡发送信号或者从sd卡接收信号. 为了简 ...

  6. Linux时间子系统之(五):POSIX Clock

    专题文档汇总目录 Notes: 本章主要介绍了若干种类的静态时钟,这些时钟都可以通过k_clock表示,注册到posix_clocks中.这些都是静态时钟,可以分为三大类:各种REALTIME时钟.带 ...

  7. Linux时间子系统之时钟源层(Clock Source)

    所谓时钟源设备,Linux将其抽象为一个可以记录时间流逝的设备,其值随着时间的流逝递增.将前一次读取的值和当前的值做比较就知道过去了多长的时间.但是它不一定是记录当前具体时间的设备,它只记录过去了多少 ...

  8. linux下编写时钟代码,Linux时间子系统之一:clock source(时钟源)【转】(示例代码)...

    clock source用于为linux内核提供一个时间基线,如果你用linux的date命令获取当前时间,内核会读取当前的clock source,转换并返回合适的时间单位给用户空间.在硬件层,它通 ...

  9. Linux时间子系统之一:clock source(时钟源)【转】

    本文转载自:http://blog.csdn.net/droidphone/article/details/7975694 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] cl ...

最新文章

  1. c#中结构与类的区别
  2. Android开发--图形图像与动画(五)--详解LayoutAnimationController
  3. 阿里云查看mysql版本_查看mysql版本的四种方法及常用命令
  4. redis中的string
  5. Day4-Springmvc表单数据
  6. 块语法Block在MVC思维的妙用之多重M层代理传值
  7. GDI+:自定义控件时如何使用Region来输出特定区域
  8. 子元素的margin-top会影响父元素
  9. 2014-7-29-阿里电面-第一轮
  10. Openstak(M版)控制节点安装
  11. xshell 5连接NAT模式的虚拟机
  12. asp毕业设计——基于asp+access的网上音乐网站设计与实现(毕业论文+程序源码)——网上音乐网站
  13. 20220103_数据库过程:异常业务量情况通报
  14. Java全系列教程:『Java学习指南』
  15. 区块链入门(一)------ 区块链简介(持续更新)
  16. 佳能Canon imageCLASS MF725Cdn 一体机驱动
  17. java小游戏_Java开发小游戏,30分钟教会你
  18. 修复YYC松鼠短视频系统搜索功能无法使用问题
  19. 编译原理-LL(1)语法分析器
  20. Go语言编程设计学习Day1:helloworld 变量 常量

热门文章

  1. 人工神经网络有哪些模型,神经网络属于什么模型
  2. TTS 最全中文正则化代码:英文处理、数字处理、韵律预测、汉字转拼音
  3. CSS中表格介绍,表格相关的样式以及长表格的使用
  4. 粉笔公考——方法精讲——判断推理
  5. NTKO OFFICE应用实例
  6. 字符型变量与整型变量的比较
  7. 推免复习之数据结构与算法 佛洛依德算法
  8. 非常全的各大IT公司面试题集
  9. Riber 的两项研究 MBE 订单
  10. Linux安装python3.8时报错error: no acceptable C compiler found in $PATH