📄 i2c-algo-pcf.c
字号:
"error - no ack.\n", i2c_adap->name); return -EREMOTEIO; /* got a better one ?? */ }#endif } i2c_stop(adap); return (wrcount);}static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count){ int rdcount=0, i, status, timeout, dummy=1; struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; for (i=0; i<count; ++i) { buf[rdcount] = i2c_inb(adap); if (dummy) { dummy = 0; } else { rdcount++; } timeout = wait_for_pin(adap, &status); if (timeout) { i2c_stop(adap); printk("i2c-algo-pcf.o: i2c_read: " "i2c_inb timed out.\n"); return (-1); }#ifndef STUB_I2C if (status & I2C_PCF_LRB) { i2c_stop(adap); printk("i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n"); return (-1); }#endif } set_pcf(adap, 1, I2C_PCF_ESO); buf[rdcount] = i2c_inb(adap); if (dummy) { dummy = 0; } else { rdcount++; } timeout = wait_for_pin(adap, &status); if (timeout) { i2c_stop(adap); printk("i2c-algo-pcf.o: i2c_read: i2c_inb timed out.\n"); return (-1); } i2c_stop(adap); /* Read final byte from S0 register */ buf[rdcount++] = i2c_inb(adap); return (rdcount);}static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap, struct i2c_msg *msg, int retries) { unsigned short flags = msg->flags; 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(adap, addr, retries); if (ret!=1) { printk("died at extended address code.\n"); return -EREMOTEIO; } /* the remaining 8 bit address */ i2c_outb(adap,msg->addr & 0x7f);/* Status check comes here */ if (ret != 1) { 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(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; i2c_outb(adap, addr); } return 0;}static int pcf_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num){ struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; struct i2c_msg *pmsg; int i = 0; int ret, timeout, status; pmsg = &msgs[i]; /* Send address here if Read */ if (pmsg->flags & I2C_M_RD) { ret = pcf_doAddress(adap, pmsg, i2c_adap->retries); } /* Check for bus busy */ timeout = wait_for_bb(adap); if (timeout) { DEB2(printk("i2c-algo-pcf.o: " "Timeout waiting for BB in pcf_xfer\n");) return -EIO; } /* Send address here if Write */ if (!(pmsg->flags & I2C_M_RD)) { ret = pcf_doAddress(adap, pmsg, i2c_adap->retries); } /* Send START */ i2c_start(adap); /* Wait for PIN (pending interrupt NOT) */ timeout = wait_for_pin(adap, &status); if (timeout) { i2c_stop(adap); DEB2(printk("i2c-algo-pcf.o: Timeout waiting " "for PIN(1) in pcf_xfer\n");) return (-EREMOTEIO); } #ifndef STUB_I2C /* Check LRB (last rcvd bit - slave ack) */ if (status & I2C_PCF_LRB) { i2c_stop(adap); DEB2(printk("i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");) return (-EREMOTEIO); }#endif DEB3(printk("i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", i, msgs[i].addr, msgs[i].flags, msgs[i].len);) /* Read */ if (pmsg->flags & I2C_M_RD) { /* read bytes into buffer*/ ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len); if (ret != pmsg->len) { DEB2(printk("i2c-algo-pcf.o: fail: " "only read %d bytes.\n",ret)); } else { DEB2(printk("i2c-algo-pcf.o: read %d bytes.\n",ret)); } } else { /* Write */ /* Write bytes from buffer */ ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len); if (ret != pmsg->len) { DEB2(printk("i2c-algo-pcf.o: fail: " "only wrote %d bytes.\n",ret)); } else { DEB2(printk("i2c-algo-pcf.o: wrote %d bytes.\n",ret)); } } return (num);}static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg){ return 0;}static u32 pcf_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 pcf_algo = { "PCF8584 algorithm", I2C_ALGO_PCF, pcf_xfer, NULL, NULL, /* slave_xmit */ NULL, /* slave_recv */ algo_control, /* ioctl */ pcf_func, /* functionality */};/* * registering functions to load algorithms at runtime */int i2c_pcf_add_bus(struct i2c_adapter *adap){ int i, status; struct i2c_algo_pcf_data *pcf_adap = adap->algo_data; if (pcf_test) { int ret = test_bus(pcf_adap, adap->name); if (ret<0) return -ENODEV; } DEB2(printk("i2c-algo-pcf.o: hw routines for %s registered.\n", adap->name)); /* register new adapter to i2c module... */ adap->id |= pcf_algo.id; adap->algo = &pcf_algo; adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */#ifdef MODULE MOD_INC_USE_COUNT;#endif i2c_add_adapter(adap); pcf_init_8584(pcf_adap); /* scan bus */ if (pcf_scan) { printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n", adap->name); for (i = 0x00; i < 0xff; i+=2) { i2c_outb(pcf_adap, i); i2c_start(pcf_adap); if ((wait_for_pin(pcf_adap, &status) >= 0) && ((status & I2C_PCF_LRB) == 0)) { printk("(%02x)",i>>1); } else { printk("."); } i2c_stop(pcf_adap); udelay(pcf_adap->udelay); } printk("\n"); } return 0;}int i2c_pcf_del_bus(struct i2c_adapter *adap){ int res; if ((res = i2c_del_adapter(adap)) < 0) return res; DEB2(printk("i2c-algo-pcf.o: adapter unregistered: %s\n",adap->name));#ifdef MODULE MOD_DEC_USE_COUNT;#endif return 0;}int __init i2c_algo_pcf_init (void){ printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n"); return 0;}EXPORT_SYMBOL(i2c_pcf_add_bus);EXPORT_SYMBOL(i2c_pcf_del_bus);#ifdef MODULEMODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");MODULE_PARM(pcf_test, "i");MODULE_PARM(pcf_scan, "i");MODULE_PARM(i2c_debug,"i");MODULE_PARM_DESC(pcf_test, "Test if the I2C bus is available");MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus");MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");int init_module(void) { return i2c_algo_pcf_init();}void cleanup_module(void) {}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -