Skip to content

Commit

Permalink
i2c: octeon: thunderx: Limit register access retries
Browse files Browse the repository at this point in the history
Do not infinitely retry register readq and writeq operations
in order to not lock up the CPU in case the TWSI gets stuck.

Return -EIO in case of a failed data read. For all other
cases just return so subsequent operations will fail
and trigger the recovery.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
  • Loading branch information
Jan Glauber authored and Wolfram Sang committed Dec 17, 2016
1 parent 59331c2 commit 493ff7e
Showing 2 changed files with 19 additions and 6 deletions.
4 changes: 3 additions & 1 deletion drivers/i2c/busses/i2c-octeon-core.c
Original file line number Diff line number Diff line change
@@ -342,7 +342,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
if (result)
return result;

data[i] = octeon_i2c_data_read(i2c);
data[i] = octeon_i2c_data_read(i2c, &result);
if (result)
return result;
if (recv_len && i == 0) {
if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
return -EPROTO;
21 changes: 16 additions & 5 deletions drivers/i2c/busses/i2c-octeon-core.h
Original file line number Diff line number Diff line change
@@ -141,11 +141,14 @@ static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
*/
static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
{
int tries = 1000;
u64 tmp;

__raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
do {
tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
if (--tries < 0)
return;
} while ((tmp & SW_TWSI_V) != 0);
}

@@ -163,24 +166,32 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8
*
* The I2C core registers are accessed indirectly via the SW_TWSI CSR.
*/
static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
static inline int octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg,
int *error)
{
int tries = 1000;
u64 tmp;

__raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
do {
tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
if (--tries < 0) {
/* signal that the returned data is invalid */
if (error)
*error = -EIO;
return 0;
}
} while ((tmp & SW_TWSI_V) != 0);

return tmp & 0xFF;
}

#define octeon_i2c_ctl_read(i2c) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
#define octeon_i2c_data_read(i2c) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL)
#define octeon_i2c_data_read(i2c, error) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)
#define octeon_i2c_stat_read(i2c) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL)

/**
* octeon_i2c_read_int - read the TWSI_INT register

0 comments on commit 493ff7e

Please sign in to comment.