qup_i2c: Fix state check in polling code.

If QUP core is in PAUSE state then the state check returns true
for any other state incorrectly. Also, if the core is in RUN state
and it's being put in RESET, then RESET state check may return true
even if it's not out of RUN (and if VALID bit is set).
State mask is used to verify what state QUP core is in to avoid this
problem.

Signed-off-by: Sagar Dharia <sdharia@codeaurora.org>
This commit is contained in:
Sagar Dharia
2011-08-05 11:03:03 -06:00
committed by Bryan Huntsman
parent 7ab6a9cb65
commit 518e230f4a

View File

@@ -327,19 +327,30 @@ static int qup_i2c_poll_clock_ready(struct qup_i2c_dev *dev)
}
static int
qup_i2c_poll_state(struct qup_i2c_dev *dev, uint32_t state)
qup_i2c_poll_state(struct qup_i2c_dev *dev, uint32_t req_state, bool only_valid)
{
uint32_t retries = 0;
dev_dbg(dev->dev, "Polling Status for state:0x%x\n", state);
dev_dbg(dev->dev, "Polling for state:0x%x, or valid-only:%d\n",
req_state, only_valid);
while (retries != 2000) {
uint32_t status = readl_relaxed(dev->base + QUP_STATE);
if ((status & (QUP_STATE_VALID | state)) ==
(QUP_STATE_VALID | state))
/*
* If only valid bit needs to be checked, requested state is
* 'don't care'
*/
if (status & QUP_STATE_VALID) {
if (only_valid)
return 0;
else if (retries++ == 1000)
else if ((req_state & QUP_I2C_MAST_GEN) &&
(status & QUP_I2C_MAST_GEN))
return 0;
else if ((status & QUP_STATE_MASK) == req_state)
return 0;
}
if (retries++ == 1000)
udelay(100);
}
return -ETIMEDOUT;
@@ -551,10 +562,10 @@ qup_issue_write(struct qup_i2c_dev *dev, struct i2c_msg *msg, int rem,
static int
qup_update_state(struct qup_i2c_dev *dev, uint32_t state)
{
if (qup_i2c_poll_state(dev, 0) != 0)
if (qup_i2c_poll_state(dev, 0, true) != 0)
return -EIO;
writel_relaxed(state, dev->base + QUP_STATE);
if (qup_i2c_poll_state(dev, state) != 0)
if (qup_i2c_poll_state(dev, state, false) != 0)
return -EIO;
return 0;
}
@@ -687,7 +698,7 @@ qup_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
}
writel_relaxed(1, dev->base + QUP_SW_RESET);
ret = qup_i2c_poll_state(dev, QUP_RESET_STATE);
ret = qup_i2c_poll_state(dev, QUP_RESET_STATE, false);
if (ret) {
dev_err(dev->dev, "QUP Busy:Trying to recover\n");
goto out_err;
@@ -720,7 +731,7 @@ qup_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev->err = 0;
dev->complete = &complete;
if (qup_i2c_poll_state(dev, QUP_I2C_MAST_GEN) != 0) {
if (qup_i2c_poll_state(dev, QUP_I2C_MAST_GEN, false) != 0) {
ret = -EIO;
goto out_err;
}