你需要知道的Linux 系统下外设时钟管理

嵌入式系统一般要求低功耗,出于这个原因,一般只把需要使用到的外设时钟源打开,其他不需要使用到的模块,则默认关闭它们。

LCD 模块,上电时候默认情况是关闭的,所以,要想使用 LCD 模块,配置它寄存器必须先开启它时钟。

如何知道,哪个模块时钟源是打开的?哪些模块时钟源是关闭的?不同的芯片时钟设置一定不相同的,所以实现代码是编写在和具体芯片相关的文件中:

Clock-exynos4.c (arch\arm\mach-exynos)

内核使用 struct clk 结构描述一个外设模块的时钟信息:

struct clk {
struct list_head list;
struct module *owner;
struct clk *parent;
const char *name;
const char *devname;//设备名,用来查找。
int id;
int usage;
unsigned long rate;
unsigned long ctrlbit;

struct clk_ops *ops;
int (*enable)(struct clk *, int enable);//指向模块时钟使能/禁止时钟的函数
struct clk_lookup lookup;
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
struct dentry *dent; /* For visible tree hierarchy */
#endif
};

一个已经移植好,可以运行的内核,它的外设时钟都已经在系统初期已经完成注册,实现文件就在

Clock-exynos4.c  arch\arm\Mach-exynos

关于 LCD 控制器(fimd0)模块的时钟定义:

把 exynos4_clk_fimd0 结构放入数组中:

void __init exynos4_register_clocks(void)
{
int ptr;

s3c24xx_register_clocks(exynos4_clks, ARRAY_SIZE(exynos4_clks));

for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
s3c_register_clksrc(exynos4_sysclks[ptr], 1);

for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
//注册时钟源,其中 sclk_fimd0 就是在这里注册的 ,在 exynos4_clksrcs 数组中定义
s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
//默认打开时钟的模块
s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));

s3c_register_clocks(exynos4_init_audss_clocks, ARRAY_SIZE(exynos4_init_audss_clocks));
s3c_disable_clocks(exynos4_init_audss_clocks, ARRAY_SIZE(exynos4_init_audss_clocks));

s3c24xx_register_clocks(exynos4_gate_clocks, ARRAY_SIZE(exynos4_gate_clocks));
//fyyy:注册设备时钟,其中 LCD 时钟就在这里注册,可以通过 clk_get 获得
s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
//fyyy:注册后禁止它,为了降低功耗
for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);//这里有禁止 lcd 相关的时钟 fimd0

s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
//默认关闭时钟的模块
s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
//可以查找的时钟 ,可以通过 clk_get 获得
Clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));

register_syscore_ops(&exynos4_clock_syscore_ops);
s3c24xx_register_clock(&dummy_apb_pclk);

s3c_pwmclk_init();
}

分析:

s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));

是注册了 fimd0 模块的时钟信息

//fyyy:注册后禁止它,为了降低功耗
for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++) {
s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);//这里有禁止 lcd 相关的时钟 fimd0
}

要使用这个模块,必须先开这个模块的时钟。

clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));

这一行是把可以通过设备名查找到的 clk 结构加到可查询的链表上。内核 struct clk_lookup 结构来表示一个可以被查找到的时钟结构。

Clkdev.h linux-3.5\include\Linux
//它是用来查找 struct clk 结构的。
//有了它,就可以通过设备名或时钟源的名字来找到相应的 struct clk 结构。
struct clk_lookup {
struct list_head node;
const char *dev_id; //设备名,提供对外搜索的名字,匹配使用的
const char *con_id; //总线名,也可以用来搜索,匹配使用
struct clk *clk; //指向模块时钟信息结构
};

实际的匹配过程是会比较 dev_id 和 con_id 两个成员的,如果匹配上,则返回 clk 结构。

内核提供一个辅助填充宏:CLKDEV_INIT

定义如下:

#define CLKDEV_INIT(d, n, c) \
{ \
.dev_id = d, \
.con_id = n, \
.clk = c, \
}
//可以被查找操作的模块时钟
//它是用来查找 struct clk 结构的。
//有了它,就可以通过设备名或时钟源的名字来找到相应的 struct clk 结构。
static struct clk_lookup exynos4_clk_lookup[] = {
……
//通过设备名或时钟源名查找到 exynos4_clk_fimd0 结构
CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
……
};
struct device dev;
struct clk * clk_bus;
dev. init_name = "exynos4-fb.0";
clk_bus = clk_get(&dev, "lcd" );

如何找到模块的时钟结构?内核提供了操作时钟相关的 API 函数,这些 API 接口函数是通用的,声明在 Clk.h linux-3.5\include\Linux 。时钟获得结构获取函数:

struct clk *clk_get(struct device *dev, const char *id);

功能:通过 dev. init_name 和参数 id 进行在 struct clk_lookup 注册到内核的时钟结构链表查找。参数 dev. init_name 和 clk_lookup 结构中的 dev_id 成员比较 参数 id 和 clk_lookup 结构中的 con_id 比较 如果两个成员都相同就返回 clk_lookup 结构中的中 clk 指针。

