91 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 3f450d3eea14799b14192231840c1753a660f150 Mon Sep 17 00:00:00 2001
 | ||
| From: Abhishek Sahu <absahu@codeaurora.org>
 | ||
| Date: Mon, 12 Mar 2018 18:44:56 +0530
 | ||
| Subject: [PATCH 07/13] i2c: qup: proper error handling for i2c error in BAM
 | ||
|  mode
 | ||
| 
 | ||
| Currently the i2c error handling in BAM mode is not working
 | ||
| properly in stress condition.
 | ||
| 
 | ||
| 1. After an error, the FIFO are being written with FLUSH and
 | ||
|    EOT tags which should not be required since already these tags
 | ||
|    have been written in BAM descriptor itself.
 | ||
| 
 | ||
| 2. QUP state is being moved to RESET in IRQ handler in case
 | ||
|    of error. When QUP HW encounters an error in BAM mode then it
 | ||
|    moves the QUP STATE to PAUSE state. In this case, I2C_FLUSH
 | ||
|    command needs to be executed while moving to RUN_STATE by writing
 | ||
|    to the QUP_STATE register with the I2C_FLUSH bit set to 1.
 | ||
| 
 | ||
| 3. In Error case, sometimes, QUP generates more than one
 | ||
|    interrupt which will trigger the complete again. After an error,
 | ||
|    the flush operation will be scheduled after doing
 | ||
|    reinit_completion which should be triggered by BAM IRQ callback.
 | ||
|    If the second QUP IRQ comes during this time then it will call
 | ||
|    the complete and the transfer function will assume the all the
 | ||
|    BAM HW descriptors have been completed.
 | ||
| 
 | ||
| 4. The release DMA is being called after each error which
 | ||
|    will free the DMA tx and rx channels. The error like NACK is very
 | ||
|    common in I2C transfer and every time this will be overhead. Now,
 | ||
|    since the error handling is proper so this release channel can be
 | ||
|    completely avoided.
 | ||
| 
 | ||
| Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
 | ||
| Reviewed-by: Sricharan R <sricharan@codeaurora.org>
 | ||
| Reviewed-by: Austin Christ <austinwc@codeaurora.org>
 | ||
| Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
 | ||
| ---
 | ||
|  drivers/i2c/busses/i2c-qup.c | 25 ++++++++++++++++---------
 | ||
|  1 file changed, 16 insertions(+), 9 deletions(-)
 | ||
| 
 | ||
| --- a/drivers/i2c/busses/i2c-qup.c
 | ||
| +++ b/drivers/i2c/busses/i2c-qup.c
 | ||
| @@ -219,9 +219,24 @@ static irqreturn_t qup_i2c_interrupt(int
 | ||
|  	if (bus_err)
 | ||
|  		writel(bus_err, qup->base + QUP_I2C_STATUS);
 | ||
|  
 | ||
| +	/*
 | ||
| +	 * Check for BAM mode and returns if already error has come for current
 | ||
| +	 * transfer. In Error case, sometimes, QUP generates more than one
 | ||
| +	 * interrupt.
 | ||
| +	 */
 | ||
| +	if (qup->use_dma && (qup->qup_err || qup->bus_err))
 | ||
| +		return IRQ_HANDLED;
 | ||
| +
 | ||
|  	/* Reset the QUP State in case of error */
 | ||
|  	if (qup_err || bus_err) {
 | ||
| -		writel(QUP_RESET_STATE, qup->base + QUP_STATE);
 | ||
| +		/*
 | ||
| +		 * Don’t reset the QUP state in case of BAM mode. The BAM
 | ||
| +		 * flush operation needs to be scheduled in transfer function
 | ||
| +		 * which will clear the remaining schedule descriptors in BAM
 | ||
| +		 * HW FIFO and generates the BAM interrupt.
 | ||
| +		 */
 | ||
| +		if (!qup->use_dma)
 | ||
| +			writel(QUP_RESET_STATE, qup->base + QUP_STATE);
 | ||
|  		goto done;
 | ||
|  	}
 | ||
|  
 | ||
| @@ -848,20 +863,12 @@ static int qup_i2c_bam_do_xfer(struct qu
 | ||
|  			goto desc_err;
 | ||
|  		}
 | ||
|  
 | ||
| -		if (rx_cnt)
 | ||
| -			writel(QUP_BAM_INPUT_EOT,
 | ||
| -			       qup->base + QUP_OUT_FIFO_BASE);
 | ||
| -
 | ||
| -		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
 | ||
| -
 | ||
|  		qup_i2c_flush(qup);
 | ||
|  
 | ||
|  		/* wait for remaining interrupts to occur */
 | ||
|  		if (!wait_for_completion_timeout(&qup->xfer, HZ))
 | ||
|  			dev_err(qup->dev, "flush timed out\n");
 | ||
|  
 | ||
| -		qup_i2c_rel_dma(qup);
 | ||
| -
 | ||
|  		ret =  (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
 | ||
|  	}
 | ||
|  
 | 
