i2c: rcar: faster irq code to minimize HW race condition
To avoid the HW race condition on R-Car Gen2 and earlier, we need to write to ICMCR as soon as possible in the interrupt handler. We can improve this by writing a static value instead of masking out bits. Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
		
							parent
							
								
									357ee8841d
								
							
						
					
					
						commit
						c7b514ec97
					
				| @ -91,7 +91,6 @@ | ||||
| 
 | ||||
| #define RCAR_BUS_PHASE_START	(MDBS | MIE | ESG) | ||||
| #define RCAR_BUS_PHASE_DATA	(MDBS | MIE) | ||||
| #define RCAR_BUS_MASK_DATA	(~(ESG | FSB) & 0xFF) | ||||
| #define RCAR_BUS_PHASE_STOP	(MDBS | MIE | FSB) | ||||
| 
 | ||||
| #define RCAR_IRQ_SEND	(MNR | MAL | MST | MAT | MDE) | ||||
| @ -621,7 +620,7 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) | ||||
| /*
 | ||||
|  * This driver has a lock-free design because there are IP cores (at least | ||||
|  * R-Car Gen2) which have an inherent race condition in their hardware design. | ||||
|  * There, we need to clear RCAR_BUS_MASK_DATA bits as soon as possible after | ||||
|  * There, we need to switch to RCAR_BUS_PHASE_DATA as soon as possible after | ||||
|  * the interrupt was generated, otherwise an unwanted repeated message gets | ||||
|  * generated. It turned out that taking a spinlock at the beginning of the ISR | ||||
|  * was already causing repeated messages. Thus, this driver was converted to | ||||
| @ -630,13 +629,11 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) | ||||
| static irqreturn_t rcar_i2c_irq(int irq, void *ptr) | ||||
| { | ||||
| 	struct rcar_i2c_priv *priv = ptr; | ||||
| 	u32 msr, val; | ||||
| 	u32 msr; | ||||
| 
 | ||||
| 	/* Clear START or STOP immediately, except for REPSTART after read */ | ||||
| 	if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) { | ||||
| 		val = rcar_i2c_read(priv, ICMCR); | ||||
| 		rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA); | ||||
| 	} | ||||
| 	if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) | ||||
| 		rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); | ||||
| 
 | ||||
| 	msr = rcar_i2c_read(priv, ICMSR); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user