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;
}
}
平台驱动注册函数
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;
}
}
相关文章推荐
- Linux学习:platform平台总线、平台设备、平台驱动
- linux 下块设备驱动开发学习笔记 1
- linux 下块设备驱动开发学习笔记 2(sbull驱动在vmware上测试)
- linux字符设备驱动-重新学习-笔记-1
- linux字符设备驱动-重新学习-笔记-2
- [linux驱动]linux块设备学习笔记(三)——程序设计
- 学习笔记 --- LINUX MTD设备之NANDFLASH驱动分析
- linux学习笔记1:linux驱动设备概述
- [linux驱动]linux块设备学习笔记(一)
- linux网络设备应用与驱动编程学习笔记(2)——网络驱动基础
- [linux驱动]linux块设备学习笔记(四)——请求处理
- Linux网络设备驱动学习笔记(-)
- Linux设备驱动程序学习笔记 高级字符驱动学习--阻塞型I/0
- linux I/O内存驱动设备--学习笔记
- linux 设备驱动开发学习笔记(一):并发控制
- 学习笔记 --- LINUX MTD设备之NORFLASH驱动分析
- [Linux驱动]字符设备驱动学习笔记(三)———高级
- Linux设备与驱动学习笔记(概述)
- linux字符设备驱动学习笔记3
- [linux驱动]linux块设备学习笔记(二)