platform驱动模型一

主要参考:http://blog.chinaunix.net/uid-26285146-id-3307147.html

http://blog.chinaunix.net/uid-26285146-id-3307147.html

重要的结构体

<1>struct device     <linux/device.h>

//用于描述设备相关的信息设备之间的层次关系,以及设备与总线、驱动的关系

http://blog.csdn.net/abo8888882006/article/details/5424363

重要成员:

void *platform_data; /* Platform specific data, device core doesn‘t touch it */

struct device_driver *driver;

//指向被分配到该设备的设备驱动

//在really_probe(struct device *dev, struct device_driver *drv)函数中dev->driver = drv;将设备和驱动绑定

char bus_id[BUS_ID_SIZE]; /* position on parent bus */

struct bus_type *bus;

//在platform_device_add()中pdev->dev.bus = &platform_bus_type;

struct device *parent; //指向其父设备在platform_device_add中被赋值为&platform_bus;

void (*release)(struct device * dev); //释放设备描述符的回调函数

<2>struct resource                <linux/ioport.h>

//这个结构表示设备所拥有的资源,即I/O端口、I/O映射内存、中断及DMA等。这里的地址指的是物理地址。

成员:

resource_size_t start;  //定义资源的起始地址
resource_size_t end;  //定义资源的结束地址
const char *name; //定义资源的名称
unsigned long flags; //定义资源的类型,比如MEM,IO,IRQ,DMA类型
struct resource *parent, *sibling, *child;

<3>struct device_driver         <linux/device.h>

const char              *name;
struct bus_type         *bus;
struct module           *owner;
const char              *mod_name;      /* used for built-in modules */
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
struct attribute_group **groups;
struct driver_private *p;

device_driver提供了一些操作接口,但其并没有实现,相当于一些虚函数,由派生类platform_driver进行重载,无论何种类型的driver都是基于device_driver派生而来的,具体的各种操作都是基于统一的基类接口的,这样就实现了面向对象的设计。

device_driver结构中name变量和platform_device中name变量一致。内核正是通过这个一致性来为驱动程序找到资源,即 platform_device中的resource。

<4>struct platform_device          <linux/platform_device.h>

成员:

const char      * name; //定义平台设备的名称,此处设备的命名应和相应驱动程序命名一致

int             id;
struct device   dev;    //描述了设备的情况,platform_device由device派生而来,是一种特殊的device
u32             num_resources;
struct resource * resource;  //定义平台设备的资源

<4>struct platform_driver           <linux/platform_device.h>

//该结构中需要实现 shutdown,suspend,resume这三个函数,若不支持,将他们设为null。

成员:

int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;

重要函数

<1>

platform_device_register(srtuct platform_device *pdev)      //   drivers/base/platform.c

//调用platform_device_add(pdev)注册到platform总线上

//platform_device_add调用device_add()

platform_device_unregister()

device_register(struct device *dev)           //     linux/drivers/base/core.c

//调用device_add(dev)

//将该device对象dev插入设备模型中

device_unregister()

device_register()和 platform_device_register()都会首先初始化设备,区别在于第二步:其实platform_device_add()包括 device_add(),不过要先注册resources,然后将设备挂接到特定的platform总线。

<2>

platform_driver_register(struct platform_driver *drv)                  //    drivers/base/platform.c

//调用driver_register(&drv->driver)

platform_driver_unregister()

platform_device_alloc()   //动态申请一个platform_device设备

然后通过platform_device_add_resources及platform_device_add_data等添加相关资源和属性。

//最终通过platform_device_add注册到platform总线上

<3>platform_add_devices()

系统中的设备资源可以通过指针数组列举在一起

static struct platform_device *smdk6410_devices[] __initdata = {

......

&s3c_device_usbgadget,
 &s3c_device_usb,  //jeff add.

......

}

然后在初始化函数中执行

platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));将所有的device添加进系统。platform_add_devices的好处在于它是一次性的执行多个platform_device_register。

device和driver的绑定的实现

<1>虚拟总线 "platform"的属性和操作的定义: //    drivers/base/platform.c

struct bus_type platform_bus_type = {

.name = "platform",

.dev_attrs = platform_dev_attrs,

.match = platform_match,

.uevent = platform_uevent,

.pm = &platform_dev_pm_ops,

};

//总线bus是联系driver和device的中间枢纽。Device通过所属的bus找到driver,由match操作方法进行匹配。

static int platform_match(struct device *dev, struct device_driver *drv)

{

struct platform_device *pdev = to_platform_device(dev);

struct platform_driver *pdrv = to_platform_driver(drv);

...

return (strcmp(pdev->name, drv->name) == 0);

}

<2>设备注册platform_device_register()->platform_device_add()->(pdev->dev.bus = &platform_bus_type)把设备挂在虚拟的platform bus下;

<3>驱动注册platform_driver_register(struct platform_driver *drv)

->driver_register(struct device_driver *drv)

->bus_add_driver(struct device_driver *drv)

->driver_attach(struct device_driver *drv) //return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

->bus_for_each_dev(),对每个挂在虚拟的platform bus的设备作__driver_attach(struct device *dev, void *data)

->driver_probe_device(struct device_driver *drv, struct device *dev),

判断drv->bus->match()是否存在并且是否执行成功,此时通过指针执行platform_match,比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),

如果相符就调用really_probe(struct device *dev, struct device_driver *drv)//driver_sysfs_add()

在该函数中有drv->probe(dev):调用device_driver的probe(dev),实际就是执行的相应设备的platform_driver->probe(platform_device)

