📄 i2c-core.c
字号:
"%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); device_register(&client->dev); device_create_file(&client->dev, &dev_attr_client_name); return 0;}int i2c_detach_client(struct i2c_client *client){ struct i2c_adapter *adapter = client->adapter; int res = 0; if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0)) { dev_warn(&client->dev, "Client [%s] still busy, " "can't detach\n", client->name); return -EBUSY; } if (adapter->client_unregister) { res = adapter->client_unregister(client); if (res) { dev_err(&client->dev, "client_unregister [%s] failed, " "client not detached\n", client->name); goto out; } } down(&adapter->clist_lock); list_del(&client->list); init_completion(&client->released); device_remove_file(&client->dev, &dev_attr_client_name); device_unregister(&client->dev); up(&adapter->clist_lock); wait_for_completion(&client->released); out: return res;}static int i2c_inc_use_client(struct i2c_client *client){ if (!try_module_get(client->driver->owner)) return -ENODEV; if (!try_module_get(client->adapter->owner)) { 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);}#define I2C_IRQ 19unsigned int status=0;irqreturn_t i2c_isr(void){ status = *(volatile unsigned int *)(I2C_ADDR+4); //printk("[4]%x\n", status); if(status & 0x30) { i2c_handler(); } return IRQ_HANDLED;}static int __init i2c_init(void){ int retval; int ret; retval = bus_register(&i2c_bus_type); if (retval) return retval; retval = driver_register(&i2c_adapter_driver); if (retval) return retval; retval = class_register(&i2c_adapter_class); if (retval) return retval; retval = i2c_dev_init(); if (retval) return retval; i2c_algo_iic_init(); //ret = request_irq(I2C_IRQ, i2c_isr, SA_INTERRUPT, 0, 0); //if(ret < 0) //{ // printk(KERN_ERR "request irq(%d) fail\n", I2C_IRQ); //} printk("I2C Hwarang\n"); return 0; }static void __exit i2c_exit(void){ i2c_dev_exit(); class_unregister(&i2c_adapter_class); driver_unregister(&i2c_adapter_driver); bus_unregister(&i2c_bus_type);}//subsys_initcall(i2c_init);module_init(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) {#ifdef DEBUG for (ret = 0; ret < num; ret++) { dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ? 'R' : 'W', msgs[ret].addr, msgs[ret].len); }#endif 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; msg.addr = client->addr; //msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf; ret = i2c_transfer(adap, &msg, count); /* If everything went ok (i.e. 1 msg transmitted), return #bytes transmitted, else error code. */ return (ret == 1) ? count : ret;}int i2c_master_recv(struct i2c_client *client, char *buf ,int count){ struct i2c_adapter *adap=client->adapter; struct GMi2c_info *fara_info=client->adapter; struct i2c_msg msg; int ret,i; msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.flags |= I2C_M_RD; msg.len = count; msg.buf = buf;#ifdef CONFIG_PLATFORM_GM8120 for (i=0 ; i < count ; i++) {//this type for cmos-driver, count > 1 for Tuner-AP msg.buf = buf; ret = i2c_transfer(adap, &msg, 1); if ( ret != 1 ) break; *buf = *(msg.buf); if ( count == 1 ) break; //adap->data++; fara_info->data++; buf++; } //ret = i2c_transfer(adap, &msg, 1);#else ret = i2c_transfer(adap, &msg, 1);#endif /* If everything went ok (i.e. 1 msg transmitted), return #bytes transmitted, else error code. */ return (ret == 1) ? count : ret;}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! * ---------------------------------------------------- */static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind, int (*found_proc) (struct i2c_adapter *, int, int)){ int err; /* Make sure the address is valid */ if (addr < 0x03 || addr > 0x77) { dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", addr); return -EINVAL; } /* Skip if already in use */ if (i2c_check_addr(adapter, addr)) return 0; /* Make sure there is something at this address, unless forced */ if (kind < 0) { if (i2c_smbus_xfer(adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) < 0) return 0; /* prevent 24RF08 corruption */ if ((addr & ~0x0f) == 0x50) i2c_smbus_xfer(adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL); } /* Finally call the custom detection function */ err = found_proc(adapter, addr, kind); /* -ENODEV can be returned if there is a chip at the given address but it isn't supported by this chip driver. We catch it here as this isn't an error. */ return (err == -ENODEV) ? 0 : err;}int i2c_probe(struct i2c_adapter *adapter, struct i2c_client_address_data *address_data, int (*found_proc) (struct i2c_adapter *, int, int)){ int i, 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; /* Force entries are done first, and are not affected by ignore entries */ if (address_data->forces) { unsigned short **forces = address_data->forces; int kind; for (kind = 0; forces[kind]; kind++) { for (i = 0; forces[kind][i] != I2C_CLIENT_END; i += 2) { if (forces[kind][i] == adap_id || forces[kind][i] == ANY_I2C_BUS) { dev_dbg(&adapter->dev, "found force " "parameter for adapter %d, " "addr 0x%02x, kind %d\n", adap_id, forces[kind][i + 1], kind); err = i2c_probe_address(adapter, forces[kind][i + 1], kind, found_proc); if (err) return err; } } } } /* Probe entries are done second, and are not affected by ignore entries either */ for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) { if (address_data->probe[i] == adap_id || address_data->probe[i] == ANY_I2C_BUS) { dev_dbg(&adapter->dev, "found probe parameter for " "adapter %d, addr 0x%02x\n", adap_id, address_data->probe[i + 1]); err = i2c_probe_address(adapter, address_data->probe[i + 1], -1, found_proc); if (err) return err; } } /* Normal entries are done last, unless shadowed by an ignore entry */ for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) { int j, ignore; ignore = 0; for (j = 0; address_data->ignore[j] != I2C_CLIENT_END; j += 2) { if ((address_data->ignore[j] == adap_id || address_data->ignore[j] == ANY_I2C_BUS) && address_data->ignore[j + 1] == address_data->normal_i2c[i]) { dev_dbg(&adapter->dev, "found ignore " "parameter for adapter %d, " "addr 0x%02x\n", adap_id, address_data->ignore[j + 1]); } ignore = 1; break; } if (ignore) continue; dev_dbg(&adapter->dev, "found normal entry for adapter %d, " "addr 0x%02x\n", adap_id, address_data->normal_i2c[i]); err = i2c_probe_address(adapter, address_data->normal_i2c[i], -1, found_proc); if (err) return err; } return 0;}struct i2c_adapter* i2c_get_adapter(int id){ struct i2c_adapter *adapter; down(&core_lists); adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; up(&core_lists); return adapter;}void i2c_put_adapter(struct i2c_adapter *adap){ module_put(adap->owner);}/* The SMBus parts */#define POLY (0x1070U << 3) static u8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -