[PATCH 4/5] tests/qtest: expand K230 I2C controller tests
Wang Zhongyu <[email protected]>
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Expand the K230 I2C qtests to cover instance isolation, read-only registers, system reset, read-to-clear interrupts, abort source reporting, and START BYTE abort handling. Signed-off-by: Wang Zhongyu <[email protected]> --- tests/qtest/k230-i2c-test.c | 532 +++++++++++++++++++++++++++++++++++- 1 file changed, 529 insertions(+), 3 deletions(-) diff --git a/tests/qtest/k230-i2c-test.c b/tests/qtest/k230-i2c-test.c index cc8dd54153..1d134de5d0 100644 --- a/tests/qtest/k230-i2c-test.c +++ b/tests/qtest/k230-i2c-test.c @@ -25,11 +25,18 @@ #define K230_IC_SAR 0x08 #define K230_IC_HS_MADDR 0x0c #define K230_IC_DATA_CMD 0x10 +#define K230_IC_SS_SCL_HCNT 0x14 +#define K230_IC_SS_SCL_LCNT 0x18 +#define K230_IC_FS_SCL_HCNT 0x1c +#define K230_IC_FS_SCL_LCNT 0x20 +#define K230_IC_HS_SCL_HCNT 0x24 +#define K230_IC_HS_SCL_LCNT 0x28 #define K230_IC_INTR_STAT 0x2c #define K230_IC_INTR_MASK 0x30 #define K230_IC_RAW_INTR_STAT 0x34 #define K230_IC_RX_TL 0x38 #define K230_IC_TX_TL 0x3c +#define K230_IC_CLR_INTR 0x40 #define K230_IC_CLR_RX_UNDER 0x44 #define K230_IC_CLR_TX_ABRT 0x54 #define K230_IC_ENABLE 0x6c @@ -37,20 +44,32 @@ #define K230_IC_TXFLR 0x74 #define K230_IC_RXFLR 0x78 #define K230_IC_TX_ABRT_SOURCE 0x80 +#define K230_IC_SDA_SETUP 0x94 +#define K230_IC_ACK_GENERAL_CALL 0x98 #define K230_IC_ENABLE_STATUS 0x9c #define K230_IC_COMP_PARAM_1 0xf4 #define K230_IC_COMP_VERSION 0xf8 #define K230_IC_COMP_TYPE 0xfc +/* IC_CON */ +#define IC_CON_MASTER_MODE BIT(0) #define IC_CON_10BITADDR_MASTER BIT(4) +#define IC_CON_RESTART_EN BIT(5) + +/* IC_TAR */ +#define IC_TAR_GC_OR_START BIT(10) +#define IC_TAR_SPECIAL BIT(11) /* IC_DATA_CMD */ +#define IC_DATA_CMD_READ BIT(8) #define IC_DATA_CMD_STOP BIT(9) /* IC_INTR_STAT and IC_RAW_INTR_STAT */ #define IC_INTR_RX_UNDER BIT(0) #define IC_INTR_TX_EMPTY BIT(4) #define IC_INTR_TX_ABRT BIT(6) +#define IC_INTR_ACTIVITY BIT(8) +#define IC_INTR_START_DET BIT(10) /* IC_STATUS */ #define IC_STATUS_TFNF BIT(1) @@ -58,6 +77,10 @@ /* IC_TX_ABRT_SOURCE */ #define IC_ABRT_7B_ADDR_NOACK BIT(0) +#define IC_ABRT_GCALL_NOACK BIT(4) +#define IC_ABRT_GCALL_READ BIT(5) +#define IC_ABRT_SBYTE_NORSTRT BIT(9) +#define IC_ABRT_MASTER_DIS BIT(11) #define K230_IC_COMP_PARAM_1_VALUE 0x001f3fae #define K230_IC_COMP_VERSION_VALUE 0x3132302a @@ -131,6 +154,38 @@ static void test_all_instances(void) qtest_quit(qts); } +static void test_instance_isolation(void) +{ + QTestState *qts = qtest_init("-machine k230"); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x2a); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_RX_TL, 17); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_INTR_MASK, 0x41); + + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TAR), + ==, 0x2a); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_RX_TL), + ==, 17); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_INTR_MASK), + ==, 0x41); + + for (int i = 1; i < K230_I2C_COUNT; i++) { + g_assert_cmphex(qtest_readl(qts, + k230_i2c_base[i] + K230_IC_TAR), + ==, 0x55); + g_assert_cmphex(qtest_readl(qts, + k230_i2c_base[i] + K230_IC_RX_TL), + ==, 0); + g_assert_cmphex(qtest_readl(qts, + k230_i2c_base[i] + + K230_IC_INTR_MASK), + ==, 0x8ff); + } + + qtest_quit(qts); +} + static void test_register_access(void) { QTestState *qts = qtest_init("-machine k230"); @@ -163,6 +218,82 @@ static void test_register_access(void) g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TX_TL), ==, 32); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_INTR_MASK, + UINT32_MAX); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_INTR_MASK), + ==, 0xfff); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SDA_SETUP, + UINT32_MAX); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_SDA_SETUP), + ==, 0xff); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ACK_GENERAL_CALL, + UINT32_MAX); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_ACK_GENERAL_CALL), + ==, 1); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE, + UINT32_MAX); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_TX_ABRT_SOURCE), + ==, 0xffff); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SS_SCL_HCNT, + 65525); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_SS_SCL_HCNT), + ==, 65525); + + /* + * Values greater than 65525 are rejected. The previous valid + * value must be preserved. + */ + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SS_SCL_HCNT, + 65526); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_SS_SCL_HCNT), + ==, 65525); + + qtest_quit(qts); +} + +static void test_readonly_registers(void) +{ + static const struct { + uint32_t offset; + uint32_t expected; + } registers[] = { + { K230_IC_INTR_STAT, 0 }, + { K230_IC_RAW_INTR_STAT, 0 }, + { K230_IC_STATUS, IC_STATUS_TFNF | IC_STATUS_TFE }, + { K230_IC_TXFLR, 0 }, + { K230_IC_RXFLR, 0 }, + { K230_IC_ENABLE_STATUS, 0 }, + { K230_IC_COMP_PARAM_1, K230_IC_COMP_PARAM_1_VALUE }, + { K230_IC_COMP_VERSION, K230_IC_COMP_VERSION_VALUE }, + { K230_IC_COMP_TYPE, K230_IC_COMP_TYPE_VALUE }, + }; + QTestState *qts = qtest_init("-machine k230"); + + for (size_t i = 0; i < G_N_ELEMENTS(registers); i++) { + qtest_writel(qts, + K230_I2C0_BASE + registers[i].offset, + UINT32_MAX); + + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + registers[i].offset), + ==, registers[i].expected); + } + qtest_quit(qts); } @@ -171,15 +302,78 @@ static void test_register_lock_while_enabled(void) QTestState *qts = qtest_init("-machine k230"); qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x22); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SAR, 0x155); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_HS_MADDR, 0x3); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SS_SCL_HCNT, 20); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SS_SCL_LCNT, 21); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_FS_SCL_HCNT, 22); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_FS_SCL_LCNT, 23); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_HS_SCL_HCNT, 24); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_HS_SCL_LCNT, 25); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); - qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x33); + /* + * Configuration registers cannot be changed while the + * controller is enabled. + */ qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, 0); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x33); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SAR, 0x222); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_HS_MADDR, 0x7); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SS_SCL_HCNT, 30); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SS_SCL_LCNT, 31); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_FS_SCL_HCNT, 32); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_FS_SCL_LCNT, 33); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_HS_SCL_HCNT, 34); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_HS_SCL_LCNT, 35); - g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TAR), - ==, 0x22); g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON), ==, 0x7f); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TAR), + ==, 0x22); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_SAR), + ==, 0x155); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_HS_MADDR), + ==, 0x3); + + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_SS_SCL_HCNT), + ==, 20); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_SS_SCL_LCNT), + ==, 21); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_FS_SCL_HCNT), + ==, 22); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_FS_SCL_LCNT), + ==, 23); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_HS_SCL_HCNT), + ==, 24); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_HS_SCL_LCNT), + ==, 25); + + /* + * Configuration registers become writable again after the + * controller is disabled. + */ + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 0); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x33); + + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TAR), + ==, 0x33); qtest_quit(qts); } @@ -281,6 +475,7 @@ static void test_address_nack(void) */ con = qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON); con &= ~IC_CON_10BITADDR_MASTER; + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x7f); qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); @@ -310,6 +505,325 @@ static void test_address_nack(void) qtest_quit(qts); } +static void test_system_reset(void) +{ + QTestState *qts = qtest_init("-machine k230"); + uint32_t raw; + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x2a); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_SAR, 0x123); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_RX_TL, 10); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TX_TL, 12); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_INTR_MASK, 0); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + + /* + * Reading an empty RX FIFO produces RX_UNDER. + */ + qtest_readl(qts, K230_I2C0_BASE + K230_IC_DATA_CMD); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + g_assert_cmphex(raw & IC_INTR_RX_UNDER, ==, IC_INTR_RX_UNDER); + + qtest_system_reset(qts); + + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON), + ==, 0x7f); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TAR), + ==, 0x55); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_SAR), + ==, 0x55); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_HS_MADDR), + ==, 0x1); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_INTR_MASK), + ==, 0x8ff); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_RX_TL), + ==, 0); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TX_TL), + ==, 0); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_ENABLE), + ==, 0); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_ENABLE_STATUS), + ==, 0); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT), + ==, 0); + g_assert_cmphex(qtest_readl(qts, + K230_I2C0_BASE + + K230_IC_TX_ABRT_SOURCE), + ==, 0); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_TXFLR), + ==, 0); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_RXFLR), + ==, 0); + g_assert_cmphex(qtest_readl(qts, K230_I2C0_BASE + K230_IC_STATUS), + ==, IC_STATUS_TFNF | IC_STATUS_TFE); + + qtest_quit(qts); +} + +static void test_clear_on_read(void) +{ + QTestState *qts = qtest_init("-machine k230"); + uint32_t con; + uint32_t raw; + uint32_t source; + + /* + * Produce RX_UNDER. + */ + qtest_readl(qts, K230_I2C0_BASE + K230_IC_DATA_CMD); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + g_assert_cmphex(raw & IC_INTR_RX_UNDER, ==, IC_INTR_RX_UNDER); + + /* + * Writing a clear register must not clear the interrupt. + */ + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CLR_RX_UNDER, 1); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + g_assert_cmphex(raw & IC_INTR_RX_UNDER, ==, IC_INTR_RX_UNDER); + + /* + * Produce an independent TX_ABRT interrupt. + */ + con = qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON); + con &= ~IC_CON_10BITADDR_MASTER; + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x7f); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_DATA_CMD, + IC_DATA_CMD_STOP | 0x55); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_RX_UNDER, ==, IC_INTR_RX_UNDER); + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source & IC_ABRT_7B_ADDR_NOACK, + ==, IC_ABRT_7B_ADDR_NOACK); + + /* + * Reading CLR_RX_UNDER clears only RX_UNDER. + */ + qtest_readl(qts, K230_I2C0_BASE + K230_IC_CLR_RX_UNDER); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + + g_assert_cmphex(raw & IC_INTR_RX_UNDER, ==, 0); + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + + /* + * Writing CLR_TX_ABRT must not clear TX_ABRT. + */ + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CLR_TX_ABRT, 1); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + + /* + * Reading CLR_TX_ABRT clears TX_ABRT and its source. + */ + qtest_readl(qts, K230_I2C0_BASE + K230_IC_CLR_TX_ABRT); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, 0); + g_assert_cmphex(source, ==, 0); + + /* + * CLR_INTR clears latched interrupts. TX_EMPTY remains asserted + * because it is recalculated from the empty TX FIFO. + */ + qtest_readl(qts, K230_I2C0_BASE + K230_IC_CLR_INTR); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + + g_assert_cmphex(raw & IC_INTR_RX_UNDER, ==, 0); + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, 0); + g_assert_cmphex(raw & IC_INTR_ACTIVITY, ==, 0); + g_assert_cmphex(raw & IC_INTR_START_DET, ==, 0); + g_assert_cmphex(raw & IC_INTR_TX_EMPTY, ==, IC_INTR_TX_EMPTY); + + qtest_quit(qts); +} + +static void test_abort_sources(void) +{ + QTestState *qts = qtest_init("-machine k230"); + uint32_t con; + uint32_t raw; + uint32_t source; + + /* + * Master mode disabled. + */ + con = qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON); + con &= ~(IC_CON_MASTER_MODE | IC_CON_10BITADDR_MASTER); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, 0x7f); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_DATA_CMD, + IC_DATA_CMD_STOP | 0x55); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source & IC_ABRT_MASTER_DIS, + ==, IC_ABRT_MASTER_DIS); + + qtest_system_reset(qts); + + /* + * A read command cannot target the General Call address. + */ + con = qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON); + con &= ~IC_CON_10BITADDR_MASTER; + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, + IC_TAR_SPECIAL); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_DATA_CMD, + IC_DATA_CMD_READ | IC_DATA_CMD_STOP); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source & IC_ABRT_GCALL_READ, + ==, IC_ABRT_GCALL_READ); + + qtest_system_reset(qts); + + /* + * No slave is attached to acknowledge the General Call. + */ + con = qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON); + con &= ~IC_CON_10BITADDR_MASTER; + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, + IC_TAR_SPECIAL); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_DATA_CMD, + IC_DATA_CMD_STOP | 0x55); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source & IC_ABRT_GCALL_NOACK, + ==, IC_ABRT_GCALL_NOACK); + + qtest_system_reset(qts); + + /* + * 10-bit master addressing is deliberately unsupported. + */ + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_DATA_CMD, + IC_DATA_CMD_STOP | 0x55); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source, ==, 0); + + qtest_quit(qts); +} + +static void test_start_byte_abort(void) +{ + QTestState *qts = qtest_init("-machine k230"); + uint32_t con; + uint32_t raw; + uint32_t source; + + /* + * START BYTE requires RESTART_EN. + */ + con = qtest_readl(qts, K230_I2C0_BASE + K230_IC_CON); + con &= ~(IC_CON_10BITADDR_MASTER | IC_CON_RESTART_EN); + + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_TAR, + IC_TAR_SPECIAL | IC_TAR_GC_OR_START); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 1); + qtest_writel(qts, K230_I2C0_BASE + K230_IC_DATA_CMD, + IC_DATA_CMD_STOP | 0x55); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source & IC_ABRT_SBYTE_NORSTRT, + ==, IC_ABRT_SBYTE_NORSTRT); + + /* + * Bit 9 remains set while the invalid configuration remains. + */ + qtest_readl(qts, K230_I2C0_BASE + K230_IC_CLR_TX_ABRT); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_TX_ABRT_SOURCE); + + g_assert_cmphex(raw & IC_INTR_TX_ABRT, ==, IC_INTR_TX_ABRT); + g_assert_cmphex(source & IC_ABRT_SBYTE_NORSTRT, + ==, IC_ABRT_SBYTE_NORSTRT); + + /* + * Remove the cause by enabling RESTART_EN, then clear again. + */ + qtest_writel(qts, K230_I2C0_BASE + K230_IC_ENABLE, 0); + + con |= IC_CON_RESTART_EN; + qtest_writel(qts, K230_I2C0_BASE + K230_IC_CON, con); + + qtest_readl(qts, K230_I2C0_BASE + K230_IC_CLR_TX_ABRT); + + raw = qtest_readl(qts, + K230_I2C0_BASE + K230_IC_RAW_INTR_STAT); + source = qtest_readl(qts, + K230_I2C0_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); @@ -318,8 +832,12 @@ int main(int argc, char **argv) test_reset_values); qtest_add_func("/k230-i2c/all-instances", test_all_instances); + qtest_add_func("/k230-i2c/instance-isolation", + test_instance_isolation); qtest_add_func("/k230-i2c/register-access", test_register_access); + qtest_add_func("/k230-i2c/readonly-registers", + test_readonly_registers); qtest_add_func("/k230-i2c/register-lock-while-enabled", test_register_lock_while_enabled); qtest_add_func("/k230-i2c/enable-disable", @@ -330,6 +848,14 @@ int main(int argc, char **argv) test_rx_underflow); qtest_add_func("/k230-i2c/address-nack", test_address_nack); + qtest_add_func("/k230-i2c/system-reset", + test_system_reset); + qtest_add_func("/k230-i2c/clear-on-read", + test_clear_on_read); + qtest_add_func("/k230-i2c/abort-sources", + test_abort_sources); + qtest_add_func("/k230-i2c/start-byte-abort", + test_start_byte_abort); return g_test_run(); } -- 2.43.0