1、Linux设备模型

站在BSP的角度来看,整个系统可以由三部分组成:设备、总线、驱动。

Linux kernel有一些总线,比如USB、I2C等。对于每一个总线都会有一些设备和驱动挂在上面。驱动服务于匹配的设备,使Linux正确的操作硬件设备。当一个设备或者驱动注册到特定的总线上的时候就会触发总线匹配函数,比如一个设备注册到了总线,所有的该总线的驱动都会被枚举,判断是不是可以服务于新添加的设备(一般通过name来匹配),反之亦然。

如果总线匹配成功,就会调用驱动的probe函数,检查指定的硬件确实存在,然后确定是否所需的资源都能够从系统申请。

事实上,设备或者驱动能够正确的合作,在probe之后,模块初始化顺序决定于probe的执行顺序,可以由BSP函数中注册设备的顺序控制。MT6572平台,L版本的BSP文件放在kernel/arch/arm/mach-mt6572/mt_devs.c,mt_board_init()函数控制着probe的顺序。

2、LCM设备模型

对于方案公司的驱动开发人员来说,对于LCM的工作主要是在Mediatek的代码架构下进行兼容和优化。和其他的所有的模块一样,Mediatek的软件架构尽可能的把所有的无需客制化的代码划分出来,从而减少对下游开发人员的工作量。

Mediatek封装了一个结构体给开发人员,包含了所有可能需要克制化的函数指针,对于不同的IC,只需要对应实现相应的函数就可以了。

LCM_DRIVER 结构体的各个成员的介绍如下:

l  在LCM_UTIL_FUNCS这个类型中,主要定义了一些接口函数,这些接口函数是mtk提供给lcm驱动开发者使用的;

l  lcm_compare_id函数中主要是通过读寄存器获取硬件的id号判断和此驱动支持的硬件lcm是否一致,如果一致就选择这个驱动。实现了驱动和设备正确匹配。在后面分析lcm的设备模型中会讲到。

l  lcm_get_params函数中主要是一些参数定义,例如屏的分辨率,屏的接口类型等;

l  下面三个函数主要和上电时序有关

[cpp]  view plain copy
  1. // for power-onsequence refinement
  2. void (*init_power)(void);
  3. void (*suspend_power)(void);
  4. void(*resume_power)(void);

l  下面几个函数和ESD有关

[cpp]  view plain copy
  1. /ESD_RECOVERY//
  2. unsigned int(*esd_check)(void);
  3. unsigned int  (*esd_recover)(void);
  4. unsigned int(*check_status)(void);
  5. unsigned int(*ata_check)(unsigned char *buffer);

言归正传,LCM的设备模型也是遵守设备总线驱动结构的,只不过在这个基础上MTK又做了一些工作,封装出LCM_DRIVER 结构体。

总线

platform虚拟总线,关在该总线的设备和驱动通过name来匹配。

设备

在文件Mt_devs.c (arch\arm\mach-mt6572)中定义了LCM设备和资源,代码如下:

驱动

驱动文件出了MTK抽象出来的具体设备驱动文件外,这里指的是挂在platform上的驱动文件。Mtkfb.c (drivers\misc\mediatek\video\mt6572) 。

驱动的名字和设备匹配后,调用驱动的probe进行探测设备,并完成资源申请,sysfs文件系统操作等。最终在/dev/下生成设备文件节点。系统通过uevent通知udev,udev会收集在sysfs/class下面的文件信息,自动创建文件节点。

mtk_fb_probe函数主要做的工作如下:

/* Called by LDM binding to probe andattach a new device.

*Initialization sequence:

*   1.allocate system fb_info structure

*     select panel type according to machine type

*   2.init LCD panel

*   3.init LCD controller and LCD DMA

*   4.init system fb_info structure

*   5.init gfx DMA

*   6.enable LCD panel

*     start LCD frame transfer

*   7.register system fb_info structure

*/

比较关键的函数是mtkfb_find_lcm_driver,这个函数调用具体设备驱动里面的函数和数据(例如:St7796s_hvga_dsi_ivo_txd.c (drivers\misc\mediatek\lcm\st7796s_hvga_dsi_ivo_txd))。

下面对其进行分析:

[cpp]  view plain copy
  1. BOOL mtkfb_find_lcm_driver(void)
  2. {
  3. p = strstr(saved_command_line, "lcm=");
  4. if(p== NULL)
  5. {
  6. //we can't find lcm string in the command line, the uboot should be old version
  7. returnDISP_SelectDevice(NULL);
  8. }
  9. if(DISP_SelectDevice(mtkfb_lcm_name))
  10. ret= TRUE;
  11. done:
  12. returnret;
  13. }

