Linux驱动中platfrom-driver/device注册及probe执行过程分析

1、platform系统

platfrom系统在linux内核中包含三个部分

①platfrom-bus虚拟总线,是一个内核抽象出来的虚拟的总线,在linux内核中以链表的形式表示,platform-driver/device通过挂载在platform虚拟总线上,实现设备和驱动之间的匹配,在内核表现形式为一系列platform-driver/device结构体组成的链表形式;

②platform-driver模型,内核中抽象出来的driver模型,表现形式为platfrom-driver的结构体,它的主要作用就是匹配paltform-device模型,获取paltform-device描述的物理设备的硬件资源,实现probe函数进行并进一步实现对真实物理设备的操作过程;

③platform-device模型,内核对真实物理设备的硬件资源进行抽象表示的一个虚拟模型,在内核表现形式为platform-device结构体;

2、platform-driver模型的注册过程(以8250串口驱动为例)

①通过内核提供的platform-driver结构体模型表示,包含对获取platform-device设备的初始化过程,初始化过程一般放在probe函数内,设备的卸载过程在remove函数内,即对相关内存资源进行释放;

static const struct of_device_id dw8250_of_match[] = {
	{ .compatible = "snps,dw-apb-uart" },
	{ .compatible = "cavium,octeon-3860-uart" },
	{ /* Sentinel */ }
};
static struct platform_driver dw8250_platform_driver = {
	.driver = {
		.name		= "dw-apb-uart",
		.pm		= &dw8250_pm_ops,
		.of_match_table	= dw8250_of_match,
		.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
	},
	.probe			= dw8250_probe,
	.remove			= dw8250_remove,
};

②platform-driver的注册过程及probe调用过程

module_platform_driver()函数是linux内核中很常用的一个宏定义,它在include/linux/platform_device.h中定义如下:

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

#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);


module_platform_driver(dw8250_platform_driver)宏定义展开后的形式为:

static int __init  dw8250_platfrom_driver_init(void)
{
        return platform_driver_register(&dw8250_platfrom_driver);
}
module_init( dw8250_platfrom_driver_init);    
static void __exit dw8250_platfrom_driver_init(void)
{
        return platform_driver_unregister(&dw8250_platfrom_driver);
}
module_exit(dw8250_platfrom_driver_exit);

platform_driver_register()函数即为platform_driver的注册函数,它的执行过程及调用probe函数的过程如下:

platform_driver_register(drv) - >__platform_driver_register(drv, THIS_MODULE) -> driver_register(&drv->driver) -> bus_add_driver(drv) -> driver_attach(drv) -> bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)

#define platform_driver_register(drv) \
	__platform_driver_register(drv, THIS_MODULE)

                    ↓

int __platform_driver_register(struct platform_driver *drv,
				struct module *owner)
{
	drv->driver.owner = owner;
	drv->driver.bus = &platform_bus_type;
	drv->driver.probe = platform_drv_probe;
	drv->driver.remove = platform_drv_remove;
	drv->driver.shutdown = platform_drv_shutdown;

	return driver_register(&drv->driver);
}

                    ↓

int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	.......

	ret = bus_add_driver(drv);      ↓
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret) {
		bus_remove_driver(drv);
		return ret;
	}
	kobject_uevent(&drv->p->kobj, KOBJ_ADD);

	return ret;
}


int bus_add_driver(struct device_driver *drv)
{
	......
	if (drv->bus->p->drivers_autoprobe) {
		if (driver_allows_async_probing(drv)) {
			pr_debug("bus: '%s': probing driver %s asynchronously\n",
			drv->bus->name, drv->name);
			async_schedule(driver_attach_async, drv);
		} else {
		error = driver_attach(drv);    ↓
		if (error)
		goto out_unregister;
		}
	}
	......
	return 0;
}

int driver_attach(struct device_driver *drv)
{
	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}

driver_match_device(drv, dev):这是driver注册过程中最关键的一部分,platform_driver遍历platform-bus总线(链表)上挂载的platform_device设备资源,对比属性是否相同,即对比compatible、id_table中的name、name属性,成功后向下调用probe函数

