Fix some ppc4xx i2c controller issues
cover Fix some ppc4xx i2c controller issues
From: Dirk Eibach <[email protected]>
Dirk Eibach (2):
ppc4xx: Fix i2c repeated start
ppc4xx: Handle i2c stuck on combined xfer
arch/powerpc/include/asm/ppc4xx-i2c.h | 2 ++ drivers/i2c/ppc4xx_i2c.c | 30 ++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-)
Signature · 1 line
1.8.3
PATCH 1/2 ppc4xx: Fix i2c repeated start
From: Dirk Eibach <[email protected]>
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.
---
drivers/i2c/ppc4xx_i2c.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/i2c/ppc4xx_i2c.c +5 -4
@@ -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;
Signature · 1 line
1.8.3
PATCH 1/2 ppc4xx: Fix i2c repeated start
Quoted 11 lines · dirk.eibach at gdsys.cc
From: Dirk Eibach <[email protected]>
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_RPSTis set on that part of the transfer that should begin with a repeated start. But repeated start is about not sending a stop condition, soIIC_CNTL_RPSThas to be set on the last transfer before the repeated start happens.Signed-off-by Dirk Eibach <[email protected]>
Thanks,
Stefan
PATCH 2/2 ppc4xx: Handle i2c stuck on combined xfer
In reply to dirk.eibach at gdsys.ccFrom: Dirk Eibach <[email protected]>
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.
---
arch/powerpc/include/asm/ppc4xx-i2c.h | 2 ++ drivers/i2c/ppc4xx_i2c.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+)
arch/powerpc/include/asm/ppc4xx-i2c.h +2 -0
@@ -72,6 +72,8 @@ struct ppc4xx_i2c {#define IIC_EXTSTS_XFRA 0x01#define IIC_EXTSTS_ICT 0x02#define IIC_EXTSTS_LA 0x04 +#define IIC_EXTSTS_BCS_MASK 0x70 +#define IIC_EXTSTS_BCS_FREE 0x40/* XTCNTLSS Register Bit definition */ #define IIC_XTCNTLSS_SRST 0x01
drivers/i2c/ppc4xx_i2c.c +21 -0
@@ -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 ; }
Signature · 1 line
1.8.3
PATCH 2/2 ppc4xx: Handle i2c stuck on combined xfer
Hello Dirk,
Am 29.10.2014 15:56, schrieb dirk.eibach at gdsys.cc:
Quoted 34 lines
From: Dirk Eibach<[email protected]>
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<[email protected]>---
arch/powerpc/include/asm/ppc4xx-i2c.h | 2 ++ drivers/i2c/ppc4xx_i2c.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+)arch/powerpc/include/asm/ppc4xx-i2c.h +2
-0@@ -72,6 +72,8 @@ struct ppc4xx_i2c {#define IIC_EXTSTS_XFRA 0x01#define IIC_EXTSTS_ICT 0x02#define IIC_EXTSTS_LA 0x04 +#define IIC_EXTSTS_BCS_MASK 0x70 +#define IIC_EXTSTS_BCS_FREE 0x40/* XTCNTLSS Register Bit definition */ #define IIC_XTCNTLSS_SRST 0x01drivers/i2c/ppc4xx_i2c.c +0
-0
drivers/i2c/ppc4xx_i2c.c static int _i2c_transfer(struct i2c_adapter *adap, · line 292
Quoted 4 lines
drivers/i2c/ppc4xx_i2c.c +1
-0@@ -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?
Nitpick only: wrong comment style ... Is it OK for you, if I fix it, when applying this patch?
Thanks!
bye,
Heiko
Quoted 23 lines
drivers/i2c/ppc4xx_i2c.c +20
-0+* 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 ; }
Signature · 2 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 2/2 ppc4xx: Handle i2c stuck on combined xfer
Hello Heiko,
Quoted 10 lines
drivers/i2c/ppc4xx_i2c.c static int _i2c_transfer(struct i2c_adapter *adap, · line 292
Quoted 6 lines
+++
b/drivers/i2c/ppc4xx_i2c.cdrivers/i2c/ppc4xx_i2c.c +1
-0@@ -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? Nitpick only: wrong comment style ... Is it OK for you, if I fix it, when applying this patch?
Oops, yes please fix it when applying. Shouldn't checkpatch catch this?
Cheers
Dirk
PATCH 2/2 ppc4xx: Handle i2c stuck on combined xfer
In reply to dirk.eibach at gdsys.ccQuoted 10 lines · dirk.eibach at gdsys.cc
From: Dirk Eibach <[email protected]>
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 <[email protected]>
Thanks,
Stefan