platform_driver注册过程

platform_driver注册过程platform_driver注册过程.__platform_driver_register设置总线类型为platform_bus_type.设置platform函数操作集合.platformdevice和driver配置成功会调用这个函数.根据设备树设置时钟.调用drv-probe.调用platform_match进行匹配,优先级如下:driver_find查看driver防止重复注册.driver_private分配内存,初始化,关联bus.driver_attach进行

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.

今天的文章platform_driver注册过程分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/25831.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注