diff options
author | Jonathan Brandmeyer <jbrandmeyer@chromium.org> | 2018-08-07 16:02:57 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-01-06 16:45:40 +0000 |
commit | 95871a36a40646b7fcd8d6b55839dd60372f750b (patch) | |
tree | 7521c0530c66a22542c0952b17aa2d7c1f48a177 | |
parent | 5831bff0db7ec07f01a9368803332ac0c5780caf (diff) | |
download | chrome-ec-95871a36a40646b7fcd8d6b55839dd60372f750b.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>
(cherry picked from commit 21e235dbe468bfa80bab86900ab4baeb48533a94)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2607209
Tested-by: David Huang <david.huang@quanta.corp-partner.google.com>
Auto-Submit: David Huang <david.huang@quanta.corp-partner.google.com>
Reviewed-by: Zhuohao Lee <zhuohao@chromium.org>
Commit-Queue: Keith Short <keithshort@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 36bdf81dd1..048891225c 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -408,6 +408,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 5683898bd6..9b429621ae 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -329,13 +329,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. |