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:
committed by
Bryan Huntsman
parent
7ab6a9cb65
commit
518e230f4a
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user