返回值:IS_ERR(clk_get 返回值) 

非 0: 获得失败,这时候应该返回 –ENODEV 错误码 IS_ERR(clk_get 返回值) 

0: 获得时钟成功

示例:

s3c_ac97.ac97_clk = clk_get(&pdev->dev, "ac97");
if (IS_ERR(s3c_ac97.ac97_clk)) {
dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n");
ret = -ENODEV;
goto err2;
}
clk_enable(s3c_ac97.ac97_clk); //获得成功后可以使能模块时钟了

时钟使能函数:

int clk_enable(struct clk *clk);

功能: 在获得 clk 结构后,就可以调用 clk_enable 函数来使能模块的时钟

返回: 0:成员;负数:失败 时钟禁止函数:

void clk_disable(struct clk *clk);

功能:当不需要使用一个模块时候,要降低功耗,可以关闭它。获得模块的运行时钟频率:

unsigned long clk_get_rate(struct clk *clk);

功能: 根据结构获得模块的运行频率 

返回:模块的运行频率,单位是 HZ 减少时钟引用计数,如果你使用

void clk_put(struct clk *clk);

当使用了 clk_get, clk_enable 后,如果不想使用模块了,则需要 clk_put 引用计数。设置模块的运行时钟:

int clk_set_rate(struct clk *clk, unsigned long rate);

参数: rate 要设置的目标运行频率

返回: 0:成员;负数:失败

—————END—————

扫码或长按关注

回复「 加群 」进入技术群聊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468150.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

千万级大表如何更快速的创建索引_分享一份生产环境mysql数据库大表归档方案,值得收藏...

概述分享下最近做的一个mysql大表归档方案&#xff0c;仅供参考。整体思路一、明确哪些大表需做归档1、数据库表概要信息统计SELECTt1.table_schema,t1.table_name,ENGINE,table_rows,CAST( data_length / 1024.0 / 1024.0 AS DECIMAL ( 10, 2 ) ) data_size(M),CAST( index_le…

载波和LoRa

最近lora这个很火&#xff0c;火的原因是因为国家出了一个政策&#xff0c;这个政策呢&#xff0c;有很多人解读了&#xff0c;我身边也有好几个朋友做这方面的&#xff0c;然后我今天找他们聊了下&#xff0c;得到的结果是&#xff0c;这个政策肯定是或多或少对现在的行情和市…

imread函数 matlab_【MATLAB图像处理学习】1.读取和显示图片

CHAPTER2 图像处理的基础函数【使用的教材&#xff1a;冈萨雷斯 数字图像处理MATLAB(Digital image processing with Matlab】【原书图片下载地址&#xff1a;点这里】先介绍三个MATLAB中图片基本操作&#xff1a;imread imshow imwrite2.2读取图片imread(filename)imread是读取…

一场不能只看结果的较量

林书豪的比赛看得真的很舒服&#xff0c;虽然输掉了比赛&#xff0c;但是看到两边不断改变打法&#xff0c;不断试图侵犯对方的夺取分数&#xff0c;就好比看了一场战争电影&#xff0c;过程酣畅淋漓&#xff0c;结果差点令人满意。第一节广东的双后卫给北京制造了非常多的麻烦…

嘻哈帝国第一季/全集Empire迅雷下载

英文译名Empire&#xff0c;第1季(2015-01-08)FOX.本季看点&#xff1a;《嘻哈帝国》卢西奥斯莱恩是一名超级音乐明星兼Empire娱乐公司的创始人&#xff0c;故事讲述了他如何在困境和失败中运营公司的故事。拥有庞大帝国的老板得了绝症&#xff0c;于是他决定培养继承人&#x…

cassandra可视化工具_一位数据科学家的私房工具清单

作为一位万人敬仰的数据科学家&#xff0c;不但需要培育一棵参天技能树&#xff0c;私人武器库里没有一票玩得转的大火力工具也是没法在江湖中呼风唤雨的。近日北卡来罗纳大学CTO&#xff0c;一位数据科学家Jefferson Heard分享了多年来收集沉淀的数据分析工具集&#xff1a;处…

Dev C++,一个好玩的猜数字游戏

周末了&#xff0c;看了一点代码&#xff0c;发现有一个好玩的数字游戏&#xff0c;贡献给大家&#xff0c;个人觉得还是挺好玩的。说个题外话&#xff0c;之前写的文章&#xff0c;都是零散的&#xff0c;主要是时间的原因&#xff0c;最近事情有点杂&#xff0c;一说到这个事…

[BZOJ 2500] 幸福的道路

照例先贴题面&#xff08;汪汪汪&#xff09; 2500: 幸福的道路 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 368 Solved: 145[Submit][Status][Discuss]Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一…

你手上的PCB怎么制作的?几张动图揭晓工厂生产流程

