Re: [PATCH 5/5] tests/qtest: test K230 I2C transfers with slave devices
Daniel Henrique Barboza <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
On 8/7/2026 12:28 PM, Wang Zhongyu wrote: > Add transfer tests using TMP105 and i2c-echo slave devices. > > Cover single- and multi-byte reads and writes, combined write/read > transfers, repeated START and STOP handling, RX threshold and > overflow behavior, data NACK reporting, restart-disabled aborts. > > Signed-off-by: Wang Zhongyu <[email protected]> > --- Reviewed-by: Daniel Henrique Barboza <[email protected]> > tests/qtest/k230-i2c-test.c | 598 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 598 insertions(+) > > diff --git a/tests/qtest/k230-i2c-test.c b/tests/qtest/k230-i2c-test.c > index 1d134de5d0..ee788216fb 100644 > --- a/tests/qtest/k230-i2c-test.c > +++ b/tests/qtest/k230-i2c-test.c > @@ -38,7 +38,11 @@ > #define K230_IC_TX_TL 0x3c > #define K230_IC_CLR_INTR 0x40 > #define K230_IC_CLR_RX_UNDER 0x44 > +#define K230_IC_CLR_RX_OVER 0x48 > #define K230_IC_CLR_TX_ABRT 0x54 > +#define K230_IC_CLR_ACTIVITY 0x5c > +#define K230_IC_CLR_STOP_DET 0x60 > +#define K230_IC_CLR_START_DET 0x64 > #define K230_IC_ENABLE 0x6c > #define K230_IC_STATUS 0x70 > #define K230_IC_TXFLR 0x74 > @@ -63,20 +67,29 @@ > /* IC_DATA_CMD */ > #define IC_DATA_CMD_READ BIT(8) > #define IC_DATA_CMD_STOP BIT(9) > +#define IC_DATA_CMD_RESTART BIT(10) > > /* IC_INTR_STAT and IC_RAW_INTR_STAT */ > #define IC_INTR_RX_UNDER BIT(0) > +#define IC_INTR_RX_OVER BIT(1) > +#define IC_INTR_RX_FULL BIT(2) > #define IC_INTR_TX_EMPTY BIT(4) > #define IC_INTR_TX_ABRT BIT(6) > #define IC_INTR_ACTIVITY BIT(8) > +#define IC_INTR_STOP_DET BIT(9) > #define IC_INTR_START_DET BIT(10) > > /* IC_STATUS */ > +#define IC_STATUS_ACTIVITY BIT(0) > #define IC_STATUS_TFNF BIT(1) > #define IC_STATUS_TFE BIT(2) > +#define IC_STATUS_RFNE BIT(3) > +#define IC_STATUS_RFF BIT(4) > +#define IC_STATUS_MST_ACTIVITY BIT(5) > > /* IC_TX_ABRT_SOURCE */ > #define IC_ABRT_7B_ADDR_NOACK BIT(0) > +#define IC_ABRT_TXDATA_NOACK BIT(3) > #define IC_ABRT_GCALL_NOACK BIT(4) > #define IC_ABRT_GCALL_READ BIT(5) > #define IC_ABRT_SBYTE_NORSTRT BIT(9) > @@ -86,6 +99,19 @@ > #define K230_IC_COMP_VERSION_VALUE 0x3132302a > #define K230_IC_COMP_TYPE_VALUE 0x44570140 > > +#define TMP105_ADDRESS 0x49 > +#define I2C_ECHO_ADDRESS 0x50 > + > +#define TMP105_REG_TEMPERATURE 0x00 > +#define TMP105_REG_CONFIG 0x01 > +#define TMP105_REG_T_LOW 0x02 > +#define TMP105_REG_T_HIGH 0x03 > + > +#define K230_I2C_SLAVE_MACHINE_ARGS \ > + "-machine k230 " \ > + "-device tmp105,id=tmp105-test,address=0x49 " \ > + "-device i2c-echo,id=i2c-echo-test,address=0x50" > + > static const uint64_t k230_i2c_base[K230_I2C_COUNT] = { > K230_I2C0_BASE, > K230_I2C1_BASE, > @@ -94,6 +120,129 @@ static const uint64_t k230_i2c_base[K230_I2C_COUNT] = { > K230_I2C4_BASE, > }; > > +static QTestState *k230_i2c_init_with_slaves(void) > +{ > + return qtest_init(K230_I2C_SLAVE_MACHINE_ARGS); > +} > + > +static void k230_i2c_configure_master(QTestState *qts, uint64_t base, > + uint8_t target, bool restart_enable) > +{ > + uint32_t con; > + > + qtest_writel(qts, base + K230_IC_ENABLE, 0); > + > + con = qtest_readl(qts, base + K230_IC_CON); > + con |= IC_CON_MASTER_MODE; > + con &= ~IC_CON_10BITADDR_MASTER; > + > + if (restart_enable) { > + con |= IC_CON_RESTART_EN; > + } else { > + con &= ~IC_CON_RESTART_EN; > + } > + > + qtest_writel(qts, base + K230_IC_CON, con); > + qtest_writel(qts, base + K230_IC_TAR, target); > + qtest_writel(qts, base + K230_IC_ENABLE, 1); > +} > + > +static void k230_i2c_assert_no_abort(QTestState *qts, uint64_t base) > +{ > + uint32_t raw; > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + > + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, 0); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_TX_ABRT_SOURCE), > + ==, 0); > +} > + > +static uint64_t k230_i2c_find_tmp105_bus(QTestState *qts) > +{ > + for (int i = 0; i < K230_I2C_COUNT; i++) { > + uint64_t base = k230_i2c_base[i]; > + uint32_t raw; > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + > + /* > + * A one-byte write selects the temperature register. The > + * controller whose bus contains TMP105 completes without aborting. > + */ > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_STOP | TMP105_REG_TEMPERATURE); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + > + if (!(raw & IC_INTR_TX_ABRT)) { > + qtest_writel(qts, base + K230_IC_ENABLE, 0); > + return base; > + } > + > + qtest_readl(qts, base + K230_IC_CLR_TX_ABRT); > + qtest_writel(qts, base + K230_IC_ENABLE, 0); > + } > + > + g_assert_not_reached(); > +} > + > +static void k230_i2c_write_bytes(QTestState *qts, uint64_t base, > + const uint8_t *data, size_t len) > +{ > + g_assert_cmpuint(len, >, 0); > + > + for (size_t i = 0; i < len; i++) { > + uint32_t command = data[i]; > + > + if (i == len - 1) { > + command |= IC_DATA_CMD_STOP; > + } > + > + qtest_writel(qts, base + K230_IC_DATA_CMD, command); > + } > + > + k230_i2c_assert_no_abort(qts, base); > +} > + > +static void k230_i2c_select_register(QTestState *qts, uint64_t base, > + uint8_t reg) > +{ > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_STOP | reg); > + k230_i2c_assert_no_abort(qts, base); > +} > + > +static void k230_i2c_queue_reads(QTestState *qts, uint64_t base, > + size_t len, bool restart_first, > + bool stop_last) > +{ > + g_assert_cmpuint(len, >, 0); > + > + for (size_t i = 0; i < len; i++) { > + uint32_t command = IC_DATA_CMD_READ; > + > + if (i == 0 && restart_first) { > + command |= IC_DATA_CMD_RESTART; > + } > + > + if (i == len - 1 && stop_last) { > + command |= IC_DATA_CMD_STOP; > + } > + > + qtest_writel(qts, base + K230_IC_DATA_CMD, command); > + } > + > + k230_i2c_assert_no_abort(qts, base); > +} > + > +static void k230_i2c_tmp105_combined_read(QTestState *qts, uint64_t base, > + uint8_t reg, size_t len) > +{ > + qtest_writel(qts, base + K230_IC_DATA_CMD, reg); > + k230_i2c_queue_reads(qts, base, len, true, true); > +} > + > static void test_reset_values(void) > { > QTestState *qts = qtest_init("-machine k230"); > @@ -824,6 +973,432 @@ static void test_start_byte_abort(void) > qtest_quit(qts); > } > > +static void test_tmp105_config_read_write(void) > +{ > + static const uint8_t write_data[] = { > + TMP105_REG_CONFIG, > + 0x60, > + }; > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + > + k230_i2c_write_bytes(qts, base, write_data, > + G_N_ELEMENTS(write_data)); > + > + k230_i2c_tmp105_combined_read(qts, base, > + TMP105_REG_CONFIG, 1); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 1); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x60); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 0); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_tmp105_limit_read_write(void) > +{ > + static const uint8_t write_data[] = { > + TMP105_REG_T_LOW, > + 0x12, > + 0x34, > + }; > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + > + k230_i2c_write_bytes(qts, base, write_data, > + G_N_ELEMENTS(write_data)); > + > + k230_i2c_tmp105_combined_read(qts, base, > + TMP105_REG_T_LOW, 2); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 2); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x12); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x30); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 0); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_tmp105_direct_read(void) > +{ > + static const uint8_t write_data[] = { > + TMP105_REG_CONFIG, > + 0x20, > + }; > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + > + k230_i2c_write_bytes(qts, base, write_data, > + G_N_ELEMENTS(write_data)); > + k230_i2c_select_register(qts, base, TMP105_REG_CONFIG); > + > + /* > + * Start a read while the controller is idle. This covers the > + * IDLE-to-RECEIVING path without a preceding repeated START. > + */ > + k230_i2c_queue_reads(qts, base, 1, false, true); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 1); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x20); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_tmp105_read_write_restart(void) > +{ > + static const uint8_t initial_data[] = { > + TMP105_REG_CONFIG, > + 0x20, > + }; > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + > + k230_i2c_write_bytes(qts, base, initial_data, > + G_N_ELEMENTS(initial_data)); > + k230_i2c_select_register(qts, base, TMP105_REG_CONFIG); > + > + /* > + * Leave the read transfer active, then switch from receiving to > + * sending with a repeated START. > + */ > + k230_i2c_queue_reads(qts, base, 1, false, false); > + > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_RESTART | TMP105_REG_CONFIG); > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_STOP | 0x60); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 1); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x20); > + > + k230_i2c_tmp105_combined_read(qts, base, > + TMP105_REG_CONFIG, 1); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x60); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_tmp105_same_direction_restart(void) > +{ > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + > + /* > + * Start in the sending state, issue an explicit repeated START > + * without changing direction, and then write the config register. > + */ > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + TMP105_REG_T_LOW); > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_RESTART | TMP105_REG_CONFIG); > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_STOP | 0x40); > + > + k230_i2c_assert_no_abort(qts, base); > + > + k230_i2c_tmp105_combined_read(qts, base, > + TMP105_REG_CONFIG, 1); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x40); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_transfer_status_with_slave(void) > +{ > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + uint32_t raw; > + uint32_t status; > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + qtest_readl(qts, base + K230_IC_CLR_INTR); > + > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + TMP105_REG_CONFIG); > + > + status = qtest_readl(qts, base + K230_IC_STATUS); > + g_assert_cmphex(status & IC_STATUS_ACTIVITY, > + ==, IC_STATUS_ACTIVITY); > + g_assert_cmphex(status & IC_STATUS_MST_ACTIVITY, > + ==, IC_STATUS_MST_ACTIVITY); > + g_assert_cmphex(status & IC_STATUS_TFNF, > + ==, IC_STATUS_TFNF); > + g_assert_cmphex(status & IC_STATUS_TFE, > + ==, IC_STATUS_TFE); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_START_DET, > + ==, IC_INTR_START_DET); > + g_assert_cmphex(raw & IC_INTR_ACTIVITY, > + ==, IC_INTR_ACTIVITY); > + > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_STOP | 0x20); > + > + status = qtest_readl(qts, base + K230_IC_STATUS); > + g_assert_cmphex(status & IC_STATUS_ACTIVITY, ==, 0); > + g_assert_cmphex(status & IC_STATUS_MST_ACTIVITY, ==, 0); > + g_assert_cmphex(status & IC_STATUS_TFNF, > + ==, IC_STATUS_TFNF); > + g_assert_cmphex(status & IC_STATUS_TFE, > + ==, IC_STATUS_TFE); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_STOP_DET, > + ==, IC_INTR_STOP_DET); > + g_assert_cmphex(raw & IC_INTR_ACTIVITY, > + ==, IC_INTR_ACTIVITY); > + > + qtest_readl(qts, base + K230_IC_CLR_START_DET); > + qtest_readl(qts, base + K230_IC_CLR_STOP_DET); > + qtest_readl(qts, base + K230_IC_CLR_ACTIVITY); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_START_DET, ==, 0); > + g_assert_cmphex(raw & IC_INTR_STOP_DET, ==, 0); > + g_assert_cmphex(raw & IC_INTR_ACTIVITY, ==, 0); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_rx_threshold_with_slave(void) > +{ > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + uint32_t raw; > + uint32_t stat; > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + qtest_writel(qts, base + K230_IC_RX_TL, 1); > + qtest_writel(qts, base + K230_IC_INTR_MASK, > + IC_INTR_RX_FULL); > + > + k230_i2c_select_register(qts, base, TMP105_REG_T_LOW); > + qtest_readl(qts, base + K230_IC_CLR_INTR); > + > + k230_i2c_queue_reads(qts, base, 1, false, false); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_RX_FULL, ==, 0); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 1); > + > + k230_i2c_queue_reads(qts, base, 1, false, true); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + stat = qtest_readl(qts, base + K230_IC_INTR_STAT); > + > + g_assert_cmphex(raw & IC_INTR_RX_FULL, > + ==, IC_INTR_RX_FULL); > + g_assert_cmphex(stat & IC_INTR_RX_FULL, > + ==, IC_INTR_RX_FULL); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 2); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x4b); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_RX_FULL, ==, 0); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x00); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_rx_overflow_with_slave(void) > +{ > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + uint32_t raw; > + uint32_t status; > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, true); > + qtest_writel(qts, base + K230_IC_RX_TL, 63); > + qtest_writel(qts, base + K230_IC_INTR_MASK, > + IC_INTR_RX_FULL | IC_INTR_RX_OVER); > + > + k230_i2c_select_register(qts, base, TMP105_REG_T_LOW); > + qtest_readl(qts, base + K230_IC_CLR_INTR); > + > + /* > + * TMP105 returns two register bytes and then 0xff. Sixty-five > + * read commands therefore fill the 64-byte RX FIFO and overflow > + * on the final command. > + */ > + k230_i2c_queue_reads(qts, base, 65, false, true); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 64); > + > + status = qtest_readl(qts, base + K230_IC_STATUS); > + g_assert_cmphex(status & IC_STATUS_RFNE, > + ==, IC_STATUS_RFNE); > + g_assert_cmphex(status & IC_STATUS_RFF, > + ==, IC_STATUS_RFF); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_RX_FULL, > + ==, IC_INTR_RX_FULL); > + g_assert_cmphex(raw & IC_INTR_RX_OVER, > + ==, IC_INTR_RX_OVER); > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x4b); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_DATA_CMD), > + ==, 0x00); > + > + for (int i = 0; i < 62; i++) { > + g_assert_cmphex(qtest_readl(qts, > + base + K230_IC_DATA_CMD), > + ==, 0xff); > + } > + > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 0); > + > + status = qtest_readl(qts, base + K230_IC_STATUS); > + g_assert_cmphex(status & IC_STATUS_RFNE, ==, 0); > + g_assert_cmphex(status & IC_STATUS_RFF, ==, 0); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_RX_FULL, ==, 0); > + g_assert_cmphex(raw & IC_INTR_RX_OVER, > + ==, IC_INTR_RX_OVER); > + > + qtest_readl(qts, base + K230_IC_CLR_RX_OVER); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_RX_OVER, ==, 0); > + > + k230_i2c_assert_no_abort(qts, base); > + qtest_quit(qts); > +} > + > +static void test_restart_disabled_abort(void) > +{ > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + uint32_t raw; > + uint32_t status; > + > + k230_i2c_configure_master(qts, base, TMP105_ADDRESS, false); > + > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + TMP105_REG_CONFIG); > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_READ | IC_DATA_CMD_STOP); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + status = qtest_readl(qts, base + K230_IC_STATUS); > + > + g_assert_cmphex(raw & IC_INTR_TX_ABRT, > + ==, IC_INTR_TX_ABRT); > + g_assert_cmphex(qtest_readl(qts, > + base + K230_IC_TX_ABRT_SOURCE), > + ==, 0); > + g_assert_cmphex(status & IC_STATUS_ACTIVITY, ==, 0); > + g_assert_cmphex(status & IC_STATUS_MST_ACTIVITY, ==, 0); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_TXFLR), > + ==, 0); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 0); > + > + qtest_readl(qts, base + K230_IC_CLR_TX_ABRT); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, 0); > + > + qtest_quit(qts); > +} > + > +static void test_echo_data_nack(void) > +{ > + static const uint8_t accepted_data[] = { > + 0x7f, > + 0x11, > + 0x22, > + }; > + QTestState *qts = k230_i2c_init_with_slaves(); > + uint64_t base = k230_i2c_find_tmp105_bus(qts); > + uint32_t raw; > + uint32_t source; > + uint32_t status; > + > + k230_i2c_configure_master(qts, base, I2C_ECHO_ADDRESS, true); > + > + for (size_t i = 0; i < G_N_ELEMENTS(accepted_data); i++) { > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + accepted_data[i]); > + } > + > + /* > + * i2c-echo accepts three bytes. The fourth byte is rejected, > + * allowing the controller's TXDATA_NOACK path to be tested. > + */ > + qtest_writel(qts, base + K230_IC_DATA_CMD, > + IC_DATA_CMD_STOP | 0x33); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + source = qtest_readl(qts, base + K230_IC_TX_ABRT_SOURCE); > + status = qtest_readl(qts, base + K230_IC_STATUS); > + > + g_assert_cmphex(raw & IC_INTR_TX_ABRT, > + ==, IC_INTR_TX_ABRT); > + g_assert_cmphex(source & IC_ABRT_TXDATA_NOACK, > + ==, IC_ABRT_TXDATA_NOACK); > + g_assert_cmphex(source & IC_ABRT_7B_ADDR_NOACK, ==, 0); > + g_assert_cmphex(status & IC_STATUS_ACTIVITY, ==, 0); > + g_assert_cmphex(status & IC_STATUS_MST_ACTIVITY, ==, 0); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_TXFLR), > + ==, 0); > + g_assert_cmphex(qtest_readl(qts, base + K230_IC_RXFLR), > + ==, 0); > + > + qtest_readl(qts, base + K230_IC_CLR_TX_ABRT); > + > + raw = qtest_readl(qts, base + K230_IC_RAW_INTR_STAT); > + source = qtest_readl(qts, base + K230_IC_TX_ABRT_SOURCE); > + > + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, 0); > + g_assert_cmphex(source, ==, 0); > + > + qtest_quit(qts); > +} > + > int main(int argc, char **argv) > { > g_test_init(&argc, &argv, NULL); > @@ -857,5 +1432,28 @@ int main(int argc, char **argv) > qtest_add_func("/k230-i2c/start-byte-abort", > test_start_byte_abort); > > + if (qtest_has_device("tmp105") && qtest_has_device("i2c-echo")) { > + qtest_add_func("/k230-i2c/tmp105-config-read-write", > + test_tmp105_config_read_write); > + qtest_add_func("/k230-i2c/tmp105-limit-read-write", > + test_tmp105_limit_read_write); > + qtest_add_func("/k230-i2c/tmp105-direct-read", > + test_tmp105_direct_read); > + qtest_add_func("/k230-i2c/tmp105-read-write-restart", > + test_tmp105_read_write_restart); > + qtest_add_func("/k230-i2c/tmp105-same-direction-restart", > + test_tmp105_same_direction_restart); > + qtest_add_func("/k230-i2c/transfer-status-with-slave", > + test_transfer_status_with_slave); > + qtest_add_func("/k230-i2c/rx-threshold-with-slave", > + test_rx_threshold_with_slave); > + qtest_add_func("/k230-i2c/rx-overflow-with-slave", > + test_rx_overflow_with_slave); > + qtest_add_func("/k230-i2c/restart-disabled-abort", > + test_restart_disabled_abort); > + qtest_add_func("/k230-i2c/echo-data-nack", > + test_echo_data_nack); > + } > + > return g_test_run(); > }