Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12bd3146 authored by Tomoya MORINAGA's avatar Tomoya MORINAGA Committed by Ben Dooks
Browse files

i2c-eg20t: Separate error processing



Error processing for NACK or wait-event must be precessed separately.
So divide wait-event error processing into NACK-receiving and timeout.
Add arbitration lost processing.

Signed-off-by: default avatarTomoya MORINAGA <tomoya-linux@dsn.lapis-semi.com>
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent c249ac20
Loading
Loading
Loading
Loading
+115 −58
Original line number Diff line number Diff line
@@ -391,6 +391,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
	u32 addr_2_msb;
	u32 addr_8_lsb;
	s32 wrcount;
	s32 rtn;
	void __iomem *p = adap->pch_base_address;

	length = msgs->len;
@@ -413,11 +414,25 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
		iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
		if (first)
			pch_i2c_start(adap);
		if (pch_i2c_wait_for_xfer_complete(adap) == 0 &&
		    pch_i2c_getack(adap) == 0) {

		rtn = pch_i2c_wait_for_xfer_complete(adap);
		if (rtn == 0) {
			if (pch_i2c_getack(adap)) {
				pch_dbg(adap, "Receive NACK for slave address"
					"setting\n");
				return -EIO;
			}
			addr_8_lsb = (addr & I2C_ADDR_MSK);
			iowrite32(addr_8_lsb, p + PCH_I2CDR);
		} else {
		} else if (rtn == -EIO) { /* Arbitration Lost */
			pch_err(adap, "Lost Arbitration\n");
			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
				   I2CMAL_BIT);
			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
				   I2CMIF_BIT);
			pch_i2c_init(adap);
			return -EAGAIN;
		} else { /* wait-event timeout */
			pch_i2c_stop(adap);
			return -ETIME;
		}
@@ -428,30 +443,48 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
			pch_i2c_start(adap);
	}

	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
	    (pch_i2c_getack(adap) == 0)) {
	rtn = pch_i2c_wait_for_xfer_complete(adap);
	if (rtn == 0) {
		if (pch_i2c_getack(adap)) {
			pch_dbg(adap, "Receive NACK for slave address"
				"setting\n");
			return -EIO;
		}
	} else if (rtn == -EIO) { /* Arbitration Lost */
		pch_err(adap, "Lost Arbitration\n");
		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
		return -EAGAIN;
	} else { /* wait-event timeout */
		return -ETIME;
	}

	for (wrcount = 0; wrcount < length; ++wrcount) {
		/* write buffer value to I2C data register */
		iowrite32(buf[wrcount], p + PCH_I2CDR);
			pch_dbg(adap, "writing %x to Data register\n",
				buf[wrcount]);

			if (pch_i2c_wait_for_xfer_complete(adap) != 0)
				return -ETIME;
		pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);

			if (pch_i2c_getack(adap))
		rtn = pch_i2c_wait_for_xfer_complete(adap);
		if (rtn == 0) {
			if (pch_i2c_getack(adap)) {
				pch_dbg(adap, "Receive NACK for slave address"
					"setting\n");
				return -EIO;
			}
			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
				   I2CMCF_BIT);
			pch_clrbit(adap->pch_base_address, PCH_I2CSR,
				   I2CMIF_BIT);
		} else { /* wait-event timeout */
			return -ETIME;
		}
	}

	/* check if this is the last message */
	if (last)
		pch_i2c_stop(adap);
	else
		pch_i2c_repstart(adap);
	} else {
		pch_i2c_stop(adap);
		return -EIO;
	}

	pch_dbg(adap, "return=%d\n", wrcount);

@@ -512,6 +545,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
	u32 addr_2_msb;
	u32 addr_8_lsb;
	void __iomem *p = adap->pch_base_address;
	s32 rtn;

	length = msgs->len;
	buf = msgs->buf;
@@ -585,9 +619,21 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
	if (first)
		pch_i2c_start(adap);

	if ((pch_i2c_wait_for_xfer_complete(adap) == 0) &&
	    (pch_i2c_getack(adap) == 0)) {
		pch_dbg(adap, "return %d\n", 0);
	rtn = pch_i2c_wait_for_xfer_complete(adap);
	if (rtn == 0) {
		if (pch_i2c_getack(adap)) {
			pch_dbg(adap, "Receive NACK for slave address"
				"setting\n");
			return -EIO;
		}
	} else if (rtn == -EIO) { /* Arbitration Lost */
		pch_err(adap, "Lost Arbitration\n");
		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
		pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
		return -EAGAIN;
	} else { /* wait-event timeout */
		return -ETIME;
	}

	if (length == 0) {
		pch_i2c_stop(adap);
@@ -606,35 +652,46 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
			if (loop != 1)
				read_index++;

				if (pch_i2c_wait_for_xfer_complete(adap) != 0) {
			rtn = pch_i2c_wait_for_xfer_complete(adap);
			if (rtn == 0) {
				if (pch_i2c_getack(adap)) {
					pch_dbg(adap, "Receive NACK for slave"
						"address setting\n");
					return -EIO;
				}
			} else { /* wait-event timeout */
				pch_i2c_stop(adap);
				return -ETIME;
			}

		}	/* end for */

		pch_i2c_sendnack(adap);

			buf[read_index] = ioread32(p + PCH_I2CDR);
		buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */

		if (length != 1)
			read_index++;

			if (pch_i2c_wait_for_xfer_complete(adap) == 0) {
		rtn = pch_i2c_wait_for_xfer_complete(adap);
		if (rtn == 0) {
			if (pch_i2c_getack(adap)) {
				pch_dbg(adap, "Receive NACK for slave"
					"address setting\n");
				return -EIO;
			}
		} else { /* wait-event timeout */
			pch_i2c_stop(adap);
			return -ETIME;
		}

		if (last)
			pch_i2c_stop(adap);
		else
			pch_i2c_repstart(adap);

				buf[read_index++] = ioread32(p + PCH_I2CDR);
		buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */
		count = read_index;
			} else {
				count = -ETIME;
			}

		}
	} else {
		count = -ETIME;
		pch_i2c_stop(adap);
	}

	return count;