您的位置:首页 > 运维架构 > Linux

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

2011-08-29 16:29 459 查看
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结构。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: