mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 01:21:49 +00:00
Use mutex to arbitrate I2C buses.
We now have a task contantly polling temperature sensors, so we need to use mutex to arbitrate I2C buses. Signed-off-by: Vic Yang <victoryang@chromium.org> BUG=chrome-os-partner:7491 TEST=temps, i2cscan, and i2cread all work fine. Change-Id: I1360afb22d98b47da3da0820c95df45c15056f82
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#define NUM_PORTS 6
|
||||
|
||||
static task_id_t task_waiting_on_port[NUM_PORTS];
|
||||
static struct mutex port_mutex[NUM_PORTS];
|
||||
|
||||
|
||||
static int wait_idle(int port)
|
||||
@@ -52,6 +53,8 @@ int i2c_read16(int port, int slave_addr, int offset, int* data)
|
||||
int rv;
|
||||
int d;
|
||||
|
||||
mutex_lock(port_mutex + port);
|
||||
|
||||
*data = 0;
|
||||
|
||||
/* Transmit the offset address to the slave; leave the master in
|
||||
@@ -61,16 +64,20 @@ int i2c_read16(int port, int slave_addr, int offset, int* data)
|
||||
LM4_I2C_MCS(port) = 0x03;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Send repeated start followed by receive */
|
||||
LM4_I2C_MSA(port) = (slave_addr & 0xff) | 0x01;
|
||||
LM4_I2C_MCS(port) = 0x0b;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Read the first byte */
|
||||
d = LM4_I2C_MDR(port) & 0xff;
|
||||
@@ -79,14 +86,17 @@ int i2c_read16(int port, int slave_addr, int offset, int* data)
|
||||
LM4_I2C_MCS(port) = 0x05;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Read the second byte */
|
||||
if (slave_addr & I2C_FLAG_BIG_ENDIAN)
|
||||
*data = (d << 8) | (LM4_I2C_MDR(port) & 0xff);
|
||||
else
|
||||
*data = ((LM4_I2C_MDR(port) & 0xff) << 8) | d;
|
||||
mutex_unlock(port_mutex + port);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -95,6 +105,8 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
|
||||
{
|
||||
int rv;
|
||||
|
||||
mutex_lock(port_mutex + port);
|
||||
|
||||
/* Transmit the offset address to the slave; leave the master in
|
||||
* transmit state. */
|
||||
LM4_I2C_MDR(port) = offset & 0xff;
|
||||
@@ -102,8 +114,10 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
|
||||
LM4_I2C_MCS(port) = 0x03;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Transmit the first byte */
|
||||
if (slave_addr & I2C_FLAG_BIG_ENDIAN)
|
||||
@@ -113,8 +127,10 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
|
||||
LM4_I2C_MCS(port) = 0x01;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Transmit the second byte and then a stop */
|
||||
if (slave_addr & I2C_FLAG_BIG_ENDIAN)
|
||||
@@ -123,6 +139,7 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
|
||||
LM4_I2C_MDR(port) = (data >> 8) & 0xff;
|
||||
LM4_I2C_MCS(port) = 0x05;
|
||||
|
||||
mutex_unlock(port_mutex + port);
|
||||
return wait_idle(port);
|
||||
}
|
||||
|
||||
@@ -132,6 +149,8 @@ int i2c_read8(int port, int slave_addr, int offset, int* data)
|
||||
{
|
||||
int rv;
|
||||
|
||||
mutex_lock(port_mutex + port);
|
||||
|
||||
*data = 0;
|
||||
|
||||
/* Transmit the offset address to the slave; leave the master in
|
||||
@@ -141,8 +160,10 @@ int i2c_read8(int port, int slave_addr, int offset, int* data)
|
||||
LM4_I2C_MCS(port) = 0x03;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Send repeated start followed by receive and stop */
|
||||
LM4_I2C_MSA(port) = (slave_addr & 0xff) | 0x01;
|
||||
@@ -152,12 +173,15 @@ int i2c_read8(int port, int slave_addr, int offset, int* data)
|
||||
* I think.
|
||||
*/
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Read the byte */
|
||||
*data = LM4_I2C_MDR(port) & 0xff;
|
||||
|
||||
mutex_unlock(port_mutex + port);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -165,6 +189,8 @@ int i2c_write8(int port, int slave_addr, int offset, int data)
|
||||
{
|
||||
int rv;
|
||||
|
||||
mutex_lock(port_mutex + port);
|
||||
|
||||
/* Transmit the offset address to the slave; leave the master in
|
||||
* transmit state. */
|
||||
LM4_I2C_MDR(port) = offset & 0xff;
|
||||
@@ -172,13 +198,16 @@ int i2c_write8(int port, int slave_addr, int offset, int data)
|
||||
LM4_I2C_MCS(port) = 0x03;
|
||||
|
||||
rv = wait_idle(port);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Send repeated start followed by transmit and stop */
|
||||
LM4_I2C_MDR(port) = data & 0xff;
|
||||
LM4_I2C_MCS(port) = 0x05;
|
||||
|
||||
mutex_unlock(port_mutex + port);
|
||||
return wait_idle(port);
|
||||
}
|
||||
|
||||
@@ -225,6 +254,8 @@ static void scan_bus(int port, char *desc)
|
||||
|
||||
uart_printf("Scanning %s I2C bus (%d)...\n", desc, port);
|
||||
|
||||
mutex_lock(port_mutex + port);
|
||||
|
||||
for (a = 0; a < 0x100; a += 2) {
|
||||
uart_puts(".");
|
||||
|
||||
@@ -235,6 +266,9 @@ static void scan_bus(int port, char *desc)
|
||||
if (rv == EC_SUCCESS)
|
||||
uart_printf("\nFound device at 8-bit addr 0x%02x\n", a);
|
||||
}
|
||||
|
||||
mutex_unlock(port_mutex + port);
|
||||
|
||||
uart_puts("\n");
|
||||
}
|
||||
|
||||
@@ -278,6 +312,7 @@ static int command_i2cread(int argc, char **argv)
|
||||
|
||||
uart_printf("Reading %d bytes from I2C device %d:0x%02x...\n",
|
||||
count, port, addr);
|
||||
mutex_lock(port_mutex + port);
|
||||
LM4_I2C_MSA(port) = addr | 0x01;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i == 0)
|
||||
@@ -285,11 +320,14 @@ static int command_i2cread(int argc, char **argv)
|
||||
else
|
||||
LM4_I2C_MCS(port) = (i == count - 1 ? 0x05 : 0x09);
|
||||
rv = wait_idle(port);
|
||||
if (rv != EC_SUCCESS)
|
||||
if (rv != EC_SUCCESS) {
|
||||
mutex_unlock(port_mutex + port);
|
||||
return rv;
|
||||
}
|
||||
d = LM4_I2C_MDR(port) & 0xff;
|
||||
uart_printf("0x%02x ", d);
|
||||
}
|
||||
mutex_unlock(port_mutex + port);
|
||||
uart_puts("\n");
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user