rk27xx: Turn off i2c clock when not in use

Change-Id: Ifc6c25a53ace1a5f4d716a33d4979ea0a37fac98
This commit is contained in:
Marcin Bukat 2012-08-27 23:18:31 +02:00
parent 16335da1cf
commit ae27c331e1

View file

@ -40,7 +40,7 @@ static struct mutex i2c_mtx;
static bool i2c_write_byte(uint8_t data, bool start) static bool i2c_write_byte(uint8_t data, bool start)
{ {
long timeout = current_tick + 50; long timeout = current_tick + HZ/50;
/* START */ /* START */
I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */ I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
@ -121,6 +121,8 @@ void i2c_init(void)
{ {
mutex_init(&i2c_mtx); mutex_init(&i2c_mtx);
/* ungate i2c module clock */
SCU_CLKCFG &= ~(1<< 20); SCU_CLKCFG &= ~(1<< 20);
I2C_OPR |= (1<<7); /* reset state machine */ I2C_OPR |= (1<<7); /* reset state machine */
@ -142,15 +144,23 @@ void i2c_init(void)
I2C_IER = 0x00; I2C_IER = 0x00;
I2C_OPR |= (1<<6); /* enable i2c core */ I2C_OPR |= (1<<6); /* enable i2c core */
/* turn off i2c module clock until we need to comunicate */
SCU_CLKCFG |= (1<< 20);
} }
int i2c_write(unsigned char slave, int address, int len, int i2c_write(unsigned char slave, int address, int len,
const unsigned char *data) const unsigned char *data)
{ {
int ret = 0;
mutex_lock(&i2c_mtx); mutex_lock(&i2c_mtx);
i2c_iomux(slave); i2c_iomux(slave);
/* ungate i2c clock */
SCU_CLKCFG &= ~(1<<20);
/* clear all flags */ /* clear all flags */
I2C_ISR = 0x00; I2C_ISR = 0x00;
I2C_IER = 0x00; I2C_IER = 0x00;
@ -158,16 +168,16 @@ int i2c_write(unsigned char slave, int address, int len,
/* START */ /* START */
if (! i2c_write_byte(slave & ~1, true)) if (! i2c_write_byte(slave & ~1, true))
{ {
mutex_unlock(&i2c_mtx); ret = 1;
return 1; goto end;
} }
if (address >= 0) if (address >= 0)
{ {
if (! i2c_write_byte(address, false)) if (! i2c_write_byte(address, false))
{ {
mutex_unlock(&i2c_mtx); ret = 2;
return 2; goto end;
} }
} }
@ -176,28 +186,35 @@ int i2c_write(unsigned char slave, int address, int len,
{ {
if (! i2c_write_byte(*data++, false)) if (! i2c_write_byte(*data++, false))
{ {
mutex_unlock(&i2c_mtx); ret = 4;
return 4; goto end;
} }
} }
/* STOP */ /* STOP */
if (! i2c_stop()) if (! i2c_stop())
{ {
mutex_unlock(&i2c_mtx); ret = 5;
return 5; goto end;
} }
end:
mutex_unlock(&i2c_mtx); mutex_unlock(&i2c_mtx);
return 0; SCU_CLKCFG |= (1<<20);
return ret;
} }
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)
{ {
int ret = 0;
mutex_lock(&i2c_mtx); mutex_lock(&i2c_mtx);
i2c_iomux(slave); i2c_iomux(slave);
/* ungate i2c module clock */
SCU_CLKCFG &= ~(1<<20);
/* clear all flags */ /* clear all flags */
I2C_ISR = 0x00; I2C_ISR = 0x00;
I2C_IER = 0x00; I2C_IER = 0x00;
@ -207,23 +224,23 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
/* START */ /* START */
if (! i2c_write_byte(slave & ~1, true)) if (! i2c_write_byte(slave & ~1, true))
{ {
mutex_unlock(&i2c_mtx); ret = 1;
return 1; goto end;
} }
/* write address */ /* write address */
if (! i2c_write_byte(address, false)) if (! i2c_write_byte(address, false))
{ {
mutex_unlock(&i2c_mtx); ret = 2;
return 2; goto end;
} }
} }
/* (repeated) START */ /* (repeated) START */
if (! i2c_write_byte(slave | 1, true)) if (! i2c_write_byte(slave | 1, true))
{ {
mutex_unlock(&i2c_mtx); ret = 3;
return 3; goto end;
} }
I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */ I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */
@ -232,8 +249,8 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
{ {
if (! i2c_read_byte(data++)) if (! i2c_read_byte(data++))
{ {
mutex_unlock(&i2c_mtx); ret = 4;
return 4; goto end;
} }
if (len == 1) if (len == 1)
@ -247,10 +264,12 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
/* STOP */ /* STOP */
if (! i2c_stop()) if (! i2c_stop())
{ {
mutex_unlock(&i2c_mtx); ret = 5;
return 5; goto end;
} }
end:
mutex_unlock(&i2c_mtx); mutex_unlock(&i2c_mtx);
return 0; SCU_CLKCFG |= (1<<20);
return ret;
} }