I2C 子系统 --my

it2022-05-09  19

I2C 子系统转载请注明 来自  http://www.cnblogs.com/sdphome/一.重要结构体1.一个 i2c 设备的驱动程序由 i2c_driver数据结构描述,定义于 include/linux/i2c.h: struct i2c_driver { int id; unsigned int class; /* Notifies the driver that a new bus has appeared or is about to be * removed. You should avoid using this if you can, it will probably * be removed in a near future. */ int (*attach_adapter)(struct i2c_adapter *); int (*detach_adapter)(struct i2c_adapter *); /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); /* driver model interfaces that don't relate to enumeration */ void (*shutdown)(struct i2c_client *); int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(struct i2c_client *); /* a ioctl like command that can be used to perform specific functions * with the device. */ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); struct device_driver driver; const struct i2c_device_id *id_table; /* Device detection callback for automatic device creation */ int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *); const struct i2c_client_address_data *address_data; struct list_head clients;};2.一个 i2c 设备由 i2c_client数据结构进行描述: struct i2c_client { unsigned short flags; /* div., see below */ unsigned short addr; /* chip address - NOTE: 7bit */ char name[I2C_NAME_SIZE]; struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_driver *driver; /* and our access routines */ struct device dev; /* the device structure */ int irq; /* irq issued by device */ struct list_head detected;};3.一个 i2c 适配器由 i2c_adapter数据结构描述:struct i2c_adapter { struct module *owner; unsigned int id; unsigned int class; /* classes to allow probing for */ const struct i2c_algorithm *algo; /* the algorithm to access the bus */ void *algo_data; /* data fields that are valid for all devices */ u8 level; /* nesting level for lockdep */ struct mutex bus_lock; int timeout; /* in jiffies */ int retries; struct device dev; /* the adapter device */ int nr; char name[48]; struct completion dev_released;};4.具体 i2c 适配器的通信方法由 i2c_algorithm数据结构进行描述: struct i2c_algorithm { /* master_xfer should return the number of messages successfully processed, or a negative value on error */ int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data); /* To determine what the adapter supports */ u32 (*functionality) (struct i2c_adapter *);};二.i2c-core.c的初始化1.i2c_init函数static int __init i2c_init(void){ int retval; retval = bus_register(&i2c_bus_type); if (retval) return retval; retval = class_register(&i2c_adapter_class); if (retval) goto bus_err; retval = i2c_add_driver(&dummy_driver); if (retval) goto class_err; return 0;class_err: class_unregister(&i2c_adapter_class);bus_err: bus_unregister(&i2c_bus_type); return retval;}I2c总线通信方法1.init函数static struct platform_driver i2c_imx_driver = { .remove = __exit_p(i2c_imx_remove), .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, }};static int __init i2c_adap_imx_init(void){ return platform_driver_probe(&i2c_imx_driver, i2c_imx_probe);}subsys_initcall(i2c_adap_imx_init);注册申请一个platform驱动,并且启动时放在前面注册2. probe函数static int __init i2c_imx_probe(struct platform_device *pdev){ struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata; void __iomem *base; resource_size_t res_size; int irq; int ret; dev_dbg(&pdev->dev, "<%s>\n", __func__); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //得到地址资源 if (!res) { dev_err(&pdev->dev, "can't get device resources\n"); return -ENOENT; } irq = platform_get_irq(pdev, 0); //得到中断资源 if (irq < 0) { dev_err(&pdev->dev, "can't get irq number\n"); return -ENOENT; } pdata = pdev->dev.platform_data; if (pdata && pdata->init) { ret = pdata->init(&pdev->dev); if (ret) return ret; } res_size = resource_size(res); if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { ret = -EBUSY; goto fail0; } base = ioremap(res->start, res_size); //将物理地址映射成虚拟地址 if (!base) { dev_err(&pdev->dev, "ioremap failed\n"); dev_err(&pdev->dev, "ioremap failed\n"); ret = -EIO; goto fail1; } i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); if (!i2c_imx) { dev_err(&pdev->dev, "can't allocate interface\n"); ret = -ENOMEM; goto fail2; } /* Setup i2c_imx driver structure */ strcpy(i2c_imx->adapter.name, pdev->name); i2c_imx->adapter.owner = THIS_MODULE; i2c_imx->adapter.algo = &i2c_imx_algo; //总线通信方法 i2c_imx->adapter.dev.parent = &pdev->dev; i2c_imx->adapter.nr = pdev->id; i2c_imx->irq = irq; i2c_imx->base = base; i2c_imx->res = res; /* Get I2C clock */ i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); if (IS_ERR(i2c_imx->clk)) { ret = PTR_ERR(i2c_imx->clk); dev_err(&pdev->dev, "can't get I2C clock\n"); goto fail3; } /* Request IRQ */ //申请中断 ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); if (ret) { dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq); goto fail4; } /* Init queue */ init_waitqueue_head(&i2c_imx->queue); //初始化等待队列 /* Set up adapter data */ i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); /* Set up clock divider */ //配置i2c通信速率 if (pdata && pdata->bitrate) i2c_imx_set_clk(i2c_imx, pdata->bitrate); else i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE); /* Set up chip registers to defaults */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); writeb(0, i2c_imx->base + IMX_I2C_I2SR); /* Add I2C adapter */ ret = i2c_add_numbered_adapter(&i2c_imx->adapter); if (ret < 0) { dev_err(&pdev->dev, "registration failed\n"); goto fail5; } /* Set up platform driver data */ platform_set_drvdata(pdev, i2c_imx); dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq); dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n", i2c_imx->res->start, i2c_imx->res->end); dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n", res_size, i2c_imx->res->start); dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", i2c_imx->adapter.name); dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); return 0; /* Return OK */fail5: free_irq(i2c_imx->irq, i2c_imx);fail4: clk_put(i2c_imx->clk);fail3: kfree(i2c_imx);fail2: iounmap(base);fail1: release_mem_region(res->start, resource_size(res));fail0: if (pdata && pdata->exit) pdata->exit(&pdev->dev); return ret; /* Return error number */}static struct i2c_algorithm i2c_imx_algo = { .master_xfer = i2c_imx_xfer, .functionality = i2c_imx_func,};static int i2c_imx_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num){ unsigned int i, temp; int result; struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); /* Start I2C transfer */ result = i2c_imx_start(i2c_imx); //首先产生一个start信号 if (result) goto fail0; /* read/write data */ for (i = 0; i < num; i++) { if (i) { //产生restart信号,i=0时是第一条信息,不执行if中的内容 dev_dbg(&i2c_imx->adapter.dev, "<%s> repeated start\n", __func__); temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp |= I2CR_RSTA; //如果不是第一个消息,需要产生一个restart writeb(temp, i2c_imx->base + IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 1); /* 检测总线是否已经进入忙碌状态 */ if (result) goto fail0; } /* write/read data */ if (msgs[i].flags & I2C_M_RD) result = i2c_imx_read(i2c_imx, &msgs[i]); else result = i2c_imx_write(i2c_imx, &msgs[i]); if (result) goto fail0; }fail0: /* Stop I2C transfer */ i2c_imx_stop(i2c_imx); dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, (result < 0) ? "error" : "success msg", (result < 0) ? result : num); return (result < 0) ? result : num;}/* 如果for_busy为1,则需要I2SR这一位也为1才能跳出循环,可以看出这是一个检测超时的函数 一般用于检测忙碌位,如果是start信号后检测应该为忙,如果是stop信号后,应该是闲 */static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy){ unsigned long orig_jiffies = jiffies; /* 保存开始检测的时间 */ unsigned int temp; dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); while (1) { temp = readb(i2c_imx->base + IMX_I2C_I2SR); if (for_busy && (temp & I2SR_IBB)) break; if (!for_busy && !(temp & I2SR_IBB)) break; if (signal_pending(current)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C Interrupted\n", __func__); return -EINTR; } if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { /* 延时检测设为500ms */ dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C bus is busy\n", __func__); return -ETIMEDOUT; } schedule(); } return 0;}static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx){ int result; result = wait_event_interruptible_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); //100ms if (unlikely(result < 0)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); return result; } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); return -ETIMEDOUT; } dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); i2c_imx->i2csr = 0; return 0;}// 1.使能时钟,2.配置芯片速率寄存器3.清状态寄存器4.配置为主设备 master mode 5.检测总线是不是处于忙碌状态,如果是正确 6.使能中断static int i2c_imx_start(struct imx_i2c_struct *i2c_imx){ unsigned int temp = 0; int result; clk_enable(i2c_imx->clk); writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR); /* Enable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2SR); writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); /* 配置为从设备,disable中断 */ /* Wait controller to be stable */ udelay(50); /* Start I2C transaction */ temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp |= I2CR_MSTA; //master mode writeb(temp, i2c_imx->base + IMX_I2C_I2CR); result = i2c_imx_bus_busy(i2c_imx, 1); if (result) { printk("i2c busy 1 error : %s, ret=%d\n", __func__, result); return result; } i2c_imx->stopped = 0; temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; /* 使能中断,无应答信号 */ writeb(temp, i2c_imx->base + IMX_I2C_I2CR); return result;}static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx){ unsigned int temp = 0; if (!i2c_imx->stopped) { /* Stop I2C transaction */ dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); /* 配置为slave mode */ writeb(temp, i2c_imx->base + IMX_I2C_I2CR); } if (cpu_is_mx1()) { /* * This delay caused by an i.MXL hardware bug. * If no (or too short) delay, no "STOP" bit will be generated. */ udelay(i2c_imx->disable_delay); /* FIXME */ } if (!i2c_imx->stopped) { if (i2c_imx_bus_busy(i2c_imx, 0)) printk("i2c busy 0 error : %s\n", __func__); i2c_imx->stopped = 1; } /* Disable I2C controller */ writeb(0, i2c_imx->base + IMX_I2C_I2CR); clk_disable(i2c_imx->clk);}static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx){ if (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_RXAK) { dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__); return -EIO; /* No ACK */ } dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__); return 0;}/* the interrupt is set when one of the following occurs 1. one byte transfer is completed 2. an address is received that matches its own specific address in slave-receive mode 3. arbitration is lost */static irqreturn_t i2c_imx_isr(int irq, void *dev_id){ struct imx_i2c_struct *i2c_imx = dev_id; unsigned int temp; temp = readb(i2c_imx->base + IMX_I2C_I2SR); if (temp & I2SR_IIF) { /* save status register */ i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; writeb(temp, i2c_imx->base + IMX_I2C_I2SR); wake_up_interruptible(&i2c_imx->queue); return IRQ_HANDLED; } return IRQ_NONE;}static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs){ int i, result; dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n", __func__, msgs->addr << 1); /* write slave address */ writeb(msgs->addr << 1, i2c_imx->base + IMX_I2C_I2DR); /* 先写从设备地址 */ result = i2c_imx_trx_complete(i2c_imx); //写完地址查看是否收到中断 if (result) { printk("i2c try complete error addr: %s,ret=%d\n", __func__, result); return result; } result = i2c_imx_acked(i2c_imx); //写完地址,检测是否收到应该信号,如果检测不到会有I/O错误,一般是没有检测到芯片。 if (result) { printk("i2c acked error addr: %s,ret=%d\n", __func__, result); return result; } dev_dbg(&i2c_imx->adapter.dev, "<%s> write data\n", __func__); /* write data */ //开始写数据 for (i = 0; i < msgs->len; i++) { writeb(msgs->buf[i], i2c_imx->base + IMX_I2C_I2DR); //依次写数据 result = i2c_imx_trx_complete(i2c_imx); //检测是否收到中断,检测不到会有超时错误 if (result) { printk("i2c try complete error msg :%d: %s,ret=%d\n", i, __func__, result); return result; } result = i2c_imx_acked(i2c_imx); //检测是否收到应答信号 if (result) { printk("i2c acked error msg:%d : %s,ret=%d\n", i, __func__, result); return result; } } return 0;}static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs){ int i, result; unsigned int temp; /* write slave address */ //写地址,并且将最低位赋1,标志是读操作 writeb((msgs->addr << 1) | 0x01, i2c_imx->base + IMX_I2C_I2DR); result = i2c_imx_trx_complete(i2c_imx); //写完地址查看是否收到中断 if (result) { printk("i2c try complete error addr: %s,ret=%d\n", __func__, result); return result; } result = i2c_imx_acked(i2c_imx); //写完地址,检测是否收到应该信号,如果检测不到会有I/O错误,一般是没有检测到芯片 if (result) { printk("i2c acked error addr: %s,ret=%d\n", __func__, result); return result; } /* setup bus to read data */ temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp &= ~I2CR_MTX; //接收 if (msgs->len - 1) temp &= ~I2CR_TXAK; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); readb(i2c_imx->base + IMX_I2C_I2DR); /* dummy read */ dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__); /* read data */ for (i = 0; i < msgs->len; i++) { result = i2c_imx_trx_complete(i2c_imx); if (result) { printk("i2c try complete error msg:%d: %s,ret=%d\n", i, __func__, result); return result; } if (i == (msgs->len - 1)) { /* 最后一条信息 */ /* It must generate STOP before read I2DR to prevent controller from generating another clock cycle */ dev_dbg(&i2c_imx->adapter.dev, "<%s> clear MSTA\n", __func__); temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, i2c_imx->base + IMX_I2C_I2CR); if (i2c_imx_bus_busy(i2c_imx, 0)) printk("i2c busy error msg%d: %s\n", i, __func__); i2c_imx->stopped = 1; } else if (i == (msgs->len - 2)) { /* 倒数第二个信息 */ dev_dbg(&i2c_imx->adapter.dev, "<%s> set TXAK\n", __func__); temp = readb(i2c_imx->base + IMX_I2C_I2CR); temp |= I2CR_TXAK; writeb(temp, i2c_imx->base + IMX_I2C_I2CR); } msgs->buf[i] = readb(i2c_imx->base + IMX_I2C_I2DR); dev_dbg(&i2c_imx->adapter.dev, "<%s> read byte: B%d=0x%X\n", __func__, i, msgs->buf[i]); } return 0;}I2c_register_driver/***********************************************************/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; /* 将这个驱动添加到i2c驱动链表中,在驱动核心程序driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type;/*返回的时候,driver core已经执行过probe()对于所有匹配了但是unbound的设备*/ 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, __process_new_driver); mutex_unlock(&core_lock); return 0;}/***********************************************************/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);//在总线中找到和该驱动同名的驱动.说白了,就是看看这个驱动之前注册过没,返回NULL的话才能进行后续的驱动注册 if (other) { put_driver(other); //假如注册过,将不再进行注册,留意减少驱动引用,由于在driver_find中增加过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;}struct device_driver *driver_find(const char *name, struct bus_type *bus){ struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); //在总线集合中找到名称为name的kobject对象,实际就是驱动名称了,如果找到了,在这个函数里会增加驱动的引用计数,通过函数kobject_get函数 struct driver_private *priv; if (k) { //假如找到了 priv = to_driver(k); //通过kobject变量得到driver_private结构体 return priv->driver; //返回驱动指针 } return NULL;}void put_driver(struct device_driver *drv){ kobject_put(&drv->p->kobj); //减少引用计数kobject_put-→kref_put--->atomic_dec_and_test}int bus_add_driver(struct device_driver *drv){ struct bus_type *bus; struct driver_private *priv; int error = 0; bus =bus_get(drv->bus);//kset_get(&bus->p->subsys)查找与驱动相关的总线 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; //填充driver_private结构体,继承了device_driver drv->p = priv; //可以看出driver_private是device_driver的上一级结构体 priv->kobj.kset = bus->p->drivers_kset; //设置驱动kobject所属集合,显然这里就是对于总线的驱动集合了。对于kobject方面的知识尚需学习 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name); //初始化并添加驱动kobject对象到总线驱动中,其中包括kobject_init(kobj,ktype)和kobject_add_varg(kobj, parent, fmt, args)两个函数 //在kobject_init中通过kobject_init_internal初始化了一些kobject中的一些变量,同时使kobj->ktype = ktype;而ktype为driver_ktype的形参,static struct kobj_type driver_ktype = { .sysfs_ops = &driver_sysfs_ops, .release = driver_release,};static const struct sysfs_ops driver_sysfs_ops = { .show = drv_attr_show, .store = drv_attr_store,};//即设置了一些默认sys接口函数 if (error) goto out_unregister;//driver_autoprobe的初始值为1,默认允许自动进行匹配,则默认会执行下面的driver_attach if (drv->bus->p->drivers_autoprobe) { error = driver_attach(drv); //bus_for_each_dev,从bus中查找匹配的device 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: kobject_put(&priv->kobj); kfree(drv->p); drv->p = NULL;out_put_bus: bus_put(bus); return error;}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) return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, (start ? &start->p->knode_bus : NULL)); //初始化i结构体,klist_iter while ((dev = next_device(&i)) && !error) //在总线设备链表中遍历链表 error = fn(dev, data); //然后将设备和驱动匹配,fn=__driver_attach klist_iter_exit(&i); //清除结构体 return error;}struct klist_iter { struct klist *i_klist; //所属链表 struct klist_node *i_cur; //链表中的节点};void klist_iter_init_node(struct klist *k, struct klist_iter *i, struct klist_node *n){ i->i_klist = k; i->i_cur = n; //这里n为NULL if (n) kref_get(&n->n_ref);}static struct device *next_device(struct klist_iter *i){ struct klist_node *n = klist_next(i); //以i->i_cur节点为出发点,得到链表i->i_klist的下一个节点 struct device *dev = NULL; struct device_private *dev_prv; if (n) { //假如有返回该设备 dev_prv = to_device_private_bus(n); dev = dev_prv->device; } return dev;}struct klist_node *klist_next(struct klist_iter *i){ void (*put)(struct klist_node *) = i->i_klist->put; struct klist_node *last = i->i_cur; struct klist_node *next; spin_lock(&i->i_klist->k_lock); if (last) { //这里的last为空 next = to_klist_node(last->n_node.next); if (!klist_dec_and_del(last)) put = NULL; } else next = to_klist_node(i->i_klist->k_list.next); //得到链表的第一个节点 i->i_cur = NULL; while (next != to_klist_node(&i->i_klist->k_list)) { //遍历链表,假如没有到头 if (likely(!knode_dead(next))) { //假如发现节点next为有效节点 kref_get(&next->n_ref); //增加节点引用 i->i_cur = next; //将i结构的起始节点设为next break; //找到有效节点则退出 } next = to_klist_node(next->n_node.next); //继续遍历链表中的下一个节点 } spin_unlock(&i->i_klist->k_lock); if (put && last) put(last); return i->i_cur;}static int __driver_attach(struct device *dev, void *data){ struct device_driver *drv = data; if (!driver_match_device(drv, dev)) //将驱动和设备匹配,假如成功返回1,1取反为0,则继续向下执行。 return 0;//总线没有匹配成功没关系,因为它只是一个很低级的匹配函数,我们还有更高级的 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;//这里就要用到总线的match函数了,所有的匹配都是用过它来的}//匹配成功返回1static int i2c_device_match(struct device *dev, struct device_driver *drv){ struct i2c_client *client =i2c_verify_client(dev);//根据dev得到上级的i2c_client//i2c_client结构体是在i2c-core中进行注册申请的,根据平台文件产生的__i2c_board_list来生成 struct i2c_driver *driver; if (!client) return 0; driver = to_i2c_driver(drv); //根据标准driver得到上级的i2c_driver /* match on an id table if there is one */ if (driver->id_table) return i2c_match_id(driver->id_table, client) != NULL; return 0;}static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, const struct i2c_client *client){ //通过name匹配 while (id->name[0]) { if (strcmp(client->name, id->name) == 0) return id; id++; } return NULL;}staticint 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); //真正执行probe,探测函数 pm_runtime_put_sync(dev); return ret;}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) { //假如总线的probe函数存在,就用总线的。在总线的probe里会调用驱动的probe ret = dev->bus->probe(dev); if (ret) goto probe_failed; } else if (drv->probe) { //总线不存在,则用驱动的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;}static int i2c_device_probe(struct device *dev){ struct i2c_client *client = i2c_verify_client(dev); //得到i2c_client结构 struct i2c_driver *driver; int status; if (!client) return 0; driver = to_i2c_driver(dev->driver); //得到i2c_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) { //返回0为正确执行 client->driver = NULL; i2c_set_clientdata(client, NULL); } return status;}static void driver_bound(struct device *dev){ if (klist_node_attached(&dev->p->knode_driver)) { //假如设备已经绑定了一个驱动,则返回 printk(KERN_WARNING "%s: device %s already bound\n", __func__, kobject_name(&dev->kobj)); return; } pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev), __func__, dev->driver->name); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); //将设备节点插入到该设备对应的驱动链表上 if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev); //将device添加到driver的支持列表,并通知bus上的设备,表明BOUND_DRIVER}int klist_node_attached(struct klist_node *n){ return (n->n_klist != NULL); //n_klist变量不为空说明已经绑定过,否则为未绑定}void module_add_driver(struct module *mod, struct device_driver *drv){ char *driver_name; int no_warn; struct module_kobject *mk = NULL; if (!drv) return; if (mod) //本例中为THIS_MODULE,执行下面的 mk = &mod->mkobj; else if (drv->mod_name) { struct kobject *mkobj; /* Lookup built-in module entry in /sys/modules */ mkobj = kset_find_obj(module_kset, drv->mod_name); if (mkobj) { mk = container_of(mkobj, struct module_kobject, kobj); /* remember our module structure */ drv->p->mkobj = mk; /* kset_find_obj took a reference */ kobject_put(mkobj); } } if (!mk) return; /* Don't check return codes; these calls are idempotent */ no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module"); driver_name = make_driver_name(drv); if (driver_name) { module_create_drivers_dir(mk); no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, driver_name); kfree(driver_name); }}int driver_add_groups(struct device_driver *drv, const struct attribute_group **groups){ int error = 0; int i; if (groups) { for (i = 0; groups[i]; i++) { error = sysfs_create_group(&drv->p->kobj, groups[i]); if (error) { while (--i >= 0) sysfs_remove_group(&drv->p->kobj, groups[i]); break; } } } return error;}static int __process_new_driver(struct device *dev, void *data){ if (dev->type != &i2c_adapter_type) return 0; return i2c_do_add_adapter(data, to_i2c_adapter(dev));}static int i2c_do_add_adapter(struct i2c_driver *driver, struct i2c_adapter *adap){ /* Detect supported devices on that bus, and instantiate them */ i2c_detect(adap, driver); /* Let legacy drivers scan this bus for matching devices */ if (driver->attach_adapter) { /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } return 0;}/***********************************************************/驱动注册流程1.在总线上找找该驱动有没有被注册过2.若没有注册过,则将驱动加进到总线驱动集合中3.在总线上找能匹配驱动的设备1)将总线上每个设备进行匹配2)首先用总线的match函数进行低级匹配3)然后再用总线的probe函数进行高级匹配,若失败,则用驱动上的probe进行高级匹配4)假如匹配成功则将设备绑定到驱动链表中

转载于:https://www.cnblogs.com/sdphome/archive/2011/09/26/2191243.html


最新回复(0)