u-boot下的DM驱动模型 阶梯状 (转)
U-boot 下DM驱动模型的相关笔记
要注意的关键两点:
DM驱动模型的一般流程bind->ofdata_to_platdata(可选)->probe
启动,bind操作时单独完成的,主要完成设备和驱动的绑定,以及node 注:node是匹配到驱动的设备节点 之间的连接。ofdata_to_platdata(可选)->probe 则是在device_probe函数中完成的。
明确了以上两点,接下来就开始展开分析U-boot下设计到驱动模型的一半流程,我依据的是U-boot 2018.03版本
和DM相关的初始化流程主要有两次,入口函数分别是static int initf_dm(void)和static int initr_dm(void)。
第一次是在重定位之前,调用的是initf_dm函数,函数的调用关系如下所示:
initf_dm//执行bind操作,初始化一个dm模型的树形结构
dm_init_and_scan(true)//初始化根节点设备,并bind根节点的带有u-boot,dm-pre-reloc属性的一级子节点。
dm_init//将根节点绑定到gd->dm_root上,初始化根节点设备
dm_scan_platdata//搜索使用宏U_BOOT_DEVICE定义的设备进行驱动匹配,也就是bind子节点
dm_extended_scan_fdt//在其他地方(设备树)搜索设备并进行驱动匹配,然后bind
dm_scan_fdt//在设备树种搜索设备并进行驱动匹配,然后bind
dm_scan_fdt_node//具体绑定设备的入口,在该函数中会确定设备是否具有boot,dm-pre-reloc属性,如果没有则不会绑定
lists_bind_fdt//搜索可以匹配到该设备的驱动
device_bind_with_driver_data//如果匹配到进行绑定
device_bind_common//匹配设备和驱动,并将设备节点和parent节点建立联系,也就是建立树形结构
uclass_bind_device//将该设备挂在对应的U_CLASS链表上
drv->bind(dev)//设备驱动的bind接口函数
parent->driver->child_post_bind(dev)//父节点驱动的child_post_bind接口函数
uc->uc_drv->post_bind//设备所属类的驱动的post_bind接口函数(具体的设备节点就是在这个接口下在soc下进行展开的)
至此,dm相关的一半bind流程就介绍完了,执行完initf_dm之后,内存中就有了一个深度最深为2(只有根节点时,深度为1)的树形结构,根节点挂在gd->dm_root上。
同样的,static int initr_dm(void)执行了类似的操作,只不过,
gd->dm_root_f = gd->dm_root; gd->dm_root = NULL;
重定位之后,首先将gd->dm_root的值赋值给gd->dm_root_f;然后清零了gd->dm_root,接下来才是重新执行dm_init_and_scan(false)操作,
dm_init_and_scan(false)//初始化根节点设备,并bind根节点的所有子节点
************省略,见initf_dm函数流程
bind操作完成之后,就可以对设备进行probe操作了,示例一下sdram的初始化流程,我用的板子是基于stm32f767igt的YYFISH board。和sdram基于fmc,并且除了sdram,fmc下还挂了一个4Gbit 的 nand flash,设备树相关的源码如下:
&fmc {
pinctrl-0 = <&fmc_pins>;
pinctrl-names = "default";
status = "okay";
#address-cells = <1>;
#size-cells = <1>;
/* Memory configuration from sdram datasheet MT48LC_4M32_B2B5-6A */
bank1: bank@0 {
st,sdram-control = /bits/ 8 <NO_COL_9 NO_ROW_13 MWIDTH_16 BANKS_4
CAS_3 SDCLK_2 RD_BURST_EN
RD_PIPE_DL_1>;
st,sdram-timing = /bits/ 8 <TMRD_2 TXSR_8 TRAS_7 TRC_7 TWR_2
TRP_2 TRCD_2>;
/* refcount = (64msec/total_row_sdram)*freq - 20 */
st,sdram-refcount = < 1421 >;
};
bank3: stm32_nand {
reg = <0xA0000080 0x20>;
/*Nand flash configuretion from flash datasheet MT29F4G08ABADA*/
compatible = "micron,mt29f4g", "st,nand-flash";
st,nand-control = /bits/ 8 <FMC_PWAIT_DIS FMC_PWID_8 FMC_ECC_DIS
FMC_TCLR_6 FMC_TAR_6 FMC_ECCPS_512>;
st,nand-timing = /bits/ 8 <MEMSET_VALE_2 MEMWAIT_VALE_4 MEMHOLD_VALE_2
MEMHIZ_VALE_2>;
u-boot,dm-pre-reloc;
};
};
从设备树文件可以看出,fmc下挂了两个节点,但是bank3;stm32_nand是我后来添加的,为了增加nand_flash的支持,所以stm32_nand就是fmc的一级子节点。fmc是root的子节点,树形结构的示意图如下
root
\
soc
\
fmc
\
stm32_nand
根据上面对initf_dm和initr_dm的分析,可知,这两个函数只是完成了root的一级子节点的树形创建,并且sdram的初始化是在重定向之前,也就是执行了initf_dm之后完成的(稍后会具体分析)。所以initf_dm执行之后,内存中只有如下的一个树形图:
root
\
soc
\
fmc
这时候是没有nand_flash这个设备节点的。nand_flash这个设备节点的绑定,我放在了fmc这个节点的probe流程中,具体是在ofdata_to_platdata这个接口函数中完成的。具体如下所示:
dev_for_each_subnode(bank_node, dev) {
/* extract the bank index from DT */
bank_name = (char *)ofnode_get_name(bank_node);
if (!strncmp("stm32_nand", bank_name, strlen("stm32_nand")))//iysheng
{
lists_bind_fdt(dev, bank_node, NULL);
continue;
}
}
从上述代码可以看出,当我device_probe fmc这个设备节点的时候,我会首先调用对应driver的ofdata_to_platdata函数接口,在这个接口函数中,会遍历子节点,如果发现名字是以stm32_nand开头的,那么会将这个设备节点进行进行bind操作,执行完这句话之后,设备树中的fmc节点下就会出现一个stm32_nand子节点,这时候树的深度从2变为了3。
接着会调用fmc节点对应驱动的probe接口函数,具体如下:
static int stm32_fmc_probe(struct udevice *dev)
{
******省略一些内容,和sdram初始化相关的内容
if (device_has_children(dev))
{
struct udevice * child_devp;
int index = 0;
while(!device_get_child(dev, index++, &child_devp)) {
ret = device_probe(child_devp);
if (ret < 0)
break;
}
}
}
可以看出,stm32_fmc_probe的时候,会尝试probe fmc节点下的所有子节点。因为之前已经添加了stm32_nand节点,这时候就会去probe stm32_nand那个设备了。
接下来简述一下sdram的probe流程。函数调用过程如下:
int dram_init(void)
uclass_get_device(UCLASS_RAM, 0, &dev)
uclass_find_device(id, index, &dev)
uclass_get_device_tail(dev, ret, devp)
device_probe(dev)
device_probe(dev->parent)//递归probe父节点
uclass_resolve_seq//父节点都probe之后,会分配一个seq给该设备
dev->flags |= DM_FLAG_ACTIVATED//设置该设备的flag为激活状态
pinctrl_select_state(dev, "default")//和引脚相关的初始化设置<需要进一步分析>
dev->parent->driver->child_pre_probe(dev)//执行父节点驱动的child_pre_probe接口函数
drv->ofdata_to_platdata(dev)//执行设备驱动的ofdata_to_platdata接口函数
clk_set_defaults(dev)//设备时钟相关的设置
drv->probe(dev)//调用设备驱动的probe接口函数
uclass_post_probe_device(dev)//调用所属CLASS驱动的post_probe接口函数
至此,sdram的初始化流程介绍了一下,从上可以看出,device_probe过程中,会首先调用ofdata_to_platdata接口函数,然后才会执行probe接口函数。
————————————————
版权声明:本文为CSDN博主「iysheng」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/iysheng/article/details/79921825
u-boot下的DM驱动模型 阶梯状 (转)的更多相关文章
- 详解Linux2.6内核中基于platform机制的驱动模型 (经典)
[摘要]本文以Linux 2.6.25 内核为例,分析了基于platform总线的驱动模型.首先介绍了Platform总线的基本概念,接着介绍了platform device和platform dri ...
- Linux下 USB设备驱动分析(原创)
之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...
- 从串口驱动的移植看linux2.6内核中的驱动模型 platform device & platform driver【转】
转自:http://blog.csdn.net/bonnshore/article/details/7979705 写在前面的话: 博主新开了个人站点:你也可以在这里看到这篇文章,点击打开链接 本文是 ...
- 让天堂的归天堂,让尘土的归尘土——谈Linux的总线、设备、驱动模型
本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 公元1951年5月15日的国会听证上, ...
- [uboot] (番外篇)uboot 驱动模型(转)重要
[uboot] uboot流程系列:[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)[project X] tiny210(s5pv210)从存储设备加载代码到D ...
- 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...
- Linux中总线设备驱动模型及平台设备驱动实例
本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...
- 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台
本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”. 一.预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中 ...
- linux驱动模型<输入子系统>
在linux中提供一种输入子系统的驱动模型,其主要是实现在input.c中. 在输入子系统这套模型中,他把驱动分层分类.首先分为上下两层,上层为input.c .下层为驱动的实现,下层分为两部分,一部 ...
随机推荐
- Redis集群的原理和搭建(转载)
转载来源:https://www.jianshu.com/p/c869feb5581d Redis集群的原理和搭建 前言 Redis 是我们目前大规模使用的缓存中间件,由于它强大高效而又便捷的功能,得 ...
- 【机器学习】ICA 原理以及相关概率论,信息论知识简介
看完了sparse coding,开始看ICA模型,本来ng的教程上面就只有一个简短的介绍,怎奈自己有强迫症,爱钻牛角尖,于是乎就搜索了一些ICA的介绍文章(都是从百度文库中搜来的),看完之后感觉这个 ...
- Java垃圾收集算法1
Java垃圾收集算法 由于垃圾收集算法的实现涉及大量的程序细节,而且每个平台的虚拟机操作内存的方法又各不相同,因此博客中不过多的讨论算法的实现,只是介绍几种算法的思想以及发展. 相关阅读: 1.深入理 ...
- iterm 2快捷键
快捷键 作用说明 command + f 搜索&查找,如果输入搜索内容后,按下 tab 键,就会 iTerm 自动帮选中搜索关键词,并且自动的帮我们复制到了剪贴板中.如果输入的是 shift+ ...
- 2019牛客暑期多校训练营(第八场)-C CDMA(递归构造)
题目链接:https://ac.nowcoder.com/acm/contest/888/C 题意:输入m(为2的n次幂,n<=10),构造一个m*m的矩阵满足任意不同的两行的元素乘积和为0. ...
- linux各种IPC机制
docker中的资源隔离,一种就是IPC的隔离.IPC是进程间通信. 下面的文章转载自https://blog.csdn.net/yyq_9623/article/details/78794775 原 ...
- 【LOJ】#3044. 「ZJOI2019」Minimax 搜索
LOJ#3044. 「ZJOI2019」Minimax 搜索 一个菜鸡的50pts暴力 设\(dp[u][j]\)表示\(u\)用\(j\)次操作能使得\(u\)的大小改变的方案数 设每个点的初始答案 ...
- Linux就该这么学——新手必须掌握的命令之常用的系统工作命令
echo命令 含义:echo命令用于在终端输出字符串或变量提取后的值,格式为 : echo [字符串|$变量] 示例: 将”Linuxprobe.com”输出到终端屏幕的命令为: [root@linu ...
- 首篇-记录自己学习python之路!
对于自己学习python的目的比较明确——爬虫和量化. 目前找了一些资源进行学习,先进行量化方面的学习,爬虫滞后.目前的目标是“180天掌握尽可能多的量化能力”! 以后定时发送自己学习思考内容以作自己 ...
- Python开发之IDE选择
Python开发之IDE 一.为什么用IDE 到现在为止,谁还不是个写过代码的人啦,但你有没有发现,每次写代码要新建文件.写完保存时还要选择存放地点,执行时还要切换到命令行调用python解释器,好麻 ...