在PCB出现之前&#xff0c;电路是通过点到点的接线组成的。这种方法的可靠性很低&#xff0c;因为随着电路的老化&#xff0c;线路的破裂会导致线路节点的断路或者短路。绕线技术是电路技术的一个重大进步&#xff0c;这种方法通过将小口径线材绕在连接点的柱子上&#xff0c;提…

linux开发板作为蓝牙音箱,USB 蓝牙适配器在ARM 开发板下的使用

4、可能出现的问题和解决方案&#xff1a;4.1 编译dbus 时出现&#xff1a;1checking for accept4... yeschecking abstract socket namespace... nochecking for pkg-config... (cached) /usr/local/bin/pkg-configchecking pkg-config is at least version 0.9.0... yescheck…

细丝极恐的华为251事件

事情的来龙去脉我就不再详细描述了&#xff0c;我提几个问题点&#xff0c;觉得有点疑惑&#xff0c;也是自己对这个事件的看法。1、李洪元于2005年入职华为&#xff0c;2018年1月离职&#xff0c;在2016年11月21日向公司的投诉邮箱发了一份匿名邮件&#xff0c;至于发邮件的东…

mysql set语句_mysql--乱码解决(6)

1.字符集介绍mysql数据库字符集包括字符集(character)和校对规则(collation)两个概念&#xff0c;其中字符集是用来定义mysql数据字符串的存储方式&#xff0c;而校对规则则是定义比较字符串的方式。2.常见字符集3.解决中文乱码思想&#xff1a;保持linux、服务端、库、表、客户…

C 语言,你真的懂递归了吗?

什么是递归&#xff1f;要说到递归如果不说栈的话&#xff0c;我觉得有点不合适&#xff0c;递归特点就是不断的调用同一个函数&#xff0c;如果这个函数没有一个递归界限&#xff0c;那么就是死循环了&#xff0c;所以讨论递归&#xff0c;就必须要讨论递归的界限&#xff0c;…

github page hexo博客gitee_利用Github和hexo搭建个人免费博客

利用Github和hexo搭建个人免费博客详细过程&#xff1a;概述&#xff1a;详细的介绍了利用github和hexo搭建免费的博客&#xff0c;内容详细&#xff0c;浅显易懂&#xff0c;容易上手&#xff0c;大家一起进来看看吧&#xff01;1、配置Github相关操作&#xff1a;​ ①新建一…

漫画:三种 “奇葩” 的排序算法

在算法的世界里&#xff0c;有许多高效率的排序算法&#xff0c;比如快速排序、归并排序、桶排序......它们大大提高了程序的性能。但是&#xff0c;也有一些比较奇葩的排序算法&#xff0c;它们既不能做到高效率&#xff0c;也没有很好的可读性。那它们存在的意义是什么呢&…

常用c语言小程序,c语言经典小程序汇总大全

网上有很多的人说编程有多么多么无聊&#xff0c;其实&#xff1a;不要管别人怎么说&#xff0c;别人说什么&#xff0c;做你自己喜欢做的事就好。坚持下来&#xff0c;你会发现编程的乐趣的。当然&#xff0c;如果你觉得学习编程语言很痛苦&#xff0c;坚持了一段时间后无果&a…

opencv 二值化_Python-OpenCV获取图像轮廓的图像处理方法

一、引言在《OpenCV阈值处理函数threshold处理32位彩色图像的案例》介绍了threshold 函数&#xff0c;但threshold 的图像阈值处理对于某些光照不均的图像&#xff0c;这种全局阈值分割的方法并不能得到好的效果。图像阈值化操作中&#xff0c;我们更关心的是从二值化图像中分离…

让你不再害怕指针.pdf

今天推荐一本书&#xff0c;是讲解指针的&#xff0c;C 语言理解指针应该算一个重点&#xff0c;也算是一个难点&#xff0c;这个pdf 文章总结非常好&#xff0c;推荐给大家。想获取书籍Pdf的同学&#xff0c;请在公众号后台回复 「指针」&#xff0c;希望这本书籍让你们不再害…

revit如何根据坐标进行画线_在工程设计中如何根据工艺阀门的结构与特点来进行设计呢?...

在工程设计的实践中发现&#xff0c;因为阀门的种类繁多&#xff0c;每种阀门都有自己的特点&#xff0c;工程设计人员&#xff0c;尤其年轻的设计者由于不太了解阀门的结构和特点往往选错阀门&#xff0c;造成设计失误。系统的了解阀门&#xff0c;对工程设计人员(不是阀门设计…

c语言中二维数组中产生随机数,C语言中是如何进行随机数生成的[多图]

C语言中是如何进行随机数生成的.C语言是编程人员经常会到的一款计算机编程语言,有的朋友想知道怎样使用C语言进行随机数生成,那么就快随小编一起来看看这篇C语言中是如何进行随机数生成的吧!其中不仅为大家介绍了生成随机数的函数,还提供了测试代码!同时为大家附带了随机数字生…