Linux加载DTS设备节点的过程(以高通8974平台为例)
DTS是Device Tree Source的缩写,用来描述设备的硬件细节。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。为了去掉这些垃圾代码,Linux采用DTS这种新的数据结构来描述硬件设备。采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。
有关DTS的语法格式,网上有很多资料,这里我就不再赘述了。本文主要讲Linux是怎样加载DTS设备节点的流程。下面以高通QCT8974平台(Linux内核)为例进行讲解:
(1)使用DTS注册平台总线的过程
在讲注册过程之前,我们先看看DTS是怎样描述平台总线结构的,以i2c总线为例:
- / {
 - model = "Qualcomm MSM 8974";
 - compatible = "qcom,msm8974";
 - interrupt-parent = <&intc>;
 - aliases {
 - spi0 = &spi_0;
 - spi7 = &spi_7;
 - sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
 - sdhc2 = &sdhc_2; /* SDC2 SD card slot */
 - sdhc3 = &sdhc_3; /* SDC3 SDIO slot */
 - sdhc4 = &sdhc_4; /* SDC4 SDIO slot */
 - };
 - memory {
 - secure_mem: secure_region {
 - linux,contiguous-region;
 - reg = <0 0x7800000="">;
 - label = "secure_mem";
 - };
 - adsp_mem: adsp_region {
 - linux,contiguous-region;
 - reg = <0 0x2000000="">;
 - label = "adsp_mem";
 - };
 - };
 - intc: interrupt-controller@F9000000 {
 - compatible = "qcom,msm-qgic2";
 - interrupt-controller;
 - #interrupt-cells = <3>;
 - reg = <0xf9000000 0x1000="">,
 - <0xf9002000 0x1000="">;
 - };
 - msmgpio: gpio@fd510000 {
 - compatible = "qcom,msm-gpio";
 - gpio-controller;
 - #gpio-cells = <2>;
 - interrupt-controller;
 - #interrupt-cells = <2>;
 - reg = <0xfd510000 0x4000="">;
 - ngpio = <146>;
 - interrupts = <0 208="" 0="">;
 - qcom,direct-connect-irqs = <8>;
 - };
 - wcd9xxx_intc: wcd9xxx-irq {
 - compatible = "qcom,wcd9xxx-irq";
 - interrupt-controller;
 - #interrupt-cells = <1>;
 - interrupt-parent = <&msmgpio>;
 - interrupts = <72 0="">;
 - interrupt-names = "cdc-int";
 - };
 - timer {
 - compatible = "arm,armv7-timer";
 - interrupts = <1 2="" 0="" 1="" 3="" 0="">;
 - clock-frequency = <19200000>;
 - };
 - i2c_0: i2c@f9967000 { /* BLSP#11 */
 - cell-index = <0>;
 - compatible = "qcom,i2c-qup";
 - reg = <0xf9967000 0x1000="">;
 - #address-cells = <1>;
 - #size-cells = <0>;
 - reg-names = "qup_phys_addr";
 - interrupts = <0 105="" 0="">;
 - interrupt-names = "qup_err_intr";
 - qcom,i2c-bus-freq = <100000>;
 - qcom,i2c-src-freq = <50000000>;
 - };
 - i2c_2: i2c@f9924000 {
 - cell-index = <2>;
 - compatible = "qcom,i2c-qup";
 - reg = <0xf9924000 0x1000="">;
 - #address-cells = <1>;
 - #size-cells = <0>;
 - reg-names = "qup_phys_addr";
 - interrupts = <0 96="" 0="">;
 - interrupt-names = "qup_err_intr";
 - qcom,i2c-bus-freq = <100000>;
 - qcom,i2c-src-freq = <50000000>;
 - };
 - spi_0: spi@f9923000 {
 - compatible = "qcom,spi-qup-v2";
 - reg = <0xf9923000 0x1000="">;
 - interrupts = <0 95="" 0="">;
 - spi-max-frequency = <19200000>;
 - #address-cells = <1>;
 - #size-cells = <0>;
 - gpios = <&msmgpio 3 0>, /* CLK */
 - <&msmgpio 1 0>, /* MISO */
 - <&msmgpio 0 0>; /* MOSI */
 - cs-gpios = <&msmgpio 9 0>;
 - };
 - };
 