p =strstr(saved_command_line, "lcm=");获取从lk(uboot)传入的cmdline中的"lcm="数据,为LCM设备的名称。众所周知,uboot把控制权交给kernel之后会传入一些参数,其中cmdline为uboot传入kernel参数命令行。可以通过如下指令获得:cat /proc/cmdline .

<< /proc/cmdline >>:

console=tty0 console=ttyMT0,921600n1 root=/dev/ram vmalloc=496Mslub_max_order=0 slub_debug=O  lcm=1-st7796s_hvga_dsi_ivo_txd fps=5480 vram=4194304bootprof.pl_t=1830 bootprof.lk_t=1628 printk.disable_uart=0ddebug_query="file *mediatek* +p ; file *gpu* =_" boot_reason=0androidboot.serialno=0123456789ABCDEF androidboot.bootreason=power_key

获得LCM名称以后就会调用if(DISP_SelectDevice(mtkfb_lcm_name)) 函数根据mtkfb_lcm_name 从LCM_DRIVER链表中获取对应的结构体指针,然后就传入了上面介绍的MTK客制化的一些LCM函数。

问题来了,uboot(LK)是怎么知道LCM的名字的呢?

在LK中也会有和kernel具体LCM驱动相同的设备驱动文件如

St7796s_hvga_dsi_ivo_txd.c(dev\lcm\st7796s_hvga_dsi_ivo_txd)。

LK也会把一系列LCM_DRIVER放入链表中,然后通过调用LCM_DRIVER里面的lcm_compare_id函数进行ID匹配,如果读到硬件的id和此驱动支持的id匹配,则选择此驱动。下面是对LK代码中LCM驱动的选择流程分析。

首先是LK总体代码执行的流程图:

在Kmain()函数中会有以下的函数调用流程:

在函数platform_early_init()函数里进行一系列的硬件初始化,看代码(精简):

[cpp]  view plain copy
  1. void platform_early_init(void)
  2. {
  3. //preloader won't reach max speed. It will done by LK.
  4. if (g_boot_arg->boot_mode != DOWNLOAD_BOOT)
  5. {
  6. mtk_set_arm_clock();//设置时钟
  7. }
  8. /* initialize the uart */
  9. uart_init_early();//串口初始化
  10. platform_init_interrupts();//中断
  11. platform_early_init_timer();//时钟
  12. mt_gpio_set_default();//gpio
  13. mt_i2c_init();//i2c
  14. clk_init();//clk
  15. mtk_wdt_init();//看门狗
  16. isink0_init();              //turnon PMIC6329 isink0
  17. mt_disp_init((void *)g_fb_base);//LCM
  18. #ifdef CONFIG_CFB_CONSOLE
  19. drv_video_init();
  20. #endif
  21. #if defined(TARGET_S4)
  22. pmic_init();//pmu
  23. #endif
  24. }

mt_disp_init((void *)g_fb_base);函数会调用

DISP_CHECK_RET(DISP_Init((UINT32)lcdbase, (UINT32)lcdbase, FALSE));

DISP_Init函数在Disp_drv.c(platform\mt6572)    中定义,然后继续调用disp_drv_init_context()函数--》

if(!isLCMFound)

DISP_DetectDevice();

--》

lcm_drv = disp_drv_get_lcm_driver(NULL);

--》判断LCM_DRIVER链表中lcm驱动的数量,如果为1个就直接拿来用给设备,不需要调用compare_id函数,如果多个就需要匹配硬件id号了。

[cpp]  view plain copy
  1. if(lcm_count ==1)
  2. {
  3. // we need to verify whether the lcm is connected
  4. // even there is only one lcm type defined
  5. lcm = lcm_driver_list[0];
  6. lcm->set_util_funcs(&lcm_utils);
  7. lcm->get_params(&s_lcm_params);
  8. u4IndexOfLCMList = 0;
  9. lcm_params = &s_lcm_params;
  10. lcm_drv = lcm;
  11. isLCMFound= TRUE;
  12. }
  13. for(i = 0;i < lcm_count;i++)
  14. {
  15. ……
  16. if(lcm->compare_id != NULL && lcm->compare_id())
  17. {
  18. printk("\t\t[success]\n");
  19. isLCMFound = TRUE;
  20. lcm_drv = lcm;
  21. u4IndexOfLCMList = i;
  22. goto done;
  23. }
  24. }

驱动找到会把LCD_DRIVER结构体指针赋值到全局变量lcm_drv中。通过调用文件Mt_boot.c (app\mt_boot)中的intboot_linux_from_storage(void)函数

[cpp]  view plain copy
  1. strlen += sprintf(commanline, "%s lcm=%1d-%s", commanline,DISP_IsLcmFound(), mt_disp_get_lcm_id());
  2. strlen += sprintf(commanline, "%s fps=%1d", commanline,mt_disp_get_lcd_time());
  3. strlen += sprintf(commanline, "%s vram=%1d", commanline,DISP_GetVRamSize());

