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 | |
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>
-rw-r--r-- | common/i2c_master.c | 36 | ||||
-rw-r--r-- | include/i2c.h | 19 |
2 files changed, 54 insertions, 1 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); diff --git a/include/i2c.h b/include/i2c.h index 78038ea6af..0bd47fd24f 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -278,13 +278,30 @@ int i2c_unwedge(int port); * * <len> : the max length of receiving buffer. to read N bytes * ascii, len should be at least N+1 to include the - * terminating 0. + * terminating 0. Similar to strlcpy, the terminating null is + * always written into the output buffer. * <len> == 0 : buffer size > 255 */ int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, int len); /** + * Read a data block of <len> 8-bit transfers from the slave at 8-bit slave + * address <slaveaddr>, at the specified 8-bit <offset> in the slave's address + * space. + */ +int i2c_read_block(int port, int slave_addr, int offset, uint8_t *data, + int len); + +/** + * Write a data block of <len> 8-bit transfers to the slave at 8-bit slave + * address <slaveaddr>, at the specified 8-bit <offset> in the slave's address + * space. + */ +int i2c_write_block(int port, int slave_addr, int offset, const uint8_t *data, + int len); + +/** * Convert port number to controller number, for multi-port controllers. * This function will only be called if CONFIG_I2C_MULTI_PORT_CONTROLLER is * defined. |