📄 i2c-algo-bit.c
字号:
/* ----- Utility functions *//* try_address tries to contact a chip for a number of * times before it gives up. * return values: * 1 chip answered * 0 chip did not answer * -x transmission error */static inline int try_address(struct i2c_adapter *i2c_adap, unsigned char addr, int retries){ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; int i,ret = -1; for (i=0;i<=retries;i++) { ret = i2c_outb(i2c_adap,addr); if (ret==1) break; /* success! */ i2c_stop(adap); udelay(5/*adap->udelay*/); if (i==retries) /* no success */ break; i2c_start(adap); udelay(adap->udelay); } DEB2(if (i) printk("i2c-algo-bit.o: needed %d retries for %d\n", i,addr)); return ret;}static int sendbytes(struct i2c_adapter *i2c_adap,const char *buf, int count){ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; char c; const char *temp = buf; int retval; int wrcount=0; while (count > 0) { c = *temp; DEB2(printk("i2c-algo-bit.o: %s i2c_write: writing %2.2X\n", i2c_adap->name, c&0xff)); retval = i2c_outb(i2c_adap,c); if (retval>0) { count--; temp++; wrcount++; } else { /* arbitration or no acknowledge */ printk("i2c-algo-bit.o: %s i2c_write: error - bailout.\n", i2c_adap->name); i2c_stop(adap); return (retval<0)? retval : -EFAULT; /* got a better one ?? */ }#if 0 /* from asm/delay.h */ __delay(adap->mdelay * (loops_per_sec / 1000) );#endif } return wrcount;}static inline int readbytes(struct i2c_adapter *i2c_adap,char *buf,int count){ char *temp = buf; int inval; int rdcount=0; /* counts bytes read */ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; while (count > 0) { inval = i2c_inb(i2c_adap);/*printk("%#02x ",inval); if ( ! (count % 16) ) printk("\n"); */ if (inval>=0) { *temp = inval; rdcount++; } else { /* read timed out */ printk("i2c-algo-bit.o: i2c_read: i2c_inb timed out.\n"); break; } if ( count > 1 ) { /* send ack */ sdalo(adap); DEBPROTO(printk(" Am ")); } else { sdahi(adap); /* neg. ack on last byte */ DEBPROTO(printk(" NAm ")); } if (sclhi(adap)<0) { /* timeout */ sdahi(adap); printk("i2c-algo-bit.o: i2c_read: Timeout at ack\n"); return -ETIMEDOUT; }; scllo(adap); sdahi(adap); temp++; count--; } return rdcount;}/* doAddress initiates the transfer by generating the start condition (in * try_address) and transmits the address in the necessary format to handle * reads, writes as well as 10bit-addresses. * returns: * 0 everything went okay, the chip ack'ed * -x an error occurred (like: -EREMOTEIO if the device did not answer, or * -ETIMEDOUT, for example if the lines are stuck...) */static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int retries) { unsigned short flags = msg->flags; struct i2c_algo_bit_data *adap = i2c_adap->algo_data; unsigned char addr; int ret; if ( (flags & I2C_M_TEN) ) { /* a ten bit address */ addr = 0xf0 | (( msg->addr >> 7) & 0x03); DEB2(printk("addr0: %d\n",addr)); /* try extended address code...*/ ret = try_address(i2c_adap, addr, retries); if (ret!=1) { printk("died at extended address code.\n"); return -EREMOTEIO; } /* the remaining 8 bit address */ ret = i2c_outb(i2c_adap,msg->addr & 0x7f); if (ret != 1) { /* the chip did not ack / xmission error occurred */ printk("died at 2nd address code.\n"); return -EREMOTEIO; } if ( flags & I2C_M_RD ) { i2c_repstart(adap); /* okay, now switch into reading mode */ addr |= 0x01; ret = try_address(i2c_adap, addr, retries); if (ret!=1) { printk("died at extended address code.\n"); return -EREMOTEIO; } } } else { /* normal 7bit address */ addr = ( msg->addr << 1 ); if (flags & I2C_M_RD ) addr |= 1; if (flags & I2C_M_REV_DIR_ADDR ) addr ^= 1; ret = try_address(i2c_adap, addr, retries); if (ret!=1) { return -EREMOTEIO; } } return 0;}static int bit_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num){ struct i2c_msg *pmsg; struct i2c_algo_bit_data *adap = i2c_adap->algo_data; int i,ret; i2c_start(adap); for (i=0;i<num;i++) { pmsg = &msgs[i]; if (!(pmsg->flags & I2C_M_NOSTART)) { if (i) { i2c_repstart(adap); } ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries); if (ret != 0) { DEB2(printk("i2c-algo-bit.o: NAK from device adr %#2x msg #%d\n" ,msgs[i].addr,i)); return (ret<0) ? ret : -EREMOTEIO; } } if (pmsg->flags & I2C_M_RD ) { /* read bytes into buffer*/ ret = readbytes(i2c_adap,pmsg->buf,pmsg->len); DEB2(printk("i2c-algo-bit.o: read %d bytes.\n",ret)); if (ret < pmsg->len ) { return (ret<0)? ret : -EREMOTEIO; } } else { /* write bytes from buffer */ ret = sendbytes(i2c_adap,pmsg->buf,pmsg->len); DEB2(printk("i2c-algo-bit.o: wrote %d bytes.\n",ret)); if (ret < pmsg->len ) { return (ret<0) ? ret : -EREMOTEIO; } } } i2c_stop(adap); return num;}static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg){ return 0;}static u32 bit_func(struct i2c_adapter *adap){ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;}/* -----exported algorithm data: ------------------------------------- */static struct i2c_algorithm i2c_bit_algo = { "Bit-shift algorithm", I2C_ALGO_BIT, bit_xfer, NULL, NULL, /* slave_xmit */ NULL, /* slave_recv */ algo_control, /* ioctl */ bit_func, /* functionality */};/* * registering functions to load algorithms at runtime */int i2c_bit_add_bus(struct i2c_adapter *adap){ int i; struct i2c_algo_bit_data *bit_adap = adap->algo_data; if (bit_test) { int ret = test_bus(bit_adap, adap->name); if (ret<0) return -ENODEV; } DEB2(printk("i2c-algo-bit.o: hw routines for %s registered.\n", adap->name)); /* register new adapter to i2c module... */ adap->id |= i2c_bit_algo.id; adap->algo = &i2c_bit_algo; adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ /* scan bus */ if (bit_scan) { int ack; printk(KERN_INFO " i2c-algo-bit.o: scanning bus %s.\n", adap->name); for (i = 0x00; i < 0xff; i+=2) { i2c_start(bit_adap); ack = i2c_outb(adap,i); i2c_stop(bit_adap); if (ack>0) { printk("(%02x)",i>>1); } else printk("."); } printk("\n"); } MOD_INC_USE_COUNT; i2c_add_adapter(adap); return 0;}int i2c_bit_del_bus(struct i2c_adapter *adap){ int res; if ((res = i2c_del_adapter(adap)) < 0) return res; DEB2(printk("i2c-algo-bit.o: adapter unregistered: %s\n",adap->name)); MOD_DEC_USE_COUNT; return 0;}static int __init i2c_algo_bit_init (void){ printk(KERN_DEBUG "i2c-algo-bit.o: i2c bit algorithm module\n"); return 0;}EXPORT_SYMBOL(i2c_bit_add_bus);EXPORT_SYMBOL(i2c_bit_del_bus);MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");MODULE_LICENSE("GPL");MODULE_PARM(bit_test, "i");MODULE_PARM(bit_scan, "i");MODULE_PARM(i2c_debug,"i");MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");module_init(i2c_algo_bit_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -