static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); struct saa716x_dev *saa716x = i2c->saa716x; u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); int i, j, err = 0; int t; dprintk(SAA716x_DEBUG, 0, "\n"); dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); mutex_lock(&i2c->i2c_lock); for (t = 0; t < 3; t++) { for (i = 0; i < num; i++) { if (msgs[i].flags & I2C_M_RD) err = saa716x_i2c_read_msg(i2c, DEV, msgs[i].addr, msgs[i].buf, msgs[i].len, i == (num - 1)); else err = saa716x_i2c_write_msg(i2c, DEV, msgs[i].addr, msgs[i].buf, msgs[i].len, i == (num - 1)); if (err < 0) { err = -EIO; goto retry; } } break; retry: dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); for (i = 0; i < num; i++) { dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", i, msgs[i].addr, msgs[i].len, msgs[i].flags); if (!(msgs[i].flags & I2C_M_RD)) { for (j = 0; j < msgs[i].len; j++) { dprintk(SAA716x_INFO, 1, " <W %04x> 0x%02x", j, msgs[i].buf[j]); } } } err = saa716x_i2c_hwinit(i2c, DEV); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Error Reinit"); err = -EIO; goto bail_out; } } mutex_unlock(&i2c->i2c_lock); return num; bail_out: dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); mutex_unlock(&i2c->i2c_lock); return err; }
static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) { struct saa716x_dev *saa716x = i2c->saa716x; int i, err = 0; u32 reg; /* Check FIFO status before TX */ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); i2c->stat_tx_prior = reg; if (reg & SAA716x_I2C_TXBUSY) { for (i = 0; i < 100; i++) { /* TODO! check for hotplug devices */ msleep(10); reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); if (reg & SAA716x_I2C_TXBUSY) { dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); err = saa716x_i2c_hwinit(i2c, I2C_DEV); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Error Reinit"); err = -EIO; goto exit; } } else { break; } } } /* Write to FIFO */ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); /* Check for data write */ for (i = 0; i < 1000; i++) { /* TODO! check for hotplug devices */ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); if (reg & I2C_TRANSMIT_CLEAR) { break; } } i2c->stat_tx_done = reg; if (!(reg & I2C_TRANSMIT_CLEAR)) { dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); err = -EIO; goto exit; } return err; exit: dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); return err; }
static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); struct saa716x_dev *saa716x = i2c->saa716x; u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); int i, j, err = 0; int t; u32 data; mutex_lock(&i2c->i2c_lock); for (t = 0; t < 3; t++) { for (i = 0; i < num; i++) { /* first write START width I2C address */ data = (msgs[i].addr << 1) | I2C_START_BIT; if (msgs[i].flags & I2C_M_RD) data |= 1; err = saa716x_i2c_send(i2c, DEV, data); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Address write failed"); err = -EIO; goto retry; } /* now read or write the data */ for (j = 0; j < msgs[i].len; j++) { if (msgs[i].flags & I2C_M_RD) data = 0x00; /* dummy write for reading */ else { data = msgs[i].buf[j]; } if (i == (num - 1) && j == (msgs[i].len - 1)) data |= I2C_STOP_BIT; err = saa716x_i2c_send(i2c, DEV, data); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Data send failed"); err = -EIO; goto retry; } if (msgs[i].flags & I2C_M_RD) { err = saa716x_i2c_recv(i2c, DEV, &data); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Data receive failed"); err = -EIO; goto retry; } msgs[i].buf[j] = data; } } } break; retry: dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); err = saa716x_i2c_hwinit(i2c, DEV); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Error Reinit"); err = -EIO; goto bail_out; } } mutex_unlock(&i2c->i2c_lock); if (t == 3) return -EIO; else return num; bail_out: dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); mutex_unlock(&i2c->i2c_lock); return err; }