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

linux平台设备驱动学习笔记

2013-12-16 22:24 375 查看
最近学习了下PLATFORM驱动设计,,下面是一些学习笔记,比较乱,,水平也很低,慢慢完善,以后再回来整理,先就这样吧

平台驱动注册函数

platform_driver_register(&led_drv);

1,首先,定义一个平台驱动结构体

struct platform_driver led_drv

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; //平台驱动也属于一般驱动,所以最后会注册回去的

struct platform_device_id *id_table;

};

定义的led平台驱动结构

struct platform_driver led_drv = {

.probe
= led_probe,

.remove
= led_remove,

.driver
= {

.name = "myled",

}

};

platform_driver_register(&led_drv);

drv->driver.bus = &platform_bus_type;

给driver结构体中函数指针给定义

driver_register(&drv->driver);register driver with bus

driver_find(drv->name, drv->bus);//查找驱动,看系统中是否已经注册过这个驱动

locate driver on a bus by its name.

如果发现这个名字的驱动,返回,

bus_add_driver(drv);bus_add_driver - Add a driver to the bus.

driver_add_groups//这个是什么意思我还没搞懂

注册一个平台设备流程分析

平台设备结构体

struct platform_device {

const char
* name; //设备名字

int id; //id这个还不知道是什么用,一般为-1

struct device
dev; //一般性的设备结构体

u32 num_resources; //struct resource结构中的资源个数

struct resource* resource;//struct resource,定义了硬件资源信息

struct platform_device_id*id_entry; //入口ID,干什么还不知道???

};

struct resource结构体

struct resource {

resource_size_t start;//开始信息,,可填入地址信息,也可填入中断号,,根据需要填入

resource_size_t end; //结束信息,根据需要设置

const char *name; //

unsigned long flags;

/*#define IORESOURCE_TYPE_BITS 0x00000f00/* Resource type */

*#define IORESOURCE_IO 0x00000100

*#define IORESOURCE_MEM 0x00000200

*#define IORESOURCE_IRQ 0x00000400

*#define IORESOURCE_DMA 0x00000800

*/

struct resource *parent, *sibling, *child;//这些我也不是很清楚,一般都不用

};

示例

static struct resource led_resource[] = {

[0] = {

.start = 0x56000010, /* TQ2440的LED是GPB5,6,7,8, GPBCON地址是0x56000010 */

.end = 0x56000010 + 8 - 1,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = 5, /* LED1 */

.end = 5,

.flags = IORESOURCE_IRQ,

}

};

static struct platform_device led_dev = {

.name = "myled",

.id = -1,

.num_resources = ARRAY_SIZE(led_resource),

.resource = led_resource,

.dev = {

.release = led_release,

},

};

注册一个platform_device

/*add a platform-level device*/

platform_device_register(struct platform_device *pdev)

/*This prepares the device for use by other layers by initializing its fields.*/

device_initialize(&pdev->dev);init device structure.初始化设备结构体,

/*add a platform device to device hierarchy

*增加一个平台设备到设备层*/

platform_device_add(pdev);

pdev->dev.parent = &platform_bus;

pdev->dev.bus = &platform_bus_type; //指定属于的总线

/* This is part 2 of device_register(), though may be called

* separately _iff_ device_initialize() has been called separately.

*设备注册的第二部分,

* This adds @dev to the kobject hierarchy via kobject_add(), adds it

* to the global and sibling lists for the device, then

* adds it to the other relevant subsystems of the driver model.

*增加DEV到kobject层通过kobject_add(),把它加到全局和兄弟姐妹的列表中

*然后加到其他相关的驱动模型子系统

device_add(&pdev->dev);//增加设备之后只有通过put_device()去释放设备

注册了设备和驱动后,,只要加载模块,,平台机制就会在设备总线下和驱动总线下根据名字

寻找匹配的驱动和设备,,如果匹配那么驱动和设备就联系了起来,,然后会执行驱动的.probe函数

在probe函数中即可根据自己需要,注册真正的驱动,,platform只是提供了一种机制,这种机制

使得硬件信息和驱动分离,使得驱动的移植性更好

然后驱动中需要注册的设备中的硬件资源时,可通过接口函数获得

/* get a resource for a device

* @dev: platform device 平台设备

* @type: resource type 资源类型,可为寄存器资源或中断号资源

* @num: resource index */

platform_get_resource(pdev, IORESOURCE_MEM, 0);//获得资源,

for (i = 0; i < dev->num_resources; i++) { //for循环扫描资源

struct resource *r = &dev->resource[i];

if (type == resource_type(r) && num-- == 0)//比较资源类型,匹配则返回

return r;

}

注册一个平台驱动的过程大体上就是上面的过程

在一个内核的配置文件中一般会注册很多平台设备

在内核2.6.30中,mach-smdk2440.c中

static struct platform_device *smdk2440_devices[] __initdata = {

&s3c_device_usb,

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c0,

&s3c_device_iis,

&s3c_device_dm9000,

};

这里有很多平台设备

在smdk2440_machine_init(void)函数中会有

platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));

这个函数里很简单

for (i = 0; i < num; i++) {

ret = platform_device_register(devs[i]);//注册平台设备

if (ret) {

while (--i >= 0)

platform_device_unregister(devs[i]);

break;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: