platform_driver_registerAPI使用说明及原理分析

platform_driver_register API使用及原理

1. API 使用介绍

int platform_driver_register(struct platform_driver *drv)
	 1。 返回0代表成功,小于0出错
	 2。通常最少需要实现probe, remove 函数,
	 3。driver 中至少填入name 和 module,
	 4。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 (*suspend_late)(struct platform_device *, pm_message_t state);
    int (*resume_early)(struct platform_device *);
    int (*resume)(struct platform_device *);
    struct pm_ext_ops *pm;
    **struct device_driver** driver;
};

2. API 工作原理分析

2.1 platform_driver_register 函数分析

该函数比较简单,主要将user 传入function 加入到driver 字段中,然后调用driver_register 函数。
注:platform driver 可理解为区别于外设driver(USB, I2C, etc), 一般CPU 片上资源driver 或者一些不依赖外设driver
platform driver 向 driver/device 框注册时同样需要绑定bus type,即为platform_bus_type

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;
	if (drv->suspend)
		drv->driver.suspend = platform_drv_suspend;
	if (drv->resume)
		drv->driver.resume = platform_drv_resume;
	if (drv->pm)
		drv->driver.pm = &drv->pm->base;
	**return driver_register(&drv->driver);**
}

2.2 driver_register 函数分析

  1. 首先检查 bus 字段是否已初始化,(platform_init 时完成)
  2. driver_find 检查是否已注册过名字为name 的driver
  3. bus_add_driver 向platform_bus 注册该driver.
int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	if ((drv->bus->probe && drv->probe) ||
	    (drv->bus->remove && drv->remove) ||
	    (drv->bus->shutdown && drv->shutdown))
		printk(KERN_WARNING "Driver '%s' needs updating - please use "
			"bus_type methods\n", drv->name);

	other = driver_find(drv->name, drv->bus);
	if (other) {
		put_driver(other);
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EEXIST;
	}

	ret = bus_add_driver(drv);
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret)
		bus_remove_driver(drv);
	return ret;
}

2.3 bus_add_driver 函数分析

该函数判断是否为autoprobe driver, 执行 driver_attach 实现与device 绑定。

int bus_add_driver(struct device_driver *drv)
{
	struct bus_type *bus;
	struct driver_private *priv;
	int error = 0;

	bus = bus_get(drv->bus);

    //创建并且填充driver私有信息
	priv = kzalloc(sizeof(*priv), GFP_KERNEL); 
	klist_init(&priv->klist_devices, NULL, NULL);
	priv->driver = drv;
	drv->p = priv;
	priv->kobj.kset = bus->p->drivers_kset;
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
				     "%s", drv->name);

    // 支持autoprobe, 执行driver_attach
	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
	module_add_driver(drv->owner, drv);

    //其它相关文件节点创建及绑定
}

2.3 driver_attach函数分析

  1. 遍历所有device, 检查该driver 适用于哪个device, 匹配到一个device 即退出
int driver_attach(struct device_driver *drv)
{
	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
  1. __driver_attach 首先检查是否支持match 比较,使用对应match 函数检查dev, drv 是否匹配
    platform driver 使用platform 向bus 注册的match 函数。随后执行driver_probe_device
static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;

	if (drv->bus->match && !drv->bus->match(dev, drv))
		return 0;

	down(&dev->sem);
	if (!dev->driver)
		driver_probe_device(drv, dev);
	up(&dev->sem);

	return 0;
}
static int platform_match(struct device *dev, struct device_driver *drv)
{
	struct platform_device *pdev;

	pdev = container_of(dev, struct platform_device, dev);
	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
}

struct bus_type platform_bus_type = {
	.name		= "platform",
	.dev_attrs	= platform_dev_attrs,
	.match		= platform_match,
	.uevent		= platform_uevent,
	.pm		= PLATFORM_PM_OPS_PTR,
};

2.3 driver_probe_device函数分析

该函数负责将driver 对应 device 工作起来,具体实现在really_probe。

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

	if (!device_is_registered(dev))
		return -ENODEV;
	if (drv->bus->match && !drv->bus->match(dev, drv))
		goto done;

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

	ret = really_probe(dev, drv);

done:
	return ret;
}

really_probe 执行具体的dev->bus->probe 或者drv->probe,
drv->probe 为 2.1 中 由platform_driver_register 注册的函数,
platform_drv_probe, platform_drv_probe 解析出具体driver 的probe 函数,
至些driver probe 函数得到执行。

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

	atomic_inc(&probe_count);

	dev->driver = drv;
	
	if (dev->bus->probe) {
		ret = dev->bus->probe(dev);
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {
		ret = drv->probe(dev);
		if (ret)
			goto probe_failed;
	}

	driver_bound(dev);
	ret = 1;
	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
		 drv->bus->name, __func__, dev->bus_id, drv->name);
	goto done;

done:
	atomic_dec(&probe_count);
	wake_up(&probe_waitqueue);
	return ret;
}
static int platform_drv_probe(struct device *_dev)
{
	struct platform_driver *drv = to_platform_driver(_dev->driver);
	struct platform_device *dev = to_platform_device(_dev);

	return drv->probe(dev);
}

你可能感兴趣的:(Linux,c++,开发语言)