diff options
author | Michael Sparmann <theseven@rockbox.org> | 2009-10-10 17:22:06 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2009-10-10 17:22:06 +0000 |
commit | 31464f7930cd8857ef8d00ed75534087057058e2 (patch) | |
tree | 7ccbbd402ab9b9e0b07f0cc4537a611808ad1c04 /firmware | |
parent | e2aeef7501d0a0ef1c33432692cdaeff225d5d8b (diff) |
Add a timeout for I2C transfers (S5L870x)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23077 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/s5l8700/i2c-s5l8700.c | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/firmware/target/arm/s5l8700/i2c-s5l8700.c b/firmware/target/arm/s5l8700/i2c-s5l8700.c index fed10578c2..a5661c5848 100644 --- a/firmware/target/arm/s5l8700/i2c-s5l8700.c +++ b/firmware/target/arm/s5l8700/i2c-s5l8700.c @@ -67,31 +67,53 @@ void i2c_init(void) int i2c_write(unsigned char slave, int address, int len, const unsigned char *data) { mutex_lock(&i2c_mtx); + long timeout = current_tick + HZ / 50; /* START */ IICDS = slave & ~1; IICSTAT = 0xF0; IICCON = 0xB7; - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 1; + } + if (address >= 0) { /* write address */ IICDS = address; IICCON = 0xB7; - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 2; + } } /* write data */ while (len--) { IICDS = *data++; IICCON = 0xB7; - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 4; + } } /* STOP */ IICSTAT = 0xD0; IICCON = 0xB7; - while ((IICSTAT & (1 << 5)) != 0); + while ((IICSTAT & (1 << 5)) != 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 5; + } mutex_unlock(&i2c_mtx); return 0; @@ -100,36 +122,62 @@ int i2c_write(unsigned char slave, int address, int len, const unsigned char *da int i2c_read(unsigned char slave, int address, int len, unsigned char *data) { mutex_lock(&i2c_mtx); + long timeout = current_tick + HZ / 50; if (address >= 0) { /* START */ IICDS = slave & ~1; IICSTAT = 0xF0; IICCON = 0xB7; - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 1; + } /* write address */ IICDS = address; IICCON = 0xB7; - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 2; + } } /* (repeated) START */ IICDS = slave | 1; IICSTAT = 0xB0; IICCON = 0xB7; - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 3; + } while (len--) { IICCON = (len == 0) ? 0x37 : 0xB7; /* NACK or ACK */ - while ((IICCON & 0x10) == 0); + while ((IICCON & 0x10) == 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 4; + } *data++ = IICDS; } /* STOP */ IICSTAT = 0x90; IICCON = 0xB7; - while ((IICSTAT & (1 << 5)) != 0); + while ((IICSTAT & (1 << 5)) != 0) + if (TIME_AFTER(current_tick, timeout)) + { + mutex_unlock(&i2c_mtx); + return 5; + } mutex_unlock(&i2c_mtx); return 0; |