示例#1
0
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_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;
}