你需要知道的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…

Android手机摇一摇的实现SensorEventListener

Android手机摇一摇的实现SensorEventListener 看实例 package com.example.shakeactivity;import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.Se…

linux cas 钥匙生成,gcc linux利用CAS实现无锁编程

利用__sync_bool_compare_and_swap()&#xff0c;实现无锁编程CAS即compare and swap,每次都会和old 值进行比较&#xff0c;如果没有发生更改再用new值给ptr赋值&#xff0c;然后返回true#include #include #include #include #ifdef __GNUC__//#define ATOMIC#define CAS#def…

载波和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;结果差点令人满意。第一节广东的双后卫给北京制造了非常多的麻烦…

log4js linux,日志管理 log4js

版本&#xff1a;express&#xff1a;"~4.13.4"log4js&#xff1a;"^0.6.38"安装npm install log4js封装 log4js&#xff1a;在项目根目录下新建文件 logger.js&#xff1a;var log4js require(log4js);log4js.configure({appenders: [{type: console // …

嘻哈帝国第一季/全集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终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一…

c语言如何赋值星期到字母,C语言程序设计课程教案.doc

C语言程序设计课程教案《C语言程序设计》课程教案课题C语言概述课型新授课授课日期课时2教学目的1、了解C语言的特点&#xff1b;2、掌握C简单程序的结构&#xff1b;3、熟练掌握C程序的编辑、编译、链接和运行的过程。教学重点难点教学重点&#xff1a;C语言的特点与编程环境教…

python高并发架构_python高并发的解决方案

一.cdn加速 简单说就是把静态资源放到别人服务器上 全称:Content Delivery Network或Content Ddistribute Network&#xff0c;即内容分发网络 基本思路&#xff1a; 尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输的更快、更稳定。通过…

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

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

ANR

出现类型&#xff1a; 1、按键或触摸事件在规定事件内未响应。 2、BroadcastReceiver在特定时间内未完成处理。 3、小概率service在特定时间内为完成处理。 常见的超时引发的ANR Activity: onCreate(), onResume(), onDestroy(), onKeyDown(), onClick()等&#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、服务端、库、表、客户…

Android WebView常见问题及解决方案汇总【很全很实用】

http://www.cnblogs.com/olartan/p/5713013.html转载于:https://www.cnblogs.com/genggeng/p/7196484.html

c语言中字符 12是多少,c语言中字符串的讲解(DOC可编).doc

c语言中字符串的讲解(DOC可编).doc第一部分:字符串的概念---字符串:用双引号引起来的一串字符。在C语言&#xff0c;系统将自动的为字符串添加一个结束标志\0 ,该结束标志不作为字符串的实际长度&#xff0c;但作为结束标志在内存中占有1个字节的存储空间。例如: "abc&quo…