现在的位置: 首页 > 综合 > 正文

I2C 子系统 –my

2013年07月16日 ⁄ 综合 ⁄ 共 23610字 ⁄ 字号 评论关闭

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函数了,所有的匹配都是用过它来的
}
//匹配成功返回1
static 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)假如匹配成功则将设备绑定到驱动链表中

抱歉!评论已关闭.