summaryrefslogtreecommitdiff
path: root/include/i2c.h
diff options
context:
space:
mode:
authorJonathan Brandmeyer <jbrandmeyer@chromium.org>2018-08-09 12:58:03 -0600
committerchrome-bot <chrome-bot@chromium.org>2018-08-16 13:14:49 -0700
commit39ab7a039676ef3738171ed00dc3c7f61802e7b3 (patch)
treea32fdd410d4d41f2092dbaf283c44b528d4b03c4 /include/i2c.h
parent94d06cd5f92e163fca391529509f85909ed65ac6 (diff)
downloadchrome-ec-39ab7a039676ef3738171ed00dc3c7f61802e7b3.tar.gz
i2c: Split i2c_xfer into locked/unlocked versions.
Rename i2c_xfer to i2c_xfer_unlocked. Audit all users of i2c_xfer to see if they can use simple locking semantics or require their own locking. Since locked accesses are only safe for I2C_XFER_SINGLE transactions, remove the flags parameter from i2c_xfer. This also makes the audit a bit easier. Some remaining applications hold the bus locked across several transactions that would otherwise be atomic, and a few others implement complex I2C transactions in multiple commands. Add a (nondeterministic) verification on the I2C port locking correctness. This will catch all statically incorrect locking patterns, although dynamically incorrect locking patterns may not be caught. Related: Revise the i2c_port_active_count to be a bitmap of the active ports instead of a count of the active ports. The EC's mutex does not provide an is_locked() primitive, and we would prefer not to have one. - board/glados: Custom locking for battery reset - board/mchpevb1: Custom locking for battery reset - board/oak: Custom locking for battery reset - board/samus: Custom locking for lightbar reset - board/sweetberry: simple locking - board/servo_micro: Custom locking for funky i2c transfers - capsense: simple locking - host_command_master: multi-command transactions - lb_common: manual locking to support samus power sequence - smbus: multi-command transactions - usb_i2c: simple locking - driver/tcpm/fusb302: simple locking and multi-command transactions - driver/tcpm/tcpi: Forward _unlocked and implicitly locked interface to fusb302 - driver/touchpad_elan: simple locking BUG=chromium:871851 BRANCH=none TEST=buildall; very careful audit TEST=grunt clamshell and Coral clamshell, test boot, battery charging, PD communication, and TCPC port low-power mode. Signed-off-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Change-Id: Ieabf22bcab42780bdb994fca3ced5d8c62519d56 Reviewed-on: https://chromium-review.googlesource.com/1169913 Commit-Ready: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Tested-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'include/i2c.h')
-rw-r--r--include/i2c.h21
1 files changed, 14 insertions, 7 deletions
diff --git a/include/i2c.h b/include/i2c.h
index 0bd47fd24f..8ae21566cb 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -83,7 +83,7 @@ extern struct i2c_stress_test i2c_stress_tests[];
extern const int i2c_test_dev_used;
#endif
-/* Flags for i2c_xfer() */
+/* Flags for i2c_xfer_unlocked() */
#define I2C_XFER_START (1 << 0) /* Start smbus session from idle state */
#define I2C_XFER_STOP (1 << 1) /* Terminate smbus session with stop bit */
#define I2C_XFER_SINGLE (I2C_XFER_START | I2C_XFER_STOP) /* One transaction */
@@ -91,10 +91,8 @@ extern const int i2c_test_dev_used;
/**
* Transmit one block of raw data, then receive one block of raw data. However,
* received data might be capped at CONFIG_I2C_CHIP_MAX_READ_SIZE if
- * CONFIG_I2C_XFER_LARGE_READ is not defined.
- *
- * This is a wrapper function for chip_i2c_xfer(), a low-level chip-dependent
- * function. It must be called between i2c_lock(port, 1) and i2c_lock(port, 0).
+ * CONFIG_I2C_XFER_LARGE_READ is not defined. The transfer is strictly atomic,
+ * by locking the I2C port and performing an I2C_XFER_SINGLE transfer.
*
* @param port Port to access
* @param slave_addr Slave device address
@@ -102,11 +100,20 @@ extern const int i2c_test_dev_used;
* @param out_size Number of bytes to send
* @param in Destination buffer for received data
* @param in_size Number of bytes to receive
- * @param flags Flags (see I2C_XFER_* above)
* @return EC_SUCCESS, or non-zero if error.
*/
int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size,
- uint8_t *in, int in_size, int flags);
+ uint8_t *in, int in_size);
+
+/**
+ * Same as i2c_xfer, but the bus is not implicitly locked. It must be called
+ * between i2c_lock(port, 1) and i2c_lock(port, 0).
+ *
+ * @param flags Flags (see I2C_XFER_* above)
+ */
+int i2c_xfer_unlocked(int port, int slave_addr,
+ const uint8_t *out, int out_size,
+ uint8_t *in, int in_size, int flags);
#define I2C_LINE_SCL_HIGH (1 << 0)
#define I2C_LINE_SDA_HIGH (1 << 1)