驱动 driver 相关的函数

查看注册虚拟 platform 和 I2c 驱动共同点

/**
 *	platform_driver_register
 *	@drv: platform driver structure
 */
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;
	return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
/* ------------------------------------------------------------------------- */

/*
 * An i2c_driver is used with one or more i2c_client (device) nodes to access
 * i2c slave chips, on a bus instance associated with some i2c_adapter.  There
 * are two models for binding the driver to its device:  "new style" drivers
 * follow the standard Linux driver model and just respond to probe() calls
 * issued if the driver core sees they match(); "legacy" drivers create device
 * nodes themselves.
 */

int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
	int res;

	/* new style driver methods can't mix with legacy ones */
	if (is_newstyle_driver(driver)) {
		if (driver->attach_adapter || driver->detach_adapter
				|| driver->detach_client) {
			printk(KERN_WARNING
					"i2c-core: driver [%s] is confused\n",
					driver->driver.name);
			return -EINVAL;
		}
	}

	/* add the driver to the list of i2c drivers in the driver core */
	driver->driver.owner = owner;
	driver->driver.bus = &i2c_bus_type;

	/* for new style drivers, when registration returns the driver core
	 * will have called probe() for all matching-but-unbound devices.
	 */
	res = driver_register(&driver->driver);
	if (res)
		return res;

	mutex_lock(&core_lists);

	list_add_tail(&driver->list,&drivers);
	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);

	/* legacy drivers scan i2c busses directly */
	if (driver->attach_adapter) {
		struct i2c_adapter *adapter;

		list_for_each_entry(adapter, &adapters, list) {
			driver->attach_adapter(adapter);
		}
	}

	mutex_unlock(&core_lists);
	return 0;
}
EXPORT_SYMBOL(i2c_register_driver);

由上可得
driver->driver.bus = &i2c_bus_type;

res = driver_register(&driver->driver);

int driver_register(struct device_driver * drv)
{
	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);
	}
	klist_init(&drv->klist_devices, NULL, NULL);
	return bus_add_driver(drv);
}
void klist_init(struct klist * k, void (*get)(struct klist_node *),
		void (*put)(struct klist_node *))
{
	INIT_LIST_HEAD(&k->k_list);//初始化头节点
	spin_lock_init(&k->k_lock);//初始化自旋锁
	k->get = get;
	k->put = put;
}
/**
 1. bus_add_driver - Add a driver to the bus.
 2. @drv:	driver.
 3.  */
int bus_add_driver(struct device_driver *drv)
{
	struct bus_type * bus = get_bus(drv->bus);
	int error = 0;

	if (!bus)
		return -EINVAL;

	pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
	error = kobject_set_name(&drv->kobj, "%s", drv->name);
	if (error)
		goto out_put_bus;
	drv->kobj.kset = &bus->drivers;
	if ((error = kobject_register(&drv->kobj)))
		goto out_put_bus;

	if (drv->bus->drivers_autoprobe) {
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
	klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
	module_add_driver(drv->owner, drv);

	error = driver_add_attrs(bus, drv);
	if (error) {
		/* How the hell do we get out of this pickle? Give up */
		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
			__FUNCTION__, drv->name);
	}
	error = add_bind_files(drv);
	if (error) {
		/* Ditto */
		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
			__FUNCTION__, drv->name);
	}

	return error;
out_unregister:
	kobject_unregister(&drv->kobj);
out_put_bus:
	put_bus(bus);
	return error;
}
int bus_add_driver(struct device_driver *drv)
	|---> bus_get/*获取总线类型(bus_type)*/
    |--->driver_attach //调用该函数,那么drv驱动程序会和drv所在总线上连接了的物理设备进行一一匹配
    |--->module_add_driver //添加drv的module
    |--->driver_add_attrs//加入driver目录下
    |--->add_bind_files //add_bind_files()函数(实际上是由add_bind_files()函数调用driver_create_file()函数)在sys文件系统下为其创建一个新的目录。

driver_attach
查看
driver_attach()函数 分析

可以学习到的函数

platform_driver_register
driver_register    // driver->driver.bus = &i2c_bus_type;    被 driver_register 需要
INIT_LIST_HEAD(&k->k_list);//初始化头节点
spin_lock_init(&k->k_lock);//初始化自旋锁
int bus_add_driver(struct device_driver *drv)
	|---> bus_get/*获取总线类型(bus_type)*/
    |--->driver_attach //调用该函数,那么drv驱动程序会和drv所在总线上连接了的物理设备进行一一匹配
    |--->module_add_driver //添加drv的module
    |--->driver_add_attrs//加入driver目录下
    |--->add_bind_files //add_bind_files()函数(实际上是由add_bind_files()函数调用driver_create_file()函数)在sys文件系统下为其创建一个新的目录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值