summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2015-06-13 19:41:24 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-17 13:10:58 +0000
commitcca70a517b21d32e45880d1296997436d026e7b7 (patch)
tree1c37f28074f4d9050070d7a540780fd592ff9719
parentb33531e262561e297ba1a02fc829a2110c6df515 (diff)
downloadchrome-ec-cca70a517b21d32e45880d1296997436d026e7b7.tar.gz
common: Add i2c 32bit read/write
Add functions and associated test to read/write a 32 bit register BRANCH=smaug TEST=Test on smaug with bm160 driver BUG=chromium:39900 Change-Id: Ieff24b65f1eb8610874fe13c4a8fadf583a218cb Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/277535 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/host/i2c.c30
-rw-r--r--common/i2c.c62
-rw-r--r--core/host/host_exe.lds8
-rw-r--r--include/i2c.h12
-rw-r--r--include/link_defs.h4
-rw-r--r--include/test_util.h12
-rw-r--r--test/stress.c6
7 files changed, 130 insertions, 4 deletions
diff --git a/chip/host/i2c.c b/chip/host/i2c.c
index 1ce7da9340..ebf3894a43 100644
--- a/chip/host/i2c.c
+++ b/chip/host/i2c.c
@@ -75,6 +75,36 @@ static int test_check_detached(int port, int slave_addr)
return 0;
}
+int i2c_read32(int port, int slave_addr, int offset, int *data)
+{
+ const struct test_i2c_read_dev *p;
+ int rv;
+
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
+ for (p = __test_i2c_read32; p < __test_i2c_read32_end; ++p) {
+ rv = p->routine(port, slave_addr, offset, data);
+ if (rv != EC_ERROR_INVAL)
+ return rv;
+ }
+ return EC_ERROR_UNKNOWN;
+}
+
+int i2c_write32(int port, int slave_addr, int offset, int data)
+{
+ const struct test_i2c_write_dev *p;
+ int rv;
+
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
+ for (p = __test_i2c_write32; p < __test_i2c_write32_end; ++p) {
+ rv = p->routine(port, slave_addr, offset, data);
+ if (rv != EC_ERROR_INVAL)
+ return rv;
+ }
+ return EC_ERROR_UNKNOWN;
+}
+
int i2c_read16(int port, int slave_addr, int offset, int *data)
{
const struct test_i2c_read_dev *p;
diff --git a/common/i2c.c b/common/i2c.c
index 4a851da39d..518bca0647 100644
--- a/common/i2c.c
+++ b/common/i2c.c
@@ -77,15 +77,68 @@ void i2c_prepare_sysjump(void)
i2c_lock(i2c_ports[i].port, 1);
}
+int i2c_read32(int port, int slave_addr, int offset, int *data)
+{
+ int rv;
+ uint8_t reg, buf[sizeof(uint32_t)];
+
+ reg = offset & 0xff;
+ /* I2C read 32-bit word: transmit 8-bit offset, and read 32bits */
+ i2c_lock(port, 1);
+ rv = i2c_xfer(port, slave_addr, &reg, 1, buf, sizeof(uint32_t),
+ I2C_XFER_SINGLE);
+ i2c_lock(port, 0);
+
+ if (rv)
+ return rv;
+
+ if (slave_addr & I2C_FLAG_BIG_ENDIAN)
+ *data = ((int)buf[0] << 24) | ((int)buf[1] << 16) |
+ ((int)buf[0] << 8) | buf[1];
+ else
+ *data = ((int)buf[3] << 24) | ((int)buf[2] << 16) |
+ ((int)buf[1] << 8) | buf[0];
+
+ return EC_SUCCESS;
+}
+
+int i2c_write32(int port, int slave_addr, int offset, int data)
+{
+ int rv;
+ uint8_t buf[1 + sizeof(uint32_t)];
+
+ buf[0] = offset & 0xff;
+
+ if (slave_addr & I2C_FLAG_BIG_ENDIAN) {
+ buf[1] = (data >> 24) & 0xff;
+ buf[2] = (data >> 16) & 0xff;
+ buf[3] = (data >> 8) & 0xff;
+ buf[4] = data & 0xff;
+ } else {
+ buf[1] = data & 0xff;
+ buf[2] = (data >> 8) & 0xff;
+ buf[3] = (data >> 16) & 0xff;
+ buf[4] = (data >> 24) & 0xff;
+ }
+
+ i2c_lock(port, 1);
+ rv = i2c_xfer(port, slave_addr, buf, sizeof(uint32_t) + 1, NULL, 0,
+ I2C_XFER_SINGLE);
+ i2c_lock(port, 0);
+
+ return rv;
+}
+
int i2c_read16(int port, int slave_addr, int offset, int *data)
{
int rv;
- uint8_t reg, buf[2];
+ uint8_t reg, buf[sizeof(uint16_t)];
reg = offset & 0xff;
/* I2C read 16-bit word: transmit 8-bit offset, and read 16bits */
i2c_lock(port, 1);
- rv = i2c_xfer(port, slave_addr, &reg, 1, buf, 2, I2C_XFER_SINGLE);
+ rv = i2c_xfer(port, slave_addr, &reg, 1, buf, sizeof(uint16_t),
+ I2C_XFER_SINGLE);
i2c_lock(port, 0);
if (rv)
@@ -102,7 +155,7 @@ int i2c_read16(int port, int slave_addr, int offset, int *data)
int i2c_write16(int port, int slave_addr, int offset, int data)
{
int rv;
- uint8_t buf[3];
+ uint8_t buf[1 + sizeof(uint16_t)];
buf[0] = offset & 0xff;
@@ -115,7 +168,8 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
}
i2c_lock(port, 1);
- rv = i2c_xfer(port, slave_addr, buf, 3, NULL, 0, I2C_XFER_SINGLE);
+ rv = i2c_xfer(port, slave_addr, buf, 1 + sizeof(uint16_t), NULL, 0,
+ I2C_XFER_SINGLE);
i2c_lock(port, 0);
return rv;
diff --git a/core/host/host_exe.lds b/core/host/host_exe.lds
index e61b2d1c48..a30ebb4219 100644
--- a/core/host/host_exe.lds
+++ b/core/host/host_exe.lds
@@ -104,6 +104,14 @@ SECTIONS {
*(.rodata.test_i2c.write16)
__test_i2c_write16_end = .;
+ __test_i2c_read32 = .;
+ *(.rodata.test_i2c.read32)
+ __test_i2c_read32_end = .;
+
+ __test_i2c_write32 = .;
+ *(.rodata.test_i2c.write32)
+ __test_i2c_write32_end = .;
+
__test_i2c_read_string = .;
*(.rodata.test_i2c.read_string)
__test_i2c_read_string_end = .;
diff --git a/include/i2c.h b/include/i2c.h
index dbc51eebbd..674dd84e80 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -162,6 +162,18 @@ void i2c_prepare_sysjump(void);
void i2c_set_timeout(int port, uint32_t timeout);
/**
+ * Read a 32-bit register from the slave at 8-bit slave address <slaveaddr>, at
+ * the specified 8-bit <offset> in the slave's address space.
+ */
+int i2c_read32(int port, int slave_addr, int offset, int *data);
+
+/**
+ * Write a 32-bit register to the slave at 8-bit slave address <slaveaddr>, at
+ * the specified 8-bit <offset> in the slave's address space.
+ */
+int i2c_write32(int port, int slave_addr, int offset, int data);
+
+/**
* Read a 16-bit register from the slave at 8-bit slave address <slaveaddr>, at
* the specified 8-bit <offset> in the slave's address space.
*/
diff --git a/include/link_defs.h b/include/link_defs.h
index 92783eb946..8c775affa2 100644
--- a/include/link_defs.h
+++ b/include/link_defs.h
@@ -64,8 +64,12 @@ extern const struct test_i2c_write_dev __test_i2c_write8[];
extern const struct test_i2c_write_dev __test_i2c_write8_end[];
extern const struct test_i2c_read_dev __test_i2c_read16[];
extern const struct test_i2c_read_dev __test_i2c_read16_end[];
+extern const struct test_i2c_read_dev __test_i2c_read32[];
+extern const struct test_i2c_read_dev __test_i2c_read32_end[];
extern const struct test_i2c_write_dev __test_i2c_write16[];
extern const struct test_i2c_write_dev __test_i2c_write16_end[];
+extern const struct test_i2c_write_dev __test_i2c_write32[];
+extern const struct test_i2c_write_dev __test_i2c_write32_end[];
extern const struct test_i2c_read_string_dev __test_i2c_read_string[];
extern const struct test_i2c_read_string_dev __test_i2c_read_string_end[];
diff --git a/include/test_util.h b/include/test_util.h
index f8f50fcc76..b62e965563 100644
--- a/include/test_util.h
+++ b/include/test_util.h
@@ -256,6 +256,18 @@ struct test_i2c_write_dev {
__attribute__((section(".rodata.test_i2c.write16"))) \
= {routine}
+/* Register an I2C 32-bit read function. */
+#define DECLARE_TEST_I2C_READ32(routine) \
+ const struct test_i2c_read_dev __test_i2c_read32_##routine \
+ __attribute__((section(".rodata.test_i2c.read32"))) \
+ = {routine}
+
+/* Register an I2C 32-bit write function. */
+#define DECLARE_TEST_I2C_WRITE32(routine) \
+ const struct test_i2c_write_dev __test_i2c_write32_##routine \
+ __attribute__((section(".rodata.test_i2c.write32"))) \
+ = {routine}
+
#define DECLARE_TEST_I2C_READ_STRING(routine) \
const struct test_i2c_read_string_dev __test_i2c_rs_##routine \
__attribute__((section(".rodata.test_i2c.read_string"))) \
diff --git a/test/stress.c b/test/stress.c
index 58a727adbe..5e31d4e466 100644
--- a/test/stress.c
+++ b/test/stress.c
@@ -98,6 +98,12 @@ static int test_i2c(void)
else if (param->width == 16 && param->data >= 0)
res = i2c_write16(param->port, param->addr,
param->offset, param->data);
+ else if (param->width == 32 && param->data == -1)
+ res = i2c_read32(param->port, param->addr,
+ param->offset, &dummy_data);
+ else if (param->width == 32 && param->data >= 0)
+ res = i2c_write32(param->port, param->addr,
+ param->offset, param->data);
return res;
}