bus_for_each_dev(drv->bus, NULL, drv, __driver_attach) -> __driver_attach() -> driver_match_device(drv, dev) ->  platform_match(struct device *dev, struct device_driver *drv)

int driver_attach(struct device_driver *drv)
{
	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
               
                     ↓

int bus_for_each_dev(struct bus_type *bus, struct device *start,
		     void *data, int (*fn)(struct device *, void *))
{
	struct klist_iter i;
	struct device *dev;
	int error = 0;

	if (!bus || !bus->p)
		return -EINVAL;

	klist_iter_init_node(&bus->p->klist_devices, &i,
			     (start ? &start->p->knode_bus : NULL));
	while ((dev = next_device(&i)) && !error)      //遍历总线(platform_device组成的链表)
		error = fn(dev, data);  ↓                  
	klist_iter_exit(&i);
	return error;
}

static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;

	if (!driver_match_device(drv, dev))  ↓   //成功向下执行driver_probe_device(drv, dev);
		return 0;

	if (dev->parent)	/* Needed for USB */
		device_lock(dev->parent);
	device_lock(dev);
	if (!dev->driver)
		driver_probe_device(drv, dev);
	device_unlock(dev);
	if (dev->parent)
		device_unlock(dev->parent);

	return 0;
}

static inline int driver_match_device(struct device_driver *drv,
				      struct device *dev)
{
	return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}

                       ↓

struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_groups	= platform_dev_groups,
	.match		= platform_match,    ↓
	.uevent		= platform_uevent,
	.pm		= &platform_dev_pm_ops,
};

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_match_table
		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)                        //其次比较.id_table
		return platform_match_id(pdrv->id_table, pdev) != NULL;

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

匹配成功向下执行driver_probe_device(drv, dev),过程如下:

__driver_attach(struct device *dev, void *data) -> driver_probe_device(drv, dev)  -> really_probe(dev, drv) -> drv->probe(dev) [即dw8250_probe函数,并将匹配成功的platform_device设备资源作为参数传递给probe]

static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;

	if (!driver_match_device(drv, dev)) 
		return 0;

	if (dev->parent)	/* Needed for USB */
		device_lock(dev->parent);
	device_lock(dev);
	if (!dev->driver)
		driver_probe_device(drv, dev);   ↓
	device_unlock(dev);
	if (dev->parent)
		device_unlock(dev->parent);

	return 0;
}

int driver_probe_device(struct device_driver *drv, struct device *dev)
{
	int ret = 0;

	if (!device_is_registered(dev))
		return -ENODEV;

	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
		 drv->bus->name, __func__, dev_name(dev), drv->name);

	if (dev->parent)
		pm_runtime_get_sync(dev->parent);

	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);    ↓
	pm_request_idle(dev);

	if (dev->parent)
		pm_runtime_put(dev->parent);

	return ret;
}

static int really_probe(struct device *dev, struct device_driver *drv)
{
	int ret = 0;
	int local_trigger_count = atomic_read(&deferred_trigger_count);

    .......	

	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {
		ret = drv->probe(dev);   ↓    执行platform_driver的probe函数
		if (ret)
			goto probe_failed;
	}

    ......
   
	return ret;
}

static struct platform_driver dw8250_platform_driver = {
	.driver = {
		.name		= "dw-apb-uart",
		.pm		= &dw8250_pm_ops,
		.of_match_table	= dw8250_of_match,
		.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
	},
	.probe			= dw8250_probe,    //执行此函数
	.remove			= dw8250_remove,
};

3、platform-device(linux设备树版本)

设备树(即dts文件)一般放在:kernel/arch/arm64/boot/dts/soc厂家/具体的dts信息

在linux设备树版本中,物理设备硬件信息以新的方式被定义dts设备树节点,最终编译成platform_device类型,匹配流程类似与platform_driver,对比.compatible属性,成功执行probe函数

未完待续

 

猜你喜欢

转载自blog.csdn.net/QQ135102692/article/details/114528666