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  下面三个函数主要和上电时序有关

  // for power-onsequence refinementvoid (*init_power)(void);void (*suspend_power)(void);  void(*resume_power)(void);

l  下面几个函数和ESD有关

   /ESD_RECOVERY//unsigned int(*esd_check)(void);unsigned int  (*esd_recover)(void);unsigned int(*check_status)(void);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))。

下面对其进行分析:

BOOL mtkfb_find_lcm_driver(void)
{p = strstr(saved_command_line, "lcm=");if(p== NULL){//we can't find lcm string in the command line, the uboot should be old versionreturnDISP_SelectDevice(NULL);}if(DISP_SelectDevice(mtkfb_lcm_name))ret= TRUE;
done:returnret;
}

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()函数里进行一系列的硬件初始化,看代码(精简):

void platform_early_init(void)
{//preloader won't reach max speed. It will done by LK.if (g_boot_arg->boot_mode != DOWNLOAD_BOOT){mtk_set_arm_clock();//设置时钟}/* initialize the uart */uart_init_early();//串口初始化platform_init_interrupts();//中断platform_early_init_timer();//时钟mt_gpio_set_default();//gpiomt_i2c_init();//i2cclk_init();//clkmtk_wdt_init();//看门狗isink0_init();              //turnon PMIC6329 isink0mt_disp_init((void *)g_fb_base);//LCM
#ifdef CONFIG_CFB_CONSOLEdrv_video_init();
#endif
#if defined(TARGET_S4)pmic_init();//pmu
#endif
}

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号了。

if(lcm_count ==1){// we need to verify whether the lcm is connected// even there is only one lcm type definedlcm = lcm_driver_list[0];lcm->set_util_funcs(&lcm_utils);lcm->get_params(&s_lcm_params);u4IndexOfLCMList = 0;lcm_params = &s_lcm_params;lcm_drv = lcm;isLCMFound= TRUE;
}
for(i = 0;i < lcm_count;i++){……if(lcm->compare_id != NULL && lcm->compare_id()){printk("\t\t[success]\n");isLCMFound = TRUE;lcm_drv = lcm;u4IndexOfLCMList = i;goto done;}}

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

   strlen += sprintf(commanline, "%s lcm=%1d-%s", commanline,DISP_IsLcmFound(), mt_disp_get_lcm_id());strlen += sprintf(commanline, "%s fps=%1d", commanline,mt_disp_get_lcd_time());strlen += sprintf(commanline, "%s vram=%1d", commanline,DISP_GetVRamSize());

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

mtk设备模型之LCM相关推荐

  1. MTK设备模型——LCM

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

  2. mtk设备模型之LCM--学习

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

  3. Linux那些事儿之我是Sysfs(3)设备模型上层容器

    §1 bus 系统中总线由struct bus_type描述,定义为: include/linux/device.h struct bus_type { const char *name;总线类型的名 ...

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

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

  5. linux 统一设备模型 pci,Linux设备驱动模型摘抄

    Linux设备驱动模型摘抄Linux设备驱动模型摘抄Linux设备驱动模型摘抄Linux设备驱动模型摘抄Linux设备驱动模型摘抄 Linux设备驱动模型摘抄(1) Linux统一设备模型 简介 Li ...

  6. Linux-2.6设备模型与sysfs文件系统

    kobject对象: 它是设备模型的基本结构,对应于sysfs文件系统中的一个目录,它是一个结构体,不过在Linux中引入了面向对象的思想,从某些角度,也可以看成是一个类.kobject对象通常被嵌入 ...

  7. linux设备模型 字符设备,Linux 字符设备驱动模型之框架解说

    一.软件操作硬件设备模型 在进行嵌入式开发的过程中,在常做的事情就是驱动配置硬件设 备,然后根据功能需求使用硬件设备,实现功能的逻辑.如下图为其 相互之间的关系. 如上图所示: 驱动程序:主要作为操作 ...

  8. LINUX设备驱动之设备模型一--kobject

    http://blog.csdn.net/yangzhu1982/article/details/6186016 Linux设备驱动之设备模型一kobject Eric Fang  2010-01-1 ...

  9. Linux设备模型(热插拔、mdev 与 firmware)

    转自:http://blog.chinaunix.net/space.php?uid=20543672&do=blog&cuid=460882 热插拔 有 2 个不同角度来看待热插拔: ...

最新文章

  1. dft变换的两幅图_快速傅里叶变换FFT计算方法 原理及公式
  2. Android的网络Http判断是否连接服务器
  3. 微信支付分申请接入流程
  4. QT的QNetworkAccessManager类的使用
  5. MySQL中的+作用,进行字符串的拼接用concat
  6. 4.9 内容代价函数
  7. @Scheduled不执行的原因
  8. 类python中高级用法
  9. 5.4使用Mockito to mock来测试
  10. SSH框架 openSessionInView的配置
  11. oracle PL/SQL 这些查询结果不可更新,请包括ROWID或使用SELECT ...FOR UPDATE 获得可
  12. ElasticSearch创建索引指定分片和副本
  13. 为佳作喝彩: Google Play 2022 年度中国开发者最佳榜单
  14. mysql 复制 1032_mysql slave复制1032错误解决方法
  15. akoj-1267-独木舟上的荡漾
  16. 深度学习实战(十):使用 PyTorch 进行 3D 医学图像分割
  17. 华为服务器BMC方式安装系统-官方文档解读
  18. 链接预测(Link Prediction)
  19. windows server 2012 r2 搭建企业文件共享存储
  20. spring.xml配置类属性--喜闻乐见

热门文章

  1. 数据分析 kaggle 天池 竞赛常用函数整理
  2. IT农民工如何来美国工作(续)
  3. 数组中a与a[0]的区别
  4. 求生之路 自定义服务器,求生之路2·教你如何自定义绑定快捷键
  5. CrossOrigin注解的方式实现接口的跨域访问
  6. 免费领取百度云盘2048G永久空间,永久离线下载特权
  7. 网络费用报销管理系统的设计与实现
  8. Chaos Emulator v0.2.3 自建引力模拟器分享
  9. Re:从零开始的DS学习之查找算法
  10. C语言计算一元二次方程的根(完全版)