Linux驱动:module_platform_driver


原文链接: Linux驱动:module_platform_driver

该宏是用来定义驱动的入口函数 module_platform_driver(hibvt_i2c_driver);

static SIMPLE_DEV_PM_OPS(hibvt_i2c_dev_pm, hibvt_i2c_suspend,
		hibvt_i2c_resume);

static const struct of_device_id hibvt_i2c_match[] = {
	{ .compatible = "hisilicon,hibvt-i2c"},
	{ .compatible = "hisilicon,hi3516cv300-i2c"},
	{ .compatible = "hisilicon,hi3536dv100-i2c"},
	{},
};
MODULE_DEVICE_TABLE(of, hibvt_i2c_match);

static struct platform_driver hibvt_i2c_driver = {
	.driver		= {
		.name	= "hibvt-i2c",
		.of_match_table = hibvt_i2c_match,
		.pm	= &hibvt_i2c_dev_pm,
	},
	.probe		= hibvt_i2c_probe,
	.remove		= hibvt_i2c_remove,
};

module_platform_driver(hibvt_i2c_driver);

/* 

module_platform_driver 宏等价于以下代码

static int __init hibvt_i2c_driver_init(void)
 {
   return platform_driver_register(&(hibvt_i2c_driver) );
 }
module_init(hibvt_i2c_driver_init); 

static void __exit hibvt_i2c_driver_exit(void) 
{ 
    platform_driver_unregister(&(hibvt_i2c_driver) ); 
} 
module_exit(hibvt_i2c_driver_exit);
*/
MODULE_AUTHOR("Pan Wen, <wenpan@hisilicon.com>");
MODULE_DESCRIPTION("HISILICON BVT I2C Bus driver");
MODULE_LICENSE("GPL v2");

使用方法:

include <linux/platform_device.h>

static struct platform_driver power_supply_driver ={
      .driver  = { 
        .name = "power-supply",
        .owner = THIS_MODULE,
        .of_match_table = power_supply_id_table,
    },
    .probe   = power_supply_probe,
    .remove  = power_supply_remove,
    .suspend = power_supply_suspend,
    .resume  = power_supply_resume,
}

module_platform_driver(power_supply_driver)

platform_driver

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 (*resume)(struct platform_device *);
    struct device_driver driver;
    const struct platform_device_id *id_table;
    bool prevent_deferred_probe;
 };

原理:

  • module_platform_driver :

#define module_platform_driver(__platform_driver) \
    module_driver(__platform_driver, platform_driver_register, \
            platform_driver_unregister)

上面的宏定义展开如下:

module_driver(power_supply_driver, platform_driver_register, \
            platform_driver_unregister)

  • module_driver

    定义:linux/device.h

#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
    return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
    __unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

展开规则:

__driver         ----->    power_supply_driver
    __register      ----->   platform_driver_unregister
    __unregister  ----->   platform_driver_register
    __VA_ARGS__ ----->  .....

注意

C99 引入了对参数个数可变的函数式宏的正式支持。在宏原型的末尾加上符号 ... (就像在参数可变的函数定义中), 宏定义中的伪宏__VA_ARGS__ 就会在调用是 替换成可变参数。
    ##__VA_ARGS__
    当可变参数...的个数为0 时,'##'操作将使预处理器(preprocessor)去除掉它前面的那个逗号,保证编译能够通过

所以上面的方法最终形式如下:

static int __init power_supply_driver_init(void)
 {
   return platform_driver_register(&(power_supply_driver) );
 }
module_init(power_supply_driver_init); 

static void __exit power_supply_driver_exit(void) 
{ 
    platform_driver_unregister(&(power_supply_driver) ); 
} 
module_exit(power_supply_driver_exit);

结论

驱动中使用module_platform_driver 来注册驱动 跟自定义module_init &&module_exit 的结果是一致的,module_platform_driver 更加简洁,推荐使用

`