将lcm相关的信息,写到cmdline中,传递给kernel。

mtk设备模型之LCM--学习相关推荐

  1. mtk设备模型之LCM

    1.Linux设备模型 站在BSP的角度来看,整个系统可以由三部分组成:设备.总线.驱动. Linux kernel有一些总线,比如USB.I2C等.对于每一个总线都会有一些设备和驱动挂在上面.驱动服 ...

  2. MTK设备模型——LCM

    我认为,这篇文档应该是足够你在初期了解以及想进一步深入所用 1.Linux设备模型 站在BSP的角度来看,整个系统可以由三部分组成:设备.总线.驱动. Linux kernel有一些总线,比如USB. ...

  3. linux设备驱动--字符设备模型

    linux设备驱动--字符设备模型 最近正在学习设备驱动开发,因此打算写一个系列博客,即是对自己学习的一个总结,也是对自己的一个督促,有不对,不足,需要改正的地方还望大家指出,而且希望结识志同道合的朋 ...

  4. 学习《Linux设备模型浅析之设备篇》笔记(一)

    最近在学习Linux设备模型,前面几篇文章也是读这篇的时候遇到问题,然后为了搞清楚先转去摸索才写出来的. 当然了,刚开始是先读到<Linux那些事儿之我是Sysfs>,搞不清楚才去读的&l ...

  5. linux lddbus设备,Linux设备驱动程序学习(14)-Linux设备模型(各环节的整合)

    Linux设备驱动程序学习(14) -Linux设备模型(各环节的整合) 通过一个设备在内核中生命周期的各个阶段,可以更好地理解Linux设备模型.我将通过分析lddbus和sculld的源码来了解L ...

  6. linux设备驱动程序架构的研究,Linux设备驱动程序学习(12)-Linux设备模型(底层原理简介)...

    Linux设备驱动程序学习(12) -Linux设备模型(底层原理简介) 以<LDD3>的说法:Linux设备模型这部分内容可以认为是高级教材,对于多数程序作者来说是不必要的.但是我个人认 ...

  7. linux父设备,linux 设备模型---学习记录(二)

    通过bus_register()函数可以弄清楚整个设备模型的骨架.大致的架构弄清楚之后就可以继续填充这个模型了.根据总线.设备.驱动由高层到底层的顺序,可以以设备为入口点来继续探索. 设备的入口在de ...

  8. Linux设备驱动程序学习-Linux设备模型(总线、设备、驱动程序和类)

    文章的例子和实验使用<LDD3>所配的lddbus模块(稍作修改). 总线 总线是处理器和一个或多个设备之间的通道,在设备模型中, 所有的设备都通过总线相连, 甚至是内部的虚拟" ...

  9. rtt_IO设备模型(学习笔记)

    一.结构介绍 I/O设备管理层:实现对设备驱动程序的封装.应用程序通过IO设备层提供的标准接口访问底层设备. 设备驱动管理层:对同类硬件设备驱动的抽象,将不同厂家的同类设备驱动中相同的部分抽取出来,将 ...

最新文章

  1. CentOS 7.0,启用iptables防火墙
  2. 宏基因组合种树第292期—侧柏、樟子松,为祖国绿化做贡献
  3. MongoDB与Mysql常用命令解释
  4. 网易来聊聊子弹短信的消息漫游技术
  5. windows下使用net-snmp实现agent扩展(三)
  6. linux tar进行归档压缩和解压
  7. maven 加入第三方库_添加第三方库到Maven资源库
  8. paip.mysql 性能测试by mysqlslap
  9. Ubuntu打包发布qt程序
  10. 快速搭建一个端对端加密的在线聊天室
  11. GIS(地理信息系统)近年来应用及发展状态
  12. GitHub---团队合作
  13. 隐私计算头条周刊(7.31-8.6)
  14. shell 脚本实战 五
  15. js正则去除头尾的指定符号
  16. 路径中 斜杠/和反斜杠\ 的区别
  17. Scrapy+MySQL爬取去哪儿网
  18. 一些纳税常识[公司]
  19. 微信小程序之基础指南
  20. phpbb论坛及其安装使用常见问题集

热门文章

  1. IP-guard 双机热备使用说明
  2. 第57期:LPWAN技术之超窄带(UNB)浅析
  3. 内存泄漏检测工具.和一些内存管理建议
  4. Java基础21 多线程线程两种实现方式 锁
  5. android渲染是skia与egl,opengl和skia哪个快 游戏电脑问题解决分享!
  6. 鹅鸭杀否认被腾讯收购 ;苹果已累计售出超 23.2 亿部 iPhone 手机;Android 13 测实用新功能|极客头条...
  7. 将最大位1000位的16进制转化位8进制(蓝桥杯)
  8. 测试通过与失败的标准
  9. 内网安全体系建设工作思路
  10. Java用for循环打印99乘法表