[第二次修改:linux中有各个模块init函数放在init断中。最先init的设备(驱动最先被注册),睡眠唤醒的时候最后被suspend最先被resume。]
需求:dsi这边的驱动需要比我一个挂载在i2c上的设备晚.
也就是说.平台端要先初始化i2c从设备以后,再输出mipi信号.
平台:qcom 8930
做法
1.修改dsi
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -3180,6 +3180,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
static int te_irq_registered;
struct mdss_panel_data *pdata;
+// msleep(5000);
+// mdelay(5000);
+ printk("mdss ctrl probe sleep 5s\n");
if (!pdev || !pdev->dev.of_node) {
pr_err("%s: pdev not found for DSI controller\n", __func__);
return -ENODEV;
@@ -4357,6 +4358,7 @@ static int __init mdss_dsi_driver_init(void)
return ret;
}
module_init(mdss_dsi_driver_init);
+//late_initcall(mdss_dsi_driver_init);
static int mdss_dsi_ctrl_register_driver(void)
@@ -4377,6 +4379,7 @@ static int __init mdss_dsi_ctrl_driver_init(void)
return ret;
}
module_init(mdss_dsi_ctrl_driver_init);
+//late_initcall(mdss_dsi_ctrl_driver_init);
msleep与mdelay都试过。不行。这个线程delay导致整个probe流程都不行。方法一失败
将module_init的逻辑改为late_initcall 。mdss_dsi这边确实会往后推。但是mdss逻辑probe太多。如果不全部往后推。系统panic挂掉。方法二也失败。
module_init的顺序其实如下
#define module_init(x) __initcall(x); //include\linux\init.h
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
[第一次更新:后来去试了一下,因为我们的从设备仅仅依赖gpio,i2c总线的初始化,其实我们可以使用rootfs_initcall即可将我们的i2c从设备的初始化顺序拉到mdss_dsi之前]
言归正传,INITCALLS在__initcall_start = .与__initcall_end = .之间,
表示INITCALLS宏内涵的相关段代码顺序存放在这里,module_init所代表段的镶嵌其中
#define pure_initcall(fn) __define_initcall("0",fn,0)
#define core_initcall(fn) __define_initcall("1",fn,1)
#define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
#define postcore_initcall(fn) __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
#define subsys_initcall(fn) __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
#define fs_initcall(fn) __define_initcall("5",fn,5)
#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn) __define_initcall("7",fn,7)
#define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
MODULE是在kernel 根目录下面的makefile中定义的
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
因此如果在build module的时候会定义MODULE。而定了了MODULE的话,则下面的都是同一个优先级
#define early_initcall(fn) module_init(fn)
#define core_initcall(fn) module_init(fn)
#define core_initcall_sync(fn) module_init(fn)
#define postcore_initcall(fn) module_init(fn)
#define postcore_initcall_sync(fn) module_init(fn)
#define arch_initcall(fn) module_init(fn)
#define subsys_initcall(fn) module_init(fn)
#define subsys_initcall_sync(fn) module_init(fn)
#define fs_initcall(fn) module_init(fn)
#define fs_initcall_sync(fn) module_init(fn)
#define rootfs_initcall(fn) module_init(fn)
#define device_initcall(fn) module_init(fn)
#define device_initcall_sync(fn) module_init(fn)
#define late_initcall(fn) module_init(fn)
#define late_initcall_sync(fn) module_init(fn)
#define console_initcall(fn) module_init(fn)
#define security_initcall(fn) module_init(fn)
---------------------
作者:tiantao2012
来源:CSDN
原文:https://blog.csdn.net/tiantao2012/article/details/54311085
版权声明:本文为博主原创文章,转载请附上博文链接!
遍历相同优先级的initcall时,是按照地址从低到高进行的,因此调用顺序就是编译时连接到initcall section的顺序,通过System.map可以查到顺序,例如:
62054:ffffffc000e61c38 T __initcall_start
62055:ffffffc000e61c38 t __initcall_trace_init_flags_sys_exitearly
62057:ffffffc000e61c40 t __initcall_trace_init_flags_sys_enterearly
62058:ffffffc000e61c48 t __initcall_init_hw_perf_eventsearly
62059:ffffffc000e61c50 t __initcall_cpu_suspend_initearly
链接顺序可以通过调整Makefile中的.o文件的先后进行调整。
最后用的方法是:查看kernel_log 发现在kernel_log之前有一个i2c上的从设备probe成功了。
将我的驱动代码放在这个从设备的代码路径。make bootimage 烧录。解决
翻阅了System.map以后从我看到的情况来说。最早的probe顺序是放在pin脚的probe之后,毕竟这个时候驱动对外部的依赖基本满足.