最近在看SPI、I2C这样简单点的总线驱动程 序,从Linux2.6起,内核引入了一套新的驱动管理和注册机制:Platform_device和Platform_driver。现在Linux中 大部分的设备驱动都可以使用这套机制,总线为platform_bus,设备用platform_device表示,驱动用 platform_driver进行注册。

Linux的这种platform driver机制和传统的device_driver机制相比,一个十分明显的优势在于platform机制将本身的资源注册进内核,由内核统一管理,在 驱动程序中使用这些资源时通过platform_device提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性 和安全性。下面是SPI驱动层次示意图,Linux中的SPI总线可理解为SPI控制器引出的总线:

和传统的驱动一样,platform机制也分为三个步骤:

1、总线注册阶段:

内核启动初始化时的main.c文件中的 kernel_init()→do_basic_setup()→driver_init()→platform_bus_init()→bus_register(&platform_bus_type), 注册了一条platform总线(虚拟总线,platform_bus)。

2、添加设备阶段:

设备注册的时候Platform_device_register()→platform_device_add()→(pdev→dev.bus = &platform_bus_type)→device_add(),就这样把设备给挂到虚拟的总线上。

3、驱动注册阶段:

Platform_driver_register()→driver_register()→bus_add_driver()→driver_attach()→bus_for_each_dev(), 对在每个挂在虚拟的platform bus的设备作__driver_attach()→driver_probe_device(),判断drv→bus→match()是否执行成功,此 时通过指针执行platform_match→strncmp(pdev→name , drv→name , BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行相应设备的 platform_driver→probe(platform_device)。)开始真正的探测,如果probe成功,则绑定设备到该驱动。

从上面可以看出,platform机制最后还是调用了bus_register() , device_add() , driver_register()这三个关键的函数。

下面看几个结构体:

  1. struct platform_device           (/include/linux/Platform_device.h)
  2. {
  3. const char  * name;
  4. int     id;
  5. struct device   dev;
  6. u32     num_resources;
  7. struct resource * resource;
  8. };

Platform_device结构体描述了一个platform结构的设备,在其中包含了一般设备的结构体struct device  dev;设备的资源结构体struct resource   * resource;还有设备的名字const char * name。(注意,这个名字一定要和后面platform_driver.driver àname相同,原因会在后面说明。)

该结构体中最重要的就是resource结构,这也是之所以引入platform机制的原因。

  1. struct resource                            ( /include/linux/ioport.h)
  2. {
  3. resource_size_t start;
  4. resource_size_t end;
  5. const char *name;
  6. unsigned long flags;
  7. struct resource *parent, *sibling, *child;
  8. };

其中 flags位表示该资源的类型,start和end分别表示该资源的起始地址和结束地址(/include/linux/Platform_device.h):

  1. struct platform_driver
  2. {
  3. int (*probe)(struct platform_device *);
  4. int (*remove)(struct platform_device *);
  5. void (*shutdown)(struct platform_device *);
  6. int (*suspend)(struct platform_device *, pm_message_t state);
  7. int (*suspend_late)(struct platform_device *, pm_message_t state);
  8. int (*resume_early)(struct platform_device *);
  9. int (*resume)(struct platform_device *);
  10. struct device_driver driver;
  11. };

Platform_driver结构体描述了一个platform结构的驱动。其中除了一些函数指针外,还有一个一般驱动的device_driver结构。

名字要一致的原因:

上面说的驱动在注册的时候会调用函数bus_for_each_dev(), 对在每个挂在虚拟的platform bus的设备作__driver_attach()→driver_probe_device(),在此函数中会对dev和drv做初步的匹配,调用的是 drv->bus->match所指向的函数。platform_driver_register函数中 drv->driver.bus = &platform_bus_type,所以drv->bus->match就为platform_bus_type→match, 为platform_match函数,该函数如下:

  1. static int platform_match(struct device * dev, struct device_driver * drv)
  2. {
  3. struct platform_device *pdev = container_of(dev, struct platform_device, dev);
  4. return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
  5. }

是比较dev和drv的name,相同则会进入really_probe()函数,从而进入自己写的probe函数做进一步的匹配。所以dev→name和driver→drv→name在初始化时一定要填一样的。

不同类型的驱动,其match函数是不一样的,这个platform的驱动,比较的是dev和drv的名字,还记得usb类驱动里的match吗?它比较的是Product ID和Vendor ID。

个人总结Platform机制的好处:

1、提供platform_bus_type类型的总线,把那些不是总线型的soc设备都添加到这条虚拟总线上。使得,总线——设备——驱动的模式可以得到普及。

2、提供platform_device和 platform_driver类型的数据结构,将传统的device和driver数据结构嵌入其中,并且加入resource成员,以便于和Open Firmware这种动态传递设备资源的新型bootloader和kernel 接轨。

