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函数
未完待续