I2C 核心(drivers/i2c/i2c-core.c)中提供了一组不依赖于硬件平台的接口函数,这个文件一般不需要被工程师修改,但是理解其中的主要函数非常关键,因为 I2C 总线驱动和设备驱动之间依赖于 I2C 核心作为纽带。I2C 核心中的主要函数如下。
(1)增加/删除 i2c_adapter。
int i2c_add_adapter(struct i2c_adapter *adap); int i2c_del_adapter(struct i2c_adapter *adap);(2)增加/删除 i2c_driver。
int i2c_register_driver(struct module *owner, struct *driver); int i2c_del_driver(struct i2c_driver *driver); inline int i2c_add_driver(struct i2c_driver *driver);(3)i2c_client 依附/脱离。
int i2c_attach_client(struct i2c_client *client); int i2c_detach_client(struct i2c_client *client);当一个具体的 client 被侦测到并被关联的时候,设备和 sysfs 文件将被注册。相反地,在 client 被取消关联的时候,sysfs 文件和设备也被注销,如代码如下所示:
int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; int res = 0; mutex_lock(&adapter->clist_lock); if (__i2c_check_addr(client->adapter, client->addr)) { res = -EBUSY; goto out_unlock; } list_add_tail(&client->list,&adapter->clients); client->usage_count = 0; client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; if (client->driver) client->dev.driver = &client->driver->driver; if (client->driver && !is_newstyle_driver(client->driver)) { client->dev.release = i2c_client_release; client->dev.uevent_suppress = 1; } else client->dev.release = i2c_client_dev_release; snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "%d-%04x", i2c_adapter_id(adapter), client->addr); dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", client->name, client->dev.bus_id); res = device_register(&client->dev); if (res) goto out_list; mutex_unlock(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { dev_dbg(&adapter->dev, "client_register " "failed for client [%s] at 0x%02x\n", client->name, client->addr); } } return 0; out_list: list_del(&client->list); dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " "(%d)\n", client->name, client->addr, res); out_unlock: mutex_unlock(&adapter->clist_lock); return res; }(4)I2C 传输、发送和接收。
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num); int i2c_master_send(struct i2c_client *client,const char *buf ,int count); int i2c_master_recv(struct i2c_client *client, char *buf ,int count);i2c_transfer() 函 数 用 于 进 行 I2C 适 配 器 和 I2C 设 备 之 间 的 一 组 消 息 交 互 ,
代码如下:
i2c_master_send
int i2c_master_send(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; msg.flags = client->flags & I2C_M_TEN; 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; }i2c_master_recv
int i2c_master_recv(struct i2c_client *client, char *buf ,int count) { struct i2c_adapter *adap=client->adapter; struct i2c_msg msg; int ret; //构造一个读消息 msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.flags |= I2C_M_RD; msg.len = count; msg.buf = 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; }i2c_transfer()函数本身不具备驱动适配器物理硬件完成消息交互的能力,它只是寻找到 i2c_adapter 对应的 i2c_algorithm,并使用 i2c_algorithm 的 master_xfer()函数真正驱动硬件流程,
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) { int ret; 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 mutex_lock_nested(&adap->bus_lock, adap->level); ret = adap->algo->master_xfer(adap,msgs,num);//调用algo中的master_xfer函数进行硬件驱动 mutex_unlock(&adap->bus_lock); return ret; } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); return -ENOSYS; } }