通过clk驱动框架可以看出,clk主要分core和hardware两层,而core层的主要函数是clk_register,它是把clk注册到系统中,而hardware层的注册函数因种类而异,不过最终都会统一调用clk_register来注册,本文只拿gate来举例;另外本文介绍下操作clk的主要API的过程

1.clk_register

clk_register首先分配一个结构体clk,然后调用_clk_register来进行实际的注册

1.1_clk_register

static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)

这个函数主要根据hardware结构体clk_hw来对clk进行初始化:

clk->ops = hw->init->ops;
clk->hw = hw;
clk->flags = hw->init->flags;
clk->num_parents = hw->init->num_parents;for (i = 0; i < clk->num_parents; i++) {clk->parent_names[i] = kstrdup(hw->init->parent_names[i],GFP_KERNEL);
}

接着调用__clk_init来进行初始化

1.2__clk_init

int __clk_init(struct device *dev, struct clk *clk)

下面根据代码分步骤来介绍下初始化过程:

  • 检查各个clk字段是否符合要求
  • 如果clk有多个parent,那么分配一段内存保存多个parent,并寻找现存系统中适配的parent
  • 调用__clk_init_parent来找到parent,此步骤主要是用clk自己的ops->get_parent来寻找parent(上一步已经适配了parent,为什么还要多此一举,首先上一步有了条件是多个parent,另外上一步在适配parent的时候是利用的parent_names来做的,不能保证一定会寻找到)
  • 把clk加入系统链表:clk有parent,那么要加入clk->parent->children;如果clk没有parent,那么clk有标志CLK_IS_ROOT,就加入到clk_root_list,否则加入到clk_orphan_list
static HLIST_HEAD(clk_root_list);--------clk的parent链表
static HLIST_HEAD(clk_orphan_list);------clk的孤儿链表
  • 设置clk的rate:

    if (clk->ops->recalc_rate)clk->rate = clk->ops->recalc_rate(clk->hw,__clk_get_rate(clk->parent));
    else if (clk->parent)clk->rate = clk->parent->rate;
    elseclk->rate = 0;
    

2clk_register_HARDWARE

2.1注册函数

不同hardware的注册函数如下:
(include/linux/clk-provider.h)

struct clk *clk_register_fixed_rate(struct device *dev, const char *name,const char *parent_name, unsigned long flags,unsigned long fixed_rate);struct clk *clk_register_gate(struct device *dev, const char *name,const char *parent_name, unsigned long flags,void __iomem *reg, u8 bit_idx,u8 clk_gate_flags, spinlock_t *lock);struct clk *clk_register_divider(struct device *dev, const char *name,const char *parent_name, unsigned long flags,void __iomem *reg, u8 shift, u8 width,u8 clk_divider_flags, spinlock_t *lock);struct clk *clk_register_mux(struct device *dev, const char *name,const char **parent_names, u8 num_parents, unsigned long flags,void __iomem *reg, u8 shift, u8 width,u8 clk_mux_flags, spinlock_t *lock);struct clk *clk_register_fixed_factor(struct device *dev, const char *name,const char *parent_name, unsigned long flags,unsigned int mult, unsigned int div);struct clk *clk_register_composite(struct device *dev, const char *name,const char **parent_names, int num_parents,struct clk_hw *mux_hw, const struct clk_ops *mux_ops,struct clk_hw *rate_hw, const struct clk_ops *rate_ops,struct clk_hw *gate_hw, const struct clk_ops *gate_ops,unsigned long flags);

2.2clk_register_gate


struct clk *clk_register_gate(struct device *dev, const char *name,const char *parent_name, unsigned long flags,void __iomem *reg, u8 bit_idx,u8 clk_gate_flags, spinlock_t *lock)
{struct clk_gate *gate;struct clk *clk;struct clk_init_data init;if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {if (bit_idx > 16) {pr_err("gate bit exceeds LOWORD field\n");return ERR_PTR(-EINVAL);}}/* allocate the gate */gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);if (!gate) {pr_err("%s: could not allocate gated clk\n", __func__);return ERR_PTR(-ENOMEM);}init.name = name;init.ops = &clk_gate_ops;init.flags = flags | CLK_IS_BASIC;init.parent_names = (parent_name ? &parent_name: NULL);init.num_parents = (parent_name ? 1 : 0);/* struct clk_gate assignments */gate->reg = reg;gate->bit_idx = bit_idx;gate->flags = clk_gate_flags;gate->lock = lock;gate->hw.init = &init;clk = clk_register(dev, &gate->hw);if (IS_ERR(clk))kfree(gate);return clk;
}

从代码可以看出,不同的hardware注册函数,主要是根据其需要分别初始化不同的clk_hw,最终都要调用clk_register来进行注册

3几个clk-API的执行流程

clk的API有许多,具体参考include/linux/clk.h,下面介绍两个典型的:使能clk和设置clk-rate

