summaryrefslogtreecommitdiff
path: root/common/i2c_controller.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-12-23 12:25:50 -0700
committerCommit Bot <commit-bot@chromium.org>2020-12-24 17:37:04 +0000
commitee2b0bcd66589e9d72eed553274f8da3d737c76c (patch)
treecb3de8dfee8e84281516444630de8f30216e721b /common/i2c_controller.c
parent817cb64cfd2623ac233b953f7bcca5e85c2f2409 (diff)
downloadchrome-ec-ee2b0bcd66589e9d72eed553274f8da3d737c76c.tar.gz
zephyr: Support multi-step I2C transactions
At present the Zephyr implementation of i2c_xfer_unlocked() assumes this is the only call for the whole transaction. However in some cases the function is called several times, e.g. to write a register number, read a length, then read that number of bytes). Add support for this, so i2c_read_string() works, for example. BUG=b:176189170 TEST=build and boot on volteer, with Nuvoton's I2C fix See that LION is shown as such, and not LIO > battery Status: 0x0080 INIT Param flags:00000003 Temp: 0x0bb7 = %.1d K (%.1d C) V: 0x31f6 = 12790 mV V-desired: 0x3390 = 13200 mV I: 0x00ac = 172 mA(CHG) I-desired: 0x0a19 = 2585 mA Charging: Allowed Charge: 92 % Manuf: LGC Device: AC17A8M Chem: LION Serial: 0xb754 V-design: 0x2d1e = 11550 mV Mode: 0x6001 Abs charge:87 % Remaining: 4648 mAh Cap-full: 5040 mAh (4939 mAh with 98 % compensation) Display: 96.9 % Design: 5360 mAh Time-full: 2h:47 Empty: 0h:0 Signed-off-by: Simon Glass <sjg@chromium.org> Change-Id: I1fe08c0c919a98fa66510048d4c05ae6e10072d9 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2600933 Reviewed-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org>
Diffstat (limited to 'common/i2c_controller.c')
-rw-r--r--common/i2c_controller.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/common/i2c_controller.c b/common/i2c_controller.c
index 49a6cf0458..a76c58691a 100644
--- a/common/i2c_controller.c
+++ b/common/i2c_controller.c
@@ -201,8 +201,45 @@ int i2c_xfer_unlocked(const int port,
for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) {
#ifdef CONFIG_ZEPHYR
- ret = i2c_write_read(i2c_get_device_for_port(port), no_pec_af,
- out, out_size, in, in_size);
+ struct i2c_msg msg[2];
+ int num_msgs = 0;
+
+ /* Be careful to respect the flags passed in */
+ if (out_size) {
+ unsigned int wflags = I2C_MSG_WRITE;
+
+ msg[num_msgs].buf = (uint8_t *)out;
+ msg[num_msgs].len = out_size;
+
+ /* If this is the last write, add a stop */
+ if (!in_size && (flags & I2C_XFER_STOP))
+ wflags |= I2C_MSG_STOP;
+ msg[num_msgs].flags = wflags;
+ num_msgs++;
+ }
+ if (in_size) {
+ unsigned int rflags = I2C_MSG_READ;
+
+ msg[num_msgs].buf = (uint8_t *)in;
+ msg[num_msgs].len = in_size;
+ rflags = I2C_MSG_READ;
+
+ /* If a stop is requested, add it */
+ if (flags & I2C_XFER_STOP)
+ rflags |= I2C_MSG_STOP;
+
+ /*
+ * If this read follows a write (above) then we need a
+ * restart
+ */
+ if (num_msgs)
+ rflags |= I2C_MSG_RESTART;
+ msg[num_msgs].flags = rflags;
+ num_msgs++;
+ }
+
+ return i2c_transfer(i2c_get_device_for_port(port), msg,
+ num_msgs, no_pec_af);
#elif defined(CONFIG_I2C_XFER_LARGE_TRANSFER)
ret = i2c_xfer_no_retry(port, no_pec_af,
out, out_size, in,