下面这个结构 体,对于移植过系统的来说已经不陌生了,而系统也正是通过这个结构体加载相关驱动,下面这个结构体只列出比较的几个驱动程序,其实系统中远不只如此。
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_lcd,
&s3c_device_bl,
&s3c_device_wdt,
&s3c_device_i2c,//下面的案例
&s3c_device_adc,
&s3c_device_nand,
&s3c_device_ts,
&s3c_device_buttons,
&s3c_device_rtc,
};
下面就以一个 s3c2440的I2C驱动为例进行说明:
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C24XX_PA_IIC,//内存资源
.end = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IIC, //中断资源,只有一个中断
.end = IRQ_IIC,
.flags = IORESOURCE_IRQ,
}
};
这里定义了两组resource,它描述了一个I2C设备的资源,第1组描 述了这个I2C设备所占用的总线地址范围, IORESOURCE_MEM表示第1组描述的是内存类型的资源信息,第2组描述了这个I2C设备的中断号, IORESOURCE_IRQ表示第2组描述的是中断资源信息。设备驱动会根据flags来获取相应的资源信息。有了resource信息,就可以定义platform_device了:
struct platform_device s3c_device_i2c = {//这个名称是在static struct platform_device *smdk2410_devices[] __initdata中,系统加载时调用
.name = "s3c2410-i2c",//这个名是实现device与driver匹配的关键,与后面的driver将相同
.id = -1,
.num_resources = ARRAY_SIZE(s3c_i2c_resource),//可用资源数
.resource = s3c_i2c_resource,//前面出现的资源
};
定义好了platform_device结构体后就可以调用函数platform_add_devices向系统中添加该设备了,之后可以调用platform_driver_register()进行设备注册。要注意的是,这里的platform_device设备的注册过程必须在相应设备驱动加载之前被调用,即执行platform_driver_register之前,原因是因为驱动注册时需要匹配内核中所以已注册的设备名。
static struct platform_driver s3c2410_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
.name = "s3c2410-i2c",
},
};
在驱动初始化函数中调用函数platform_driver_register()注册platform_driver,需要注意的是s3c_device_i2c结构中name元素和s3c2410_i2c_driver结构中driver.name必须是相同的,这样在platform_driver_register()注册时会对所有已注册的所有platform_device中的name和当前注册的platform_driver的driver.name进行比较,只有找到相同的名称的platfomr_device才能注册成功,当注册成功时会调用platform_driver结构元素probe函数指针,这里就是s3c24xx_i2c_probe,当进入probe函数后,需要获取设备的资源信息,常用获取资源的函数主要是:
struct resource * platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);
根据参数type所指定类型,例如IORESOURCE_MEM,来获取指定的资源。
struct int platform_get_irq(struct platform_device *dev, unsigned int num);获取资源中的中断号。