From 7e78f7ad7f7f666598bc2ff115ea7a35f8e059f1 Mon Sep 17 00:00:00 2001 From: Dirk Eibach Date: Wed, 29 Oct 2014 15:56:43 +0100 Subject: ppc4xx: Fix i2c repeated start Debugging some i2c trouble I saw on my scope that repeated start is not working properply. The 4xx even held clock pulled down after transfers. Having a look in the driver I realized that IIC_CNTL_RPST is set on that part of the transfer that should begin with a repeated start. But repeated start is about not sending a stop condition, so IIC_CNTL_RPST has to be set on the last transfer before the repeated start happens. Signed-off-by: Dirk Eibach Reviewed-by: Stefan Roese --- drivers/i2c/ppc4xx_i2c.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index e7a15ba..d2ff86c 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c @@ -158,8 +158,7 @@ static void ppc4xx_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) * * Typical case is a Write of an addr followd by a Read. The * IBM FAQ does not cover this. On the last byte of the write - * we don't set the creg CHT bit, and on the first bytes of the - * read we set the RPST bit. + * we don't set the creg CHT bit but the RPST bit. * * It does not support address only transfers, there must be * a data part. If you want to write the address yourself, put @@ -247,6 +246,10 @@ static int _i2c_transfer(struct i2c_adapter *adap, if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt)) creg |= IIC_CNTL_CHT; + /* last part of address, prepare for repeated start on read */ + if (cmd_type && (ptr == addr) && ((tran + bc) == cnt)) + creg |= IIC_CNTL_RPST; + if (reading) { creg |= IIC_CNTL_READ; } else { @@ -314,8 +317,6 @@ static int _i2c_transfer(struct i2c_adapter *adap, cnt = data_len; tran = 0; reading = cmd_type; - if (reading) - creg = IIC_CNTL_RPST; } } return result; -- cgit v1.1 From b97cd6814ec08be56225975a050ee486bfa7c13a Mon Sep 17 00:00:00 2001 From: Dirk Eibach Date: Wed, 29 Oct 2014 15:56:44 +0100 Subject: ppc4xx: Handle i2c stuck on combined xfer ppc4xx i2c master gets stuck on errors while repeated start is active. Can be easily reproduced by "i2c md" on an unpopulated i2c address. There is not stop condition given, scl remains pulled low. The only way out seems to be doing a stop manually and then a soft reset. Signed-off-by: Dirk Eibach Reviewed-by: Stefan Roese --- drivers/i2c/ppc4xx_i2c.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index d2ff86c..df88885 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c @@ -289,6 +289,27 @@ static int _i2c_transfer(struct i2c_adapter *adap, /* Transfer aborted? */ if (status & IIC_EXTSTS_XFRA) result = IIC_NOK_XFRA; + /* Is bus free? + * If error happened during combined xfer + * IIC interface is usually stuck in some strange + * state without a valid stop condition. + * Brute, but working: generate stop, then soft reset. + */ + if ((status & IIC_EXTSTS_BCS_MASK) + != IIC_EXTSTS_BCS_FREE){ + u8 mdcntl = in_8(&i2c->mdcntl); + + /* Generate valid stop condition */ + out_8(&i2c->xtcntlss, IIC_XTCNTLSS_SRST); + out_8(&i2c->directcntl, IIC_DIRCNTL_SCC); + udelay(10); + out_8(&i2c->directcntl, + IIC_DIRCNTL_SCC | IIC_DIRCNTL_SDAC); + out_8(&i2c->xtcntlss, 0); + + ppc4xx_i2c_init(adap, (mdcntl & IIC_MDCNTL_FSM) + ? 400000 : 100000, 0); + } } else if ( status & IIC_STS_PT) { result = IIC_NOK_TOUT; } -- cgit v1.1 From 6dd38cc35245db624443ee596eb78853fa9cca7a Mon Sep 17 00:00:00 2001 From: Shaveta Leekha Date: Mon, 3 Nov 2014 10:43:14 +0530 Subject: drivers/i2c/fsl_i2c: Change CONFIG_I2C_TIMEOUT to 100ms Some slow I2C devices like Power Monitor(ZM7304) at times do not work well with low timeout value, so I2C bus get stuck during read cycle with this device, changing it to 100ms from 10ms works fine A lot of other i2c drivers like mxc and i2c drivers of BOOTROM also use relax timeouts to give sufficient ticks to work well with slower devices Signed-off-by: Shaveta Leekha Signed-off-by: Poonam Aggrwal --- drivers/i2c/fsl_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index 811033b..7bb1702 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -38,7 +38,7 @@ * generic value. */ #ifndef CONFIG_I2C_TIMEOUT -#define CONFIG_I2C_TIMEOUT 10000 +#define CONFIG_I2C_TIMEOUT 100000 #endif #define I2C_READ_BIT 1 -- cgit v1.1 From cd818a381ddcdc2440a167757394298f28b70240 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 4 Nov 2014 13:28:50 +0900 Subject: i2c: rcar_i2c: Fix order of restart and clear status In case of repeated START condition, the restart has to be kicked before clear status (MSR register). If it is kicked after clear status, R-Car I2C may transfer data (TXD register) or receive data (RXD register) instead of transferring slave address (MAR register). Signed-off-by: Ryo Kataoka Signed-off-by: Nobuhiro Iwamatsu --- drivers/i2c/rcar_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/rcar_i2c.c b/drivers/i2c/rcar_i2c.c index 50cebd6..90ad116 100644 --- a/drivers/i2c/rcar_i2c.c +++ b/drivers/i2c/rcar_i2c.c @@ -119,10 +119,10 @@ rcar_i2c_raw_read(struct rcar_i2c *dev, u8 chip, uint addr) /* set slave address, receive */ writel((chip << 1) | 1, &dev->icmar); - /* clear status */ - writel(0, &dev->icmsr); /* start master receive */ writel(MCR_MDBS | MCR_MIE | MCR_ESG, &dev->icmcr); + /* clear status */ + writel(0, &dev->icmsr); while ((readl(&dev->icmsr) & (MSR_MAT | MSR_MDR)) != (MSR_MAT | MSR_MDR)) -- cgit v1.1