summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-06-04 10:55:16 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-06-04 10:55:16 +0000
commitc2829a25736acb2ac079b9d8f4578e9fd67f2295 (patch)
tree68301153afb09311d8e99ee0d25e998a0c988fcc /firmware/target/arm
parent26a92fa9e17fc659ad1cd27b2365493df0d16950 (diff)
fix rockchip i2c driver
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29952 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/rk27xx/i2c-rk27xx.c58
1 files changed, 36 insertions, 22 deletions
diff --git a/firmware/target/arm/rk27xx/i2c-rk27xx.c b/firmware/target/arm/rk27xx/i2c-rk27xx.c
index 34a6f49a32..62f6d01c85 100644
--- a/firmware/target/arm/rk27xx/i2c-rk27xx.c
+++ b/firmware/target/arm/rk27xx/i2c-rk27xx.c
@@ -40,28 +40,28 @@ static struct mutex i2c_mtx;
static bool i2c_write_byte(uint8_t data, bool start)
{
- long timeout = current_tick + HZ / 50;
+ long timeout = current_tick + 50;
- /* START */
- I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
- I2C_MTXR = data;
+ /* START */
+ I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
+ I2C_MTXR = data;
- if (start)
- I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */
- else
- I2C_LCMR = (1<<2); /* resume op */
+ if (start)
+ I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */
+ else
+ I2C_LCMR = (1<<2); /* resume op */
- I2C_CONR &= ~(1<<4); /* ACK enable */
+ I2C_CONR &= ~(1<<4); /* ACK enable */
- /* wait for ACK from slave */
- while ( !(I2C_ISR & (1<<0)) || (I2C_LSR & (1<<0)) )
- if (TIME_AFTER(current_tick, timeout))
- return false;
+ /* wait for ACK from slave */
+ while ( (!(I2C_ISR & (1<<0))) || (I2C_LSR & (1<<1)) )
+ if (TIME_AFTER(current_tick, timeout))
+ return false;
- /* clear status bit */
- I2C_ISR &= ~(1<<0);
+ /* clear status bit */
+ I2C_ISR &= ~(1<<0);
- return true;
+ return true;
}
static bool i2c_read_byte(unsigned char *data)
@@ -70,7 +70,7 @@ static bool i2c_read_byte(unsigned char *data)
I2C_LCMR = (1<<2); /* resume op */
- while (I2C_ISR & (1<<1))
+ while (!(I2C_ISR & (1<<1)))
if (TIME_AFTER(current_tick, timeout))
return false;
@@ -97,7 +97,7 @@ static bool i2c_stop(void)
}
/* route i2c bus to internal codec or external bus
- * internal codec has 0x27 i2c slave address so
+ * internal codec has 0x4e i2c slave address so
* access to this address is routed to internal bus.
* All other addresses are routed to external pads
*/
@@ -105,15 +105,15 @@ static void i2c_iomux(unsigned char slave)
{
unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14);
- if (slave == (0x27<<1))
+ if ((slave & 0xfe) == (0x27<<1))
{
/* internal codec */
- SCU_IOMUXA_CON = muxa | (1<<16) | (1<<14);
+ SCU_IOMUXA_CON = (muxa | (1<<16) | (1<<14));
}
else
{
/* external I2C bus */
- SCU_IOMUXA_CON = muxa | (1<<18);
+ SCU_IOMUXA_CON = (muxa | (1<<18));
}
}
@@ -131,7 +131,13 @@ void i2c_init(void)
* APBfreq = 50Mhz
* SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1))
*/
- I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | 1<<0;
+
+ /* we are driving this slightly above specs
+ * (6<<3) | (1<<0) 416kHz
+ * (7<<3) | (1<<0) 357kHz
+ * (6<<3) | (2<<0) 208kHz
+ */
+ I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | (1<<0);
I2C_IER = 0x00;
@@ -145,6 +151,10 @@ int i2c_write(unsigned char slave, int address, int len,
i2c_iomux(slave);
+ /* clear all flags */
+ I2C_ISR = 0x00
+ I2C_IER = 0x00;
+
/* START */
if (! i2c_write_byte(slave & ~1, true))
{
@@ -188,6 +198,10 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
i2c_iomux(slave);
+ /* clear all flags */
+ I2C_ISR = 0x00;
+ I2C_IER = 0x00;
+
if (address >= 0)
{
/* START */