]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
dm: i2c: Add tests for I2C
authorSimon Glass <sjg@chromium.org>
Wed, 10 Dec 2014 15:55:55 +0000 (08:55 -0700)
committerSimon Glass <sjg@chromium.org>
Thu, 11 Dec 2014 20:18:43 +0000 (13:18 -0700)
Add some basic tests to check that the system works as expected.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Heiko Schocher <hs@denx.de>
include/dm/ut.h
test/dm/Makefile
test/dm/i2c.c [new file with mode: 0644]
test/dm/test.dts

index fa9eac0226537a542cc0a711473b9e7f1c5b8c5c..ec6146545b2e371a8b97f2da5615ff7aa8e22ba6 100644 (file)
@@ -89,6 +89,18 @@ void ut_failf(struct dm_test_state *dms, const char *fname, int line,
        }                                                               \
 }
 
+/* Assert that a pointer is not NULL */
+#define ut_assertnonnull(expr) {                                       \
+       const void *val = (expr);                                       \
+                                                                       \
+       if (val == NULL) {                                              \
+               ut_failf(dms, __FILE__, __LINE__, __func__,             \
+                        #expr " = NULL",                               \
+                        "Expected non-null, got NULL");                \
+               return -1;                                              \
+       }                                                               \
+}
+
 /* Assert that an operation succeeds (returns 0) */
 #define ut_assertok(cond)      ut_asserteq(0, cond)
 
index 75d3d41536bfb47079f37a284beca95bd982b425..612aa957fa2d9ccb832382c6f0e55d3d037b3c67 100644 (file)
@@ -20,4 +20,5 @@ ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
 obj-$(CONFIG_DM_SPI) += spi.o
 obj-$(CONFIG_DM_SPI_FLASH) += sf.o
+obj-$(CONFIG_DM_I2C) += i2c.o
 endif
diff --git a/test/dm/i2c.c b/test/dm/i2c.c
new file mode 100644 (file)
index 0000000..a53e28d
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Note: Test coverage does not include 10-bit addressing
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <dm/ut.h>
+#include <dm/util.h>
+#include <asm/state.h>
+#include <asm/test.h>
+
+static const int busnum;
+static const int chip = 0x2c;
+
+/* Test that we can find buses and chips */
+static int dm_test_i2c_find(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       const int no_chip = 0x10;
+
+       ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_I2C, busnum,
+                                                      false, &bus));
+
+       /*
+        * i2c_post_bind() will bind devices to chip selects. Check this then
+        * remove the emulation and the slave device.
+        */
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_probe(bus, chip, 0, &dev));
+       ut_asserteq(-ENODEV, i2c_probe(bus, no_chip, 0, &dev));
+       ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_I2C, 1, &bus));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_find, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_read_write(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0AB\0", sizeof(buf)));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_read_write, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_speed(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_set_bus_speed(bus, 100000));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(i2c_set_bus_speed(bus, 400000));
+       ut_asserteq(400000, i2c_get_bus_speed(bus));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_asserteq(-EINVAL, i2c_write(dev, 0, buf, 5));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_speed, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_offset_len(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_set_chip_offset_len(dev, 1));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+
+       /* This is not supported by the uclass */
+       ut_asserteq(-EINVAL, i2c_set_chip_offset_len(dev, 5));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_offset_len, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_probe_empty(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_probe_empty, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_bytewise(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev;
+       struct udevice *eeprom;
+       uint8_t buf[5];
+
+       ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+       ut_assertok(i2c_get_chip(bus, chip, &dev));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
+
+       /* Tell the EEPROM to only read/write one register at a time */
+       ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom));
+       ut_assertnonnull(eeprom);
+       sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_SINGLE_BYTE);
+
+       /* Now we only get the first byte - the rest will be 0xff */
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
+
+       /* If we do a separate transaction for each byte, it works */
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf)));
+
+       /* This will only write A */
+       ut_assertok(i2c_set_chip_flags(dev, 0));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
+
+       /* Check that the B was ignored */
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0A\0\0\0", sizeof(buf)));
+
+       /* Now write it again with the new flags, it should work */
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf)));
+
+       ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS |
+                                               DM_I2C_CHIP_RD_ADDRESS));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "\0\0AB\0\0", sizeof(buf)));
+
+       /* Restore defaults */
+       sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_NONE);
+       ut_assertok(i2c_set_chip_flags(dev, 0));
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_bytewise, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+static int dm_test_i2c_offset(struct dm_test_state *dms)
+{
+       struct udevice *eeprom;
+       struct udevice *dev;
+       uint8_t buf[5];
+
+       ut_assertok(i2c_get_chip_for_busnum(busnum, chip, &dev));
+
+       /* Do a transfer so we can find the emulator */
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom));
+
+       /* Offset length 0 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 0);
+       ut_assertok(i2c_set_chip_offset_len(dev, 0));
+       ut_assertok(i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0\0", sizeof(buf)));
+
+       /* Offset length 1 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 1);
+       ut_assertok(i2c_set_chip_offset_len(dev, 1));
+       ut_assertok(i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0, buf, 5));
+       ut_assertok(memcmp(buf, "ABAB\0", sizeof(buf)));
+
+       /* Offset length 2 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
+       ut_assertok(i2c_set_chip_offset_len(dev, 2));
+       ut_assertok(i2c_write(dev, 0x210, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0x210, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+
+       /* Offset length 3 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
+       ut_assertok(i2c_set_chip_offset_len(dev, 2));
+       ut_assertok(i2c_write(dev, 0x410, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0x410, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+
+       /* Offset length 4 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
+       ut_assertok(i2c_set_chip_offset_len(dev, 2));
+       ut_assertok(i2c_write(dev, 0x420, (uint8_t *)"AB", 2));
+       ut_assertok(i2c_read(dev, 0x420, buf, 5));
+       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+
+       /* Restore defaults */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 1);
+
+       return 0;
+}
+DM_TEST(dm_test_i2c_offset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
index 1fba7925642a928fd60f10fd4ed7ee1bcc192890..fb0272a59cd25472b4e733afbe832a35c607d1d8 100644 (file)
                num-gpios = <10>;
        };
 
+       i2c@0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0>;
+               compatible = "sandbox,i2c";
+               clock-frequency = <100000>;
+               eeprom@2c {
+                       reg = <0x2c>;
+                       compatible = "i2c-eeprom";
+                       emul {
+                               compatible = "sandbox,i2c-eeprom";
+                               sandbox,filename = "i2c.bin";
+                               sandbox,size = <256>;
+                       };
+               };
+       };
+
        spi@0 {
                #address-cells = <1>;
                #size-cells = <0>;