注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
daicheng的个人空间 https://home.eeworld.com.cn/space-uid-78216.html [收藏] [复制] [分享] [RSS]
日志

Linux内核驱动的的platform机制

已有 1692 次阅读2009-12-2 09:43 |

在弄网口的时候遇到了点问题,看到了这篇文章!

从Linux 2.6起引入了一套新的驱动管理和注册机制:platform_device和platform_driver。Linux中大部分的设备驱动,都可以使用这套机制,设备用platform_device表示,驱动用platform_driver进行注册。

Linux platform driver机制和传统的device driver 机制(通过driver_register函数进行注册)相比,一个十分明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过platform device提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性(这些标准接口是安全的)。platform机制的本身使用并不复杂,由两部分组成:platform_device和platfrom_driver。

platform_device结构体用来描述设备的名称、资源信息等。该结构被定义在include/linux/platform_device.h中,定义原型如下:

struct platform_device {

const char * name;    //定义平台设备的名称

int id;

struct device dev;

u32 num_resources;

struct resource * resource; //定义平台设备的资源。

};

下面来看一下platform_device结构体中最重要的一个成员struct resource * resource。struct resource被定义在include/linux/ioport.h中,定义原型如下:

struct resource {

resource_size_t start;  //定义资源的起始地址

resource_size_t end;  //定义资源的结束地址

const char *name;    //定义资源的名称

unsigned long flags; //定义资源的类型,比如MEM,IO,IRQ,DMA类型

struct resource *parent, *sibling, *child;  //资源链表指针

};

  以我们的RTC驱动为例(为什么用RTC,RTC是一个标准的plartform device,机制是相同的,但是相对比较简单) 在我们的arch/arm/mach-sep4020/devices.c中写了rtc的plartform_device结构体和resources结构体: /* RTC controller */
static struct resource sep4020_rtc_resource[] = {
 [0] = {
  .start = RTC_BASE_V,
  .end   = RTC_BASE_V+ 0x2f,
  .flags = IORESOURCE_MEM,
 },
 [1] = {
  .start = INTSRC_RTC,
  .end   = INTSRC_RTC,
  .flags = IORESOURCE_IRQ,
 }
};
struct platform_device sep4020_device_rtc = {
 .name    = "sep4020_rtc",
 .id    = -1,
 .num_resources   = ARRAY_SIZE(sep4020_rtc_resource),
 .resource   = sep4020_rtc_resource,
};
  然后通过4020.c文件中将这个plartform_device结构体注册进去了: static struct platform_device *devices[] __initdata = {
 &serial_device,
 &sep4020_device_rtc,
 &epson_ohci_device,
      &sep4020_device_usbgadget
};
  platform_add_devices(devices, ARRAY_SIZE(devices)); 通过调用函数platform_add_devices()向系统中添加该设备了,该函数内部调用platform_device_register( )进行设备注册。要注意的是,这里的platform_device设备的注册过程必须在相应设备驱动加载之前被调用,即执行platform_driver_register()之前,原因是驱动注册时需要匹配内核中所有已注册的设备名。(后面会详细介绍device和driver之间是如何通过注册的名字进行连接的

接下来来看platform_driver结构体的原型定义,在include/linux/platform_device.h中,代码如下:

struct platform_driver {

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;

};

内核提供的platform_driver结构体的注册函数为platform_driver_register(),其原型定义在driver/base/platform.c文件中,具体实现代码如下:

int platform_driver_register(struct platform_driver *drv)

{

drv->driver.bus = &platform_bus_type;

if (drv->probe)

drv->driver.probe = platform_drv_probe;

if (drv->remove)

drv->driver.remove = platform_drv_remove;

if (drv->shutdown)

drv->driver.shutdown = platform_drv_shutdown;

if (drv->suspend)

drv->driver.suspend = platform_drv_suspend;

if (drv->resume)

drv->driver.resume = platform_drv_resume;

return driver_register(&drv->driver);

}

总结,通常情况下只要和内核本身运行依赖性不大的外围设备,相对独立的,拥有各自独自的资源(地址总线和IRQs),都可以用platform_driver实现。如:LCD,网卡、USB、UART等,都可以用platfrom_driver写,而timer,irq等小系统之内的设备则最好不用platfrom_driver机制。

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章