probe函数一般完成硬件设备使能,struct resource的获取以及虚拟地址的动态映射和具体类型设备的注册(因为平台设备只是一种虚拟的设备类型);remove函数完成硬件设备的关闭,struct resource以及虚拟地址的动态映射的释放和具体类型设备的注销

注意:platform_drv_probe的_dev参数是由bus_for_each_dev的next_device获得)开始真正的探测加载,如果probe成功则绑定该设备到该驱动。

int bus_for_each_dev(struct bus_type * bus,

struct device * start,

void * data,

int (*fn)(struct device *, void *))

{

struct klist_iter i;

struct device * dev;

int error = 0;

if (!bus)

return -EINVAL;

klist_iter_init_node(&bus->klist_devices, &i,

(start ? &start->knode_bus : NULL));

while ((dev = next_device(&i)) && !error)

error = fn(dev, data);

klist_iter_exit(&i);

return error;

}

<4>init/main.c中:

start_kernel 》 rest_init 》 kernel_init 》 do_basic_setup》driver_init 》platform_bus_init初始化platform_bus(虚拟总线);(先)

start_kernel 》 rest_init 》 kernel_init 》 do_basic_setup》do_initcalls platform driver和platform device的初始化(后)

创建了platform_bus设备,后续platform的设备都会以此为parent。在sysfs中表示为:所有platform类型的设备都会添加在 platform_bus所代表的目录下,即 /sys/devices/platform下面

时间: 2024-10-20 11:33:45

platform驱动模型一的相关文章

Linux 驱动之 platform 驱动模型总结 (基于tiny210 平台 LED 驱动)

1.概述 在一般情况下,2.6内核中已经初始化并挂载了一条platform总线在sysfs文件系统中.那么我们编写platform模型驱动时,需要完成两个工作:1:实现platform驱动 2:实现platform设备,然而在实现这两个工作的过程中还需要实现其他的很多小工作,在后面介绍.platform模型驱动的实现过程核心架构就很简单,如下所示. platform驱动模型三个对象:platform总线.platform设备.platform驱动. platform总线对应的内核结构:struc

基于platform驱动模型的LED驱动

上一篇博文<platform设备驱动框架搭建分析>主要是根据内核源码来分析platform驱动模型工作的原理,在实际的驱动开发中如何使用Linux的这么一种模型来管理这种类型的设备呢?把tq2440开发板上的LED1当做是平台设备注册到Linux系统中,让系统可以用这种platform驱动来管理他. ①总线层:代码不用我们自己去写,内核已经提供了 ②设备层:向platform总线层注册硬件相关的资源,一般是寄存器地址.内存空间.中断号(序号的一种代表)等等 led_dev.c #include

linux驱动(九)platform驱动模型详解,以及基于platform驱动模型的led驱动

参考: http://blog.csdn.net/qq_28992301/article/details/52385518 http://blog.csdn.net/zoe6553/article/details/6372445 http://blog.chinaunix.net/uid-25014876-id-111745.html 1:什么是platform总线?platform总线是区别于实体总线USB. I2C.SPI .PIC总线的虚拟总线,一些usb设备选址的话需要通过USB总线来进

RTC驱动模型分析

①RTC设备层: 设备资源的定义:arch/arm/plat-s3c24xx/devs.c static struct resource s3c_rtc_resource[] = { [0] = { .start = S3C24XX_PA_RTC, .end = S3C24XX_PA_RTC + 0xff, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_RTC, .end = IRQ_RTC, .flags = IORESOURCE_IRQ,

从串口驱动的移植看linux2.6内核中的驱动模型 platform device &amp; platform driver【转】

转自:http://blog.csdn.net/bonnshore/article/details/7979705 写在前面的话: 博主新开了个人站点:你也可以在这里看到这篇文章,点击打开链接 本文是博主学习linux驱动移植整整两周后通过查阅资料并结合自己的一些观察所做的一些记录,旨在作为日后温习材料,由于博主尚无太多经验文中内可能会出现一些谬误,希望看到的热心朋友能拍砖指正. 在我前面的日中已经提到了我所做的SC16C550的串口移植,本来是没有什么技术难度,但对于新人来讲了解内核代码的结构

20150226 IMX257 总线设备驱动模型编程之平台总线设备platform

20150226 IMX257 总线设备驱动模型编程之平台总线设备platform 2015-02-26 李海沿 前面我们实现了总线设备驱动模型,下面我们来了解一下平台总线,平台设备驱动 分为平台设备和平台驱动两种,和前面所说的设备驱动差不多 platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为platform_device. 一.平台设备介绍 1. p

Linux驱动模型解析bus之platform bus

这是内核启动之后要调用的驱动模型的开始代码: drivers/base/init.c/** * driver_init - initialize driver model. * * Call the driver model init functions to initialize their * subsystems. Called early from init/main.c. */ void __init driver_init(void) { /* These are the core

Linux内核部件分析 设备驱动模型之device

来源:Linux社区 -- http://www.linuxidc.com/Linux/2011-10/44627p6.htm 作者 : qb_2008 linux的设备驱动模型,是建立在sysfs和kobject之上的,由总线.设备.驱动.类所组成的关系结构.从本节开始,我们将对linux这一设备驱动模型进行深入分析. 头文件是include/linux/device.h,实现在drivers/base目录中.本节要分析的,是其中的设备,主要在core.c中. struct device {

8.总线设备驱动模型

总线设备驱动模型 总线:创建一条总线,跟我们前面的按键一样,首先是描述总线结构,接着是注册总线,注销总线.总线设备,例如usb总线,上面会有很多类型的usb的驱动,例如鼠标.键盘.....等,当我们把之一的usb插上的时候,usb总线会把每个驱动遍历一遍,找到相应的驱动程序执行. 接下来用bus.c创建一条总线. #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #in