diff options
author | Jonathan Brandmeyer <jbrandmeyer@chromium.org> | 2018-08-07 16:02:57 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-08-09 11:40:02 -0700 |
commit | 21e235dbe468bfa80bab86900ab4baeb48533a94 (patch) | |
tree | 29abed0575657333d8402ab663587988f548263c /common/i2c_master.c | |
parent | ab6090e0c013519968a85661353c4d635cb78386 (diff) | |
download | chrome-ec-21e235dbe468bfa80bab86900ab4baeb48533a94.tar.gz |
i2c master: Add block read/write commands.
These commands are used by several modules that manage their own block
read/write protocols today. This is the first of a series that
refactors several modules to use the I2C driver functions instead of
their own.
BUG=chromium:871851
BRANCH=none
TEST=make -j buildall; USB-PD and motionsense testing on Grunt
convertible, which exercises several users of the new interface.
Signed-off-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Change-Id: I08475a72031e5fbf49dc344d5b4858622f0d5e93
Reviewed-on: https://chromium-review.googlesource.com/1167957
Commit-Ready: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Tested-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'common/i2c_master.c')
-rw-r--r-- | common/i2c_master.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/common/i2c_master.c b/common/i2c_master.c index 7915451b32..aa6340610c 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -322,6 +322,42 @@ exit: return rv; } +int i2c_read_block(int port, int slave_addr, int offset, uint8_t *data, + int len) +{ + int rv; + uint8_t reg_address = offset; + + i2c_lock(port, 1); + rv = i2c_xfer(port, slave_addr, ®_address, 1, data, len, + I2C_XFER_SINGLE); + i2c_lock(port, 0); + return rv; +} + +int i2c_write_block(int port, int slave_addr, int offset, const uint8_t *data, + int len) +{ + int rv0, rv1; + uint8_t reg_address = offset; + + /* + * Split into two transactions to avoid the stack space consumption of + * appending the destination address with the data array. Even if the + * first transaction fails, unconditionally perform the second one in + * order to have a better chance at sending out the stop bit. + */ + i2c_lock(port, 1); + rv0 = i2c_xfer(port, slave_addr, ®_address, 1, NULL, 0, + I2C_XFER_START); + rv1 = i2c_xfer(port, slave_addr, data, len, NULL, 0, + I2C_XFER_STOP); + i2c_lock(port, 0); + + /* Guess that the first error seen is more helpful. */ + return (rv0 != EC_SUCCESS) ? rv0 : rv1; +} + int get_sda_from_i2c_port(int port, enum gpio_signal *sda) { const struct i2c_port_t *i2c_port = get_i2c_port(port); |