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; }
static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, u16 addr, u8 *buf, u16 len, u8 add_stop) { struct saa716x_dev *saa716x = i2c->saa716x; u32 data; int err; int i; int bytes; saa716x_i2c_irq_start(i2c, I2C_DEV); /* first write START with I2C address */ data = I2C_START_BIT | (addr << 1) | 1; dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); err = saa716x_i2c_send(i2c, I2C_DEV, data); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Address write failed"); goto exit; } bytes = i2c->block_size - 1; /* now read the data */ while (len > 0) { if (bytes == i2c->block_size) { /* this is not the first round, so restart irq */ saa716x_i2c_irq_start(i2c, I2C_DEV); } if (bytes > len) bytes = len; for (i = 0; i < bytes; i++) { data = 0x00; /* dummy write for reading */ if (add_stop && i == (len - 1)) data |= I2C_STOP_BIT; err = saa716x_i2c_send(i2c, I2C_DEV, data); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Data send failed"); goto exit; } } err = saa716x_i2c_irq_wait(i2c, I2C_DEV); if (err < 0) { goto exit; } for (i = 0; i < bytes; i++) { err = saa716x_i2c_recv(i2c, I2C_DEV, &data); if (err < 0) { dprintk(SAA716x_ERROR, 1, "Data receive failed"); goto exit; } dprintk(SAA716x_DEBUG, 0, " <R %04x> 0x%02x\n\n", i, data); buf[i] = data; } len -= bytes; buf += bytes; bytes = i2c->block_size; } return 0; exit: dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); return err; }