linux设备与驱动是怎么匹配的,linux驱动之平台设备驱动模型(一):platform_device与platform_driver的匹配...

kernel版本:4.4.143

一、注册 platform_device 的过程

注册platform_device有两个入口

1.device_node转换为platform_device过程中

device_node转换为platform_device过程中,在of_platform_device_create_pdata函数中会调用of_device_add(dev)

int of_device_add(struct platform_device *ofdev)

int device_add(struct device *dev)

......

第一种注册platform_device的过程可参考设备树(三):device_node转换为platform_device

2.调用platform_device_register注册过程

int platform_device_register(struct platform_device *pdev)

int platform_device_add(struct platform_device *pdev)

int device_add(struct device *dev)

........

之后两个注册入口走下面的公共路径

int device_add(struct device *dev)

void bus_probe_device(struct device *dev)

void device_initial_probe(struct device *dev)

static int __device_attach(struct device *dev, bool allow_async)

static int __device_attach_driver(struct device_driver *drv, void *_data)

static inline int driver_match_device(struct device_driver *drv, struct device *dev)

return drv->bus->match ? drv->bus->match(dev, drv) : 1;

**最终调用platform_bus_type中的match函数指向的函数,即 static int platform_match(struct device dev, struct device_driver drv) //drivers\base\Platform.c

二、注册platform_deriver的过程

platform_deriver注册会在具体驱动中通过调用platform_driver_probe开始,例如

static int rockchip_cpuinfo_probe(struct platform_device *pdev) //pdev指向与该驱动匹配成功的platform_device

{

struct device *dev = &pdev->dev;

............

}

static const struct of_device_id rockchip_cpuinfo_of_match[] = {

{ .compatible = "rockchip,cpuinfo", },

{ },

};

MODULE_DEVICE_TABLE(of, rockchip_cpuinfo_of_match);

static struct platform_driver rockchip_cpuinfo_driver = {

.probe = rockchip_cpuinfo_probe,

.driver = {

.name = "rockchip-cpuinfo",

.of_match_table = rockchip_cpuinfo_of_match,

},

};

static int __init rockchip_cpuinfo_init(void)

{

return platform_driver_register(&rockchip_cpuinfo_driver);

}

**最终结果和注册 platform_device一样,调用platform_bus_type中的match函数指向的函数,即 static int platform_match(struct device dev, struct device_driver drv) //drivers\base\Platform.c

#define platform_driver_probe(drv, probe) __platform_driver_probe(drv, probe, THIS_MODULE)

int __init_or_module __platform_driver_probe(struct platform_driver *drv,int (*probe)(struct platform_device *), struct module *module)

int __platform_driver_register(struct platform_driver *drv,struct module *owner)

int driver_register(struct device_driver *drv)

int bus_add_driver(struct device_driver *drv)

int driver_attach(struct device_driver *drv)

static int __driver_attach(struct device *dev, void *data)

static inline int driver_match_device(struct device_driver *drv,struct device *dev)

{

return drv->bus->match ? drv->bus->match(dev, drv) : 1;

}

三、platform_device与platform_driver的匹配

匹配过程按优先顺序如下:

a. 比较 platform_dev.driver_override 和 platform_driver.drv->name

b. 比较 platform_dev.dev.of_node的compatible属性 和 platform_driver.drv->of_match_table

c. 比较 platform_dev.name 和 platform_driver.id_table->name

d. 比较 platform_dev.name 和 platform_driver.drv->name

有一个成功, 即匹配成功

static int platform_match(struct device *dev, struct device_driver *drv)

{

struct platform_device *pdev = to_platform_device(dev);

struct platform_driver *pdrv = to_platform_driver(drv);

/* When driver_override is set, only bind to the matching driver */

if (pdev->driver_override)

return !strcmp(pdev->driver_override, drv->name); //

/* Attempt an OF style match first */

if (of_driver_match_device(dev, drv)) // 驱动中of_device_id的compatible和device_node中的"compatible"属性比较

return 1;

/* Then try ACPI style match */

if (acpi_driver_match_device(dev, drv))

return 1;

/* Then try to match against the id table */

if (pdrv->id_table)

return platform_match_id(pdrv->id_table, pdev) != NULL; //platform_device的name和device_driver的platform_device_id中的name比较

/* fall-back to driver name match */

return (strcmp(pdev->name, drv->name) == 0); //platform_device的name和device_driver的name比较

}

在__driver_attach函数中platform_device与platform_driver匹配成功后,会调用driver_probe_device函数

int driver_probe_device(struct device_driver *drv, struct device *dev)

static int really_probe(struct device *dev, struct device_driver *drv)

dev->driver = drv;

drv->probe(dev); //调用device_driver的probe函数,最终调用platform_driver->probe

在driver_probe_device函数中接着完成2件事,

(1)platform_device的platform_device的device_driver 指向 platform_driver的device_driver

(2)调用驱动中的platform_driver.probe函数,至此一个platform_device或一个platform_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;

};

struct device_driver {

const char*name;

struct bus_type*bus; //struct bus_type platform_bus_type = {

//.name= "platform",

//.dev_groups= platform_dev_groups,

//.match= platform_match,

//.uevent= platform_uevent,

//.pm= &platform_dev_pm_ops,

//};

struct module*owner;

const char*mod_name;/* used for built-in modules */

bool suppress_bind_attrs;/* disables bind/unbind via sysfs */

enum probe_type probe_type;

const struct of_device_id*of_match_table;

const struct acpi_device_id*acpi_match_table;

int (*probe) (struct device *dev); //指向platform_drv_probe(platform.c),最终调用platform_driver->probe

int (*remove) (struct device *dev); //指向platform_drv_remove(platform.c),最终调用platform_driver->remove

void (*shutdown) (struct device *dev); 指向platform_drv_shutdown(platform.c),最终调用platform_driver->shutdown

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

int (*resume) (struct device *dev);

const struct attribute_group **groups;

const struct dev_pm_ops *pm;

struct driver_private *p; //p->driver指向自己

};

struct of_device_id {

charname[32];

chartype[32];

charcompatible[128];

const void *data;

};

struct platform_device_id {

char name[PLATFORM_NAME_SIZE];

kernel_ulong_t driver_data;

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值