diff options
author | Jonathan Brandmeyer <jbrandmeyer@chromium.org> | 2018-08-09 12:58:03 -0600 |
---|---|---|
committer | Vadim Bendebury <vbendeb@chromium.org> | 2019-09-21 13:46:52 -0700 |
commit | ca8d189c16ae9ab371990fb1019641ead545ee8d (patch) | |
tree | c211771229df3ecbb7e091f0740e2f8d1ade6ec0 /include | |
parent | ddf0c7ac7420efad388b87cd878cbe364c0356ba (diff) | |
download | chrome-ec-ca8d189c16ae9ab371990fb1019641ead545ee8d.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
Conflicts:
The following boards are not in this branch:
board/glados
board/mchpevb1
board/oak
board/samus
board/servo_micro
board/sweetberry
Thiese conflicts were resolved manually:
driver/tcpm/tcpci.c
driver/tcpm/tcpm.h
driver/touchpad_elan.c
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>
(cherry picked from commit 39ab7a039676ef3738171ed00dc3c7f61802e7b3)
Reviewed-on: https://chromium-review.googlesource.com/c/1278030
Commit-Queue: Vadim Bendebury <vbendeb@chromium.org>
Tested-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
(cherry picked from commit 97efa7737b8116c369def1fafe9e9bc896634eb9)
Reviewed-on: https://chromium-review.googlesource.com/c/1366971
(cherry picked from commit caaaa47fdd4cbb0cc81a835c6b2ed9c73db3d526)
Diffstat (limited to 'include')
-rw-r--r-- | include/i2c.h | 21 |
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) |