📄 i2c-core.c
字号:
module_put(client->driver->owner); return -ENODEV; } return 0;}static void i2c_dec_use_client(struct i2c_client *client){ module_put(client->driver->owner); module_put(client->adapter->owner);}int i2c_use_client(struct i2c_client *client){ int ret; ret = i2c_inc_use_client(client); if (ret) return ret; if (client->flags & I2C_CLIENT_ALLOW_USE) { if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE) client->usage_count++; else if (client->usage_count > 0) goto busy; else client->usage_count++; } return 0; busy: i2c_dec_use_client(client); return -EBUSY;}int i2c_release_client(struct i2c_client *client){ if(client->flags & I2C_CLIENT_ALLOW_USE) { if(client->usage_count>0) client->usage_count--; else { pr_debug("i2c-core: %s used one too many times\n", __FUNCTION__); return -EPERM; } } i2c_dec_use_client(client); return 0;}void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg){ struct list_head *item; struct i2c_client *client; down(&adap->clist_lock); list_for_each(item,&adap->clients) { client = list_entry(item, struct i2c_client, list); if (!try_module_get(client->driver->owner)) continue; if (NULL != client->driver->command) { up(&adap->clist_lock); client->driver->command(client,cmd,arg); down(&adap->clist_lock); } module_put(client->driver->owner); } up(&adap->clist_lock);}/* match always succeeds, as we want the probe() to tell if we really accept this match */static int i2c_device_match(struct device *dev, struct device_driver *drv){ return 1;}struct bus_type i2c_bus_type = { .name = "i2c", .match = i2c_device_match,};static int __init i2c_init(void){ int retval; retval = bus_register(&i2c_bus_type); if (retval) return retval; retval = driver_register(&i2c_adapter_driver); if (retval) return retval; return class_register(&i2c_adapter_class);}static void __exit i2c_exit(void){ class_unregister(&i2c_adapter_class); driver_unregister(&i2c_adapter_driver); bus_unregister(&i2c_bus_type);}subsys_initcall(i2c_init);module_exit(i2c_exit);/* ---------------------------------------------------- * the functional interface to the i2c busses. * ---------------------------------------------------- */int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num){ int ret; if (adap->algo->master_xfer) { dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num); down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); up(&adap->bus_lock); return ret; } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); return -ENOSYS; }}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; if (client->adapter->algo->master_xfer) { msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf; dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", count); down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); up(&adap->bus_lock); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. */ return (ret == 1 )? count : ret; } else { dev_err(&client->adapter->dev, "I2C level transfers not supported\n"); return -ENOSYS; }}int i2c_master_recv(struct i2c_client *client, char *buf ,int count){ struct i2c_adapter *adap=client->adapter; struct i2c_msg msg; int ret; if (client->adapter->algo->master_xfer) { msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.flags |= I2C_M_RD; msg.len = count; msg.buf = buf; dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", count); down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); up(&adap->bus_lock); dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n", ret, count, client->addr); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. */ return (ret == 1 )? count : ret; } else { dev_err(&client->adapter->dev, "I2C level transfers not supported\n"); return -ENOSYS; }}int i2c_control(struct i2c_client *client, unsigned int cmd, unsigned long arg){ int ret = 0; struct i2c_adapter *adap = client->adapter; dev_dbg(&client->adapter->dev, "i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg); switch (cmd) { case I2C_RETRIES: adap->retries = arg; break; case I2C_TIMEOUT: adap->timeout = arg; break; default: if (adap->algo->algo_control!=NULL) ret = adap->algo->algo_control(adap,cmd,arg); } return ret;}/* ---------------------------------------------------- * the i2c address scanning function * Will not work for 10-bit addresses! * ---------------------------------------------------- */int i2c_probe(struct i2c_adapter *adapter, struct i2c_client_address_data *address_data, int (*found_proc) (struct i2c_adapter *, int, int)){ int addr,i,found,err; int adap_id = i2c_adapter_id(adapter); /* Forget it if we can't probe using SMBUS_QUICK */ if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK)) return -1; for (addr = 0x00; addr <= 0x7f; addr++) { /* Skip if already in use */ if (i2c_check_addr(adapter,addr)) continue; /* If it is in one of the force entries, we don't do any detection at all */ found = 0; for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) { if (((adap_id == address_data->force[i]) || (address_data->force[i] == ANY_I2C_BUS)) && (addr == address_data->force[i+1])) { dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adap_id, addr); if ((err = found_proc(adapter,addr,0))) return err; found = 1; } } if (found) continue; /* If this address is in one of the ignores, we can forget about it right now */ for (i = 0; !found && (address_data->ignore[i] != I2C_CLIENT_END); i += 2) { if (((adap_id == address_data->ignore[i]) || ((address_data->ignore[i] == ANY_I2C_BUS))) && (addr == address_data->ignore[i+1])) { dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, " "addr %04x\n", adap_id ,addr); found = 1; } } for (i = 0; !found && (address_data->ignore_range[i] != I2C_CLIENT_END); i += 3) { if (((adap_id == address_data->ignore_range[i]) || ((address_data->ignore_range[i]==ANY_I2C_BUS))) && (addr >= address_data->ignore_range[i+1]) && (addr <= address_data->ignore_range[i+2])) { dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, " "addr %04x\n", adap_id,addr); found = 1; } } if (found) continue; /* Now, we will do a detection, but only if it is in the normal or probe entries */ for (i = 0; !found && (address_data->normal_i2c[i] != I2C_CLIENT_END); i += 1) { if (addr == address_data->normal_i2c[i]) { found = 1; dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, " "addr %02x", adap_id,addr); } } for (i = 0; !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END); i += 2) { if ((addr >= address_data->normal_i2c_range[i]) && (addr <= address_data->normal_i2c_range[i+1])) { found = 1; dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, " "addr %04x\n", adap_id,addr); } } for (i = 0; !found && (address_data->probe[i] != I2C_CLIENT_END); i += 2) { if (((adap_id == address_data->probe[i]) || ((address_data->probe[i] == ANY_I2C_BUS))) && (addr == address_data->probe[i+1])) { found = 1; dev_dbg(&adapter->dev, "found probe parameter for adapter %d, " "addr %04x\n", adap_id,addr); } } for (i = 0; !found && (address_data->probe_range[i] != I2C_CLIENT_END); i += 3) { if (((adap_id == address_data->probe_range[i]) || (address_data->probe_range[i] == ANY_I2C_BUS)) && (addr >= address_data->probe_range[i+1]) && (addr <= address_data->probe_range[i+2])) { found = 1; dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, " "addr %04x\n", adap_id,addr); } } if (!found) continue; /* OK, so we really should examine this address. First check whether there is some client here at all! */ if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) if ((err = found_proc(adapter,addr,-1))) return err; } return 0;}/* * return id number for a specific adapter */int i2c_adapter_id(struct i2c_adapter *adap){ return adap->nr;}struct i2c_adapter* i2c_get_adapter(int id){ struct list_head *item; struct i2c_adapter *adapter; down(&core_lists); list_for_each(item,&adapters) { adapter = list_entry(item, struct i2c_adapter, list); if (id == adapter->nr && try_module_get(adapter->owner)) { up(&core_lists); return adapter; } } up(&core_lists); return NULL;}void i2c_put_adapter(struct i2c_adapter *adap){ module_put(adap->owner);}/* The SMBus parts */#define POLY (0x1070U << 3) static u8crc8(u16 data){ int i; for(i = 0; i < 8; i++) { if (data & 0x8000) data = data ^ POLY; data = data << 1; } return (u8)(data >> 8);}/* CRC over count bytes in the first array plus the bytes in the rest array if it is non-null. rest[0] is the (length of rest) - 1 and is included. */u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest){ int i; for(i = 0; i < count; i++) crc = crc8((crc ^ first[i]) << 8); if(rest != NULL) for(i = 0; i <= rest[0]; i++) crc = crc8((crc ^ rest[i]) << 8); return crc;}u8 i2c_smbus_pec(int count, u8 *first, u8 *rest){ return i2c_smbus_partial_pec(0, count, first, rest);}/* Returns new "size" (transaction type) Note that we convert byte to byte_data and byte_data to word_data rather than invent new xxx_PEC transactions. */int i2c_smbus_add_pec(u16 addr, u8 command, int size, union i2c_smbus_data *data){ u8 buf[3]; buf[0] = addr << 1; buf[1] = command; switch(size) { case I2C_SMBUS_BYTE: data->byte = i2c_smbus_pec(2, buf, NULL); size = I2C_SMBUS_BYTE_DATA; break; case I2C_SMBUS_BYTE_DATA: buf[2] = data->byte; data->word = buf[2] || (i2c_smbus_pec(3, buf, NULL) << 8); size = I2C_SMBUS_WORD_DATA; break; case I2C_SMBUS_WORD_DATA: /* unsupported */ break; case I2C_SMBUS_BLOCK_DATA: data->block[data->block[0] + 1] = i2c_smbus_pec(2, buf, data->block); size = I2C_SMBUS_BLOCK_DATA_PEC; break; } return size; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -