I2C适配器驱动被作为一个单独的模块被加载进内核,在模块的加载和卸载函数中,只需注册和注销一个platform_driver结构体,如代码清单15.25。
代码清单15.25 S3C2410 I2C总线驱动模块加载与卸载 1 static int __init i2c_adap_s3c_init(void) 2 { 3 int ret; 4
5 ret = platform_driver_register(&s3c2410_i2c_driver); 6 if (ret == 0) {
7 ret = platform_driver_register(&s3c2440_i2c_driver); 8 if (ret)
9 platform_driver_unregister(&s3c2410_i2c_driver); 10 } 11
12 return ret; 13 } 14
15 static void __exit i2c_adap_s3c_exit(void) 16 {
17 platform_driver_unregister(&s3c2410_i2c_driver); 18 platform_driver_unregister(&s3c2440_i2c_driver);
19 }
20 module_init(i2c_adap_s3c_init); 21 module_exit(i2c_adap_s3c_exit);
platform_driver结构体包含了具体适配器的probe()函数、remove()函数、resume()函数指针等信息,它需要被定义和赋值,如代码清单15.26。
代码清单15.26 platform_driver结构体
1 static struct platform_driver s3c2410_i2c_driver = { 2 .probe = s3c24xx_i2c_probe, 3 .remove = s3c24xx_i2c_remove, 4 .resume = s3c24xx_i2c_resume, 5 .driver = {
6 .owner = THIS_MODULE, 7 .name = \8 }, 9 };
当 通过Linux内核源代码/drivers/base/platform.c文件中定义platform_driver_unregister()函数注 册platform_driver结构体时,其中probe指针指向的s3c24xx_i2c_probe()函数将被调用以初始化适配器硬件,如代码清 单15.27。
代码清单15.27 S3C2410 I2C总线驱动中的s3c24xx_i2c_probe函数 1 static int s3c24xx_i2c_probe(struct platform_device *pdev)
2 {
3 struct s3c24xx_i2c *i2c = &s3c24xx_i2c; 4 struct resource *res; 5 int ret; 6
7 /* 使能I2C的时钟 */ 8 i2c->dev = &pdev->dev;
9 i2c->clk = clk_get(&pdev->dev, \10 if (IS_ERR(i2c->clk)) {
11 dev_err(&pdev->dev, \12 ret = -ENOENT; 13 goto out; 14 }
15 clk_enable(i2c->clk); 16
17 /* 映射寄存器 */
18 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 19 if (res == NULL) {
20 dev_err(&pdev->dev, \21 ret = -ENOENT; 22 goto out; 23 }