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

Commit ab0831d0 authored by Danielle Costantino's avatar Danielle Costantino Committed by Wolfram Sang
Browse files

i2c: mpc: report correct I2C error return codes



This patch enforces correct I2C error returned codes from Freescale's
MPC i2c bus driver, allowing for proper user-space/kernel error
handling.

Signed-off-by: default avatarDanielle Costantino <danielle.costantino@gmail.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 550d0407
Loading
Loading
Loading
Loading
+9 −9
Original line number Original line Diff line number Diff line
@@ -124,7 +124,7 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c)
static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
{
{
	unsigned long orig_jiffies = jiffies;
	unsigned long orig_jiffies = jiffies;
	u32 x;
	u32 cmd_err;
	int result = 0;
	int result = 0;


	if (!i2c->irq) {
	if (!i2c->irq) {
@@ -133,11 +133,11 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
			if (time_after(jiffies, orig_jiffies + timeout)) {
			if (time_after(jiffies, orig_jiffies + timeout)) {
				dev_dbg(i2c->dev, "timeout\n");
				dev_dbg(i2c->dev, "timeout\n");
				writeccr(i2c, 0);
				writeccr(i2c, 0);
				result = -EIO;
				result = -ETIMEDOUT;
				break;
				break;
			}
			}
		}
		}
		x = readb(i2c->base + MPC_I2C_SR);
		cmd_err = readb(i2c->base + MPC_I2C_SR);
		writeb(0, i2c->base + MPC_I2C_SR);
		writeb(0, i2c->base + MPC_I2C_SR);
	} else {
	} else {
		/* Interrupt mode */
		/* Interrupt mode */
@@ -150,28 +150,28 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
			result = -ETIMEDOUT;
			result = -ETIMEDOUT;
		}
		}


		x = i2c->interrupt;
		cmd_err = i2c->interrupt;
		i2c->interrupt = 0;
		i2c->interrupt = 0;
	}
	}


	if (result < 0)
	if (result < 0)
		return result;
		return result;


	if (!(x & CSR_MCF)) {
	if (!(cmd_err & CSR_MCF)) {
		dev_dbg(i2c->dev, "unfinished\n");
		dev_dbg(i2c->dev, "unfinished\n");
		return -EIO;
		return -EIO;
	}
	}


	if (x & CSR_MAL) {
	if (cmd_err & CSR_MAL) {
		dev_dbg(i2c->dev, "MAL\n");
		dev_dbg(i2c->dev, "MAL\n");
		return -EIO;
		return -EAGAIN;
	}
	}


	if (writing && (x & CSR_RXAK)) {
	if (writing && (cmd_err & CSR_RXAK)) {
		dev_dbg(i2c->dev, "No RXAK\n");
		dev_dbg(i2c->dev, "No RXAK\n");
		/* generate stop */
		/* generate stop */
		writeccr(i2c, CCR_MEN);
		writeccr(i2c, CCR_MEN);
		return -EIO;
		return -ENXIO;
	}
	}
	return 0;
	return 0;
}
}