Skip to content

Commit 33a015e

Browse files
Joakim Tjernlundsmb49
authored andcommitted
i2c: mpc: Correct I2C reset procedure
BugLink: https://bugs.launchpad.net/bugs/1960566 [ Upstream commit ebe82cf ] Current I2C reset procedure is broken in two ways: 1) It only generate 1 START instead of 9 STARTs and STOP. 2) It leaves the bus Busy so every I2C xfer after the first fixup calls the reset routine again, for every xfer there after. This fixes both errors. Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com> Acked-by: Scott Wood <oss@buserror.net> Signed-off-by: Wolfram Sang <wsa@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent b1ab20d commit 33a015e

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

drivers/i2c/busses/i2c-mpc.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,23 +105,30 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
105105
/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
106106
* the bus, because it wants to send ACK.
107107
* Following sequence of enabling/disabling and sending start/stop generates
108-
* the 9 pulses, so it's all OK.
108+
* the 9 pulses, each with a START then ending with STOP, so it's all OK.
109109
*/
110110
static void mpc_i2c_fixup(struct mpc_i2c *i2c)
111111
{
112112
int k;
113-
u32 delay_val = 1000000 / i2c->real_clk + 1;
114-
115-
if (delay_val < 2)
116-
delay_val = 2;
113+
unsigned long flags;
117114

118115
for (k = 9; k; k--) {
119116
writeccr(i2c, 0);
120-
writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
117+
writeb(0, i2c->base + MPC_I2C_SR); /* clear any status bits */
118+
writeccr(i2c, CCR_MEN | CCR_MSTA); /* START */
119+
readb(i2c->base + MPC_I2C_DR); /* init xfer */
120+
udelay(15); /* let it hit the bus */
121+
local_irq_save(flags); /* should not be delayed further */
122+
writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSTA); /* delay SDA */
121123
readb(i2c->base + MPC_I2C_DR);
122-
writeccr(i2c, CCR_MEN);
123-
udelay(delay_val << 1);
124+
if (k != 1)
125+
udelay(5);
126+
local_irq_restore(flags);
124127
}
128+
writeccr(i2c, CCR_MEN); /* Initiate STOP */
129+
readb(i2c->base + MPC_I2C_DR);
130+
udelay(15); /* Let STOP propagate */
131+
writeccr(i2c, 0);
125132
}
126133

127134
static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)

0 commit comments

Comments
 (0)