丰富linux驱动内容笔记——platform设备驱动

来源:互联网 发布:sql注入进阶 编辑:程序博客网 时间:2024/06/05 06:42

http://blog.csdn.net/yongan1006/article/details/6729874

linux设备驱动关心总线、设备和驱动3个实体。总线会将设备和驱动绑定。一个现实的Linux设备和驱动通常都需要挂载在一种总线上。但是一些Soc中,它将外设控制器直接挂载到Soc内存空间,即CPU可以通过访问寄存器来控制它们。这些设备没有相应的实际总线。为解决这个问题,linux自定义了一种虚拟总线——platform。

n         相关概念定义

linux源码根目录中drivers/base/platform.c

有如下描述

struct device platform_bus = {

       .bus_id           = "platform",

};

 

struct bus_type platform_bus_type = {

       .name             = "platform",

       .dev_attrs       = platform_dev_attrs,

       .match           = platform_match,

       .uevent           = platform_uevent,

       .pm         = PLATFORM_PM_OPS_PTR,

};

紧接着便是platform_bus_type总线和platform_bus设备的注册。

nt __init platform_bus_init(void)

{

       int error;

 

       error = device_register(&platform_bus);

       if (error)

              return error;

       error =  bus_register(&platform_bus_type);

       if (error)

              device_unregister(&platform_bus);

       return error;

}

 

在源代码/include/linux/platform_device.h有如下定义

struct platform_device {

       const char      * name;

       int           id;

       struct device   dev;

       u32         num_resources;

       struct resource       * resource;

};

n         lpc32xx相关

lpc32xx已有的平台设备/mach-lpc32xx/arch-lpc32xx.c

static struct platform_device* lpc32xx_devs[] __initdata = {

       &serial_std_platform_device,

       &serial_hspd_platform_device,

#if defined (CONFIG_RTC_DRV_LPC32XX)

       &rtc_device,

#endif

#if defined(CONFIG_SPI_LPC32XX)

#if defined(CONFIG_MACH_LPC32XX_SSP0_ENABLE)

       &ssp0_device,

#endif

#if defined(CONFIG_MACH_LPC32XX_SSP1_ENABLE)

       &ssp1_device,

#endif

#endif

#if defined (CONFIG_MACH_LPC32XX_I2C0_ENABLE)

       &i2c0_device,

#endif

#if defined (CONFIG_MACH_LPC32XX_I2C1_ENABLE)

       &i2c1_device,

#endif

#if defined (CONFIG_MACH_LPC32XX_USBOTG_I2C_ENABLE)

       &i2c2_device,

#endif

#if defined(CONFIG_MTD_NAND_SLC_LPC32XX)

       &slc_nand_device,

#endif

#if defined(CONFIG_TOUCHSCREEN_LPC32XX)

       &tsc_device,

#endif

#if defined(CONFIG_KEYBOARD_LPC32XX)

       &kscan_device,

#endif

#if defined (CONFIG_LPC32XX_MII)

       &net_device,

#endif

#if defined(CONFIG_USB_OHCI_HCD)

       &ohci_device,

#endif

#if defined(CONFIG_LPC32XX_WATCHDOG)

       &watchdog_device,

#endif

#if defined(CONFIG_USB_GADGET_LPC32XX)

       &usbd_device,

#endif

};

 

在同一文件的__init lpc32xx_init ()又有如下描述

void __init lpc32xx_init (void)

{

       ……

       platform_add_devices (lpc32xx_devs, ARRAY_SIZE (lpc32xx_devs));

       ……

}

platform_add_devices()函数是platform_device_register()的扩展版本。它通过循环调用platform_device_register()实现多个平台设备的注册。

 

因此像静态I/O映射一样,如果要增加平台设备只需要在BSP的板文件中增加platform_device的结构体描述,然后再将平台设备结构体指针加入到platform_device* lpc32xx_devs[] __initdata{}中即可。

 

因为在BSP的板文件中完成了相关平台设备的注册,所以在编写驱动程序时只需要注册相应的驱动就行。

 

n         驱动编写

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 pm_ext_ops *pm;

       struct device_driver driver;

};

 

这个结构体中,probe和 remove是必须实现的,其它的方法则和电源管理相关。大部情况下,设备驱动不提供 suspend_late和resume_early方法。resume和suspend一般是这样处理的:开关设备,开关时钟。

probe方法:在字符设备驱动中,申请设备号,cdev结构,初始化注册cdev等的工作可以放在这个里面来完成。

remove方法则完成和probe相反的工作。

在模块加载和卸载函数中,只需要注册或注销平台设备驱动。

由于在编写驱动时通常需要些有关于设备自身的一些信息。因而在描述平台设备时,最好将自己编写的设备结构描述指针赋值给plafform_device->dev->platform_data结构。

原创粉丝点击