platform_driver注册过程

platform_driver注册过程.

platform_driver_register

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

	static struct platform_driver mxs_phy_driver = {
		.probe = mxs_phy_probe,
		.remove = mxs_phy_remove,
		.driver = {
			.name = DRIVER_NAME,
			.of_match_table = mxs_phy_dt_ids,
			.pm = &mxs_phy_pm,
		 },
	};

__platform_driver_register

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

设置总线类型为platform_bus_type.
设置platform函数操作集合.

platform_drv_probe

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);
		int ret;

		ret = of_clk_set_defaults(_dev->of_node, false);
		if (ret < 0)
			return ret;

		ret = dev_pm_domain_attach(_dev, true);
		if (ret != -EPROBE_DEFER) {
			if (drv->probe) {
				ret = drv->probe(dev);
				if (ret)
					dev_pm_domain_detach(_dev, true);
			} else {
				/* don't fail if just dev_pm_domain_attach failed */
				ret = 0;
			}
		}

		if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
			dev_warn(_dev, "probe deferral not supported\n");
			ret = -ENXIO;
		}

		return ret;
	}

platform device 和 driver 配置成功会调用这个函数.
根据设备树设置时钟.
调用drv->probe.

platform_bus_type

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

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

	const struct of_device_id *of_match_device(const struct of_device_id *matches,
						   const struct device *dev)
	{
		if ((!matches) || (!dev->of_node))
			return NULL;
		return of_match_node(matches, dev->of_node);
	}

调用platform_match进行匹配,优先级如下:

  • driver_override 和 drv->name
  • 设备树compatible 和 of_device_id
  • acpi
  • id_table 和 pdev->name
  • pdev->name 和 drv->name

driver_register

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

		BUG_ON(!drv->bus->p);

		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) {
			printk(KERN_ERR "Error: Driver '%s' is already registered, "
				"aborting...\n", drv->name);
			return -EBUSY;
		}

		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;
	}

driver_find查看driver防止重复注册.

bus_add_driver

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

		bus = bus_get(drv->bus);
		if (!bus)
			return -EINVAL;

		pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
		if (!priv) {
			error = -ENOMEM;
			goto out_put_bus;
		}
		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);
		if (error)
			goto out_unregister;

		klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
		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;
			}
		}
		module_add_driver(drv->owner, drv);

		error = driver_create_file(drv, &driver_attr_uevent);
		if (error) {
			printk(KERN_ERR "%s: uevent attr (%s) failed\n",
				__func__, drv->name);
		}
		error = driver_add_groups(drv, bus->drv_groups);
		if (error) {
			/* How the hell do we get out of this pickle? Give up */
			printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
				__func__, drv->name);
		}

		if (!drv->suppress_bind_attrs) {
			error = add_bind_files(drv);
			if (error) {
				/* Ditto */
				printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
					__func__, drv->name);
			}
		}

		return 0;
	}

driver_private分配内存,初始化,关联bus.
driver_attach进行driver 和 device 匹配.
最后在sysfs创建目录文件.

driver_attach

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)
			error = fn(dev, data);
		klist_iter_exit(&i);
		return error;
	}

bus_for_each_dev遍历bus下的所有device,调用__driver_attach.

__driver_attach

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

		/*
		 * Lock device and try to bind to it. We drop the error
		 * here and always return 0, because we need to keep trying
		 * to bind to devices and some drivers will return an error
		 * simply if it didn't support the device.
		 *
		 * driver_probe_device() will spit a warning if there
		 * is an error.
		 */

		ret = driver_match_device(drv, dev);
		if (ret == 0) {
			/* no match */
			return 0;
		} else if (ret == -EPROBE_DEFER) {
			dev_dbg(dev, "Device match requests probe deferral\n");
			driver_deferred_probe_add(dev);
		} else if (ret < 0) {
			dev_dbg(dev, "Bus failed to match device: %d", ret);
			return ret;
		} /* ret > 0 means positive match */

		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;
	}

调用bus->match匹配函数.

driver_probe_device

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

		pm_runtime_get_suppliers(dev);
		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);

		pm_runtime_put_suppliers(dev);
		return ret;
	}

really_probe

static int really_probe(struct device *dev, struct device_driver *drv)
	{
		int ret = -EPROBE_DEFER;
		int local_trigger_count = atomic_read(&deferred_trigger_count);
		bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) &&
				   !drv->suppress_bind_attrs;

		if (defer_all_probes) {
			/*
			 * Value of defer_all_probes can be set only by
			 * device_defer_all_probes_enable() which, in turn, will call
			 * wait_for_device_probe() right after that to avoid any races.
			 */
			dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
			driver_deferred_probe_add(dev);
			return ret;
		}

		ret = device_links_check_suppliers(dev);
		if (ret)
			return ret;

		atomic_inc(&probe_count);
		pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
			 drv->bus->name, __func__, drv->name, dev_name(dev));
		WARN_ON(!list_empty(&dev->devres_head));

	re_probe:
		dev->driver = drv;

		/* If using pinctrl, bind pins now before probing */
		ret = pinctrl_bind_pins(dev);
		if (ret)
			goto pinctrl_bind_failed;

		ret = dma_configure(dev);
		if (ret)
			goto dma_failed;

		if (driver_sysfs_add(dev)) {
			printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
				__func__, dev_name(dev));
			goto probe_failed;
		}

		if (dev->pm_domain && dev->pm_domain->activate) {
			ret = dev->pm_domain->activate(dev);
			if (ret)
				goto probe_failed;
		}

		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;
		}

		if (test_remove) {
			test_remove = false;

			if (dev->bus->remove)
				dev->bus->remove(dev);
			else if (drv->remove)
				drv->remove(dev);

			devres_release_all(dev);
			driver_sysfs_remove(dev);
			dev->driver = NULL;
			dev_set_drvdata(dev, NULL);
			if (dev->pm_domain && dev->pm_domain->dismiss)
				dev->pm_domain->dismiss(dev);
			pm_runtime_reinit(dev);

			goto re_probe;
		}

		pinctrl_init_done(dev);

		if (dev->pm_domain && dev->pm_domain->sync)
			dev->pm_domain->sync(dev);

		driver_bound(dev);
		ret = 1;
		pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
			 drv->bus->name, __func__, dev_name(dev), drv->name);
		goto done;
	done:
		atomic_dec(&probe_count);
		wake_up(&probe_waitqueue);
		return ret;
	}

pinctrl_bind_pins进行引脚bind和配置.
dma_configure进行dma配置.
dev->bus->probe, 在bus probe函数中调用driver 的probe.
driver_bound进行driver bind.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值