📄 i2c-algo-biths.c
字号:
printk(KERN_INFO "i2c-algo-biths.o: %s bus test\n", adap->name); while ( test[i][0]!=-1 ) { ssda = test[i][0]; sscl = test[i][1]; adap->errors = 0; __setsda(ssda, T_min); gsda = __getsda() ? 1 : 0; errors = adap->errors & (_HS_HW_FAIL | _HS_SDA_ARB); if (errors) printk(KERN_WARNING "i2c-algo-biths.o: %s %s\n", adap->name, i2c_strerr(errflag(errors))); __setscl(sscl, T_min); gscl = __getscl() ? 1 : 0; errors = adap->errors & (_HS_HW_FAIL | _HS_TIMEOUT); if (errors) printk(KERN_WARNING "i2c-algo-biths.o: %s %s\n", adap->name, i2c_strerr(errflag(errors))); printk(KERN_DEBUG "i2c-algo-biths.o: %s SCL: %d SDA: %d\n", adap->name, gscl, gsda); if ( sscl!=gscl ) printk(KERN_WARNING "i2c-algo-biths.o: %s SCL set %d, got %d!\n", adap->name, sscl, gscl); if ( ssda!=gsda ) printk(KERN_WARNING "i2c-algo-biths.o: %s SDA set %d, got %d!\n", adap->name, ssda, gsda); if ( (adap->errors) || sscl!=gscl || ssda!=gsda ) break; i++; } __setsda(1,0); __setscl(1,0); adap->errors = 0; if (test[i][0]==-1) { printk(KERN_INFO "i2c-algo-biths.o: %s passed bus test.\n",adap->name); return 0; } else { printk(KERN_INFO "i2c-algo-biths.o: %s failed bus test.\n",adap->name); return -ENODEV; }}/* doAddress transmits the address in the necessary format to handle * reads, writes as well as 10bit-addresses. */static void doAddress(struct i2c_algo_biths_data *adap, struct i2c_msg *msg) { unsigned char addr[2]; int count; if ( msg->flags & I2C_M_TEN ) { /* a ten bit address */ count = 2; addr[0] = 0xf0 | (( msg->addr >> 7) & 0x03); addr[1] = msg->addr & 0x7f; /* try extended address code ... and the remaining 8 bit address */ TRY(i2c_outb(adap, msg->flags, addr, &count)); if ( msg->flags & I2C_M_RD ) { TRY(i2c_start(adap)); /* okay, now switch into reading mode */ count = 1; addr[0] |= 0x01; TRY(i2c_outb(adap, msg->flags, addr, &count)); } } else { /* normal 7bit address */ count = 1; addr[0] = ( msg->addr << 1 ); if (msg->flags & I2C_M_RD ) addr[0] |= 1; if (msg->flags & I2C_M_REV_DIR_ADDR ) addr[0] ^= 1; TRY(i2c_outb(adap, msg->flags, addr, &count)); }}/* * return values: * 1 ACK * 0 IGNORED client NAK * -EREMOTEIO client NAK * -ETIMEDOUT from sclhi() */static int bit_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num){ struct i2c_msg *msg = msgs; struct i2c_algo_biths_data *adap = i2c_adap->algo_data; int mn, j, state; enum { MSG_INIT, MSG_START, MSG_ADDRESS, MSG_DATA, MSG_READY, MSG_STOP, MSG_EXIT }; state = MSG_INIT; mn=0; adap->dstr=NULL; if (i2c_debug>=FATAL_PROTOCOL) { adap->dstr = kmalloc(PROTO_MAX_DUMP, GFP_KERNEL); if (adap->dstr) { *adap->dstr = 0; } else { printk(KERN_DEBUG "i2c-algo-biths.o %s: missing protocol dump (-ENOMEM)\n", adap->name); } } for (j=0; j<num; j++) msgs[j].err = 0; // unprocessed do switch (state) { case MSG_INIT: msg = &msgs[mn]; if ((msg->flags & I2C_M_NOSTART) && (mn)) { state = MSG_DATA; break; } case MSG_START: i2c_start(adap); if (adap->errors) { state = MSG_STOP; break; } case MSG_ADDRESS: doAddress(adap, msg); if (adap->errors) { state = MSG_STOP; break; } case MSG_DATA: j = msg->len; if ( msg->flags & I2C_M_RD ) { i2c_inb(adap, msg->flags, msg->buf, &j); } else { i2c_outb(adap, msg->flags, msg->buf, &j); } msg->done = msg->len - j; if (adap->errors) { state = MSG_STOP; break; } case MSG_READY: mn++; if (mn<num) { msg->err = errflag(adap->errors); debug_protocol(adap, msg->err); state = MSG_INIT; break; } case MSG_STOP: msg->err = errflag(adap->errors); i2c_stop(adap); j = 0; while (adap->errors) { if ( ++j > 10) { msg->err = -ENODEV; break; } i2c_stop(adap); } debug_protocol(adap, msg->err); state = MSG_EXIT; break; default: /* not reached */ state = MSG_EXIT; msg->err = -EINVAL; break; } while (state != MSG_EXIT); if (adap->dstr) kfree(adap->dstr); for (j=0; j<num; j++) debug_printout(i2c_adap, j, msgs[j].err); return (msg->err < 0) ? msg->err : mn;}static u32 bit_func(struct i2c_adapter *i2c_adap){ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;}/* -----exported algorithm data: ------------------------------------- */static struct i2c_algorithm i2c_algo_biths = { .name = "Bit-shift algorithm", .id = I2C_ALGO_BIT, .master_xfer = bit_xfer, .functionality = bit_func,};#if ALGO_BIT_COMPATIBILITY #include "i2c-algo-bit.h"static _HS_ATTR_ void _old_setscl(void *hw_data, int hw_state){ struct i2c_algo_bit_data *old = hw_data; old->setscl(old->data, hw_state & _HS_SCL);}static _HS_ATTR_ void _old_setsda(void *hw_data, int hw_state){ struct i2c_algo_bit_data *old = hw_data; old->setsda(old->data, hw_state & _HS_SDA);}static _HS_ATTR_ int _old_getscl(void *hw_data){ struct i2c_algo_bit_data *old = hw_data; return old->getscl(old->data);}static _HS_ATTR_ int _old_getsda(void *hw_data){ struct i2c_algo_bit_data *old = hw_data; return old->getsda(old->data);}static _HS_ATTR_ void _old_setstate(struct i2c_algo_biths_data *adap){ adap->hw_state = adap->ctrl;}static struct i2c_algo_biths_data _old_template = { .setstate = _old_setstate, .setsda = _old_setsda, .setscl = _old_setscl, .getsda = _old_getsda, .getscl = _old_getscl,};/* * registering functions to load algorithms at runtime */int i2c_bit_add_bus(struct i2c_adapter *i2c_adap){ int i; struct i2c_algo_bit_data *old_adap = i2c_adap->algo_data; struct i2c_algo_biths_data *adap; adap = kmalloc(sizeof(struct i2c_algo_biths_data), GFP_KERNEL); if (adap==NULL) return -ENOMEM; memcpy(adap, &_old_template, sizeof(struct i2c_algo_biths_data)); adap->hw_data = old_adap; adap->xloops = old_adap->udelay * 0x0863; /* 1/4 vs 1/2 cycle, 0x10c6 / 2 */ adap->timeout = old_adap->timeout; i2c_adap->algo_data = adap; return i2c_biths_add_bus(i2c_adap);}int i2c_bit_del_bus(struct i2c_adapter *i2c_adap){ int res; if ((res = i2c_biths_del_bus(i2c_adap)) < 0) return res; kfree(i2c_adap->algo_data); return 0;}EXPORT_SYMBOL(i2c_bit_add_bus);EXPORT_SYMBOL(i2c_bit_del_bus);#endif#ifdef rdtscl/* TSC stuff from arch/i386/lib/delay.c */static _HS_ATTR_ void i2c_tsc_set(struct i2c_algo_biths_data *adap){ rdtscl(adap->bclock);}static _HS_ATTR_ void i2c_tsc_run(struct i2c_algo_biths_data *adap){ unsigned long now, loops; loops = ((long long) adap->xloops * current_cpu_data.loops_per_jiffy) >> 32; loops *= HZ; do { rep_nop(); rdtscl(now); } while ( (now - adap->bclock) < loops );}#else static _HS_ATTR_ void i2c_udelay_set(struct i2c_algo_biths_data *adap) {}static _HS_ATTR_ void i2c_udelay_run(struct i2c_algo_biths_data *adap){ int usecs; /* adap->xloops = usecs * 0x000010c6 / 2; */ usecs = ((adap->xloops + 0x0863) >> 12); if (adap->ctrl & _HS_DBL_DT) usecs<<=1; udelay(usecs);}#endif /* rdtscl *//* * registering functions to load algorithms at runtime */int i2c_biths_add_bus(struct i2c_adapter *i2c_adap){ struct i2c_algo_biths_data *adap = i2c_adap->algo_data; /* get name */ adap->name = i2c_adap->name; adap->dstr = 0; // no protocol dump buffer if (adap->set_timer == NULL) {#ifdef rdtscl /* if (x86_udelay_tsc) here instead ? */ adap->set_timer = i2c_tsc_set; adap->run_timer = i2c_tsc_run;#else adap->set_timer = i2c_udelay_set; adap->run_timer = i2c_udelay_run;#endif } if (bit_test) { int ret = test_bus(adap); if (ret<0) return ret; } DEB1(printk(KERN_DEBUG "i2c-algo-biths.o: hw routines for %s registered.\n", i2c_adap->name));#ifdef rdtscl DEB1(printk(KERN_DEBUG "i2c-algo-biths.o: ... will use rdtscl() for bus clock\n"));#else DEB1(printk(KERN_DEBUG "i2c-algo-biths.o: ... will use udelay() for bus clock\n"));#endif /* register new adapter to i2c module... */ i2c_adap->id |= i2c_algo_biths.id; i2c_adap->algo = &i2c_algo_biths; i2c_adap->timeout = HZ; /* default values, should */ i2c_adap->retries = 3; /* be replaced by defines */ i2c_add_adapter(i2c_adap); return 0;}int i2c_biths_del_bus(struct i2c_adapter *i2c_adap){ return i2c_del_adapter(i2c_adap);}EXPORT_SYMBOL(i2c_biths_add_bus);EXPORT_SYMBOL(i2c_biths_del_bus);MODULE_AUTHOR("Ky鰏ti M鋖kki <kmalkki@cc.hut.fi>");MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");MODULE_LICENSE("GPL");MODULE_PARM(bit_test, "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(i2c_debug, "debug level - 1 use; 2 fatal, 3 +proto; 4 all, 5 +proto");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -