rk27xx: fix i2c driver

Change-Id: I205cc92f452c1990c64da7e91b2baf00b920c922
This commit is contained in:
Marcin Bukat 2013-04-09 09:29:50 +02:00
parent dcba74155e
commit e6c0bd0350

View file

@ -24,8 +24,6 @@
#include "kernel.h"
#include "i2c-rk27xx.h"
/* NOT TESTED YET */
/* Driver for the rockchip rk27xx built-in I2C controller in master mode
Both the i2c_read and i2c_write function take the following arguments:
@ -38,12 +36,26 @@
static struct mutex i2c_mtx;
static bool i2c_write_byte(uint8_t data, bool start)
static bool i2c_stop(void)
{
long timeout = current_tick + HZ/50;
/* START */
I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
I2C_CONR |= (1<<4); /* NACK */
I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
while (I2C_LCMR & (1<<1))
if (TIME_AFTER(current_tick, timeout))
return false;
return true;
}
static bool i2c_write_byte(uint8_t data, bool start)
{
long timeout = current_tick + HZ/50;
unsigned int isr_status;
I2C_CONR = (1<<3) | (1<<2); /* master port enable, MTX mode, ACK enable */
I2C_MTXR = data;
if (start)
@ -51,13 +63,23 @@ static bool i2c_write_byte(uint8_t data, bool start)
else
I2C_LCMR = (1<<2); /* resume op */
I2C_CONR &= ~(1<<4); /* ACK enable */
/* wait for ACK from slave */
while ( (!(I2C_ISR & (1<<0))) || (I2C_LSR & (1<<1)) )
do
{
isr_status = I2C_ISR;
if (isr_status & (1<<7))
{
i2c_stop();
I2C_ISR = 0;
return false;
}
if (TIME_AFTER(current_tick, timeout))
return false;
} while ((isr_status & (1<<0)) == 0);
/* clear status bit */
I2C_ISR &= ~(1<<0);
@ -82,19 +104,7 @@ static bool i2c_read_byte(unsigned char *data)
return true;
}
static bool i2c_stop(void)
{
long timeout = current_tick + HZ/50;
I2C_CONR &= ~(1<<4);
I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
while (I2C_LCMR & (1<<1))
if (TIME_AFTER(current_tick, timeout))
return false;
return true;
}
/* route i2c bus to internal codec or external bus
* internal codec has 0x4e i2c slave address so
@ -202,6 +212,7 @@ int i2c_write(unsigned char slave, int address, int len,
end:
mutex_unlock(&i2c_mtx);
SCU_CLKCFG |= CLKCFG_I2C;
return ret;
}
@ -244,7 +255,7 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
goto end;
}
I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */
I2C_CONR = (1<<2); /* master port enable, MRX mode, ACK enable */
while (len)
{
@ -272,5 +283,6 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
end:
mutex_unlock(&i2c_mtx);
SCU_CLKCFG |= CLKCFG_I2C;
return ret;
}