煮熟的梨子是凉性的吗:platform_driver_register与of_register_platform_driver分析
来源:百度文库 编辑:中财网 时间:2024/05/21 20:58:17
在ARM体系结构中常见的是platform_driver_register
在powerpc中是of_register_platform_driver
下面通过具体的代码来分析其区别
platform_driver_register在driver/base/platform.c中定义
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
——————————————————————————————————
而of_register_platform_driver在of_platform.c中定义
static inline int of_register_platform_driver(struct of_platform_driver *drv)
{
return of_register_driver(drv, &of_platform_bus_type);
}
int of_register_driver()在driver/of/plateform.c中定义
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
drv->driver.bus = bus;
/* register with core */
return driver_register(&drv->driver);
}
而着最终都是调用的driver_register();
_____________________________________
这是由于二者结构获取硬件信息 的方式不同造成 的,在powerpc体系是通过dts
对比platform_driver和of_platform_driver
在include/linux/platform_device.h
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;
};
在include/linux/of_platform_device.h
struct of_platform_driver
{
int (*probe)(struct of_device* dev,
const struct of_device_id *match);
int (*remove)(struct of_device* dev);
int (*suspend)(struct of_device* dev, pm_message_t state);
int (*resume)(struct of_device* dev);
int (*shutdown)(struct of_device* dev);
struct device_driver driver;
};
#define to_of_platform_driver(drv) \
container_of(drv,struct of_platform_driver, driver)
of_device_id 和platform_device_id
可以看出 主要所区别在 of_device 和platform_device
***********************************************************
在arch/powerpc/include/asm/of_device.h定义了
/*
* The of_device is a kind of "base class" that is a superset of
* struct device for use by devices attached to an OF node and
* probed using OF properties.
*/
struct of_device
{
struct device dev; /* Generic device interface */
struct pdev_archdata archdata;
};
/*
* Struct used for matching a device
*/
struct of_device_id
{
char name[32];
char type[32];
char compatible[128]; //dts中看到这个东东了哈。通过它的匹配获取硬件资源
#ifdef __KERNEL__
void *data;
#else
kernel_ulong_t data;
#endif
};
——————————————————————————————————
在在include/linux/of_platform_device.h定义
struct platform_device {
const char * name;
int id;
struct device dev;//这个是通用的
u32 num_resources;
struct resource * resource; //获取硬件资源
const struct platform_device_id *id_entry;
/* arch specific additions */
struct pdev_archdata archdata;
};从上述定义的文件也可以发现powerpc 并不是一个通用的,和自己体系相关
struct platform_device_id {
char name[PLATFORM_NAME_SIZE];
kernel_ulong_t driver_data
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
*********************************
返回到我们的
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
drv->driver.bus = bus;
/* register with core */
return driver_register(&drv->driver);
}
bus 是从of_register_platform_driver中传入 of_platform_bus_type,是个全局变量在
arch/powerpc/kernel/of_platform.c中定义
struct bus_type of_platform_bus_type = {
.uevent = of_device_uevent,
};
of_device_uevent,在同上目录of_device.c定义
int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct of_device *ofdev;
const char *compat;
int seen = 0, cplen, sl;
if (!dev)
return -ENODEV;
ofdev = to_of_device(dev);
if (add_uevent_var(env, "OF_NAME=%s", ofdev->dev.of_node->name))
return -ENOMEM;
if (add_uevent_var(env, "OF_TYPE=%s", ofdev->dev.of_node->type))
return -ENOMEM;
/* Since the compatible field can contain pretty much anything
* it's not really legal to split it out with commas. We split it
* up using a number of environment variables instead. */
compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen);//根据compatible获取资源 具体看dts文件,在i2c学习中提过
while (compat && *compat && cplen > 0) {
if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
return -ENOMEM;
sl = strlen (compat) + 1;
compat += sl;
cplen -= sl;
seen++;
}
if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
return -ENOMEM;
/* modalias is trickier, we add it in 2 steps */
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
sizeof(env->buf) - env->buflen);
if (sl >= (sizeof(env->buf) - env->buflen))
return -ENOMEM;
env->buflen += sl;
return 0;
}
在powerpc中是of_register_platform_driver
下面通过具体的代码来分析其区别
platform_driver_register在driver/base/platform.c中定义
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
——————————————————————————————————
而of_register_platform_driver在of_platform.c中定义
static inline int of_register_platform_driver(struct of_platform_driver *drv)
{
return of_register_driver(drv, &of_platform_bus_type);
}
int of_register_driver()在driver/of/plateform.c中定义
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
drv->driver.bus = bus;
/* register with core */
return driver_register(&drv->driver);
}
而着最终都是调用的driver_register();
_____________________________________
这是由于二者结构获取硬件信息 的方式不同造成 的,在powerpc体系是通过dts
对比platform_driver和of_platform_driver
在include/linux/platform_device.h
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;
};
在include/linux/of_platform_device.h
struct of_platform_driver
{
int (*probe)(struct of_device* dev,
const struct of_device_id *match);
int (*remove)(struct of_device* dev);
int (*suspend)(struct of_device* dev, pm_message_t state);
int (*resume)(struct of_device* dev);
int (*shutdown)(struct of_device* dev);
struct device_driver driver;
};
#define to_of_platform_driver(drv) \
container_of(drv,struct of_platform_driver, driver)
of_device_id 和platform_device_id
可以看出 主要所区别在 of_device 和platform_device
***********************************************************
在arch/powerpc/include/asm/of_device.h定义了
/*
* The of_device is a kind of "base class" that is a superset of
* struct device for use by devices attached to an OF node and
* probed using OF properties.
*/
struct of_device
{
struct device dev; /* Generic device interface */
struct pdev_archdata archdata;
};
/*
* Struct used for matching a device
*/
struct of_device_id
{
char name[32];
char type[32];
char compatible[128]; //dts中看到这个东东了哈。通过它的匹配获取硬件资源
#ifdef __KERNEL__
void *data;
#else
kernel_ulong_t data;
#endif
};
——————————————————————————————————
在在include/linux/of_platform_device.h定义
struct platform_device {
const char * name;
int id;
struct device dev;//这个是通用的
u32 num_resources;
struct resource * resource; //获取硬件资源
const struct platform_device_id *id_entry;
/* arch specific additions */
struct pdev_archdata archdata;
};从上述定义的文件也可以发现powerpc 并不是一个通用的,和自己体系相关
struct platform_device_id {
char name[PLATFORM_NAME_SIZE];
kernel_ulong_t driver_data
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
*********************************
返回到我们的
int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
{
drv->driver.bus = bus;
/* register with core */
return driver_register(&drv->driver);
}
bus 是从of_register_platform_driver中传入 of_platform_bus_type,是个全局变量在
arch/powerpc/kernel/of_platform.c中定义
struct bus_type of_platform_bus_type = {
.uevent = of_device_uevent,
};
of_device_uevent,在同上目录of_device.c定义
int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct of_device *ofdev;
const char *compat;
int seen = 0, cplen, sl;
if (!dev)
return -ENODEV;
ofdev = to_of_device(dev);
if (add_uevent_var(env, "OF_NAME=%s", ofdev->dev.of_node->name))
return -ENOMEM;
if (add_uevent_var(env, "OF_TYPE=%s", ofdev->dev.of_node->type))
return -ENOMEM;
/* Since the compatible field can contain pretty much anything
* it's not really legal to split it out with commas. We split it
* up using a number of environment variables instead. */
compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen);//根据compatible获取资源 具体看dts文件,在i2c学习中提过
while (compat && *compat && cplen > 0) {
if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
return -ENOMEM;
sl = strlen (compat) + 1;
compat += sl;
cplen -= sl;
seen++;
}
if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
return -ENOMEM;
/* modalias is trickier, we add it in 2 steps */
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
sizeof(env->buf) - env->buflen);
if (sl >= (sizeof(env->buf) - env->buflen))
return -ENOMEM;
env->buflen += sl;
return 0;
}