summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Brandmeyer <jbrandmeyer@chromium.org>2018-08-07 16:02:57 -0600
committerCommit Bot <commit-bot@chromium.org>2021-01-06 16:45:40 +0000
commit95871a36a40646b7fcd8d6b55839dd60372f750b (patch)
tree7521c0530c66a22542c0952b17aa2d7c1f48a177
parent5831bff0db7ec07f01a9368803332ac0c5780caf (diff)
downloadchrome-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.c36
-rw-r--r--include/i2c.h19
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, &reg_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, &reg_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.