summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2012-06-26 14:19:54 -0700
committerGerrit <chrome-bot@google.com>2012-06-29 10:46:22 -0700
commit7bcf881bd60537cd3eefa1d391ad13f7c838b23c (patch)
tree611b1445195dd4e831141cc7a9931a5a03c9817d
parent7e50e844a3bf1888f5abfa57cc82a6f94b87cbe2 (diff)
downloadchrome-ec-7bcf881bd60537cd3eefa1d391ad13f7c838b23c.tar.gz
Implement board-level I2C arbitration
Add a way for boards to permit or deny access to the I2C port. This works in a board-specific manner. All I2C master traffic requires that board_i2c_claim() be called first. A dummy function is provided for boards which do not require this. BUG=chrome-os-partner:10888 TEST=manual: build for all boards boot on snow (cannot test i2c as it is broken) Change-Id: I786d4ae17f1d798faf13b303b5389679fb6720cb Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/26141
-rw-r--r--chip/stm32/i2c.c27
-rw-r--r--include/i2c.h28
2 files changed, 55 insertions, 0 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c
index 68305e0cdd..bf34f5a466 100644
--- a/chip/stm32/i2c.c
+++ b/chip/stm32/i2c.c
@@ -70,6 +70,23 @@ static inline void disable_ack(int port)
STM32_I2C_CR1(port) &= ~(1 << 10);
}
+int __board_i2c_claim(int port)
+{
+ return 0;
+}
+
+int board_i2c_claim(int port)
+ __attribute__((weak, alias("__board_i2c_claim")));
+
+
+void __board_i2c_release(int port)
+{
+}
+
+void board_i2c_release(int port)
+ __attribute__((weak, alias("__board_i2c_release")));
+
+
static int wait_tx(int port)
{
static timestamp_t deadline;
@@ -554,6 +571,12 @@ static int i2c_xfer(int port, int slave_addr, uint8_t *out, int out_bytes,
ASSERT(in || !in_bytes);
mutex_lock(&i2c_mutex);
+
+ if (board_i2c_claim(port)) {
+ rv = EC_ERROR_BUSY;
+ goto err_claim;
+ }
+
disable_i2c_interrupt(port);
rv = i2c_master_transmit(port, slave_addr, out, out_bytes,
@@ -563,6 +586,10 @@ static int i2c_xfer(int port, int slave_addr, uint8_t *out, int out_bytes,
handle_i2c_error(port, rv);
enable_i2c_interrupt(port);
+
+ board_i2c_release(port);
+
+err_claim:
mutex_unlock(&i2c_mutex);
return rv;
diff --git a/include/i2c.h b/include/i2c.h
index 726ebb641a..dbf933e102 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -48,4 +48,32 @@ int i2c_write8(int port, int slave_addr, int offset, int data);
int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data,
int len);
+/**
+ * Claim an I2C port for use in master mode
+ *
+ * If this function succeed, then you must later call board_i2c_release()
+ * to release the claim.
+ *
+ * This function may optionally be implemented by a board file. If provided
+ * then it should check the port number and arbitrate as needed.
+ *
+ * This function will not be called to claim an already-claimed port.
+ *
+ * @param port Port to claim (0 for first, 1 for second, etc.)
+ * @return 0 if claimed successfully, -1 if it is in use
+ */
+int board_i2c_claim(int port);
+
+/**
+ * Release an I2C port (after previously being claimed)
+ *
+ * This function may optionally be implemented by a board file. If provided
+ * then it should check the port number and arbitrate as needed.
+ *
+ * This function will not be called to release an already-released port.
+ *
+ * @param port Port to claim (0 for first, 1 for second, etc.)
+ */
+void board_i2c_release(int port);
+
#endif /* __CROS_EC_I2C_H */