On Wed, Dec 12, 2012 at 6:29 AM, Andreas Färber <andreas.faer...@web.de> wrote: > Exercise all four commands of the TMP105, testing for an issue in the > I2C TX path. The test case is specific to the n800's OMAP I2C for now > and is the first test case for arm. > > Signed-off-by: Andreas Färber <andreas.faer...@web.de> > --- > tests/Makefile | 2 + > tests/tmp105-test.c | 205 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 Dateien geändert, 207 Zeilen hinzugefügt(+) > create mode 100644 tests/tmp105-test.c > > diff --git a/tests/Makefile b/tests/Makefile > index b60f0fb..69eff45 100644 > --- a/tests/Makefile > +++ b/tests/Makefile > @@ -28,6 +28,7 @@ check-qtest-i386-y += tests/rtc-test$(EXESUF) > check-qtest-x86_64-y = $(check-qtest-i386-y) > check-qtest-sparc-y = tests/m48t59-test$(EXESUF) > check-qtest-sparc64-y = tests/m48t59-test$(EXESUF) > +check-qtest-arm-y = tests/tmp105-test$(EXESUF) > > GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h > tests/test-qmp-commands.h > > @@ -78,6 +79,7 @@ tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y) > tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y) > tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y) > tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o tests/libqtest.o > $(trace-obj-y) > +tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(trace-obj-y) > > # QTest rules > > diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c > new file mode 100644 > index 0000000..26d51f7 > --- /dev/null > +++ b/tests/tmp105-test.c > @@ -0,0 +1,205 @@ > +/* > + * QTest testcase for the TMP105 temperature sensor > + * > + * Copyright (c) 2012 Andreas Färber > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + */ > +#include "libqtest.h" > + > +#include <glib.h> > +#include <string.h> > + > +enum OMAPI2CRegisters { > + OMAP_I2C_REV = 0x00, > + OMAP_I2C_STAT = 0x08, > + OMAP_I2C_CNT = 0x18, > + OMAP_I2C_DATA = 0x1c, > + OMAP_I2C_CON = 0x24, > + OMAP_I2C_SA = 0x2c, > +}; > + > +enum OMAPI2CSTATBits { > + OMAP_I2C_STAT_NACK = 1 << 1, > + OMAP_I2C_STAT_ARDY = 1 << 2, > + OMAP_I2C_STAT_RRDY = 1 << 3, > + OMAP_I2C_STAT_XRDY = 1 << 4, > + OMAP_I2C_STAT_ROVR = 1 << 11, > + OMAP_I2C_STAT_SBD = 1 << 15, > +}; > + > +enum OMAPI2CCONBits { > + OMAP_I2C_CON_STT = 1 << 0, > + OMAP_I2C_CON_STP = 1 << 1, > + OMAP_I2C_CON_TRX = 1 << 9, > + OMAP_I2C_CON_MST = 1 << 10, > + OMAP_I2C_CON_BE = 1 << 14, > + OMAP_I2C_CON_I2C_EN = 1 << 15, > +}; > + > +#define OMAP2_I2C_1_BASE 0x48070000 > + > +#define N8X0_ADDR 0x48 > + > +static const uint32_t i2c_base = OMAP2_I2C_1_BASE; > + > +static void omap_i2c_init(void) > +{ > + uint16_t data; > + > + /* verify the mmio address by looking for a known signature */ > + memread(i2c_base + OMAP_I2C_REV, &data, 2); > + g_assert_cmphex(data, ==, 0x34); > +} > + > +static void omap_i2c_set_slave_addr(uint8_t addr) > +{ > + uint16_t data = addr; > + > + memwrite(i2c_base + OMAP_I2C_SA, &data, 2); > + memread(i2c_base + OMAP_I2C_SA, &data, 2); > + g_assert_cmphex(data, ==, addr); > +} > + > +static void omap_i2c_send(uint8_t addr, const void *buf, uint16_t len)
With const uint8_t *buf you could avoid a few casts below. > +{ > + uint16_t data; > + > + omap_i2c_set_slave_addr(addr); > + > + data = len; > + memwrite(i2c_base + OMAP_I2C_CNT, &data, 2); > + > + data = OMAP_I2C_CON_I2C_EN | > + OMAP_I2C_CON_TRX | > + OMAP_I2C_CON_MST | > + OMAP_I2C_CON_STT | > + OMAP_I2C_CON_STP; > + memwrite(i2c_base + OMAP_I2C_CON, &data, 2); > + memread(i2c_base + OMAP_I2C_CON, &data, 2); > + g_assert((data & OMAP_I2C_CON_STP) != 0); > + > + memread(i2c_base + OMAP_I2C_STAT, &data, 2); > + g_assert((data & OMAP_I2C_STAT_NACK) == 0); > + > + while (len > 1) { > + memread(i2c_base + OMAP_I2C_STAT, &data, 2); > + g_assert((data & OMAP_I2C_STAT_XRDY) != 0); > + > + memwrite(i2c_base + OMAP_I2C_DATA, buf, 2); > + buf = (uint8_t *)buf + 2; > + len -= 2; > + } > + if (len == 1) { > + memread(i2c_base + OMAP_I2C_STAT, &data, 2); > + g_assert((data & OMAP_I2C_STAT_XRDY) != 0); > + > + memwrite(i2c_base + OMAP_I2C_DATA, buf, 1); > + } > + > + memread(i2c_base + OMAP_I2C_CON, &data, 2); > + g_assert((data & OMAP_I2C_CON_STP) == 0); > +} > + > +static void omap_i2c_recv(uint8_t addr, void *buf, uint16_t len) > +{ > + uint16_t data, stat; > + > + omap_i2c_set_slave_addr(addr); > + > + data = len; > + memwrite(i2c_base + OMAP_I2C_CNT, &data, 2); > + > + data = OMAP_I2C_CON_I2C_EN | > + OMAP_I2C_CON_MST | > + OMAP_I2C_CON_STT | > + OMAP_I2C_CON_STP; > + memwrite(i2c_base + OMAP_I2C_CON, &data, 2); > + memread(i2c_base + OMAP_I2C_CON, &data, 2); > + g_assert((data & OMAP_I2C_CON_STP) == 0); > + > + memread(i2c_base + OMAP_I2C_STAT, &data, 2); > + g_assert((data & OMAP_I2C_STAT_NACK) == 0); > + > + memread(i2c_base + OMAP_I2C_CNT, &data, 2); > + g_assert_cmpuint(data, ==, len); > + > + while (len > 0) { > + memread(i2c_base + OMAP_I2C_STAT, &data, 2); > + g_assert((data & OMAP_I2C_STAT_RRDY) != 0); > + g_assert((data & OMAP_I2C_STAT_ROVR) == 0); > + > + memread(i2c_base + OMAP_I2C_DATA, &data, 2); > + > + memread(i2c_base + OMAP_I2C_STAT, &stat, 2); > + if ((stat & OMAP_I2C_STAT_SBD) != 0) { > + *(uint8_t *)buf = data & 0xf; > + buf = (uint8_t *)buf + 1; > + len--; > + } else { > + memcpy(buf, &data, 2); > + buf = (uint8_t *)buf + 2; > + len -= 2; > + } > + } > + > + memread(i2c_base + OMAP_I2C_CON, &data, 2); > + g_assert((data & OMAP_I2C_CON_STP) == 0); > +} > + > +static void send_and_receive(void) > +{ > + const uint8_t addr = N8X0_ADDR; > + uint8_t cmd[3]; > + uint8_t resp[2]; > + > + omap_i2c_init(); > + > + cmd[0] = 0; > + omap_i2c_send(addr, cmd, 1); > + omap_i2c_recv(addr, resp, 2); > + g_assert_cmpuint(((uint16_t)resp[0] << 8) | resp[1], ==, 0); > + > + cmd[0] = 1; > + cmd[1] = 0x0; > + omap_i2c_send(addr, cmd, 2); > + omap_i2c_recv(addr, resp, 1); > + g_assert_cmphex(resp[0], ==, cmd[1]); > + > + cmd[0] = 2; > + cmd[1] = 0x12; > + cmd[2] = 0x34; > + omap_i2c_send(addr, cmd, 3); > + omap_i2c_recv(addr, resp, 2); > + g_assert_cmphex(resp[0], ==, cmd[1]); > + g_assert_cmphex(resp[1], ==, cmd[2]); > + > + cmd[0] = 3; > + cmd[1] = 0x42; > + cmd[2] = 0x31; > + omap_i2c_send(addr, cmd, 3); > + omap_i2c_recv(addr, resp, 2); > + g_assert_cmphex(resp[0], ==, cmd[1]); > + g_assert_cmphex(resp[1], ==, cmd[2]); > +} > + > +int main(int argc, char **argv) > +{ > + QTestState *s = NULL; > + int ret; > + > + g_test_init(&argc, &argv, NULL); > + > + s = qtest_start("-display none -machine n800"); > + > + qtest_add_func("/tmp105/tx-rx", send_and_receive); A register fuzzing test (like rtc-test.c) would be nice too. > + > + ret = g_test_run(); > + > + if (s) { > + qtest_quit(s); > + } > + > + return ret; > +} > -- > 1.7.10.4 >