diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/dm/Makefile | 1 | ||||
-rw-r--r-- | test/dm/cmd_dm.c | 103 | ||||
-rw-r--r-- | test/dm/i2c.c | 216 | ||||
-rw-r--r-- | test/dm/test.dts | 17 |
4 files changed, 286 insertions, 51 deletions
diff --git a/test/dm/Makefile b/test/dm/Makefile index 75d3d41..612aa95 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -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/cmd_dm.c b/test/dm/cmd_dm.c index 26980d2..79a674e 100644 --- a/test/dm/cmd_dm.c +++ b/test/dm/cmd_dm.c @@ -16,17 +16,65 @@ #include <dm/test.h> #include <dm/uclass-internal.h> +static void show_devices(struct udevice *dev, int depth, int last_flag) +{ + int i, is_last; + struct udevice *child; + char class_name[12]; + + /* print the first 11 characters to not break the tree-format. */ + strlcpy(class_name, dev->uclass->uc_drv->name, sizeof(class_name)); + printf(" %-11s [ %c ] ", class_name, + dev->flags & DM_FLAG_ACTIVATED ? '+' : ' '); + + for (i = depth; i >= 0; i--) { + is_last = (last_flag >> i) & 1; + if (i) { + if (is_last) + printf(" "); + else + printf("| "); + } else { + if (is_last) + printf("`-- "); + else + printf("|-- "); + } + } + + printf("%s\n", dev->name); + + list_for_each_entry(child, &dev->child_head, sibling_node) { + is_last = list_is_last(&child->sibling_node, &dev->child_head); + show_devices(child, depth + 1, (last_flag << 1) | is_last); + } +} + +static int do_dm_dump_all(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct udevice *root; + + root = dm_root(); + if (root) { + printf(" Class Probed Name\n"); + printf("----------------------------------------\n"); + show_devices(root, -1, 0); + } + + return 0; +} + /** * dm_display_line() - Display information about a single device * * Displays a single line of information with an option prefix * * @dev: Device to display - * @buf: Prefix to display at the start of the line */ -static void dm_display_line(struct udevice *dev, char *buf) +static void dm_display_line(struct udevice *dev) { - printf("%s- %c %s @ %08lx", buf, + printf("- %c %s @ %08lx", dev->flags & DM_FLAG_ACTIVATED ? '*' : ' ', dev->name, (ulong)map_to_sysmem(dev)); if (dev->req_seq != -1) @@ -34,53 +82,6 @@ static void dm_display_line(struct udevice *dev, char *buf) puts("\n"); } -static int display_succ(struct udevice *in, char *buf) -{ - int len; - int ip = 0; - char local[16]; - struct udevice *pos, *n, *prev = NULL; - - dm_display_line(in, buf); - - if (list_empty(&in->child_head)) - return 0; - - len = strlen(buf); - strncpy(local, buf, sizeof(local)); - snprintf(local + len, 2, "|"); - if (len && local[len - 1] == '`') - local[len - 1] = ' '; - - list_for_each_entry_safe(pos, n, &in->child_head, sibling_node) { - if (ip++) - display_succ(prev, local); - prev = pos; - } - - snprintf(local + len, 2, "`"); - display_succ(prev, local); - - return 0; -} - -static int dm_dump(struct udevice *dev) -{ - if (!dev) - return -EINVAL; - return display_succ(dev, ""); -} - -static int do_dm_dump_all(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - struct udevice *root; - - root = dm_root(); - printf("ROOT %08lx\n", (ulong)map_to_sysmem(root)); - return dm_dump(root); -} - static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -99,7 +100,7 @@ static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc, if (list_empty(&uc->dev_head)) continue; list_for_each_entry(dev, &uc->dev_head, uclass_node) { - dm_display_line(dev, ""); + dm_display_line(dev); } puts("\n"); } diff --git a/test/dm/i2c.c b/test/dm/i2c.c new file mode 100644 index 0000000..a53e28d --- /dev/null +++ b/test/dm/i2c.c @@ -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); diff --git a/test/dm/test.dts b/test/dm/test.dts index 1fba792..fb0272a 100644 --- a/test/dm/test.dts +++ b/test/dm/test.dts @@ -93,6 +93,23 @@ 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>; |