从上面可知,系统平台上挂载了很多总线,如i2c、spi、uart等等,每一个总线分别被描述为一个节点。Linux在启动后,到C入口时,会执行以下操作,加载系统平台上的总线和设备:
start_kernel() --> setup_arch() --> unflatten_device_tree()
unflatten_device_tree()的代码如下:
- void __init unflatten_device_tree(void)
 - {
 - __unflatten_device_tree(initial_boot_params, &allnodes,
 - early_init_dt_alloc_memory_arch);
 - /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
 - of_alias_scan(early_init_dt_alloc_memory_arch);
 - }
 
在执行完unflatten_device_tree()后,DTS节点信息被解析出来,保存到allnodes链表中,allnodes会在后面被用到。
随后,当系统启动到board文件时,会调用.init_machine,高通8974平台对应的是msm8974_init()。接着调用of_platform_populate(....)接口,加载平台总线和平台设备。至此,系统平台上的所有已配置的总线和设备将被注册到系统中。注意:不是dtsi文件中所有的节点都会被注册,在注册总线和设备时,会对dts节点的状态作一个判断,如果节点里面的status属性没有被定义,或者status属性被定义了并且值被设为“ok”或者“okay”,其他情况则不被注册到系统中。
(2)使用DTS注册总线设备的过程
上面讲了Linux怎样使用DTS注册平台总线和平台设备到系统中,那么其他设备,例如i2c、spi设备是怎样注册到系统中的呢?下面我们就以i2c设备为例,讲解Linux怎样注册i2c设备到系统中。
以高通8974平台为例,在注册i2c总线时,会调用到qup_i2c_probe()接口,该接口用于申请总线资源和添加i2c适配器。在成功添加i2c适配器后,会调用of_i2c_register_devices()接口。此接口会解析i2c总线节点的子节点(挂载在该总线上的i2c设备节点),获取i2c设备的地址、中断号等硬件信息。然后调用request_module()加载设备对应的驱动文件,调用i2c_new_device(),生成i2c设备。此时设备和驱动都已加载,于是drvier里面的probe方法将被调用。后面流程就和之前一样了。
简而言之,Linux采用DTS描述设备硬件信息后,省去了大量板文件垃圾信息。Linux在开机启动阶段,会解析DTS文件,保存到全局链表allnodes中,在掉用.init_machine时,会跟据allnodes中的信息注册平台总线和设备。值得注意的是,加载流程并不是按找从树根到树叶的方式递归注册,而是只注册根节点下的第一级子节点,第二级及之后的子节点暂不注册。Linux系统下的设备大多都是挂载在平台总线下的,因此在平台总线被注册后,会根据allnodes节点的树结构,去寻找该总线的子节点,所有的子节点将被作为设备注册到该总线上。
Linux加载DTS设备节点的过程(以高通8974平台为例)的更多相关文章
- Ztree异步加载自动展开节点
		
在Ztree的官网Demo中,有自动展开的例子,是通过设置节点属性open:true来实现自动展开的,但是在异步加载中,这个属性设置为true也不会自动展开,因为open:true是指在有子节点的情况 ...
 - EasyUI 树形菜单加载父/子节点
		
通常表示一个树节点的方式就是在每一个节点存储一个 parentid. 这个也被称为邻接列表模型. 直接加载这些数据到树形菜单(Tree)是不允许的. 但是我们可以在加载树形菜单之前,把它转换为标准标准 ...
 - 雷林鹏分享:jQuery EasyUI 树形菜单 - 树形菜单加载父/子节点
		