3.1 clk-enable

int clk_enable(struct clk *clk)
{unsigned long flags;int ret;flags = clk_enable_lock();ret = __clk_enable(clk);clk_enable_unlock(flags);return ret;
}
static int __clk_enable(struct clk *clk)
{int ret = 0;if (!clk)return 0;if (WARN_ON(clk->prepare_count == 0))return -ESHUTDOWN;if (clk->enable_count == 0) {ret = __clk_enable(clk->parent);if (ret)return ret;if (clk->ops->enable) {ret = clk->ops->enable(clk->hw);--------最终调用ops->enable函数if (ret) {__clk_disable(clk->parent);return ret;}}}clk->enable_count++;return 0;
}

3.2 clk-set-rate

ref.

linux3.10

clk子系统 - 代码分析相关推荐

  1. linux i2c子系统代码分析3 ---操作函数i2c_add_adapter i2c_add_numbered_adapter介绍

    二.i2c子系统操作函数,i2c-core.c 1. kernel/driver/linux/i2c/i2c-core.c /**  * i2c_add_adapter - declare i2c a ...

  2. 【鸿蒙OS开发入门】18 - HDF驱动子系统:加速度计传感器 Driver层驱动代码分析

    [鸿蒙OS开发入门]18 - HDF驱动子系统:加速度计传感器 Driver层代码分析 一.如何添加速度计传感器驱动代码(代码.编译.配置) 1.驱动代码实现 2.驱动编译配置 2.1 linux 编 ...

  3. ARM generic timer驱动代码分析

     转自 蜗窝科技 http://www.wowotech.net/linux_kenrel/arm-generic-timer.html 一.前言 关注ARM平台上timer driver(clo ...

  4. Device Tree(三):代码分析

    2019独角兽企业重金招聘Python工程师标准>>> 一.前言 Device Tree总共有三篇,分别是: 1.为何要引入Device Tree,这个机制是用来解决什么问题的?(请 ...

  5. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  6. Device Tree(三):代码分析【转】

    转自:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html Device Tree(三):代码分析 作者:linuxer 发布于:201 ...

  7. 2018-2019-2 20165114《网络对抗技术》Exp4 恶意代码分析

    Exp4 恶意代码分析 目录 一.实验目标 (1)监控你自己系统的运行状态,看有没有可疑的程序在运行. (2)分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sys ...

  8. FPGA学习之路—应用程序—原码二位乘法器及Verilog代码分析

    FPGA学习之路--原码二位乘法器及Verilog代码分析 原理 原码乘法可以分为原码一位乘和原码二位乘,两者在实现规则上大同小异.原码一位乘每次判断乘数的最低位,对被乘数和部分积进行相应操作.而原码 ...

  9. 20155320《网络对抗》Exp4 恶意代码分析

    20155320<网络对抗>Exp4 恶意代码分析 [系统运行监控] 使用schtasks指令监控系统运行 首先在C盘目录下建立一个netstatlog.bat文件(由于是系统盘,所以从别 ...

最新文章

  1. [HEOI2017] 相逢是问候
  2. Java并发之公平锁
  3. iOS - appledoc 文档生成
  4. 乐Phone:还原联想的联想
  5. 软件研发工程师转行机器学习之路
  6. 【06】sass编译工具(弃)
  7. 字符串_字符串数组_字符_字符数组
  8. UnityShader RenderTypeQueue 渲染顺序
  9. python choice添加下拉框_自定义Django Form中choicefield下拉菜单选取数据库内容实例...
  10. 构建第一个Spring Boot2.0应用之集成dubbo上---环境搭建(九)
  11. servlet多重映射_【简答题】请简要概述什么是Servlet的多重映射,并列出Servlet多重映射的实现方式。...
  12. el表达式跟ognl表达式的区别(用法和页面取值)
  13. 适用于物联网数据共享的区块链节点存储优化方案
  14. 定时器 Cron表达式
  15. 26.【案例:敏感词汇过滤】
  16. 软工学者Ming Wen及其顶会论文解读
  17. 装黑苹果接显示器后设置分辨率
  18. C措辞教程第一章: C措辞概论 (5)
  19. python常用的颜色英文表达_python 中颜色的表示
  20. Android WebView最佳优化(WebView池)

热门文章

  1. 接口测试中的接口到底是什么?
  2. MapReduce系列之MapReduce的输出
  3. 电脑的所有浏览器打不开网页问题解决
  4. python thinker_Thinker
  5. python地形图渲染_地形渲染之彩色地形图(Painted Relief Map)
  6. hadoop命令无法创建目录
  7. python import seaborn as sns 显示中文问题
  8. C语言程序设计-关系运算符和关系表达式、逻辑运算符和逻辑表达式
  9. 使用云主机的5大好处?
  10. 计算机网络第七版3-2