Linux PowerPC I2C驱动 之 I2C设备层的注册过程

Linux下i2c驱动的加载过程,分为i2c设备层、i2c adapter层与i2c核心层

i2c设备驱动层也就是我们为特定i2c设备编写的驱动,下面是我自己理解的i2c驱动的注册过程


在我们写的i2c设备驱动中,我们会调用i2c_add_driver()开始i2c设备驱动的注册,该函数调用i2c_register_driver完成所有注册操作

static inline int i2c_add_driver(struct i2c_driver *driver)

{

return i2c_register_driver(THIS_MODULE, driver);

}

i2c_register_driver会调用driver_register() 来将设备驱动添加到总线的设备驱动链表中:

int i2c_register_driver(struct module *owner, struct i2c_driver *driver)

{

int res;

/* Can't register until after driver model init */

if (unlikely(WARN_ON(!i2c_bus_type.p)))

return -EAGAIN;

driver->driver.owner = owner;

driver->driver.bus = &i2c_bus_type;

/* 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;

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

INIT_LIST_HEAD(&driver->clients);

/* Walk the adapters that are already present */

mutex_lock(&core_lock);

bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);

mutex_unlock(&core_lock);

return 0;

}

在driver_register中,通过driver_find来判断驱动是否已经注册,然后会调用bus_add_drive

将设备驱动添加到总线上


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

put_driver(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;

}

在bus_add_driver中初始化priv->klist_devices的值,并将priv赋值给drv->p

通过调用klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers)将驱动信息保存到总线结构中,在此之前将调用driver_attach()

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;

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

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_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",

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

}

}

kobject_uevent(&priv->kobj, KOBJ_ADD);

return 0;

out_unregister:

kfree(drv->p);

drv->p = NULL;

kobject_put(&priv->kobj);

out_put_bus:

bus_put(bus);

return error;

}

在driver_attach中,通过调用bus_for_each_dev,遍历在总线上挂载的所有设备,并对每个设备(dev)调用__driver_attach()

int driver_attach(struct device_driver *drv)

{

return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

}

在__driver_attach里会调用driver_match_device()来判断dev与driv的id是否相同,在i2c驱动里就会调用i2c_bus_type->match程序进行判断,

当id相同时,将会调用driver_probe_device()

static int __driver_attach(struct device *dev, void *data)

{

struct device_driver *drv = data;

/*

 * 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.

 */

if (!driver_match_device(drv, dev))

return 0;

if (dev->parent) /* Needed for USB */

down(&dev->parent->sem);

down(&dev->sem);

if (!dev->driver)

driver_probe_device(drv, dev);

up(&dev->sem);

if (dev->parent)

up(&dev->parent->sem);

return 0;

}

在driver_probe_device(),首先会调用device_is_registered()判断dev是否注册,若没注册则返回;若已经注册,则调用really_probe

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

pm_runtime_barrier(dev);

ret = really_probe(dev, drv);

pm_runtime_put_sync(dev);

return ret;

}

在really_probe()里,首先将drv赋值给dev->driver,然后会调用总线的probe函数,在i2c驱动里,

此时将会调用i2c总线的probe函数:i2c_device_probe

 

static int really_probe(struct device *dev, struct device_driver *drv)

{

int ret = 0;

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

dev->driver = drv;

if (driver_sysfs_add(dev)) {

printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",

__func__, dev_name(dev));

goto probe_failed;

}

if (dev->bus->probe) {//此处调用i2c总线的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_name(dev), drv->name);

goto done;

probe_failed:

devres_release_all(dev);

driver_sysfs_remove(dev);

dev->driver = NULL;

if (ret != -ENODEV && ret != -ENXIO) {

/* driver matched but the probe failed */

printk(KERN_WARNING

       "%s: probe of %s failed with error %d\n",

       drv->name, dev_name(dev), ret);

}

/*

 * Ignore errors returned by ->probe so that the next driver can try

 * its luck.

 */

ret = 0;

done:

atomic_dec(&probe_count);

wake_up(&probe_waitqueue);

return ret;

}

在i2c_device_probe()里,会根据to_i2c_driver(dev->driver)获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体i2c_driver,即

static struct i2c_driver XXX_driver = {

.driver = {

.name = "XXXX_name",

.owner = THIS_MODULE,

},

.probe = XXX_probe,

.remove = XXX_remove,

.id_table = XXX_id,

};

这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe()

 

static int i2c_device_probe(struct device *dev)

{

struct i2c_client *client = i2c_verify_client(dev);

struct i2c_driver *driver;

int status;

if (!client)

return 0;

driver = to_i2c_driver(dev->driver);

if (!driver->probe || !driver->id_table)

return -ENODEV;

client->driver = driver;

if (!device_can_wakeup(&client->dev))

device_init_wakeup(&client->dev,

client->flags & I2C_CLIENT_WAKE);

dev_dbg(dev, "probe\n");

status = driver->probe(client, i2c_match_id(driver->id_table, client));//执行我们写的probe函数

if (status)

client->driver = NULL;

return status;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值