platform总线注册过程及platform_driver与platform_device的匹配

转载地址:http://xl028.blog.163.com/blog/static/199730242201231592010799/
我们知道,按platform结构写驱动,我们只需注册platform_device和platform_driver而不需要我们自己去注册platform总线,因为系统启动就有那条总线,那么它是怎么得到的呢?这里进行具体跟踪一下:

start_kernel——>rest_init——>kernel_thread(这个线程创建很重要)——>kernel_init——>do_basic_setup——>driver_init——>platform_bus_init

int __init platform_bus_init(void)
{
int error;

early_platform_cleanup();

error = device_register(&platform_bus);
if (error)
return error;
error = bus_register(&platform_bus_type);
if (error)
device_unregister(&platform_bus);
return error;
}

根据platform_bus_type总线类型得

struct bus_type platform_bus_type = {
.name = “platform”,
.dev_attrs = platform_dev_attrs,
.match = platform_match,//永远记住总线的match函数才是最终的设备与驱动的匹配函数,成功后会调用驱动的probe函数
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};

这里继续分析匹配过程:

platform_driver_register——>driver_register——>bus_add_driver——>driver_attach——>bus_for_each_dev——>__driver_attach——>driver_match_device——>drv->bus->match——>(*match)(struct device *dev, struct device_driver *drv);
这里找到总线类型中的match函数,这里只是个函数指针,很明显platform_bus_type结构下有具体match的实现,匹配后会自动调用驱动下的probe函数

struct bus_type {
const char *name;
struct bus_attribute *bus_attrs;
struct device_attribute *dev_attrs;
struct driver_attribute *drv_attrs;
do_basic_setup

int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);

int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);

const struct dev_pm_ops *pm;

struct bus_type_private *p;
};

static int platform_match(struct device *dev, struct device_driver *drv)//platform_bustype匹配函数
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);

/* match against the id table first */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;

/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
}

接下来看driver的probe函数是如何被调用的:

platform_driver_register——>driver_register——>bus_add_driver——>driver_attach——>bus_for_each_dev——>__driver_attach——>driver_probe_device——>really_probe——>drv->probe——>int (*probe) (struct device *dev)(这个函数指针就指向我们真正填写的device+driver下的probe)
注意:总线、设备、驱动结构中,总线的match函数负责匹配驱动与设备;然后匹配成功后会调用驱动中的probe函数,卸载驱动或设备的时候后调用release函数

你可能感兴趣的:(kernel-driver)