Example #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_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;
}