Commit b4c119db authored by Shubhrajyoti Datta's avatar Shubhrajyoti Datta Committed by Wolfram Sang

i2c: xiic: Add timeout to the rx fifo wait loop

Add timeout to the rx fifo empty wait loop. Also check for the return
value for xiic_reinit and pass it to xiic_start_xfer.
Signed-off-by: default avatarShubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Signed-off-by: default avatarMichal Simek <michal.simek@xilinx.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 40b2ec12
...@@ -156,6 +156,8 @@ struct xiic_i2c { ...@@ -156,6 +156,8 @@ struct xiic_i2c {
#define XIIC_RESET_MASK 0xAUL #define XIIC_RESET_MASK 0xAUL
#define XIIC_PM_TIMEOUT 1000 /* ms */ #define XIIC_PM_TIMEOUT 1000 /* ms */
/* timeout waiting for the controller to respond */
#define XIIC_I2C_TIMEOUT (msecs_to_jiffies(1000))
/* /*
* The following constant is used for the device global interrupt enable * The following constant is used for the device global interrupt enable
* register, to enable all interrupts for the device, this is the only bit * register, to enable all interrupts for the device, this is the only bit
...@@ -166,7 +168,7 @@ struct xiic_i2c { ...@@ -166,7 +168,7 @@ struct xiic_i2c {
#define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos) #define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos)
#define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos) #define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos)
static void xiic_start_xfer(struct xiic_i2c *i2c); static int xiic_start_xfer(struct xiic_i2c *i2c);
static void __xiic_start_xfer(struct xiic_i2c *i2c); static void __xiic_start_xfer(struct xiic_i2c *i2c);
/* /*
...@@ -247,17 +249,29 @@ static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask) ...@@ -247,17 +249,29 @@ static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask)
xiic_irq_en(i2c, mask); xiic_irq_en(i2c, mask);
} }
static void xiic_clear_rx_fifo(struct xiic_i2c *i2c) static int xiic_clear_rx_fifo(struct xiic_i2c *i2c)
{ {
u8 sr; u8 sr;
unsigned long timeout;
timeout = jiffies + XIIC_I2C_TIMEOUT;
for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
!(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK);
sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) {
xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
if (time_after(jiffies, timeout)) {
dev_err(i2c->dev, "Failed to clear rx fifo\n");
return -ETIMEDOUT;
}
}
return 0;
} }
static void xiic_reinit(struct xiic_i2c *i2c) static int xiic_reinit(struct xiic_i2c *i2c)
{ {
int ret;
xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
/* Set receive Fifo depth to maximum (zero based). */ /* Set receive Fifo depth to maximum (zero based). */
...@@ -270,12 +284,16 @@ static void xiic_reinit(struct xiic_i2c *i2c) ...@@ -270,12 +284,16 @@ static void xiic_reinit(struct xiic_i2c *i2c)
xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK);
/* make sure RX fifo is empty */ /* make sure RX fifo is empty */
xiic_clear_rx_fifo(i2c); ret = xiic_clear_rx_fifo(i2c);
if (ret)
return ret;
/* Enable interrupts */ /* Enable interrupts */
xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
xiic_irq_clr_en(i2c, XIIC_INTR_ARB_LOST_MASK); xiic_irq_clr_en(i2c, XIIC_INTR_ARB_LOST_MASK);
return 0;
} }
static void xiic_deinit(struct xiic_i2c *i2c) static void xiic_deinit(struct xiic_i2c *i2c)
...@@ -655,12 +673,18 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c) ...@@ -655,12 +673,18 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)
} }
static void xiic_start_xfer(struct xiic_i2c *i2c) static int xiic_start_xfer(struct xiic_i2c *i2c)
{ {
int ret;
mutex_lock(&i2c->lock); mutex_lock(&i2c->lock);
xiic_reinit(i2c);
__xiic_start_xfer(i2c); ret = xiic_reinit(i2c);
if (!ret)
__xiic_start_xfer(i2c);
mutex_unlock(&i2c->lock); mutex_unlock(&i2c->lock);
return ret;
} }
static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
...@@ -682,7 +706,11 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -682,7 +706,11 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
i2c->tx_msg = msgs; i2c->tx_msg = msgs;
i2c->nmsgs = num; i2c->nmsgs = num;
xiic_start_xfer(i2c); err = xiic_start_xfer(i2c);
if (err < 0) {
dev_err(adap->dev.parent, "Error xiic_start_xfer\n");
goto out;
}
if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
(i2c->state == STATE_DONE), HZ)) { (i2c->state == STATE_DONE), HZ)) {
...@@ -794,7 +822,11 @@ static int xiic_i2c_probe(struct platform_device *pdev) ...@@ -794,7 +822,11 @@ static int xiic_i2c_probe(struct platform_device *pdev)
if (!(sr & XIIC_SR_TX_FIFO_EMPTY_MASK)) if (!(sr & XIIC_SR_TX_FIFO_EMPTY_MASK))
i2c->endianness = BIG; i2c->endianness = BIG;
xiic_reinit(i2c); ret = xiic_reinit(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot xiic_reinit\n");
goto err_clk_dis;
}
/* add i2c adapter to i2c tree */ /* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap); ret = i2c_add_adapter(&i2c->adap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment