summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVijay Hiremath <vijay.p.hiremath@intel.com>2015-08-03 23:37:54 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-23 15:10:08 -0700
commitf9272713da615e51ea14f70872fec46fbd88e938 (patch)
tree7b12c57a3435a615718c9d3325dfc0671fc297b6
parent806aae81f6bed5ab1a26e860eaa2b5b1349a1444 (diff)
downloadchrome-ec-f9272713da615e51ea14f70872fec46fbd88e938.tar.gz
i2c: Add i2ctest console command
Added i2ctest console command to test the reliability of the I2C. By reading/writing to the known registers this tests provides the number of successful read and writes. BUG=chrome-os-partner:57487 TEST=Enabled the i2ctest config on Reef and tested the i2c read/writes. BRANCH=none Change-Id: I9e27ff96f2b85422933bc590d112a083990e2dfb Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com> Reviewed-on: https://chromium-review.googlesource.com/290427 Commit-Ready: Vijay P Hiremath <vijay.p.hiremath@intel.com> Tested-by: Vijay P Hiremath <vijay.p.hiremath@intel.com> Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--board/reef/board.c63
-rw-r--r--board/reef/board.h8
-rw-r--r--common/i2c.c161
-rw-r--r--driver/accel_kionix.c12
-rw-r--r--driver/accel_kionix.h10
-rw-r--r--driver/accel_kx022.h1
-rw-r--r--driver/accel_kxcj9.h1
-rw-r--r--driver/accelgyro_bmi160.c16
-rw-r--r--driver/accelgyro_bmi160.h3
-rw-r--r--driver/als_opt3001.c12
-rw-r--r--driver/als_opt3001.h4
-rw-r--r--driver/baro_bmp280.c16
-rw-r--r--driver/baro_bmp280.h5
-rw-r--r--driver/battery/smart.c33
-rw-r--r--driver/charger/bd9995x.c22
-rw-r--r--driver/charger/bd9995x.h4
-rw-r--r--driver/tcpm/anx74xx.c12
-rw-r--r--driver/tcpm/anx74xx.h8
-rw-r--r--driver/tcpm/ps8751.c12
-rw-r--r--driver/tcpm/ps8751.h7
-rw-r--r--driver/tcpm/tcpm.h14
-rw-r--r--include/battery.h4
-rw-r--r--include/config.h9
-rw-r--r--include/i2c.h36
24 files changed, 469 insertions, 4 deletions
diff --git a/board/reef/board.c b/board/reef/board.c
index 5b7a1f3936..bde169f3df 100644
--- a/board/reef/board.c
+++ b/board/reef/board.c
@@ -143,6 +143,69 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+#ifdef CONFIG_CMD_I2C_STRESS_TEST
+struct i2c_stress_test i2c_stress_tests[] = {
+/* NPCX_I2C_PORT0_0 */
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+ {
+ .port = NPCX_I2C_PORT0_0,
+ .addr = 0x50,
+ .i2c_test = &anx74xx_i2c_stress_test_dev,
+ },
+#endif
+
+/* NPCX_I2C_PORT0_1 */
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+ {
+ .port = NPCX_I2C_PORT0_1,
+ .addr = 0x16,
+ .i2c_test = &ps8751_i2c_stress_test_dev,
+ },
+#endif
+
+/* NPCX_I2C_PORT1 */
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+ {
+ .port = I2C_PORT_GYRO,
+ .addr = BMI160_ADDR0,
+ .i2c_test = &bmi160_i2c_stress_test_dev,
+ },
+#endif
+
+/* NPCX_I2C_PORT2 */
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+ {
+ .port = I2C_PORT_BARO,
+ .addr = BMP280_I2C_ADDRESS1,
+ .i2c_test = &bmp280_i2c_stress_test_dev,
+ },
+ {
+ .port = I2C_PORT_LID_ACCEL,
+ .addr = KX022_ADDR1,
+ .i2c_test = &kionix_i2c_stress_test_dev,
+ },
+#endif
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ALS
+ {
+ .i2c_test = &opt3001_i2c_stress_test_dev,
+ },
+#endif
+
+/* NPCX_I2C_PORT3 */
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_BATTERY
+ {
+ .i2c_test = &battery_i2c_stress_test_dev,
+ },
+#endif
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER
+ {
+ .i2c_test = &bd9995x_i2c_stress_test_dev,
+ },
+#endif
+};
+const int i2c_test_dev_used = ARRAY_SIZE(i2c_stress_tests);
+#endif /* CONFIG_CMD_I2C_STRESS_TEST */
+
const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = {
#if IS_PROTO == 1
{NPCX_I2C_PORT0_0, 0x50, &anx74xx_tcpm_drv, TCPC_ALERT_ACTIVE_HIGH},
diff --git a/board/reef/board.h b/board/reef/board.h
index 8ed35be00b..c4013270ef 100644
--- a/board/reef/board.h
+++ b/board/reef/board.h
@@ -38,7 +38,15 @@
#define BD9995X_PSYS_GAIN_SELECT \
BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW
+#define CONFIG_CMD_I2C_STRESS_TEST
+#define CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+#define CONFIG_CMD_I2C_STRESS_TEST_ALS
+#define CONFIG_CMD_I2C_STRESS_TEST_BATTERY
+#define CONFIG_CMD_I2C_STRESS_TEST_CHARGER
+#define CONFIG_CMD_I2C_STRESS_TEST_TCPC
+
/* Battery */
+#define CONFIG_BATTERY_DEVICE_CHEMISTRY "LION"
#define CONFIG_BATTERY_CUT_OFF
#define CONFIG_BATTERY_PRESENT_CUSTOM
#define CONFIG_BATTERY_REVIVE_DISCONNECT
diff --git a/common/i2c.c b/common/i2c.c
index 7563a3f612..996ffe3f09 100644
--- a/common/i2c.c
+++ b/common/i2c.c
@@ -857,3 +857,164 @@ DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer,
"r/r16/rlen/w/w16 port addr offset [value | len]",
"Read write I2C");
#endif
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST
+static void i2c_test_status(struct i2c_test_results *i2c_test, int test_dev)
+{
+ ccprintf("test_dev=%2d, ", test_dev);
+ ccprintf("r=%5d, rs=%5d, rf=%5d, ",
+ i2c_test->read_success + i2c_test->read_fail,
+ i2c_test->read_success,
+ i2c_test->read_fail);
+
+ ccprintf("w=%5d, ws=%5d, wf=%5d\n",
+ i2c_test->write_success + i2c_test->write_fail,
+ i2c_test->write_success,
+ i2c_test->write_fail);
+
+ i2c_test->read_success = 0;
+ i2c_test->read_fail = 0;
+ i2c_test->write_success = 0,
+ i2c_test->write_fail = 0;
+}
+
+#define I2C_STRESS_TEST_DATA_VERIFY_RETRY_COUNT 3
+static int command_i2ctest(int argc, char **argv)
+{
+ char *e;
+ int i, j, rv, rand;
+ int data, data_verify;
+ int port, addr;
+ int count = 10000;
+ int udelay = 100;
+ int test_dev = i2c_test_dev_used;
+ struct i2c_stress_test_dev *i2c_s_test;
+ struct i2c_test_reg_info *reg_s_info;
+ struct i2c_test_results *test_s_results;
+
+ if (argc > 1) {
+ count = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM2;
+ }
+
+ if (argc > 2) {
+ udelay = strtoi(argv[2], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM3;
+ }
+
+ if (argc > 3) {
+ test_dev = strtoi(argv[3], &e, 0);
+ if (*e || test_dev < 1 || test_dev > i2c_test_dev_used)
+ return EC_ERROR_PARAM4;
+ test_dev--;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (!(i % 1000))
+ ccprintf("running test %d\n", i);
+
+ if (argc < 4) {
+ rand = get_time().val;
+ test_dev = rand % i2c_test_dev_used;
+ }
+
+ port = i2c_stress_tests[test_dev].port;
+ addr = i2c_stress_tests[test_dev].addr;
+ i2c_s_test = i2c_stress_tests[test_dev].i2c_test;
+ reg_s_info = &i2c_s_test->reg_info;
+ test_s_results = &i2c_s_test->test_results;
+
+ rand = get_time().val;
+ if (rand & 0x1) {
+ /* read */
+ rv = i2c_s_test->i2c_read ?
+ i2c_s_test->i2c_read(port, addr,
+ reg_s_info->read_reg, &data) :
+ i2c_s_test->i2c_read_dev(
+ reg_s_info->read_reg, &data);
+ if (rv || data != reg_s_info->read_val)
+ test_s_results->read_fail++;
+ else
+ test_s_results->read_success++;
+ } else {
+ /*
+ * Reads are more than writes in the system.
+ * Read and then write same value to ensure we are
+ * not changing any settings.
+ */
+
+ /* Read the write register */
+ rv = i2c_s_test->i2c_read ?
+ i2c_s_test->i2c_read(port, addr,
+ reg_s_info->read_reg, &data) :
+ i2c_s_test->i2c_read_dev(
+ reg_s_info->read_reg, &data);
+ if (rv) {
+ /* Skip writing invalid data */
+ test_s_results->read_fail++;
+ continue;
+ } else
+ test_s_results->read_success++;
+
+ j = I2C_STRESS_TEST_DATA_VERIFY_RETRY_COUNT;
+ do {
+ /* Write same value back */
+ rv = i2c_s_test->i2c_write ?
+ i2c_s_test->i2c_write(port, addr,
+ reg_s_info->write_reg, data) :
+ i2c_s_test->i2c_write_dev(
+ reg_s_info->write_reg, data);
+ i++;
+ if (rv) {
+ /* Skip reading as write failed */
+ test_s_results->write_fail++;
+ break;
+ }
+ test_s_results->write_success++;
+
+ /* Read back to verify the data */
+ rv = i2c_s_test->i2c_read ?
+ i2c_s_test->i2c_read(port, addr,
+ reg_s_info->read_reg, &data_verify) :
+ i2c_s_test->i2c_read_dev(
+ reg_s_info->read_reg, &data_verify);
+ i++;
+ if (rv) {
+ /* Read failed try next time */
+ test_s_results->read_fail++;
+ break;
+ } else if (!rv && data != data_verify) {
+ /* Either data writes/read is wrong */
+ j--;
+ } else {
+ j = 0;
+ test_s_results->read_success++;
+ }
+ } while (j);
+ }
+
+ usleep(udelay);
+ }
+
+ ccprintf("\n**********final result **********\n");
+
+ cflush();
+ if (argc > 3) {
+ i2c_test_status(&i2c_s_test->test_results, test_dev + 1);
+ } else {
+ for (i = 0; i < i2c_test_dev_used; i++) {
+ i2c_s_test = i2c_stress_tests[i].i2c_test;
+ i2c_test_status(&i2c_s_test->test_results, i + 1);
+ msleep(100);
+ }
+ }
+ cflush();
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(i2ctest, command_i2ctest,
+ "i2ctest count|udelay|dev",
+ "I2C stress test");
+#endif /* CONFIG_CMD_I2C_STRESS_TEST */
diff --git a/driver/accel_kionix.c b/driver/accel_kionix.c
index 7600f452ee..2a9149d9a7 100644
--- a/driver/accel_kionix.c
+++ b/driver/accel_kionix.c
@@ -529,3 +529,15 @@ const struct accelgyro_drv kionix_accel_drv = {
.set_offset = set_offset,
.get_offset = get_offset,
};
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+struct i2c_stress_test_dev kionix_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = KX022_WHOAMI,
+ .read_val = KIONIX_WHO_AM_I_VAL,
+ .write_reg = KIONIX_ODR_REG(V(s)),
+ },
+ .i2c_read = &raw_read8,
+ .i2c_write = &raw_write8,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */
diff --git a/driver/accel_kionix.h b/driver/accel_kionix.h
index 6c71cb7918..04df63066f 100644
--- a/driver/accel_kionix.h
+++ b/driver/accel_kionix.h
@@ -69,4 +69,14 @@ extern const struct accelgyro_drv kionix_accel_drv;
#define KIONIX_XOUT_L(v) (KX022_XOUT_L + \
(v) * (KXCJ9_XOUT_L - KX022_XOUT_L))
+#ifdef CONFIG_ACCEL_KX022
+#define KIONIX_WHO_AM_I_VAL KX022_WHO_AM_I_VAL
+#elif defined(CONFIG_ACCEL_KXCJ9)
+#define KIONIX_WHO_AM_I_VAL KXCJ9_WHO_AM_I_VAL
+#endif
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+extern struct i2c_stress_test_dev kionix_i2c_stress_test_dev;
+#endif
+
#endif /* __CROS_EC_ACCEL_KIONIX_H */
diff --git a/driver/accel_kx022.h b/driver/accel_kx022.h
index 3ed95a30a8..d25d68b380 100644
--- a/driver/accel_kx022.h
+++ b/driver/accel_kx022.h
@@ -14,6 +14,7 @@
*/
#define KX022_ADDR0 0x3c
#define KX022_ADDR1 0x3e
+#define KX022_WHO_AM_I_VAL 0x14
/* Chip-specific registers */
#define KX022_XHP_L 0x00
diff --git a/driver/accel_kxcj9.h b/driver/accel_kxcj9.h
index 4436f38e8b..b3702ea541 100644
--- a/driver/accel_kxcj9.h
+++ b/driver/accel_kxcj9.h
@@ -16,6 +16,7 @@
*/
#define KXCJ9_ADDR0 0x1c
#define KXCJ9_ADDR1 0x1e
+#define KXCJ9_WHO_AM_I_VAL 0x0A
/* Chip-specific registers */
#define KXCJ9_XOUT_L 0x06
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c
index c8a6d18bdf..2ecc27fe4c 100644
--- a/driver/accelgyro_bmi160.c
+++ b/driver/accelgyro_bmi160.c
@@ -139,7 +139,7 @@ static inline int spi_raw_read(const int addr, const uint8_t reg,
/**
* Read 8bit register from accelerometer.
*/
-static int raw_read8(const int port, const int addr, const uint8_t reg,
+static int raw_read8(const int port, const int addr, const int reg,
int *data_ptr)
{
int rv = -EC_ERROR_PARAM1;
@@ -163,7 +163,7 @@ static int raw_read8(const int port, const int addr, const uint8_t reg,
/**
* Write 8bit register from accelerometer.
*/
-static int raw_write8(const int port, const int addr, const uint8_t reg,
+static int raw_write8(const int port, const int addr, const int reg,
int data)
{
int rv = -EC_ERROR_PARAM1;
@@ -1248,3 +1248,15 @@ const struct accelgyro_drv bmi160_drv = {
struct bmi160_drv_data_t g_bmi160_data = {
.flags = 0,
};
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+struct i2c_stress_test_dev bmi160_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = BMI160_CHIP_ID,
+ .read_val = BMI160_CHIP_ID_MAJOR,
+ .write_reg = BMI160_PMU_TRIGGER,
+ },
+ .i2c_read = &raw_read8,
+ .i2c_write = &raw_write8,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */
diff --git a/driver/accelgyro_bmi160.h b/driver/accelgyro_bmi160.h
index e6e8e19e54..ec43fb4a9d 100644
--- a/driver/accelgyro_bmi160.h
+++ b/driver/accelgyro_bmi160.h
@@ -459,5 +459,8 @@ int raw_mag_read8(const int port, const int addr, const uint8_t reg,
int raw_mag_write8(const int port, const int addr, const uint8_t reg, int data);
#endif
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+extern struct i2c_stress_test_dev bmi160_i2c_stress_test_dev;
+#endif
#endif /* __CROS_EC_ACCELGYRO_BMI160_H */
diff --git a/driver/als_opt3001.c b/driver/als_opt3001.c
index 993803bd28..bbf61a1064 100644
--- a/driver/als_opt3001.c
+++ b/driver/als_opt3001.c
@@ -87,3 +87,15 @@ int opt3001_read_lux(int *lux, int af)
return EC_SUCCESS;
}
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ALS
+struct i2c_stress_test_dev opt3001_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = OPT3001_REG_DEV_ID,
+ .read_val = OPT3001_DEVICE_ID,
+ .write_reg = OPT3001_REG_INT_LIMIT_LSB,
+ },
+ .i2c_read_dev = &opt3001_i2c_read,
+ .i2c_write_dev = &opt3001_i2c_write,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_ALS */
diff --git a/driver/als_opt3001.h b/driver/als_opt3001.h
index 3e21ba7db8..366e957995 100644
--- a/driver/als_opt3001.h
+++ b/driver/als_opt3001.h
@@ -29,4 +29,8 @@
int opt3001_init(void);
int opt3001_read_lux(int *lux, int af);
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ALS
+extern struct i2c_stress_test_dev opt3001_i2c_stress_test_dev;
+#endif
+
#endif /* __CROS_EC_ALS_OPT3001_H */
diff --git a/driver/baro_bmp280.c b/driver/baro_bmp280.c
index 6e394dbf72..3a3f3e3b6d 100644
--- a/driver/baro_bmp280.c
+++ b/driver/baro_bmp280.c
@@ -68,7 +68,7 @@
static const uint16_t standby_durn[] = {1, 63, 125, 250, 500, 1000, 2000, 4000};
-static inline int raw_read8(const int port, const int addr, const uint8_t reg,
+static inline int raw_read8(const int port, const int addr, const int reg,
int *data_ptr)
{
return i2c_read8(port, addr, reg, data_ptr);
@@ -92,7 +92,7 @@ static inline int raw_read_n(const int port, const int addr, const uint8_t reg,
/*
* Write 8bit register from accelerometer.
*/
-static inline int raw_write8(const int port, const int addr, const uint8_t reg,
+static inline int raw_write8(const int port, const int addr, const int reg,
int data)
{
return i2c_write8(port, addr, reg, data);
@@ -405,3 +405,15 @@ const struct accelgyro_drv bmp280_drv = {
.set_data_rate = bmp280_set_data_rate,
.get_data_rate = bmp280_get_data_rate,
};
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+struct i2c_stress_test_dev bmp280_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = BMP280_CHIP_ID_REG,
+ .read_val = BMP280_CHIP_ID,
+ .write_reg = BMP280_CONFIG_REG,
+ },
+ .i2c_read = &raw_read8,
+ .i2c_write = &raw_write8,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */
diff --git a/driver/baro_bmp280.h b/driver/baro_bmp280.h
index 1af1aa2125..cd4605ed1a 100644
--- a/driver/baro_bmp280.h
+++ b/driver/baro_bmp280.h
@@ -205,4 +205,9 @@ struct bmp280_drv_data_t {
extern const struct accelgyro_drv bmp280_drv;
extern struct bmp280_drv_data_t bmp280_drv_data;
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+extern struct i2c_stress_test_dev bmp280_i2c_stress_test_dev;
+#endif
+
#endif
diff --git a/driver/battery/smart.c b/driver/battery/smart.c
index ff2da13863..9e7e9f3ec6 100644
--- a/driver/battery/smart.c
+++ b/driver/battery/smart.c
@@ -475,3 +475,36 @@ DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_BLOCK,
host_command_sb_write_block,
EC_VER_MASK(0));
#endif
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_BATTERY
+test_mockable int sb_i2c_test_read(int cmd, int *param)
+{
+ char chemistry[sizeof(CONFIG_BATTERY_DEVICE_CHEMISTRY) + 1];
+ int rv;
+
+ if (cmd == SB_DEVICE_CHEMISTRY) {
+ rv = battery_device_chemistry(chemistry,
+ sizeof(CONFIG_BATTERY_DEVICE_CHEMISTRY));
+ if (rv)
+ return rv;
+ if (strcasecmp(chemistry, CONFIG_BATTERY_DEVICE_CHEMISTRY))
+ return EC_ERROR_UNKNOWN;
+
+ *param = EC_SUCCESS;
+ return EC_SUCCESS;
+ }
+
+
+ return sb_read(cmd, param);
+}
+
+struct i2c_stress_test_dev battery_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = SB_DEVICE_CHEMISTRY,
+ .read_val = EC_SUCCESS,
+ .write_reg = SB_AT_RATE,
+ },
+ .i2c_read_dev = &sb_i2c_test_read,
+ .i2c_write_dev = &sb_write,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_BATTERY */
diff --git a/driver/charger/bd9995x.c b/driver/charger/bd9995x.c
index cbc8d04132..0dd5da99de 100644
--- a/driver/charger/bd9995x.c
+++ b/driver/charger/bd9995x.c
@@ -1231,3 +1231,25 @@ DECLARE_CONSOLE_COMMAND(amonbmon, console_command_amon_bmon,
"amonbmon [a|b]",
"Get charger AMON/BMON voltage diff, current");
#endif /* CONFIG_CMD_CHARGER_ADC_AMON_BMON */
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER
+static int bd9995x_i2c_read(const int reg, int *data)
+{
+ return ch_raw_read16(reg, data, BD9995X_EXTENDED_COMMAND);
+}
+
+static int bd9995x_i2c_write(const int reg, int data)
+{
+ return ch_raw_write16(reg, data, BD9995X_EXTENDED_COMMAND);
+}
+
+struct i2c_stress_test_dev bd9995x_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = BD9995X_CMD_CHIP_ID,
+ .read_val = BD9995X_CHIP_ID,
+ .write_reg = BD9995X_CMD_ITRICH_SET,
+ },
+ .i2c_read_dev = &bd9995x_i2c_read,
+ .i2c_write_dev = &bd9995x_i2c_write,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_CHARGER */
diff --git a/driver/charger/bd9995x.h b/driver/charger/bd9995x.h
index 91a0ac1bbd..baef184d09 100644
--- a/driver/charger/bd9995x.h
+++ b/driver/charger/bd9995x.h
@@ -359,4 +359,8 @@ void bd9995x_vbus_interrupt(enum gpio_signal signal);
/* Read temperature measurement value (in Celsius) */
int bd9995x_get_battery_temp(int *temp_ptr);
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER
+extern struct i2c_stress_test_dev bd9995x_i2c_stress_test_dev;
+#endif
+
#endif /* __CROS_EC_BD9995X_H */
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index 302be88030..689d6d1799 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -882,3 +882,15 @@ const struct tcpm_drv anx74xx_tcpm_drv = {
.tcpc_discharge_vbus = &anx74xx_tcpc_discharge_vbus,
#endif
};
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+struct i2c_stress_test_dev anx74xx_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = ANX74XX_REG_VENDOR_ID_L,
+ .read_val = ANX74XX_VENDOR_ID & 0xFF,
+ .write_reg = ANX74XX_REG_CC_SOFTWARE_CTRL,
+ },
+ .i2c_read = &tcpc_i2c_read,
+ .i2c_write = &tcpc_i2c_write,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_TCPC */
diff --git a/driver/tcpm/anx74xx.h b/driver/tcpm/anx74xx.h
index de8d2b7fab..76bb44067e 100644
--- a/driver/tcpm/anx74xx.h
+++ b/driver/tcpm/anx74xx.h
@@ -13,6 +13,10 @@
#define ANX74XX_REG_IRQ_POL_LOW 0x00
#define ANX74XX_REG_IRQ_POL_HIGH 0x02
+#define ANX74XX_REG_VENDOR_ID_L 0x00
+#define ANX74XX_REG_VENDOR_ID_H 0x01
+#define ANX74XX_VENDOR_ID 0xAAAA
+
/* ANX F/W version:0x50:0x44 which contains otp firmware version */
#define ANX74XX_REG_FW_VERSION 0x44
@@ -162,4 +166,8 @@ void anx74xx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq);
void anx74xx_tcpc_clear_hpd_status(int port);
int anx74xx_tcpc_get_fw_version(int port, int *version);
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+extern struct i2c_stress_test_dev anx74xx_i2c_stress_test_dev;
+#endif
+
#endif /* __CROS_EC_USB_PD_TCPM_ANX74XX_H */
diff --git a/driver/tcpm/ps8751.c b/driver/tcpm/ps8751.c
index b9419a4696..f889f17134 100644
--- a/driver/tcpm/ps8751.c
+++ b/driver/tcpm/ps8751.c
@@ -67,3 +67,15 @@ int ps8751_tcpc_get_fw_version(int port, int *version)
return tcpc_read(port, PS8751_REG_VERSION, version);
}
#endif
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+struct i2c_stress_test_dev ps8751_i2c_stress_test_dev = {
+ .reg_info = {
+ .read_reg = PS8751_REG_VENDOR_ID_L,
+ .read_val = PS8751_VENDOR_ID & 0xFF,
+ .write_reg = PS8751_REG_CTRL_1,
+ },
+ .i2c_read = &tcpc_i2c_read,
+ .i2c_write = &tcpc_i2c_write,
+};
+#endif /* CONFIG_CMD_I2C_STRESS_TEST_TCPC */
diff --git a/driver/tcpm/ps8751.h b/driver/tcpm/ps8751.h
index e0abb491ba..71325a7d4b 100644
--- a/driver/tcpm/ps8751.h
+++ b/driver/tcpm/ps8751.h
@@ -13,11 +13,18 @@
#define PS8751_PRODUCT_ID 0x8751
#define PS8751_REG_VERSION 0x90
+#define PS8751_REG_VENDOR_ID_L 0x00
+#define PS8751_REG_VENDOR_ID_H 0x01
#define PS8751_REG_CTRL_1 0xD0
#define PS8751_REG_CTRL_1_HPD (1 << 0)
#define PS8751_REG_CTRL_1_IRQ (1 << 1)
void ps8751_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq);
int ps8751_tcpc_get_fw_version(int port, int *version);
+
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+extern struct i2c_stress_test_dev ps8751_i2c_stress_test_dev;
+#endif
+
#endif /* __CROS_EC_USB_PD_TCPM_PS8751_H */
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
index 2e24049246..7903cccffd 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -130,6 +130,20 @@ static inline void tcpc_discharge_vbus(int port, int enable)
tcpc_config[port].drv->tcpc_discharge_vbus(port, enable);
}
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_TCPC
+static inline int tcpc_i2c_read(const int port, const int addr,
+ const int reg, int *data)
+{
+ return tcpc_read(port, reg, data);
+}
+
+static inline int tcpc_i2c_write(const int port, const int addr,
+ const int reg, int data)
+{
+ return tcpc_write(port, reg, data);
+}
+#endif
+
#else
/**
diff --git a/include/battery.h b/include/battery.h
index e79ddd3adf..4f729895b9 100644
--- a/include/battery.h
+++ b/include/battery.h
@@ -333,4 +333,8 @@ void print_battery_debug(void);
*/
enum battery_disconnect_state battery_get_disconnect_state(void);
+#ifdef CONFIG_CMD_I2C_STRESS_TEST_BATTERY
+extern struct i2c_stress_test_dev battery_i2c_stress_test_dev;
+#endif
+
#endif /* __CROS_EC_BATTERY_H */
diff --git a/include/config.h b/include/config.h
index 5ec402d8a6..66732dd198 100644
--- a/include/config.h
+++ b/include/config.h
@@ -207,6 +207,9 @@
*/
#undef CONFIG_BATTERY_SMART
+/* Chemistry of the battery device */
+#undef CONFIG_BATTERY_DEVICE_CHEMISTRY
+
/*
* Critical battery shutdown timeout (seconds)
*
@@ -592,6 +595,12 @@
#undef CONFIG_CMD_HOSTCMD
#undef CONFIG_CMD_I2C_PROTECT
#define CONFIG_CMD_I2C_SCAN
+#undef CONFIG_CMD_I2C_STRESS_TEST
+#undef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
+#undef CONFIG_CMD_I2C_STRESS_TEST_ALS
+#undef CONFIG_CMD_I2C_STRESS_TEST_BATTERY
+#undef CONFIG_CMD_I2C_STRESS_TEST_CHARGER
+#undef CONFIG_CMD_I2C_STRESS_TEST_TCPC
#define CONFIG_CMD_I2C_XFER
#undef CONFIG_CMD_I2CWEDGE
#define CONFIG_CMD_IDLE_STATS
diff --git a/include/i2c.h b/include/i2c.h
index d3329df64a..ddd3dd3c7f 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -40,6 +40,42 @@ struct i2c_port_t {
extern const struct i2c_port_t i2c_ports[];
extern const unsigned int i2c_ports_used;
+#ifdef CONFIG_CMD_I2C_STRESS_TEST
+struct i2c_test_reg_info {
+ int read_reg; /* Read register (WHO_AM_I, DEV_ID, MAN_ID) */
+ int read_val; /* Expected val (WHO_AM_I, DEV_ID, MAN_ID) */
+ int write_reg; /* Read/Write reg which doesn't impact the system */
+};
+
+struct i2c_test_results {
+ int read_success; /* Successful read count */
+ int read_fail; /* Read fail count */
+ int write_success; /* Successful write count */
+ int write_fail; /* Write fail count */
+};
+
+/* Data structure to define I2C test configuration. */
+struct i2c_stress_test_dev {
+ struct i2c_test_reg_info reg_info;
+ struct i2c_test_results test_results;
+ int (*i2c_read)(const int port, const int addr,
+ const int reg, int *data);
+ int (*i2c_write)(const int port, const int addr,
+ const int reg, int data);
+ int (*i2c_read_dev)(const int reg, int *data);
+ int (*i2c_write_dev)(const int reg, int data);
+};
+
+struct i2c_stress_test {
+ int port;
+ int addr;
+ struct i2c_stress_test_dev *i2c_test;
+};
+
+extern struct i2c_stress_test i2c_stress_tests[];
+extern const int i2c_test_dev_used;
+#endif
+
/* Flags for i2c_xfer() */
#define I2C_XFER_START (1 << 0) /* Start smbus session from idle state */
#define I2C_XFER_STOP (1 << 1) /* Terminate smbus session with stop bit */