static int i2c_get_data(unsigned char *data, int ack) { int timeout = TIMEOUT*10; if (!ack) __i2c_send_nack(); else __i2c_send_ack(); while (__i2c_check_drf() == 0 && timeout) timeout--; if (timeout) { if (!ack) __i2c_send_stop(); *data = __i2c_read(); __i2c_clear_drf(); return 0; } else return -ETIMEDOUT; }
static int i2c_jz_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) { int ret, i; // printk(KERN_INFO "i2c_jz_xfer %d messages\n", num); dev_dbg(&adap->dev, "jz47xx_xfer: processing %d messages:\n", num); for (i = 0; i < num; i++, pmsg++) { unsigned char *tmpbuf = pmsg->buf; int cnt = (pmsg->flags & I2C_M_TEN) ? -2:-1; // prepare for sending address; ret = num; // assume ok dev_dbg(&adap->dev, " #%d: %s %d byte%s %s 0x%02x flags %04x\n", i, pmsg->flags & I2C_M_RD ? "reading" : "writing", pmsg->len, pmsg->len > 1 ? "s" : "", pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr, pmsg->flags); if (pmsg->flags & (/*I2C_M_TEN|I2C_M_NOSTART|*/I2C_M_REV_DIR_ADDR|/*I2C_M_IGNORE_NAK|*/I2C_M_NO_RD_ACK|I2C_M_RECV_LEN)) { dev_dbg(&adap->dev, "jz47xx_xfer: flags=%04x not supported\n", pmsg->flags); return -EINVAL; } if (!pmsg->buf) continue; /* sanity check */ // printk(KERN_INFO "addr=%x flags=%04x\n", pmsg->addr, pmsg->flags); if (!(pmsg->flags & I2C_M_NOSTART)) __i2c_send_start(); __i2c_send_ack(); // default (only last byte during receive gets nack) for(; cnt < pmsg->len; cnt++) { // printk(KERN_INFO "%d (%d)", cnt, pmsg->len); #if 0 if(cnt == pmsg->len-1 && i == num-1) { printk(" send stop\n"); __i2c_send_stop(); // last byte of last message } #endif if (cnt >= 0 && pmsg->flags & I2C_M_RD) { // read data int timeout = TIMEOUT; while(!__i2c_check_drf() && timeout--) // wait for data to arrive udelay(10); if (timeout < 0) ret = -ETIMEDOUT; else { if(cnt == pmsg->len-2) __i2c_send_nack(); // nack last byte *tmpbuf++ = __i2c_read(); // read data byte // printk(" r: %02x\n", tmpbuf[-1]); __i2c_clear_drf(); } } else { int timeout = TIMEOUT; if(cnt == -2) { // send first byte of 10-bit address // printk(" w: %02x\n", ((pmsg->addr >> 7) & 0x06) | ((pmsg->flags & I2C_M_RD) ? (0xf0 | I2C_READ) : (0xf0 | I2C_WRITE))); __i2c_write(((pmsg->addr >> 7) & 0x06) | ((pmsg->flags & I2C_M_RD) ? (0xf0 | I2C_READ) : (0xf0 | I2C_WRITE)) ); // first 2 bits } else if(cnt == -1) { // send 7 bit address or second byte if ((pmsg->flags & I2C_M_TEN)) { // printk(" w: %02x\n", pmsg->addr & 0xff); __i2c_write(pmsg->addr); // final 8 bits } else { // printk(" w: %02x\n", (pmsg->addr << 1) | ((pmsg->flags & I2C_M_RD) ? I2C_READ : I2C_WRITE)); __i2c_write((pmsg->addr << 1) | ((pmsg->flags & I2C_M_RD) ? I2C_READ : I2C_WRITE)); // set data to be written } } else { // send data // printk(" w: %02x\n", *tmpbuf); __i2c_write(*tmpbuf++); } __i2c_set_drf(); // data is ready flag while(__i2c_check_drf() && timeout--) // wait until we can push the next byte udelay(10); if(cnt == -1 || cnt == pmsg->len-1) { // last byte, wait for end of transission and final ACK // printk(" wait transmit_ended\n"); timeout = TIMEOUT; while(!__i2c_transmit_ended() && timeout--) udelay(10); } if (timeout < 0) ret = -ETIMEDOUT; else if (!(pmsg->flags & I2C_M_IGNORE_NAK) && !__i2c_received_ack()) ret = -EIO; } if(ret < 0) break; }