|
@@ -113,9 +113,10 @@
|
|
|
#define ID_ARBLOST (1 << 3)
|
|
|
#define ID_NACK (1 << 4)
|
|
|
/* persistent flags */
|
|
|
+#define ID_P_REP_AFTER_RD BIT(29)
|
|
|
#define ID_P_NO_RXDMA BIT(30) /* HW forbids RXDMA sometimes */
|
|
|
#define ID_P_PM_BLOCKED BIT(31)
|
|
|
-#define ID_P_MASK GENMASK(31, 30)
|
|
|
+#define ID_P_MASK GENMASK(31, 29)
|
|
|
|
|
|
enum rcar_i2c_type {
|
|
|
I2C_RCAR_GEN1,
|
|
@@ -345,7 +346,10 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
|
|
|
rcar_i2c_write(priv, ICMSR, 0);
|
|
|
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
|
|
|
} else {
|
|
|
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
|
|
|
+ if (priv->flags & ID_P_REP_AFTER_RD)
|
|
|
+ priv->flags &= ~ID_P_REP_AFTER_RD;
|
|
|
+ else
|
|
|
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
|
|
|
rcar_i2c_write(priv, ICMSR, 0);
|
|
|
}
|
|
|
rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
|
|
@@ -550,15 +554,15 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
|
|
|
priv->pos++;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * If next received data is the _LAST_, go to STOP phase. Might be
|
|
|
- * overwritten by REP START when setting up a new msg. Not elegant
|
|
|
- * but the only stable sequence for REP START I have found so far.
|
|
|
- * If you want to change this code, make sure sending one transfer with
|
|
|
- * four messages (WR-RD-WR-RD) works!
|
|
|
- */
|
|
|
- if (priv->pos + 1 >= msg->len)
|
|
|
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
|
|
|
+ /* If next received data is the _LAST_, go to new phase. */
|
|
|
+ if (priv->pos + 1 == msg->len) {
|
|
|
+ if (priv->flags & ID_LAST_MSG) {
|
|
|
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
|
|
|
+ } else {
|
|
|
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
|
|
|
+ priv->flags |= ID_P_REP_AFTER_RD;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG))
|
|
|
rcar_i2c_next_msg(priv);
|
|
@@ -626,9 +630,11 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
|
|
|
struct rcar_i2c_priv *priv = ptr;
|
|
|
u32 msr, val;
|
|
|
|
|
|
- /* Clear START or STOP as soon as we can */
|
|
|
- val = rcar_i2c_read(priv, ICMCR);
|
|
|
- rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
|
|
|
+ /* 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);
|
|
|
+ }
|
|
|
|
|
|
msr = rcar_i2c_read(priv, ICMSR);
|
|
|
|