summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2015-04-15 17:30:28 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-04-17 19:38:02 +0000
commit78de9268b7fe9d96c3324c22b3bf4f88901f2372 (patch)
tree42fb2e9126cdf119f8dbfbc9a44239fd6a7a52d1
parentbbdf126ef58bcc29130a4b5287da11b208ddf5bd (diff)
downloadchrome-ec-78de9268b7fe9d96c3324c22b3bf4f88901f2372.tar.gz
i2c: Support I2C controllers with multiple ports
Certain chips have I2C ports mapped to the same controller. In this case, it's necessary to lock out access to the controller during use. This configuration can be supported by adding CONFIG_I2C_MULTI_PORT_CONTROLLER, which can be defined at the chip level, along with an API function to map port index to controller index. BUG=chrome-os-partner:38335,chrome-os-partner:38945 TEST=Manual with subsequent commit. Verify that i2cscan is functional on strago. BRANCH=None Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Change-Id: I37ffa661a2ad6cd2235cef2ee77637cc3ab92523 Reviewed-on: https://chromium-review.googlesource.com/265942 Reviewed-by: Alec Berg <alecaberg@chromium.org> Reviewed-by: Kevin K Wong <kevin.k.wong@intel.com>
-rw-r--r--common/i2c.c12
-rw-r--r--include/config.h10
-rw-r--r--include/i2c.h38
3 files changed, 50 insertions, 10 deletions
diff --git a/common/i2c.c b/common/i2c.c
index 05d7f1a703..800922adea 100644
--- a/common/i2c.c
+++ b/common/i2c.c
@@ -26,10 +26,20 @@
#define CPUTS(outstr) cputs(CC_I2C, outstr)
#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
-static struct mutex port_mutex[I2C_PORT_COUNT];
+/* Only chips with multi-port controllers will define I2C_CONTROLER_COUNT */
+#ifndef I2C_CONTROLLER_COUNT
+#define I2C_CONTROLLER_COUNT I2C_PORT_COUNT
+#endif
+
+static struct mutex port_mutex[I2C_CONTROLLER_COUNT];
void i2c_lock(int port, int lock)
{
+#ifdef CONFIG_I2C_MULTI_PORT_CONTROLLER
+ /* Lock the controller, not the port */
+ port = i2c_port_to_controller(port);
+ ASSERT(port != -1);
+#endif
if (lock) {
/* Don't allow deep sleep when I2C port is locked */
disable_sleep(SLEEP_MASK_I2C);
diff --git a/include/config.h b/include/config.h
index d112e88dd7..97460a88ac 100644
--- a/include/config.h
+++ b/include/config.h
@@ -778,6 +778,16 @@
#undef CONFIG_I2C_SCL_GATE_ADDR
#undef CONFIG_I2C_SCL_GATE_GPIO
+/*
+ * I2C multi-port controller.
+ *
+ * If CONFIG_I2C_MULTI_PORT_CONTROLLER is defined, a single on-chip I2C
+ * controller may have multiple I2C ports attached. Therefore, I2c operations
+ * must lock the controller (not just the port) to prevent hardware access
+ * conflicts.
+ */
+#undef CONFIG_I2C_MULTI_PORT_CONTROLLER
+
/*****************************************************************************/
/* Current/Power monitor */
diff --git a/include/i2c.h b/include/i2c.h
index a4e105ddac..753efa0aec 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -134,20 +134,28 @@ void i2c_lock(int port, int lock);
*/
void i2c_set_timeout(int port, uint32_t timeout);
-/* Read a 16-bit register from the slave at 8-bit slave address <slaveaddr>, at
- * the specified 8-bit <offset> in the slave's address space. */
+/**
+ * Read a 16-bit register from the slave at 8-bit slave address <slaveaddr>, at
+ * the specified 8-bit <offset> in the slave's address space.
+ */
int i2c_read16(int port, int slave_addr, int offset, int *data);
-/* Write a 16-bit register to the slave at 8-bit slave address <slaveaddr>, at
- * the specified 8-bit <offset> in the slave's address space. */
+/**
+ * Write a 16-bit register to the slave at 8-bit slave address <slaveaddr>, at
+ * the specified 8-bit <offset> in the slave's address space.
+ */
int i2c_write16(int port, int slave_addr, int offset, int data);
-/* Read an 8-bit register from the slave at 8-bit slave address <slaveaddr>, at
- * the specified 8-bit <offset> in the slave's address space. */
+/**
+ * Read an 8-bit register from the slave at 8-bit slave address <slaveaddr>, at
+ * the specified 8-bit <offset> in the slave's address space.
+ */
int i2c_read8(int port, int slave_addr, int offset, int *data);
-/* Write an 8-bit register to the slave at 8-bit slave address <slaveaddr>, at
- * the specified 8-bit <offset> in the slave's address space. */
+/**
+ * Write an 8-bit register to the slave at 8-bit slave address <slaveaddr>, at
+ * the specified 8-bit <offset> in the slave's address space.
+ */
int i2c_write8(int port, int slave_addr, int offset, int data);
/**
@@ -164,7 +172,8 @@ int i2c_is_busy(int port);
*/
int i2c_unwedge(int port);
-/* Read ascii string using smbus read block protocol.
+/**
+ * Read ascii string using smbus read block protocol.
* Read bytestream from <slaveaddr>:<offset> with format:
* [length_N] [byte_0] [byte_1] ... [byte_N-1]
*
@@ -176,4 +185,15 @@ int i2c_unwedge(int port);
int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data,
int len);
+/**
+ * Convert port number to controller number, for multi-port controllers.
+ * This function will only be called if CONFIG_I2C_MULTI_PORT_CONTROLLER is
+ * defined.
+ *
+ * @parm port I2C port
+ *
+ * @return controller number, or -1 on invalid parameter
+ */
+int i2c_port_to_controller(int port);
+
#endif /* __CROS_EC_I2C_H */