总线是将设备与驱动联系在一起的纽带。
如果一个设备与驱动彼此绑在了一起,通过sys目录下的文件信息能看出其绑定的驱动/设备对象。
如:
~# ls /sys/bus/i2c/drivers/ad-7441/ -l
lrwxrwxrwx 1 root root 0 Jan 1 00:07 2-0070 -> ../../../../devices/platform/hisi_i2c.2/i2c-2/2-0070
--w------- 1 root root 4096 Jan 1 00:07 bind
--w------- 1 root root 4096 Jan 1 00:07 uevent
--w------- 1 root root 4096 Jan 1 00:07 unbind
可以看出i2c总线上的名字为ad-7441的i2c_driver找到了其绑定的设备。
同样有:
/sys/devices/platform/hisi_i2c.2/i2c-2# ls 2-0070/ -l
lrwxrwxrwx 1 root root 0 Jan 1 00:06 driver -> ../../../../../bus/i2c/drivers/ad-7441
-r--r--r-- 1 root root 4096 Jan 1 00:06 modalias
-r--r--r-- 1 root root 4096 Jan 1 00:06 name
drwxr-xr-x 2 root root 0 Jan 1 00:06 power
lrwxrwxrwx 1 root root 0 Jan 1 00:06 subsystem -> ../../../../../bus/i2c
-rw-r--r-- 1 root root 4096 Jan 1 00:06 uevent
/sys/devices/platform/hisi_i2c.2/i2c-2# cat 2-0082/name
adv8200
由于系统中没有i2c_add_driver 成员 id_table的name为adv8200的i2c_driver,所以,这里的2-0082是找不到自己的另一半的。
相反,系统中定义了:
const static struct i2c_device_id slaveid[]={
{.name="adv7441"},
{.name="GS2970"},
};
static struct i2c_driver adv7441_driver={
.probe=adv7441_probe,
.id_table=slaveid,
.driver = {
.name = "ad-7441",
.owner = THIS_MODULE,
},
};
ret=i2c_add_driver(&adv7441_driver);
就因为这样,ad-7441找到了driver,而8200却找不到driver。
通常情况下,在一个已经配置了i2c_adpter设备的系统中,如果要在内核中添加一个i2c从设备的驱动。最常用的做法是:
1. 定义 i2c_board_info,并执行i2c_register_board_info(int busnum,
struct i2c_board_info const *info, unsigned len)。该函数会申请分配i2c_board_info
并添加到__i2c_board_list为头的链表中。
struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
void *platform_data;
struct dev_archdata *archdata;
struct device_node *of_node;
int irq;
};
/*
* I2C slave devices
*/
static struct i2c_board_info __initdata i2c_devs[] = {
{ I2C_BOARD_INFO("testA8", 0xA8), },
{ I2C_BOARD_INFO("adv7441", 0x70), },
{ I2C_BOARD_INFO("adv8200", 0x82), },
};
i2c_register_board_info(2, i2c_devs, ARRAY_SIZE(i2c_devs))
2.定义i2c_driver结构体,由于i2c_bus_type的match函数是根据id_table来判断是否存在另一半的,因此i2c_driver中要定义合适的id_table字段。并执行i2c_add_driver把driver添加到i2c总线上,还可以定义probe函数,在probe函数中对i2c设备进行配置。。如:
static struct i2c_driver ds1307_driver = {
.driver = {
.name = "rtc-ds1307",
.owner = THIS_MODULE,
},
.probe = ds1307_probe,
.remove = __devexit_p(ds1307_remove),
.id_table = ds1307_id,
};
static const struct i2c_device_id ds1307_id[] = {
{ "ds1307", ds_1307 },
{ "ds1337", ds_1337 },
{ "ds1338", ds_1338 },
{ "ds1339", ds_1339 },
{ "ds1388", ds_1388 },
{ "ds1340", ds_1340 },
{ "ds3231", ds_3231 },
{ "m41t00", m41t00 },
{ "rx8025", rx_8025 },
{ }
};
const static struct i2c_device_id slaveid[]={
{.name="adv7441"},
{.name="GS2970"},
};
static struct i2c_driver adv7441_driver={
.probe=adv7441_probe,
.id_table=slaveid,
.driver = {
.name = "ad-7441",
.owner = THIS_MODULE,
},
};
那么i2c_register_driver都做了哪些操作呢?
i2c_register_driver中的i2c_driver参数,如果i2c_driver参数定义了address_list且地址探测成功,则会自动调用i2c_new_device来创建设备。
如:
/* This is the driver that will be inserted */
static struct i2c_driver ads7828_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "ads7828",
},
.probe = ads7828_probe,
.remove = ads7828_remove,
.id_table = ads7828_id,
.detect = ads7828_detect,
.address_list = normal_i2c,
};
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,I2C_CLIENT_END };
#define I2C_CLIENT_END 0xfffeU
跟踪内核源码,看i2c_register_driver的执行流程:
i2c_register_driver--》 i2c_for_each_dev(driver, __process_new_driver);---》i2c_do_add_adapter(data, to_i2c_adapter(dev));---》i2c_detect(adap, driver);---》 for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id, address_list[i]);
temp_client->addr = address_list[i];
err = i2c_detect_address(temp_client, driver);
if (unlikely(err))
break;
}
static int i2c_detect_address(struct i2c_client *temp_client,
struct i2c_driver *driver){
if (info.type[0] == '\0') {//i2c_board_info的type字段不为空
dev_err(&adapter->dev, "%s detection function provided "
"no name for 0x%x\n", driver->driver.name,
addr);
} else {
struct i2c_client *client;
/* Detection succeeded, instantiate the device */
dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
info.type, info.addr);
client = i2c_new_device(adapter, &info);
if (client)
list_add_tail(&client->detected, &driver->clients);
else
dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
info.type, info.addr);
}
}
另外在i2c_register_adapter中执行的是
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
一个是__process_new_driver,一个是__process_new_adapter,两个都执行了i2c_detect--》i2c_detect_address---》i2c_new_device。i2c_new_device中会给i2c_client的adpter成员赋值,然后会执行device_register,如果match函数返回真,则会执行i2c_device_probe。
不同的地方是__process_new_adapter执行的是 bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);遍历i2c_bus上的所有driver。
而i2c_register_driver用的是 i2c_for_each_dev(driver, __process_new_driver);---》bus_for_each_dev,遍历的是i2c_bus上的所有device的时候,可以根据device得到adpter,因为i2c_adapter中有device dev成员。通过#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
可以找到对应的adapter,然后adapter就可以作为i2c_detect的参数传进去。
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
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;
}
由此可见,在i2c_new_device的过程中,首选给client赋adapter,如果批评成功,调用了i2c_bus_type的probe函数后,又会给i2c_client赋i2c_driver。i2c_client的driver和adapter成员都会得到正确的赋值。
这说明在注册i2c_driver的时候,也可以自动的创建设备。
但不是必须这样自动创建设备的,有的i2c_driver中没有定义address_list也没有自定义attach函数,那么就不会自动创建i2c_device.
如果不在内核里做的话,可以实现i2c-dev.c的fops,在应用层调用read、write、ioctl、open系统调用来配置i2c设备。
看了上面的内容,你会觉得太表面化了,或者是心里没底,为什么这样做就可以呢。下面就来解释一下!
i2c总线结构可以分为3层:
1. i2c 核心层,主要是i2c-core.c,提供了i2c设备、驱动的注册、注销函数。I2C 通信方法(即“ algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
2. i2c设备层。这里说的设备包括“主设备从设备”,主设备是指i2c适配器,一般是集成到CPU的i2c模块,也可以是GPIO模拟的i2c模块。从设备是指我们的板子上用的支持i2c总线的芯片,如RTC、AD、E2PROM等。
3. I2C设备驱动层,驱动是指从设备的设备。主要工作是填充I2c_driver。
我觉得上面的分层比较好理解。有的书上分三层是: 核心层、总线层、设备驱动层。其中总线层是适配器端完成的,而设备驱动层是I2C硬件体系结构中设备端的实现的,主要是填充i2c_client和driver。
这样理解也行。可能是我对系统认识的不够深,仍然觉得我自己的理解比较通俗。
一个常识性的知识,就是当device_add或者driver_add的时候,都会把device或者driver添加到bus的 struct subsys_private *p;成员指向的对应链表头中,然后根据总线注册的时候是否允许drivers_autoprobe,来进行探测。探测的时候会根据总线的match函数返回结果来决定是否要绑定dev和driver。那么我们来看一下i2c_bus_type的注册后是否允许drivers_autoprobe.
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;//添加到总线上的设备链表
struct klist klist_drivers;//添加到总线上的驱动链表
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
static int __init i2c_init(void)
{
int retval;
retval = bus_register(&i2c_bus_type);
if (retval)
return retval;
}
int __bus_register(struct bus_type *bus, struct lock_class_key *key)
{
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->bus = bus;
bus->p = priv;
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
if (retval)
goto out;
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
**priv->drivers_autoprobe = 1;**
retval = kset_register(&priv->subsys);
}
很明显i2c_bus_type.p->drivers_autoprobe 是为1的。因此在添加i2c设备和i2c驱动的时候,会自动匹配另一半。而总线匹配条件一般是总线的match成员函数返回的。那么需要分析一下i2c总线的match函数:
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
if (!client)
return 0;
/* Attempt an OF style match */
if (of_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* 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)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
EXPORT_SYMBOL_GPL(i2c_bus_type);
i2c_driver的id_table里的name字段与client字段相同则返回真进行匹配。而clientd的name是从哪里来的呢?是在i2c_new_devie(adpter)的时候给赋值的。而i2c_new_device。如果执行了i2c_register_board_info,那么就会调用到i2c_scan_static_board_info。i2c_scan_static_board_info在扫描过程中,会尝试执行i2c_new_device进行匹配。匹配成功了设备与驱动就会绑定在一起。
在static int i2c_register_adapter(struct i2c_adapter *adap)中有
static int i2c_register_adapter(struct i2c_adapter *adap){
dev_set_name(&adap->dev, "i2c-%d", adap->nr);//i2c-012
adap->dev.bus = &i2c_bus_type;
adap->dev.type = &i2c_adapter_type;
res = device_register(&adap->dev);
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
/* Notify drivers */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
mutex_unlock(&core_lock);
}
static int __process_new_adapter(struct device_driver *d, void *data)
{
return i2c_do_add_adapter(to_i2c_driver(d), data);
}
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) {
dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
driver->driver.name);
dev_warn(&adap->dev, "Please use another way to instantiate "
"your i2c_client\n");
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
}
return 0;
}
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
{
const unsigned short *address_list;
struct i2c_client *temp_client;
int i, err = 0;
int adap_id = i2c_adapter_id(adapter);
address_list = driver->address_list;
if (!driver->detect || !address_list)
return 0;
/* Stop here if the classes do not match */
if (!(adapter->class & driver->class))
return 0;
/* Set up a temporary client to help detect callback */
temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!temp_client)
return -ENOMEM;
temp_client->adapter = adapter;
for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id, address_list[i]);
temp_client->addr = address_list[i];
err = i2c_detect_address(temp_client, driver);
if (unlikely(err))
break;
}
kfree(temp_client);
return err;
}
static int i2c_detect_address(struct i2c_client *temp_client,
struct i2c_driver *driver)
{
struct i2c_board_info info;
struct i2c_adapter *adapter = temp_client->adapter;
int addr = temp_client->addr;
int err;
/* Make sure the address is valid */
err = i2c_check_addr_validity(addr);
if (err) {
dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
addr);
return err;
}
/* Skip if already in use */
if (i2c_check_addr_busy(adapter, addr))
return 0;
/* Make sure there is something at this address */
if (!i2c_default_probe(adapter, addr))
return 0;
/* Finally call the custom detection function */
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = addr;
err = driver->detect(temp_client, &info);
if (err) {
/* -ENODEV is returned if the detection fails. We catch it
here as this isn't an error. */
return err == -ENODEV ? 0 : err;
}
/* Consistency check */
if (info.type[0] == '\0') {
dev_err(&adapter->dev, "%s detection function provided "
"no name for 0x%x\n", driver->driver.name,
addr);
} else {
struct i2c_client *client;
/* Detection succeeded, instantiate the device */
dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
info.type, info.addr);
client = i2c_new_device(adapter, &info);
if (client)
list_add_tail(&client->detected, &driver->clients);
else
dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
info.type, info.addr);
}
return 0;
}
static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
struct i2c_devinfo *devinfo;
down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
dev_err(&adapter->dev,
"Can't create device at 0x%02x\n",
devinfo->board_info.addr);
}
up_read(&__i2c_board_lock);
}
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
struct i2c_client *client;
int status;
client = kzalloc(sizeof *client, GFP_KERNEL);
if (!client)
return NULL;
client->adapter = adap;
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));**
/* Check for address validity */
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;
}
/* Check for address business */
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;
client->dev.type = &i2c_client_type;
client->dev.of_node = info->of_node;
/* For 10-bit clients, add an arbitrary offset to avoid collisions */
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;
out_err:
dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
"(%d)\n", client->name, client->addr, status);
out_err_silent:
kfree(client);
return NULL;
}
如果内核启动过程中没有执行i2c_register_board_info,那么__i2c_first_dynamic_bus_num的值就为0,是不会执行i2c_scan_static_board_info的。
但是仍然可以在系统起来后,以模块的形式调用i2c_new_device。如:
static struct i2c_board_info hi_info = {
I2C_BOARD_INFO("sensor_i2c", 0x6c),
};
static int hi_dev_init(void)
{
struct i2c_adapter *i2c_adap;
// use i2c0
i2c_adap = i2c_get_adapter(0);
sensor_client = i2c_new_device(i2c_adap, &hi_info);//可以使用这个client进行i2c设置。因为/
*struct i2c_client {
unsigned short flags; /* div., see below */
unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
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;
};*/
i2c_put_adapter(i2c_adap);
return 0;
}
由此可以知道执行i2c_register_board_info并添加了i2c_boar_info后,在以后执行i2c_register_adapter的时候是会主动扫描__i2c_board_list中的静态devinfo信息。如果没有执行i2c_register_board_info,那么可以通过i2c_new_device以模块的形式被动创建client。在i2c_new_device的时候执行device_add->bus.match?probe:return.
在i2c_register_adapter中有
if (adap->nr < __i2c_first_dynamic_bus_num)
i2c_scan_static_board_info(adap);
/* Notify drivers */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
mutex_unlock(&core_lock);
即当在i2c总线上注册适配器的时候,会扫描i2c总线上的drv,从i2c_bus_type.p.klist_drivers中查找驱动,遍历到一个有效的驱动后执行__process_new_adapter(drv,adap); —>i2c_do_add_adapter—->i2c_detect(adap, driver)和driver->attach_adapter。顾名思义,其中的i2c_detect就是检测i2c总线上可以使用的驱动是否与当前的适配器匹配。如果定义了i2c_driver的detect和address_list才会匹配{ if (!driver->detect || !address_list)
return 0;},匹配成功则把制作的client结构体添加到driver->clients的链表中。不过这种方法用的很少,一般在i2c_driver中不处理detect和address信息,因此这种Notify driver的方式很少用。
下面总结一下:
1.首先执行的是i2c_init-》bus_register(&i2c_bus_type);
postcore_initcall(i2c_init);
系统中有了i2c总线,才能将i2c总线的设备和驱动联系在一起。
2.完成i2c总线驱动即i2c适配器驱动,主要是adpter的algorithm成员。填充好adpter以后,用i2c_add_numbered_adapter--》i2c_register_adapter-->主动扫描__i2c_board_list中的i2c_board_info的i2c设备,如果有会执行i2c_new_device,并且在sys目录下会看到想应name的目录。--->扫描i2c总线上的所有驱动,来尝试匹配该适配器(现在基本不用)。
3.在设备驱动层要完成的是定义i2c_board_info和i2c_driver。
这样看上去,把i2c框架分成三层,i2c核心层、i2c总线层、i2c设备驱动层。这样的划分方式应该是更合理。其中i2c核心层定义了i2c适配器注册注销、i2cdriver注册注销,register_i2c_boardinfo、与具体的硬件无关的发生接收函数,如:i2c_master_send和i2c_master_recv。
加载模块调用内核态 I2C 读写程序示例:
此操作示例在内核态下通过 I2C 读写程序实现对 I2C 外围设备的读写操作。
步骤 1. 调用 I2C 核心层的函数,获得描述一个 I2C 控制器的结构体 i2c_adap:
i2c_adap = i2c_get_adapter(2);
假设我们已经知道新增的器件挂载在 I2C 控制器 2 上,直接设置 i2c_get_adapter 的参数为 2。
步骤 2. 把 I2C 控制器和新增的 I2C 外围设备关联起来,得到描述 I2C 外围设备的客户端结构
体 hi_client:
hi_client = i2c_new_device(i2c_adap, &hi_info);
hi_info 结构体提供了 I2C 外围设备的设备地址
步骤 3. 调用 I2C 核心层提供的标准读写函数对外围器件进行读写:
ret = i2c_master_send(client, buf, count);
ret = i2c_master_recv(client, buf, count);
其中i2c_master_send都是与具体的平台和硬件无关的接口,由i2c-core层定义,其中主要的是client,这个client对应于一个i2c设备,i2c_client里的adpter成员完成了i2c设备和CPU之间的通讯。
int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
{
int ret;
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg;
msg.addr = client->addr;
#ifdef CONFIG_ARCH_HI3516A
msg.flags = client->flags;
#else
msg.flags = client->flags & I2C_M_TEN;
#endif
msg.len = count;
msg.buf = (char *)buf;
ret = i2c_transfer(adap, &msg, 1);
/*
* If everything went ok (i.e. 1 msg transmitted), return #bytes
* transmitted, else error code.
*/
return (ret == 1) ? count : ret;
}
EXPORT_SYMBOL(i2c_master_send);
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
/* REVISIT the fault reporting model here is weak:
*
* - When we get an error after receiving N bytes from a slave,
* there is no way to report "N".
*
* - When we get a NAK after transmitting N bytes to a slave,
* there is no way to report "N" ... or to let the master
* continue executing the rest of this combined message, if
* that's the appropriate response.
*
* - When for example "num" is two and we successfully complete
* the first message but get an error part way through the
* second, it's unclear whether that should be reported as
* one (discarding status on the second message) or errno
* (discarding status on the first one).
*/
if (adap->algo->master_xfer) {
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
#endif
if (in_atomic() || irqs_disabled()) {
ret = i2c_trylock_adapter(adap);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
i2c_lock_adapter(adap);
}
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
i2c_unlock_adapter(adap);
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -EOPNOTSUPP;
}
}
EXPORT_SYMBOL(i2c_transfer);
而adap->algo->master_xfer就是与硬件和适配器有关的了,是驱动工程师要做的。如:
static const struct i2c_algorithm hi_i2c_algo = {
.master_xfer = hi_i2c_xfer,
.functionality = hi_i2c_func,
};
adap->algo = &hi_i2c_algo;
adap->dev.parent = &pdev->dev;
adap->nr = pdev->id;
adap->retries = CONFIG_HI_I2C_RETRIES;
errorcode = i2c_add_numbered_adapter(adap);
static int hi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct hi_i2c *pinfo;
int errorcode;
pinfo = (struct hi_i2c *)i2c_get_adapdata(adap);
pinfo->msgs = msgs;
pinfo->msg_num = num;
pinfo->msg_index = 0;
if (msgs->flags & I2C_M_RD)
errorcode = hi_i2c_read(pinfo);
else
errorcode = hi_i2c_write(pinfo);
return errorcode;
}
以i2c-dev.c提供的接口,通过应用程序读写i2c设备的方法:
用户态 I2C 读写程序示例:
此操作示例在用户态下通过 I2C 读写程序实现对 I2C 外围设备的读写操作。
步骤 1. 打开 I2C 总线对应的设备文件,获取文件描述符:
fd = open(“/dev/i2c-2”, O_RDWR);
步骤 2. 通过 ioctl 设置外围设备地址、外围设备寄存器位宽和数据位宽
ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
ioctl(fd, I2C_16BIT_REG, 0);
ioctl(fd, I2C_16BIT_DATA, 0);//ioctl 的第三个参数为 0 表示 8bit 位宽,为 1 表示 16bit 位宽。
步骤 3. 使用 read/wite 进行数据读写:
read(fd, recvbuf, reg_width);
write(fd, buf, (reg_width + data_width));
unsigned int reg_width = 1;
unsigned int data_width = 1;
unsigned int reg_step = 1;
HI_RET i2c_read(int argc, char* argv[])
{
int fd = -1;
int ret;
unsigned int i2c_num, device_addr, reg_addr, reg_addr_end;
char data;
char recvbuf[4];
int cur_addr;
memset(recvbuf, 0x0, 4);
fd = open("/dev/i2c-2", O_RDWR);
if (fd<0)
{
printf("Open i2c dev error!\n");
return -1;
}
ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
if (reg_width == 2)
ret = ioctl(fd, I2C_16BIT_REG, 1);
else
ret = ioctl(fd, I2C_16BIT_REG, 0);
if (ret < 0) {
printf("CMD_SET_REG_WIDTH error!\n");
close(fd);
return -1;
}
if (data_width == 2)
ret = ioctl(fd, I2C_16BIT_DATA, 1);
else
ret = ioctl(fd, I2C_16BIT_DATA, 0);
if (ret < 0) {
printf("CMD_SET_DATA_WIDTH error!\n");
close(fd);
return -1;
}
for (cur_addr = reg_addr; cur_addr < reg_addr_end + reg_width;
cur_addr += reg_step)
{
if (reg_width == 2) {
recvbuf[0] = cur_addr & 0xff;
recvbuf[1] = (cur_addr >> 8) & 0xff;
} else
recvbuf[0] = cur_addr & 0xff;
ret = read(fd, recvbuf, reg_width);
if (ret < 0) {
printf("CMD_I2C_READ error!\n");
close(fd);
return -1;
}
if (data_width == 2) {
data = recvbuf[0] | (recvbuf[1] << 8);
} else
data = recvbuf[0];
printf("0x%x 0x%x\n", cur_addr, data);
}
close(fd);
return 0;
}
i2c_write(int argc , char* argv[])
{
int fd = -1;
int ret =0, index = 0;
unsigned int i2c_num, device_addr, reg_addr, reg_value;
char buf[4];
fd = open("/dev/i2c-2", O_RDWR);
if(fd < 0)
{
printf("Open i2c dev error!\n");
return -1;
}
ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
if (reg_width == 2)
ret = ioctl(fd, I2C_16BIT_REG, 1);
else
ret = ioctl(fd, I2C_16BIT_REG, 0);
if (data_width == 2)
ret = ioctl(fd, I2C_16BIT_DATA, 1);
else
ret = ioctl(fd, I2C_16BIT_DATA, 0);
if (reg_width == 2) {
buf[index] = reg_addr & 0xff;
index++;
buf[index] = (reg_addr >> 8) & 0xff;
index++;
} else {
buf[index] = reg_addr & 0xff;
index++;
}
if (data_width == 2) {
buf[index] = reg_value & 0xff;
index++;
buf[index] = (reg_value >> 8) & 0xff;
index++;
} else {
buf[index] = reg_value & 0xff;
index++;
}
write(fd, buf, (reg_width + data_width));
if(ret < 0)
{
printf("I2C_WRITE error!\n");
return -1;
}
close(fd);
return 0;
}
下面简单分析一下i2c-dev.c
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,
};
static int i2cdev_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode);
struct i2c_client *client;
struct i2c_adapter *adap;
struct i2c_dev *i2c_dev;
i2c_dev = i2c_dev_get_by_minor(minor);
if (!i2c_dev)
return -ENODEV;
adap = i2c_get_adapter(i2c_dev->adap->nr);
if (!adap)
return -ENODEV;
.......
}
static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
char *tmp;
int ret;
struct i2c_client *client = file->private_data;
if (count > 8192)
count = 8192;
tmp = kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
#ifdef CONFIG_ARCH_HI3516A
copy_from_user(tmp, buf, count);
#endif
pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_recv(client, tmp, count);
if (ret >= 0)
ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
kfree(tmp);
return ret;
}
static ssize_t i2cdev_write(struct file *file, const char __user *buf,
size_t count, loff_t *offset)
{
int ret;
char *tmp;
struct i2c_client *client = file->private_data;
if (count > 8192)
count = 8192;
tmp = memdup_user(buf, count);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",
iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_send(client, tmp, count);
kfree(tmp);
return ret;
}
static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = file->private_data;
unsigned long funcs;
dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
cmd, arg);
switch (cmd) {
case I2C_SLAVE:
case I2C_SLAVE_FORCE:
/* NOTE: devices set up to work with "new style" drivers
* can't use I2C_SLAVE, even when the device node is not
* bound to a driver. Only I2C_SLAVE_FORCE will work.
*
* Setting the PEC flag here won't affect kernel drivers,
* which will be using the i2c_client node registered with
* the driver model core. Likewise, when that client has
* the PEC flag already set, the i2c-dev driver won't see
* (or use) this setting.
*/
if ((arg > 0x3ff) ||
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
return -EBUSY;
/* REVISIT: address could become busy later */
client->addr = arg;
return 0;
case I2C_TENBIT:
if (arg)
client->flags |= I2C_M_TEN;
else
client->flags &= ~I2C_M_TEN;
return 0;
case I2C_PEC:
if (arg)
client->flags |= I2C_CLIENT_PEC;
else
client->flags &= ~I2C_CLIENT_PEC;
return 0;
case I2C_16BIT_REG:
if (arg)
client->flags |= I2C_M_16BIT_REG;
else
client->flags &= ~I2C_M_16BIT_REG;
return 0;
case I2C_16BIT_DATA:
if (arg)
client->flags |= I2C_M_16BIT_DATA;
else
client->flags &= ~I2C_M_16BIT_DATA;
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
return put_user(funcs, (unsigned long __user *)arg);
case I2C_RDWR:
return i2cdev_ioctl_rdrw(client, arg);
case I2C_SMBUS:
return i2cdev_ioctl_smbus(client, arg);
case I2C_RETRIES:
client->adapter->retries = arg;
break;
case I2C_TIMEOUT:
/* For historical reasons, user-space sets the timeout
* value in units of 10 ms.
*/
client->adapter->timeout = msecs_to_jiffies(arg * 10);
break;
default:
/* NOTE: returning a fault code here could cause trouble
* in buggy userspace code. Some old kernel bugs returned
* zero in this case, and userspace code might accidentally
* have depended on that bug.
*/
return -ENOTTY;
}
return 0;
}
static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
unsigned long arg)
{
struct i2c_rdwr_ioctl_data rdwr_arg;
struct i2c_msg *rdwr_pa;
u8 __user **data_ptrs;
int i, res;
if (copy_from_user(&rdwr_arg,
(struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
rdwr_pa = memdup_user(rdwr_arg.msgs,
rdwr_arg.nmsgs * sizeof(struct i2c_msg));
if (IS_ERR(rdwr_pa))
return PTR_ERR(rdwr_pa);
data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
kfree(rdwr_pa);
return -ENOMEM;
}
res = 0;
for (i = 0; i < rdwr_arg.nmsgs; i++) {
/* Limit the size of the message to a sane amount;
* and don't let length change either. */
if ((rdwr_pa[i].len > 8192) ||
(rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
res = -EINVAL;
break;
}
data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);
if (IS_ERR(rdwr_pa[i].buf)) {
res = PTR_ERR(rdwr_pa[i].buf);
break;
}
}
if (res < 0) {
int j;
for (j = 0; j < i; ++j)
kfree(rdwr_pa[j].buf);
kfree(data_ptrs);
kfree(rdwr_pa);
return res;
}
res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
while (i-- > 0) {
if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
rdwr_pa[i].len))
res = -EFAULT;
}
kfree(rdwr_pa[i].buf);
}
kfree(data_ptrs);
kfree(rdwr_pa);
return res;
}
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
/* REVISIT the fault reporting model here is weak:
*
* - When we get an error after receiving N bytes from a slave,
* there is no way to report "N".
*
* - When we get a NAK after transmitting N bytes to a slave,
* there is no way to report "N" ... or to let the master
* continue executing the rest of this combined message, if
* that's the appropriate response.
*
* - When for example "num" is two and we successfully complete
* the first message but get an error part way through the
* second, it's unclear whether that should be reported as
* one (discarding status on the second message) or errno
* (discarding status on the first one).
*/
if (adap->algo->master_xfer) {
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
#endif
if (in_atomic() || irqs_disabled()) {
ret = i2c_trylock_adapter(adap);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
i2c_lock_adapter(adap);
}
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
i2c_unlock_adapter(adap);
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -EOPNOTSUPP;
}
}
EXPORT_SYMBOL(i2c_transfer);
i2c-dev.c创建了字符设备,主设备号都是89.次设备号跟adpter-nr的值一样,实现过程很简单,就不多说了,主要依赖于i2c适配器的algorithm的master_xfer成员函数。当用到具体的应用的时候,需要结合I2c适配器的algorithm的master_xfer成员函数和芯片手册。
如以下几个I2C硬件模块,其使用方法是不一样的。
下面以几个平台的I2C硬件模块为例,介绍一下集成到芯片内部的I2C控制器。
1.如Xarina的I2C模块,其中包含了64字节的RAM。其RAM地址空间分布如下:
在进行i2c写操作的时候,需要在RAM中准备好SLAVE地址和REG、数据,可以是多字节写入。硬件模块中提供了ICRAM寄存器,里面存放的是从RAM中发出或者读入的字节数。当i2C总线上产生起始位后,后续会将RAM中的数据写到总线上。在master端,软件上只需要控制总线的开始、再次开始、NACK、ACK时钟(只需要时钟,不需要判断SDA的电平,可以通过读取状态寄存器来判断是否有应答,这个状态寄存器是I2C硬件单元在通讯过程中自动更新的。发生NACK的时候也是硬件自动去发生的)、停止位。相对来说操作简单,而且用法灵活。
2.再如海思3516、3520D、3521、3535的I2c模块,则比较容易理解。其定义了ICR、TXR、RXR、CTRL、COMM寄存器。COMM寄存器的定义了起始位、停止位、读/写标志位,TXR专门用于发送数据的寄存器。每当写TXR寄存器后,再设置COMMAN寄存器,则会把数据从TXR传送到总线上(如果是起始位则直接写COMM即可)。如写0xa2设备的0x50寄存器为0xAA,则可以执行类似如下操作:
1.COMM.startbit=1 and COMM.writebit=1
2.waitfor_writeend(有专门状态寄存器反馈)
3.TXR=0xa2
4.COMM.writebit=1
5.同2
6.TXR=0x50
7.同4
8.同2
9.TXR=0xAA
10.同4
11.同2
3.再如海思3516A。这个芯片的I2C模块,操作更简单。有一个I2C_MST_SINGLE_CTRL的寄存器,
如果是读操作,就置bit30为1,如果为写操作就置bit30为0。I2C硬件模块会根据这个位的状态来判断是读还是写,还有一个寄存器MSG_CMD。
这个寄存器的bit[0-15]为写入或者读入的数据,bit[16-31]为需要读/写的寄存器地址。当然还有SLAVE_ADDRESS寄存器,这里就不列出了。
因此我们如果要写寄存器a8为0x37话,只需要设置I2C_MST_SIGLE_CMD为0xa837,将CTRL寄存器有0x80000000或上其他位的信息。在写寄存器的之前要等TXFIFO不满,要读数据的之前,要等RX FIFO不为空,当RXFIFO不空的时候,说明I2C硬件模块已经将数据准备好了,并且放到了CMD寄存器的低16位,这个过程是硬件自动完成的。因此软件的配置就显得相当简单,如要读寄存器0xa8。那么可以这样做:
1. 设设置slave的器件地址
2.等待TX_FIFO非满
3.写入CMD【31-16】,0xa8
4.等待RX_FIFO非空
5.从CMD【15-0】中把I2C的数据给取出来。
如果要写寄存器0xa8为0x37。就更简单了。
1. 设设置slave的器件地址
2. 等待TX_FIFO非满
3. 写入CMD【31-0】 为0xa837
对于这个模块,如下面要读取一个I2c的从设备,他的寄存器地址是16bits,寄存器数据是8bits,则下面的例子,可能是达不到你要的效果。 跟踪了一下HI3516A i2c驱动代码。当第一次写地址的时候,由于在写的时候没有准备写入的数据,只是告诉从设备要读取的地址。在驱动中就写0到寄存器了。而第二次执行了读操作,而读的时候没有指定寄存器地址,只是告诉了设备地址,因此是读不正确的。可以尝试只使用一个mgs。
读的过程也可以猜出来了吧。由此可知,在使用应用程序读写i2c设备的时候,同样的应用程序,在一个平台正确,则换个平台就不一定正确了,具体要看I2c模块介绍和Kernel里面的I2C驱动。
{
if((argc>3)&&(!strncmp("-r",argv[1],2))){
e2prom_data.nmsgs=2;
(e2prom_data.msgs[0]).len=2; //e2prom 目标数据的地址
(e2prom_data.msgs[0]).addr=strtoul((const char *)argv[2],0,0); // e2prom 设备地址
(e2prom_data.msgs[0]).flags&=~I2C_M_RD;//write
(e2prom_data.msgs[0]).flags|=I2C_M_16BIT_REG;
(e2prom_data.msgs[0]).flags&=~ I2C_M_16BIT_DATA;
(e2prom_data.msgs[0]).buf=(unsigned char*)malloc(2);
unsigned short buf = strtoul((const char *)argv[3],0,0);
printf("buf :%x\n", buf);
(e2prom_data.msgs[0]).buf[1]=((buf>>8)&0xff); //(unsigned char)atol(argv[3]);//e2prom数据地址(e2prom_data.msgs[0]).buf[0]=(buf>>8); //(unsigned char)atol(argv[3]);//e2prom数据地址
(e2prom_data.msgs[0]).buf[0]=(buf&0xff); //(unsigned char)atol(argv[3]);//e2prom数据地址
(e2prom_data.msgs[1]).len=1;//读出的数据
(e2prom_data.msgs[1]).addr=(e2prom_data.msgs[0]).addr;// e2prom 设备地址
(e2prom_data.msgs[1]).flags|=I2C_M_RD;//read
(e2prom_data.msgs[1]).flags|=I2C_M_16BIT_REG;
(e2prom_data.msgs[1]).flags&=~ I2C_M_16BIT_DATA;
(e2prom_data.msgs[1]).buf=(unsigned char*)malloc(1);//存放返回值的地址。
(e2prom_data.msgs[1]).buf[0]=0;//初始化读缓冲
ret=ioctl(fd,I2C_RDWR,(unsigned long)&e2prom_data);
}