i2c总线
先来一张g-sensor原理图
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
/**
总线上提供了probe,
根据前面博文的浅析,匹配成功后,会优先调用总线提供的这个probe将会被调用。
i2c程序中 在总线提供的probe函数中,会调用驱动提供的probe函数
*/
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.suspend = i2c_device_suspend,
.resume = i2c_device_resume,
};
: match函数: i2c_device_match,
下面是一张函数调用流程图:
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
/**
struct i2c_client *i2c_verify_client(struct device *dev)
{
return (dev->type == &i2c_client_type)? to_i2c_client(dev): NULL;
}
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
对设备的验证,检查是否是client设备,
为什么要检查?
因为有两种类型的设备可以挂接再iic总线上:
i2c_client 表示 i2c总线下的一个从设备
i2c_adapter 表示 i2c总线控制器(总线控制器也是一种设备,也挂接再i2c总线的设备链表上,是什么时候挂上去的,下面有分析)
以上两种设备类型。是根据type来分辨的。
这里要要匹配的是 总线上挂接的设备i2c_client和对应的驱动。
下面会有一个函数 : __process_new_driver()它也是来判断设备的类型的,只不过 它检测如果不是i2c_adapter类型就会返回不往下执行了
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));
}
*/
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
/**
如果不是i2c_client设备,就立即返回
*/
if (!client)
{
return 0;
}
/*
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
获取对应的驱动
*/
driver = to_i2c_driver(drv);
/**
driver中的id_table中声明了驱动支持的设备,它是一个数组,因为id_table的出现
让一个驱动支持多个设备成为了可能,如果只是简单的直接比较name,那么一个驱动只能支持一个驱动
但是在i2c_match_id()函数中还是利用name来一一匹配的
*/
if (driver->id_table)
{
/**
看看 i2c_match_id()这个函数干了什么事情
这个函数主要就是遍历id_table中的每一个表项
while (id->name[0])
{
最终还是利用name来判断的。
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
*/
return i2c_match_id(driver->id_table, client) != NULL;
}
return 0;
}
/**
看一个内核中的例子:
static const struct i2c_device_id adt7473_id[] = {
{ "adt7473", adt7473 },
{ }
};
static struct i2c_driver adt7473_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "adt7473",
},
.probe = adt7473_probe,
.remove = adt7473_remove,
.id_table = adt7473_id,
.detect = adt7473_detect,
.address_data = &addr_data,
};
*/
i2c_device_probe
/**
这个函数也只是做了,设备与驱动绑定之后调用驱动的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);
/**
如果驱动没有提供probe函数,或者驱动没有提供id_table,就出错返回
*/
if (!driver->probe || !driver->id_table)
{
return -ENODEV;
}
/**
将设备与驱动绑定
*/
client->driver = driver;
/*
如果i2c设备可以唤醒,那么系统就唤醒它
*/
if (!device_can_wakeup(&client->dev))
{
device_init_wakeup(&client->dev,client->flags & I2C_CLIENT_WAKE);
}
dev_dbg(dev, "probe\n");
/**
调用驱动提供的probe函数
最终还是调用了驱动的probe,
其他的总线,如 usb、spi...都没有提供probe函数,由于总线上没有提供probe,那么就调用了
驱动的probe函数,但是iic总线提供的probe函数也没有做其他什么操作,只是简单的检查一下类型、绑定设备与驱动后
就草草的收场了,下面有一匹配的流程图。
*/
status = driver->probe(client, i2c_match_id(driver->id_table, client));
if (status)
{
client->driver = NULL;
}
return status;
}
匹配流程图
i2c_register_board_info
/**
这个函数没有创建i2c_client,
为每一个i2c设备分配了一个i2c_devinfo,将i2c_devinfo添加到全局__i2c_board_list链表上。
那么,
为什么要把iic设备的信息放到 __i2c_board_list 链表上呢?
什么时候才创建i2c_client呢,什么时候才进行注册呢?
下面在添加iic_adapter的时候 会扫面这条链表,将iic设备的信息取出来
通过i2c_new_device()->device_register()将这条链表上的iic设备 添加到设备驱动模型中。
所以 ,不管是那种方式注册iic设备,最终都是会调用i2c_new_device来注册的。
*/
int __init i2c_register_board_info(int busnum,struct i2c_board_info const *info, unsigned len)
{
int status;
/**
写者用来获取信号量,若没获得时,则调用者睡眠等待。
*/
down_write(&__i2c_board_lock);
/**
动态分配的I2C总线号总是大于静态分配的I2C总线号。
*/
if (busnum >= __i2c_first_dynamic_bus_num)
{
__i2c_first_dynamic_bus_num = busnum + 1;
}
/**
遍历struct i2c_board_info[]数组,
*/
for (status = 0; len; len--, info++)
{
/**
struct i2c_devinfo {
struct list_head list; //用于链接到__i2c_board_list链表
int busnum; //保存i2c设备依附的i2c总线号
struct i2c_board_info board_info;//用来保存i2c设备的信息
};
*/
struct i2c_devinfo *devinfo;
/**
为i2c_devinfo分配内存空间
*/
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
if (!devinfo)
{
pr_debug("i2c-core: can't register boardinfo!\n");
status = -ENOMEM;
break;
}
/**
赋值初始化 devinfo。
*/
devinfo->busnum = busnum;
devinfo->board_info = *info;
/**
将devinfo 添加到 __i2c_board_list 链表上。
*/
list_add_tail(&devinfo->list, &__i2c_board_list);
}
up_write(&__i2c_board_lock);
return status;
}
/**
` 下面是内核中使用的例子:
*/
static struct i2c_board_info __initdata h4_i2c_board_info[] = {
{
I2C_BOARD_INFO("isp1301_omap",0x2d),
},
{
I2C_BOARD_INFO("24c01",0x52),
},
{
I2C_BOARD_INFO("24c01",0x57),
}
};
static void __init omap_h4_init(void)
{
...
i2c_register_board_info(1,h4_i2c_board_info,ARRAY_SIZE(h4_i2c_board_info));
...
}
i2c_new_device
I2C设备是在适配器注册成功之后生成的。
那么如果要再适配器注册完成之后添加i2c设备,怎么办呢?可以使用i2c_new_device()这个函数
/**
这个函数一次只能注册一个设备,但是i2c_register_board_info可以一次注册多个设备
这是他们之间的一个区别,其实iic_register_board_info底层也是通过i2c_new_device来实现的。
i2c_new_device:断定 设备是已经存在的了,即使地址和设备的地址不符合也会成功。
如:
static struct i2c_board_info xxxx = {
I2C_BOARD_INFO("hmc5883l",0x1111),
};
实验中,也是能注册的。
其实,i2c_new_probed_device 最终也会调用i2c_new_device()函数,
只是在调用i2c_new_device之前,要检查设备是否存在。
它是怎么检查设备是否存在的呢?很简单,请往下面看。
创建i2c_client的方法有很多,比如:也可以从用户空间来创建设备,
但是不关是那种方法,最终都是间接或则直接的方式来调用 下面这个函数 i2c_new_device
这个函数,主要做了以下事情 :
1 : 分配了一个i2c_client结构体
1 : 根据传入的参数,对i2c_client进行了赋值
指明,i2c_client要挂在的总线
i2c_client的类型
2 : 调用device_register()将这个i2c_client注册到设备驱动模型中
*/
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
struct i2c_client *client;
int status;
/**
为i2c_client分配内存空间
*/
client = kzalloc(sizeof *client, GFP_KERNEL);
if (!client)
{
return NULL;
}
/**
与适配器绑定
*/
client->adapter = adap;
/**
保存设备数据, 如果有,保存起来,以后需要用的时候,可以从client->dev.platform_data拿出来
这个和 file->private_data 设计的都很好。
*/
client->dev.platform_data = info->platform_data;
if (info->archdata)
{
client->dev.archdata = *info->archdata;
}
client->flags = info->flags;//标志位
client->addr = info->addr; //设备地址
client->irq = info->irq; //中断号
strlcpy(client->name, info->type, sizeof(client->name));//名字
/**
检测地址是否有效.
对于 7位的设备地址来说,不能大于 0x7f. 下面有一个小例子 来验证这个.
if (client->addr == 0x00 || client->addr > 0x7f)
return -EINVAL;
*/
status = i2c_check_client_addr_validity(client);
if (status)
{
dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
goto out_err_silent;
}
/**
检测指定适配器上该地址状态
*/
status = i2c_check_addr_busy(adap, client->addr);
if (status)
goto out_err;
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type; //指定依附的总线
/**
本次注册的设备类型是i2c_client_type类型。
上面也说过,i2c_adapter也挂接在i2c总线上
*/
client->dev.type = &i2c_client_type;
client->dev.of_node = info->of_node;
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
client->addr | ((client->flags & I2C_CLIENT_TEN)
? 0xa000 : 0));
/**
任何设备的注册 都会经过这个函数,在以前的博文中已经分析过了
*/
status = device_register(&client->dev);
if (status)
{
goto out_err;
}
dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",client->name, dev_name(&client->dev));
return client;
}
i2c_new_probed_device
/**
probe函数是可以选择的
如果没有提供,会使用默认的probe函数。
这个默认的probe函数,其实就是通过发送一个start信号,看能不能得到一个ack信号
来判断的。
*/
struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info,
unsigned short const *addr_list,
int (*probe)(struct i2c_adapter *, unsigned short addr))
{
int i;
/**
如果没有提供probe函数,那么就使用默认的probe函数
上面说了,就是看能不能得到一个ack信号
*/
if (!probe)
{
probe = i2c_default_probe;
}
/**
遍历地址列表
*/
for (i = 0; addr_list[i] != I2C_CLIENT_END; i++)
{
/**
检测地址是否有效
*/
if (i2c_check_addr_validity(addr_list[i]) < 0) {
dev_warn(&adap->dev, "Invalid 7-bit address "
"0x%02x\n", addr_list[i]);
continue;
}
/* 检测指定适配器上该地址状态 */
if (i2c_check_addr_busy(adap, addr_list[i])) {
dev_dbg(&adap->dev, "Address 0x%02x already in "
"use, not probing\n", addr_list[i]);
continue;
}
/* 坚持能不能获取到ack信号 */
if (probe(adap, addr_list[i]))
{
break;
}
}
if (addr_list[i] == I2C_CLIENT_END)
{
dev_dbg(&adap->dev, "Probing failed, no device found\n");
return NULL;
}
/**
经过上面的判断,地址确切存在,
那么还是调用了i2c_new_device()函数
*/
info->addr = addr_list[i];
return i2c_new_device(adap, info);
}
i2c设备与驱动的关系
/**
注册i2c设备驱动
*/
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
int res;
if (unlikely(WARN_ON(!i2c_bus_type.p)))
{
return -EAGAIN;
}
driver->driver.owner = owner;
/**
设置总线为 i2c总线
设备驱动模型中的 device、driver通常都是嵌入在一个更大的结构体中,表示一些通用的信息
将设备注入设备驱动模型中 很方便。
*/
driver->driver.bus = &i2c_bus_type;
/**
所有驱动的注册都会经过这个函数,可以叫做驱动加入设备驱动模型的入口吧。
那么i2c_bus_type提供的probe函数就会被调用了
*/
res = driver_register(&driver->driver);
if(res)
{
return res;
}
INIT_LIST_HEAD(&driver->clients);
mutex_lock(&core_lock);
/**
下面有一幅图,是注册一个iic设备后的log信息。
遍历i2c总线上所有的设备(adapter device 和 client device)
源码 :
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
...
while ((dev = next_device(&i)) && !error)
//__attach_adapter被调用
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
static int __attach_adapter(struct device *dev, void *data)
{
struct i2c_adapter *adapter;
struct i2c_driver *driver = data;
这里检测如果设备不是适配器,那么就直接返回
在开头的i2c_device_match()函数也赏析过。
if (dev->type != &i2c_adapter_type)
{
return 0;
}
获取适配器
adapter = to_i2c_adapter(dev);
i2c_detect()这个函数会检测:
如果驱动没有提供detect的话 就不会往下执行了
if (!driver->detect || !address_data)
{
return 0;
}
i2c_detect(adapter, driver);
如果驱动提供了attach_adapter,那么就调用他。
在会调用device_create()函数来创建设备
if (driver->attach_adapter)
{
driver->attach_adapter(adapter);
}
return 0;
}
*/
bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
mutex_unlock(&core_lock);
return 0;
}
static int __init i2c_dev_init(void)
{
int res;
printk(KERN_INFO "i2c /dev entries driver\n");
/**
注册一个字符设备,他向vfs层提供的接口是 i2cdev_fops中定义的函数
下面会详细的分析这些操作函数
static const struct file_operations i2cdev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
.unlocked_ioctl = i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
*/
ret = register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops);
if(ret)
{
goto out;
}
/**
创建类
*/
i2c_dev_class = class_create(THIS_MODULE,"i2c-dev");
if(IS_ERR(i2c_dev_class))
{
ret = PTR_ERR(i2c_dev_class);
goto out_unreg_chrdev;
}
/**
注册一个i2c_driver
他是对i2c_register_driver()的封装,上面简单的赏析过。
看看这个i2cdev_driver
static struct i2c_driver i2cdev_driver = {
.driver = {
.name = "dev_driver",
},
.attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter,
};
*/
res = i2c_add_driver(&i2cdev_driver);
if(res)
{
goto out_unreg_class;
}
return 0;
}
注册一个iic设备后 ,iic-core 打印出来的log信息
iic的读写过程
/**
1 : 这个中断处理函数是在那里、什么时候被注册的?
在s3c24xx_i2c_probe()函数中会注册这个中断处理函数
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c;
i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &s3c24xx_i2c_algorithm;
i2c->adap.retries = 2;
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
i2c->tx_setup = 50;
.....
ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,dev_name(&pdev->dev), i2c);
.....
}
2 : 那么这个中断处理函数会在什么时候被调用呢?
有下面几种情况
1 : 总线仲裁错误.(1:控制器、从设备同时控制总线,2:多个从设备同时控制总线)
2 : 发送、接受一个字节的时候会发生中断
*/
static irqreturn_t s3c24xx_i2c_irq(int irqno,void * dev_id)
{
/**
这个dev_id有一个作用:
在被中断的进程 与 中断处理程序中传递数据
前面的博文已经分析过。
这个dev_id 是在s3c24xx_i2c_probe()函数中封装好的 s3c24xx_i2c
请参考上面的s3c24xx_i2c_probe函数
*/
struct s3c24xx_i2c * i2c = dev_id;
unsigned long status;
unsigned long tmp;
/**
读取IICSTAT寄存器的值
这个IICSTAT寄存器:
bit[5] 表示总线空闲、忙....
下面的函数 s3c24xx_i2c_set_master()函数会根据这一位来判断
总线的空、忙状态。
因为适配器要发送数据到 iic总线,首先要判断总线是不是空闲状态
而且他会每隔 1 ms 尝试一次,一共会尝试 400次。
下面会有讲解
*/
status = readl(i2c->regs + S3C2410_IICSTAT);
/**
#define S3C2410_IICSTAT_ARBITR (1<<3)
这里判断的是 由总线仲裁发生的中断
*/
if (status & S3C2410_IICSTAT_ARBITR)
{
dev_err(i2c->dev,"deal with arbitration loss\n");
}
/**
如果总线处于空闲状态,这里可能是因为不是读写而引发的中断
所以要清除中断
*/
if (i2c->state == STATE_IDLE)
{
dev_dbg(i2c->dev,"IRQ : error i2c->state == IDLE\n");
/**
读取IICCON寄存器
#define S3C2410_IICCON_IRQPEND (1<<4)
清[4]为0
*/
tmp = readl(i2c->regs + S3C2410_IICCON);
tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp,i2c->regs + S3C2410_IICCON);
goto out;
}
/**
这个函数很重要,下面详细分析
*/
i2s_s3c_irq_nextbyte(i2c,status);
out:
return IRQ_HANDLED;
}