Add a timeout for I2C transfers (S5L870x)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23077 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sparmann 2009-10-10 17:22:06 +00:00
parent e2aeef7501
commit 31464f7930

View file

@ -67,31 +67,53 @@ void i2c_init(void)
int i2c_write(unsigned char slave, int address, int len, const unsigned char *data) int i2c_write(unsigned char slave, int address, int len, const unsigned char *data)
{ {
mutex_lock(&i2c_mtx); mutex_lock(&i2c_mtx);
long timeout = current_tick + HZ / 50;
/* START */ /* START */
IICDS = slave & ~1; IICDS = slave & ~1;
IICSTAT = 0xF0; IICSTAT = 0xF0;
IICCON = 0xB7; 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) { if (address >= 0) {
/* write address */ /* write address */
IICDS = address; IICDS = address;
IICCON = 0xB7; IICCON = 0xB7;
while ((IICCON & 0x10) == 0); while ((IICCON & 0x10) == 0)
if (TIME_AFTER(current_tick, timeout))
{
mutex_unlock(&i2c_mtx);
return 2;
}
} }
/* write data */ /* write data */
while (len--) { while (len--) {
IICDS = *data++; IICDS = *data++;
IICCON = 0xB7; IICCON = 0xB7;
while ((IICCON & 0x10) == 0); while ((IICCON & 0x10) == 0)
if (TIME_AFTER(current_tick, timeout))
{
mutex_unlock(&i2c_mtx);
return 4;
}
} }
/* STOP */ /* STOP */
IICSTAT = 0xD0; IICSTAT = 0xD0;
IICCON = 0xB7; 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); mutex_unlock(&i2c_mtx);
return 0; 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) int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
{ {
mutex_lock(&i2c_mtx); mutex_lock(&i2c_mtx);
long timeout = current_tick + HZ / 50;
if (address >= 0) { if (address >= 0) {
/* START */ /* START */
IICDS = slave & ~1; IICDS = slave & ~1;
IICSTAT = 0xF0; IICSTAT = 0xF0;
IICCON = 0xB7; IICCON = 0xB7;
while ((IICCON & 0x10) == 0); while ((IICCON & 0x10) == 0)
if (TIME_AFTER(current_tick, timeout))
{
mutex_unlock(&i2c_mtx);
return 1;
}
/* write address */ /* write address */
IICDS = address; IICDS = address;
IICCON = 0xB7; IICCON = 0xB7;
while ((IICCON & 0x10) == 0); while ((IICCON & 0x10) == 0)
if (TIME_AFTER(current_tick, timeout))
{
mutex_unlock(&i2c_mtx);
return 2;
}
} }
/* (repeated) START */ /* (repeated) START */
IICDS = slave | 1; IICDS = slave | 1;
IICSTAT = 0xB0; IICSTAT = 0xB0;
IICCON = 0xB7; IICCON = 0xB7;
while ((IICCON & 0x10) == 0); while ((IICCON & 0x10) == 0)
if (TIME_AFTER(current_tick, timeout))
{
mutex_unlock(&i2c_mtx);
return 3;
}
while (len--) { while (len--) {
IICCON = (len == 0) ? 0x37 : 0xB7; /* NACK or ACK */ 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; *data++ = IICDS;
} }
/* STOP */ /* STOP */
IICSTAT = 0x90; IICSTAT = 0x90;
IICCON = 0xB7; 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); mutex_unlock(&i2c_mtx);
return 0; return 0;