jQuery EasyUI 树形菜单 - 树形菜单加载父/子节点 通常表示一个树节点的方式就是在每一个节点存储一个 parentid. 这个也被称为邻接列表模型. 直接加载这些数据到树形菜单(Tree ...
 - 优化tableView加载cell与model的过程
		
优化tableView加载cell与model的过程 效果图 说明 1. 用多态的特性来优化tableView加载cell与model的过程 2. swift写起来果然要比Objective-C简洁了 ...
 - I.MX6 linux eGalaxTouch 自动获取设备节点
		
I.MX6 linux eGalaxTouch 自动获取设备节点 \\\\\\\\\\\\\\-*- 目录 -*-///////////// | 一. 需求: | 二. /proc/bus/input ...
 - linux加载指定目录的so文件
		
linux加载指定目录的so文件 http://blog.csdn.net/win_lin/article/details/8286125 download urlhttp://download.ch ...
 - 如何让linux加载当前目录的动态库
		
debian从7.0开始支持multiarch,64位库的路径改到/usr/lib/x86_64-linux-gnu了,mint.ubuntu这些衍生版有没有跟着改我就不清楚了. deepin lin ...
 - Linux Shell 判断块设备节点是否存在
		
/************************************************************************* * Linux Shell 判断块设备节点是否存在 ...
 - JQuery/JS插件 jsTree加载树,预先加载,初始化时加载前三级节点,当展开第三级节点时 就加载该节点下的所有子节点
		
jsTree加载树, 初始化时 加载前三级节点, 当展开第三级节点时 就加载该节点下的所有子节点 html: <!DOCTYPE html> <html> <head&g ...
 
随机推荐
- paper 65 :尺度不变特征变换匹配算法[转载]
			
尺度不变特征变换匹配算法 对于初学者,从David G.Lowe的论文到实现,有许多鸿沟,本文帮你跨越.1.SIFT综述 尺度不变特征转换(Scale-invariant feature transf ...
 - paper 28 :一些常见常用数据库的下载网站集锦
			
做图像处理+模式识别的童鞋怎么可以没有数据库呢? 但是,如果自己做一个数据库,费时费力费钱先不说,关键是建立的数据库的公信力一般不会高,做出的算法也别人也不好比较,所以呢,下载比较权威的公共数据库还是 ...
 - 用VS2010编C#程序扫盲
			
0. Properties文件夹 定义你程序集的属性 项目属性文件夹 一般只有一个 AssemblyInfo.cs 类文件,用于保存程序集的信息,如名称,版本等,这些信息一般与项目属性面板中的数据对应 ...
 - 出现“不能执行已释放的Script代码”错误的原因及解决办法
			
很多web开发者或许都遇到过这样的问题,程序莫名奇怪出现“不能执行已释放Script的代码”,错误行1,列1.对于这种消息描述不着边,行列描述更是让人迷茫的js错误,相信是所有调试js程序的朋友们最郁 ...
 - 清除Cookie、获取指定Cookie的值、添加一个Cookie(24小时过期)、添加一个Cookie
			
MXS&Vincene ─╄OvЁ &0000007 ─╄OvЁ MXS&Vincene MXS&Vincene ─╄OvЁ:今天很残酷,明天更残酷,后天很美好 ...
 - Java ActiveMQ 讲解(一)理解JMS 和 ActiveMQ基本使用(转)
			
转自:http://www.cnblogs.com/luochengqiuse/p/4678020.html?utm_source=tuicool&utm_medium=referral 最近 ...
 - python核心编程学习记录之Python对象
			
比较符号如<,>,=比较的是对象的值 如果要比较对象本身要用is,is not repr()的功能与''所做的事情是一样的 Python不支持的类型有char,byte,指针,short, ...
 - 统一使用GPT分区表,安装MAC 10.10 和 Win8.1 pro双系统
			
步骤一: 为Mac OS 分区,为其它分区留白1,使用OSX Mavericks制作的Mac安装U盘按住Option键启动:2,选择安装Mavericks盘符:3,进入OSX安装启动界面,选择磁盘工具 ...
 - 程序员PC选购
			
程序员PC选购[转载] http://www.cnblogs.com/legendtao/p/4631150.html 好马配上好鞍,自然事半功倍.一台好的PC能给你更好的工作娱乐体验~~(卧槽,感觉 ...
 - 161031、java.util.StringTokenizer使用及源码
			
import java.util.StringTokenizer; public class TestStringTokenizer { public static void main(String[ ...