mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
		
							parent
							
								
									40b2ec1251
								
							
						
					
					
						commit
						b4c119dbc3
					
				
					 1 changed files with 42 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -156,6 +156,8 @@ struct xiic_i2c {
 | 
			
		|||
#define XIIC_RESET_MASK             0xAUL
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 * register, to enable all interrupts for the device, this is the only bit
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +168,7 @@ struct xiic_i2c {
 | 
			
		|||
#define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_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);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -247,17 +249,29 @@ static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 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;
 | 
			
		||||
	unsigned long timeout;
 | 
			
		||||
 | 
			
		||||
	timeout = jiffies + XIIC_I2C_TIMEOUT;
 | 
			
		||||
	for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
 | 
			
		||||
		!(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);
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
	/* Set receive Fifo depth to maximum (zero based). */
 | 
			
		||||
| 
						 | 
				
			
			@ -270,12 +284,16 @@ static void xiic_reinit(struct xiic_i2c *i2c)
 | 
			
		|||
	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK);
 | 
			
		||||
 | 
			
		||||
	/* make sure RX fifo is empty */
 | 
			
		||||
	xiic_clear_rx_fifo(i2c);
 | 
			
		||||
	ret = xiic_clear_rx_fifo(i2c);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	/* Enable interrupts */
 | 
			
		||||
	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
 | 
			
		||||
 | 
			
		||||
	xiic_irq_clr_en(i2c, XIIC_INTR_ARB_LOST_MASK);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xiic_deinit(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);
 | 
			
		||||
	xiic_reinit(i2c);
 | 
			
		||||
	__xiic_start_xfer(i2c);
 | 
			
		||||
 | 
			
		||||
	ret = xiic_reinit(i2c);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		__xiic_start_xfer(i2c);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&i2c->lock);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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->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) ||
 | 
			
		||||
		(i2c->state == STATE_DONE), HZ)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -794,7 +822,11 @@ static int xiic_i2c_probe(struct platform_device *pdev)
 | 
			
		|||
	if (!(sr & XIIC_SR_TX_FIFO_EMPTY_MASK))
 | 
			
		||||
		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 */
 | 
			
		||||
	ret = i2c_add_adapter(&i2c->adap);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue