From 7bcf881bd60537cd3eefa1d391ad13f7c838b23c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Jun 2012 14:19:54 -0700 Subject: 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 Reviewed-on: https://gerrit.chromium.org/gerrit/26141 --- chip/stm32/i2c.c | 27 +++++++++++++++++++++++++++ include/i2c.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) 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 */ -- cgit v1.2.1