summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2020-11-13 12:56:34 +0800
committerCommit Bot <commit-bot@chromium.org>2020-11-17 18:00:39 +0000
commit8f8d017fb3e5f8d73bb415295495023353049f79 (patch)
tree30468b9673dbf3f9b042a2d120feab14a1dd1688
parent8ba81426bbc4030e1fa93e13f294fb3526a0d4de (diff)
downloadchrome-ec-stabilize-13605.B-master.tar.gz
i2c_master: extend i2c_xfer_no_retry to also support large writestabilize-13605.B-master
This CL extends CONFIG_I2C_XFER_LARGE_READ to also support large (greater than 255 bytes) write. Related config name is also updated to reflect the behavior change, BUG=b:169651794 TEST=flash fw successfully on Zed. BRANCH=none Signed-off-by: Ting Shen <phoenixshen@google.com> Change-Id: Icb889013da01f48708cd0227207561b8186bac63 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2537412 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Commit-Queue: Ting Shen <phoenixshen@chromium.org> Tested-by: Ting Shen <phoenixshen@chromium.org>
-rw-r--r--board/c2d2/board.h2
-rw-r--r--board/hammer/board.h2
-rw-r--r--board/servo_micro/board.h2
-rw-r--r--chip/stm32/i2c_ite_flash_support.c8
-rw-r--r--common/i2c_master.c59
-rw-r--r--docs/configuration/i2c.md2
-rw-r--r--include/config.h10
-rw-r--r--include/i2c.h6
8 files changed, 51 insertions, 40 deletions
diff --git a/board/c2d2/board.h b/board/c2d2/board.h
index 770851332c..d3a8a35bdb 100644
--- a/board/c2d2/board.h
+++ b/board/c2d2/board.h
@@ -84,7 +84,7 @@
/* See i2c_ite_flash_support.c for more information about these values */
#define CONFIG_ITE_FLASH_SUPPORT
-#define CONFIG_I2C_XFER_LARGE_READ
+#define CONFIG_I2C_XFER_LARGE_TRANSFER
#undef CONFIG_USB_I2C_MAX_WRITE_COUNT
#undef CONFIG_USB_I2C_MAX_READ_COUNT
#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1<<9) - 4)
diff --git a/board/hammer/board.h b/board/hammer/board.h
index 5903abe1df..60ec82eae7 100644
--- a/board/hammer/board.h
+++ b/board/hammer/board.h
@@ -180,7 +180,7 @@
#undef CONFIG_USB_I2C_MAX_READ_COUNT
#define CONFIG_USB_I2C_MAX_READ_COUNT (1024 - 6) /* 6 is maximum header size */
-#define CONFIG_I2C_XFER_LARGE_READ
+#define CONFIG_I2C_XFER_LARGE_TRANSFER
/* No lid switch */
#undef CONFIG_LID_SWITCH
diff --git a/board/servo_micro/board.h b/board/servo_micro/board.h
index 1565a63f9a..c597861242 100644
--- a/board/servo_micro/board.h
+++ b/board/servo_micro/board.h
@@ -90,7 +90,7 @@
/* See i2c_ite_flash_support.c for more information about these values */
#define CONFIG_ITE_FLASH_SUPPORT
-#define CONFIG_I2C_XFER_LARGE_READ
+#define CONFIG_I2C_XFER_LARGE_TRANSFER
#undef CONFIG_USB_I2C_MAX_WRITE_COUNT
#undef CONFIG_USB_I2C_MAX_READ_COUNT
#define CONFIG_USB_I2C_MAX_WRITE_COUNT ((1<<9) - 4)
diff --git a/chip/stm32/i2c_ite_flash_support.c b/chip/stm32/i2c_ite_flash_support.c
index eca3c999af..916a8c364c 100644
--- a/chip/stm32/i2c_ite_flash_support.c
+++ b/chip/stm32/i2c_ite_flash_support.c
@@ -42,11 +42,11 @@
/*
* iteflash requires 256 byte reads for verifying ITE EC firmware. Without this
- * the limit is CONFIG_I2C_CHIP_MAX_READ_SIZE which is 255 for STM32F0 due to an
- * 8 bit field, per src/platform/ec/include/config.h comment.
+ * the limit is CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE which is 255 for STM32F0 due
+ * to an 8 bit field, per src/platform/ec/include/config.h comment.
*/
-#ifndef CONFIG_I2C_XFER_LARGE_READ
-#error Must define CONFIG_I2C_XFER_LARGE_READ
+#ifndef CONFIG_I2C_XFER_LARGE_TRANSFER
+#error Must define CONFIG_I2C_XFER_LARGE_TRANSFER
#endif
#define KHz 1000
diff --git a/common/i2c_master.c b/common/i2c_master.c
index 7702beebb3..ee54468dea 100644
--- a/common/i2c_master.c
+++ b/common/i2c_master.c
@@ -142,37 +142,48 @@ __maybe_unused static int chip_i2c_xfer_with_notify(
return ret;
}
-#ifdef CONFIG_I2C_XFER_LARGE_READ
+#ifdef CONFIG_I2C_XFER_LARGE_TRANSFER
/*
- * Internal function that splits reading into multiple chip_i2c_xfer() calls
- * if in_size exceeds CONFIG_I2C_CHIP_MAX_READ_SIZE.
+ * Internal function that splits transfer into multiple chip_i2c_xfer() calls
+ * if in_size or out_size exceeds CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE.
*/
static int i2c_xfer_no_retry(const int port,
const uint16_t slave_addr_flags,
const uint8_t *out, int out_size,
uint8_t *in, int in_size, int flags)
{
- int ret;
- int out_flags = flags & I2C_XFER_START;
- int in_chunk_size = MIN(in_size, CONFIG_I2C_CHIP_MAX_READ_SIZE);
-
- in_size -= in_chunk_size;
- out_flags |= !in_size ? (flags & I2C_XFER_STOP) : 0;
- ret = chip_i2c_xfer_with_notify(port, slave_addr_flags,
- out, out_size, in,
- in_chunk_size, out_flags);
- in += in_chunk_size;
- while (in_size && ret == EC_SUCCESS) {
- in_chunk_size = MIN(in_size, CONFIG_I2C_CHIP_MAX_READ_SIZE);
- in_size -= in_chunk_size;
- ret = chip_i2c_xfer_with_notify(port, slave_addr_flags,
- NULL, 0, in,
- in_chunk_size, !in_size ? (flags & I2C_XFER_STOP) : 0);
- in += in_chunk_size;
+ for (int offset = 0; offset < out_size; ) {
+ int chunk_size = MIN(out_size - offset,
+ CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE);
+ int out_flags = 0;
+
+ if (offset == 0)
+ out_flags |= flags & I2C_XFER_START;
+ if (in_size == 0 && offset + chunk_size == out_size)
+ out_flags |= flags & I2C_XFER_STOP;
+
+ RETURN_ERROR(chip_i2c_xfer_with_notify(port, slave_addr_flags,
+ out + offset, chunk_size, NULL, 0,
+ out_flags));
+ offset += chunk_size;
}
- return ret;
+ for (int offset = 0; offset < in_size; ) {
+ int chunk_size = MIN(in_size - offset,
+ CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE);
+ int in_flags = 0;
+
+ if (offset == 0)
+ in_flags |= flags & I2C_XFER_START;
+ if (offset + chunk_size == in_size)
+ in_flags |= flags & I2C_XFER_STOP;
+
+ RETURN_ERROR(chip_i2c_xfer_with_notify(port, slave_addr_flags,
+ NULL, 0, in + offset, chunk_size, in_flags));
+ offset += chunk_size;
+ }
+ return EC_SUCCESS;
}
-#endif /* CONFIG_I2C_XFER_LARGE_READ */
+#endif /* CONFIG_I2C_XFER_LARGE_TRANSFER */
int i2c_xfer_unlocked(const int port,
const uint16_t slave_addr_flags,
@@ -192,7 +203,7 @@ int i2c_xfer_unlocked(const int port,
#ifdef CONFIG_ZEPHYR
ret = i2c_write_read(i2c_get_device_for_port(port), addr_flags,
out, out_size, in, in_size);
-#elif defined(CONFIG_I2C_XFER_LARGE_READ)
+#elif defined(CONFIG_I2C_XFER_LARGE_TRANSFER)
ret = i2c_xfer_no_retry(port, addr_flags,
out, out_size, in,
in_size, flags);
@@ -200,7 +211,7 @@ int i2c_xfer_unlocked(const int port,
ret = chip_i2c_xfer_with_notify(port, addr_flags,
out, out_size,
in, in_size, flags);
-#endif /* CONFIG_I2C_XFER_LARGE_READ */
+#endif /* CONFIG_I2C_XFER_LARGE_TRANSFER */
if (ret != EC_ERROR_BUSY)
break;
}
diff --git a/docs/configuration/i2c.md b/docs/configuration/i2c.md
index f258b3cca3..7a6241e349 100644
--- a/docs/configuration/i2c.md
+++ b/docs/configuration/i2c.md
@@ -14,7 +14,7 @@ The following parameters control the behavior of the I2C library. [config.h]
defines a reasonable default value, but you may need to change the default value
for your board.
-- `CONFIG_I2C_CHIP_MAX_READ_SIZE <bytes>`
+- `CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE <bytes>`
- `CONFIG_I2C_NACK_RETRY_COUNT <count>`
- `CONFIG_I2C_EXTRA_PACKET_SIZE <bytes>` - Only used on STM32 EC's if
`CONFIG_HOSTCMD_I2C_ADDR_FLAGS` is defined.
diff --git a/include/config.h b/include/config.h
index 4891b36617..5d67079d9a 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2313,16 +2313,16 @@
#undef CONFIG_I2C_BUS_MAY_BE_UNPOWERED
/*
- * Conservative I2C reading size per single transaction. For example, register
- * of stm32f0 and stm32l4 are limited to be 8 bits for this field.
+ * Conservative I2C transmission size per single transaction. For example,
+ * register of stm32f0 and stm32l4 are limited to be 8 bits for this field.
*/
-#define CONFIG_I2C_CHIP_MAX_READ_SIZE 255
+#define CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE 255
/*
* Enable i2c_xfer() for receiving request larger than
- * CONFIG_I2C_CHIP_MAX_READ_SIZE.
+ * CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE.
*/
-#undef CONFIG_I2C_XFER_LARGE_READ
+#undef CONFIG_I2C_XFER_LARGE_TRANSFER
/*
* If defined, makes i2c_xfer callback into board-provided functions before the
diff --git a/include/i2c.h b/include/i2c.h
index 4022976dcb..8b53f5e836 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -167,9 +167,9 @@ extern const int i2c_test_dev_used;
/**
* Transmit one block of raw data, then receive one block of raw data. However,
- * received data might be capped at CONFIG_I2C_CHIP_MAX_READ_SIZE if
- * CONFIG_I2C_XFER_LARGE_READ is not defined. The transfer is strictly atomic,
- * by locking the I2C port and performing an I2C_XFER_SINGLE transfer.
+ * transferred data might be capped at CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE if
+ * CONFIG_I2C_XFER_LARGE_TRANSFER is not defined. The transfer is strictly
+ * atomic, by locking the I2C port and performing an I2C_XFER_SINGLE transfer.
*
* @param port Port to access
* @param slave_addr Slave device address