diff --git a/Targets/LS2K/dev/i2c.c b/Targets/LS2K/dev/i2c.c index 8213810a..d0e45235 100644 --- a/Targets/LS2K/dev/i2c.c +++ b/Targets/LS2K/dev/i2c.c @@ -47,6 +47,12 @@ struct i2c_msg { #define ls2k_i2c_debug(fmt, args...) //printf(fmt, ##args) #define pr_info printf +static void ls2k_i2c_reinit() +{ + ls2k_i2c_writeb(0, LS2K_I2C_CTR_REG); + ls2k_i2c_writeb(0x80, LS2K_I2C_CTR_REG); + ls2k_i2c_writeb(CR_IACK, LS2K_I2C_CR_REG); +} static void ls2k_i2c_stop(void) { @@ -59,18 +65,24 @@ again: static int ls2k_i2c_start(int dev_addr, int flags) { - int retry = 5; + int retry = 5, sr; unsigned char addr = (dev_addr & 0x7f) << 1; addr |= (flags & I2C_M_RD)? 1:0; start: + delay(1000); ls2k_i2c_writeb(addr, LS2K_I2C_TXR_REG); ls2k_i2c_debug("%s : i2c device address: 0x%x\n", __func__, __LINE__, addr); ls2k_i2c_writeb((CR_START | CR_WRITE), LS2K_I2C_CR_REG); - while (ls2k_i2c_readb(LS2K_I2C_SR_REG) & SR_TIP) ; + while (((sr = ls2k_i2c_readb(LS2K_I2C_SR_REG)) & (SR_TIP|SR_AL)) == SR_TIP); + if(sr & SR_AL) { + ls2k_i2c_reinit(); + ls2k_i2c_stop(); + goto start; + } - if (ls2k_i2c_readb(LS2K_I2C_SR_REG) & SR_NOACK) { + if (sr & SR_NOACK) { ls2k_i2c_stop(); while (retry--) goto start; @@ -82,13 +94,17 @@ start: static int ls2k_i2c_read(unsigned char *buf, int count) { - int i; + int i, sr; for (i = 0; i < count; i++) { ls2k_i2c_writeb((i == count - 1)? (CR_READ | CR_ACK) : CR_READ, LS2K_I2C_CR_REG); - while (ls2k_i2c_readb(LS2K_I2C_SR_REG) & SR_TIP) ; + while (((sr = ls2k_i2c_readb(LS2K_I2C_SR_REG)) & (SR_TIP|SR_AL)) == SR_TIP); + if(sr & SR_AL) { + ls2k_i2c_reinit(); + break; + } buf[i] = ls2k_i2c_readb(LS2K_I2C_RXR_REG); ls2k_i2c_debug("%s : read buf[%d] <= %02x\n", __func__, __LINE__, i, buf[i]); @@ -99,16 +115,20 @@ static int ls2k_i2c_read(unsigned char *buf, int count) static int ls2k_i2c_write(unsigned char *buf, int count) { - int i; + int i, sr; for (i = 0; i < count; i++) { ls2k_i2c_writeb(buf[i], LS2K_I2C_TXR_REG); ls2k_i2c_debug("%s : write buf[%d] => %02x\n", __func__, __LINE__, i, buf[i]); ls2k_i2c_writeb(CR_WRITE, LS2K_I2C_CR_REG); - while (ls2k_i2c_readb(LS2K_I2C_SR_REG) & SR_TIP) ; + while (((sr = ls2k_i2c_readb(LS2K_I2C_SR_REG)) & (SR_TIP|SR_AL)) == SR_TIP); + if (sr & SR_AL) { + ls2k_i2c_reinit(); + break; + } - if (ls2k_i2c_readb(LS2K_I2C_SR_REG) & SR_NOACK) { + if (sr & SR_NOACK) { ls2k_i2c_debug("%s : device no ack\n", __func__, __LINE__); ls2k_i2c_stop();