summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2009-10-10 17:22:06 +0000
committerMichael Sparmann <theseven@rockbox.org>2009-10-10 17:22:06 +0000
commit31464f7930cd8857ef8d00ed75534087057058e2 (patch)
tree7ccbbd402ab9b9e0b07f0cc4537a611808ad1c04 /firmware
parente2aeef7501d0a0ef1c33432692cdaeff225d5d8b (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.c66
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;