Skip to content

Commit c7b514e

Browse files
Wolfram Sangwsakernel
authored andcommitted
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 <[email protected]> Reviewed-by: Niklas Söderlund <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 357ee88 commit c7b514e

File tree

1 file changed

+4
-7
lines changed

1 file changed

+4
-7
lines changed

drivers/i2c/busses/i2c-rcar.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191

9292
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
9393
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
94-
#define RCAR_BUS_MASK_DATA (~(ESG | FSB) & 0xFF)
9594
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
9695

9796
#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE)
@@ -621,7 +620,7 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
621620
/*
622621
* This driver has a lock-free design because there are IP cores (at least
623622
* R-Car Gen2) which have an inherent race condition in their hardware design.
624-
* There, we need to clear RCAR_BUS_MASK_DATA bits as soon as possible after
623+
* There, we need to switch to RCAR_BUS_PHASE_DATA as soon as possible after
625624
* the interrupt was generated, otherwise an unwanted repeated message gets
626625
* generated. It turned out that taking a spinlock at the beginning of the ISR
627626
* 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)
630629
static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
631630
{
632631
struct rcar_i2c_priv *priv = ptr;
633-
u32 msr, val;
632+
u32 msr;
634633

635634
/* Clear START or STOP immediately, except for REPSTART after read */
636-
if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) {
637-
val = rcar_i2c_read(priv, ICMCR);
638-
rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
639-
}
635+
if (likely(!(priv->flags & ID_P_REP_AFTER_RD)))
636+
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
640637

641638
msr = rcar_i2c_read(priv, ICMSR);
642639

0 commit comments

Comments
 (0)