platform机制的更多相关文章

  1. 详解Linux2.6内核中基于platform机制的驱动模型 (经典)

    [摘要]本文以Linux 2.6.25 内核为例,分析了基于platform总线的驱动模型.首先介绍了Platform总线的基本概念,接着介绍了platform device和platform dri ...

  2. linux设备驱动归纳总结(九):1.platform总线的设备和驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-111745.html linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxx ...

  3. [platform]linux platform device/driver(二)--Platform Device和Platform_driver注册过程之详细代码

    转自:http://www.cnblogs.com/haimeng2010/p/3582403.html 目录: 1.platform_device注册过程 2.platform_driver注册过程 ...

  4. Linux platform设备简介

    Technorati 标签: Linux platform     Linux在2.6内核中,针对一系列设备驱动,提供新的管理框架,成为platform机制,推出的目的,在于隔离驱动的资源和实现,使得 ...

  5. platform

    作者yuanlulu httpblogcsdnnetyuanlulu版权没有但是转载请保留此段声明 第1章platform驱动管理机制 platform_device 数据结构 注册流程 platfo ...

  6. 驱动之路-platform简例按键驱动☆☆☆

    一 .重要知识点: ▉1.platform设备模型 从Linux 2.6起引入了一套新的驱动管理和注册机制,platform_device和platform_driver,Linux中大部分的设备驱动 ...

  7. linux 内核驱动--Platform Device和Platform_driver注册过程

    linux 内核驱动--Platform Device和Platform_driver注册过程 从 Linux 2.6 起引入了一套新的驱动管理和注册机制 :Platform_device 和 Pla ...

  8. 两年前实习时的文档——Platform学习总结

    1  概述 驱动程序实际上是硬件与应用程序之间的中间层.在Linux操作系统中,设备驱动程序对各种不同的设备提供了一致的訪问接口,把设备映射成一个特殊的设备文件,用户程序能够像其它文件一样对设备文件进 ...

  9. 14.LINUX-platform机制实现驱动层分离(详解)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 本节目标:        学习platform机制,如何实现驱动层分离 1.先来看看我们之前分析输入子系统的分层概念,如下图所示: 如上图所示,分 ...

随机推荐

  1. phpcms v9后台多表查询分页代码

    phpcms v9里面自带的listinfo分页函数蛮好用的,可惜啊.不支持多表查询并分页. 看了一下前台模板层支持get标签,支持多表查询,支持分页.刚好可以把这个功能搬到后台来使用. 我们现在对g ...

  2. CentOS下shell显示-bash-4.1#不显示用户名路径的解决方法

    CentOS下shell显示-bash-4.1$不显示用户名路径的解决方法 问题描述: CentOS下新增一个用户,登录进去之后shell脚本的信息如下: 而不是我们经常看到的username@hos ...

  3. Linux下GPIO驱动(三) ----gpio_desc()的分析

    上篇最后提出的疑问是结构体gpio_chip中的成员函数set等是怎么实现的,在回答之前先介绍下gpio_desc这个结构体. 如上图所示,右上方部分为GPIO驱动对其它驱动提供的GPIO操作接口,其 ...

  4. python的生成器

    1.生成器 >>> def func1(): ... yield 0 ... yield 1 ... >>> a=func1() >>> a.ne ...

  5. HDFS文件读写流程 (转)

    文件读取的过程如下: 使用HDFS提供的客户端开发库Client,向远程的Namenode发起RPC请求: Namenode会视情况返回文件的部分或者全部block列表,对于每个block,Namen ...

  6. Sublime Text 3之Package Control 安装

    1.通过快捷键 ctrl+` 或者 View > Show Console 打开控制台,然后粘贴以下安装代码: import urllib.request,os; pf = 'Package C ...

  7. asp.net mvc NPOI 生成Excel文件

    private string PushToDown(string addtime) { DataTable dt = _bCreateCode.PushtoExcel(addtime); //1.实例 ...

  8. mysql procedure返回多数据集

    返回多数据集写法:第一种 DROP PROCEDURE IF EXISTS `p_query_user` ; DELIMITER // CREATE PROCEDURE p_query_user( p ...

  9. ruby的gem和boundle安装解决办法

    gem和boundle安装在国内被墙,淘宝提供了淘宝提供了RubyGems的国内镜像站点,解决办法是: 对于gem: $ gem sources --remove https://rubygems.o ...

  10. asp.net 文件复制或删除用相对路径,File.Copy中用相对路径,巧用相对路径复制文件

    再复制文件 File.Copy(Server.MapPath("被复制的文件相对路径"), Server.MapPath("目的位置相对路径"), true); ...