dm: i2c: EEPROM simulator allow tests visibility of addr and offset
authorRobert Beckett <bob.beckett@collabora.com>
Mon, 28 Oct 2019 17:44:58 +0000 (17:44 +0000)
committerHeiko Schocher <hs@denx.de>
Tue, 17 Dec 2019 05:57:22 +0000 (06:57 +0100)
Improve i2c EEPROM simulator testing by providing access functions to
check the previous chip addr and offset.

Given that we can now directly test the offsets, also simplified the
offset mapping and allow for wrapping acceses.

Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
arch/sandbox/include/asm/test.h
drivers/misc/i2c_eeprom_emul.c
test/dm/i2c.c

index b885e1a14f19f803e18b6344a025d25d0609001f..f3a8b455d52b8aec1ef0996ca73c3348cb83a075 100644 (file)
@@ -72,6 +72,10 @@ void sandbox_i2c_eeprom_set_test_mode(struct udevice *dev,
 
 void sandbox_i2c_eeprom_set_offset_len(struct udevice *dev, int offset_len);
 
+uint sanbox_i2c_eeprom_get_prev_addr(struct udevice *dev);
+
+uint sanbox_i2c_eeprom_get_prev_offset(struct udevice *dev);
+
 /**
  * sandbox_i2c_rtc_set_offset() - set the time offset from system/base time
  *
index 29ed45923ffddbf3fdb4d2f8f51ca92446dcab74..284267f2ea35fb90423dd0af75b0dc82311964ae 100644 (file)
@@ -27,6 +27,8 @@ struct sandbox_i2c_flash_plat_data {
 
 struct sandbox_i2c_flash {
        uint8_t *data;
+       uint prev_addr;         /* slave address of previous access */
+       uint prev_offset;       /* offset of previous access */
 };
 
 void sandbox_i2c_eeprom_set_test_mode(struct udevice *dev,
@@ -44,6 +46,20 @@ void sandbox_i2c_eeprom_set_offset_len(struct udevice *dev, int offset_len)
        plat->offset_len = offset_len;
 }
 
+uint sanbox_i2c_eeprom_get_prev_addr(struct udevice *dev)
+{
+       struct sandbox_i2c_flash *priv = dev_get_priv(dev);
+
+       return priv->prev_addr;
+}
+
+uint sanbox_i2c_eeprom_get_prev_offset(struct udevice *dev)
+{
+       struct sandbox_i2c_flash *priv = dev_get_priv(dev);
+
+       return priv->prev_offset;
+}
+
 static int sandbox_i2c_eeprom_xfer(struct udevice *emul, struct i2c_msg *msg,
                                  int nmsgs)
 {
@@ -52,6 +68,10 @@ static int sandbox_i2c_eeprom_xfer(struct udevice *emul, struct i2c_msg *msg,
 
        debug("\n%s\n", __func__);
        debug_buffer(0, priv->data, 1, 16, 0);
+
+       /* store addr for testing visibity */
+       priv->prev_addr = msg->addr;
+
        for (; nmsgs > 0; nmsgs--, msg++) {
                struct sandbox_i2c_flash_plat_data *plat =
                                dev_get_platdata(emul);
@@ -60,11 +80,6 @@ static int sandbox_i2c_eeprom_xfer(struct udevice *emul, struct i2c_msg *msg,
 
                if (!plat->size)
                        return -ENODEV;
-               if (msg->addr + msg->len > plat->size) {
-                       debug("%s: Address %x, len %x is outside range 0..%x\n",
-                             __func__, msg->addr, msg->len, plat->size);
-                       return -EINVAL;
-               }
                len = msg->len;
                debug("   %s: msg->len=%d",
                      msg->flags & I2C_M_RD ? "read" : "write",
@@ -73,7 +88,16 @@ static int sandbox_i2c_eeprom_xfer(struct udevice *emul, struct i2c_msg *msg,
                        if (plat->test_mode == SIE_TEST_MODE_SINGLE_BYTE)
                                len = 1;
                        debug(", offset %x, len %x: ", offset, len);
-                       memcpy(msg->buf, priv->data + offset, len);
+                       if (offset + len > plat->size) {
+                               int overflow = offset + len - plat->size;
+                               int initial = len - overflow;
+
+                               memcpy(msg->buf, priv->data + offset, initial);
+                               memcpy(msg->buf + initial, priv->data,
+                                      overflow);
+                       } else {
+                               memcpy(msg->buf, priv->data + offset, len);
+                       }
                        memset(msg->buf + len, '\xff', msg->len - len);
                        debug_buffer(0, msg->buf, 1, msg->len, 0);
                } else if (len >= plat->offset_len) {
@@ -87,15 +111,24 @@ static int sandbox_i2c_eeprom_xfer(struct udevice *emul, struct i2c_msg *msg,
                        if (plat->test_mode == SIE_TEST_MODE_SINGLE_BYTE)
                                len = min(len, 1);
 
-                       /* For testing, map offsets into our limited buffer */
-                       for (i = 24; i > 0; i -= 8) {
-                               if (offset > (1 << i)) {
-                                       offset = (offset >> i) |
-                                               (offset & ((1 << i) - 1));
-                                       offset += i;
-                               }
+                       /* store offset for testing visibility */
+                       priv->prev_offset = offset;
+
+                       /* For testing, map offsets into our limited buffer.
+                        * offset wraps every 256 bytes
+                        */
+                       offset &= 0xff;
+                       debug("mapped offset to %x\n", offset);
+
+                       if (offset + len > plat->size) {
+                               int overflow = offset + len - plat->size;
+                               int initial = len - overflow;
+
+                               memcpy(priv->data + offset, ptr, initial);
+                               memcpy(priv->data, ptr + initial, overflow);
+                       } else {
+                               memcpy(priv->data + offset, ptr, len);
                        }
-                       memcpy(priv->data + offset, ptr, len);
                }
        }
        debug_buffer(0, priv->data, 1, 16, 0);
index cbbd4aa29a1fdc8752b1e7d2b9334f9035ad241d..bf5597b7a6b6478b6f3a784f794cd6bb5e1283f8 100644 (file)
@@ -15,6 +15,7 @@
 #include <dm/test.h>
 #include <dm/uclass-internal.h>
 #include <dm/util.h>
+#include <hexdump.h>
 #include <test/ut.h>
 
 static const int busnum;
@@ -185,35 +186,54 @@ static int dm_test_i2c_offset(struct unit_test_state *uts)
        ut_assertok(i2c_set_chip_offset_len(dev, 0));
        ut_assertok(dm_i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2));
        ut_assertok(dm_i2c_read(dev, 0, buf, 5));
-       ut_assertok(memcmp(buf, "AB\0\0\0\0", sizeof(buf)));
+       ut_asserteq_mem("AB\0\0\0\0", buf, sizeof(buf));
+       ut_asserteq(0, sanbox_i2c_eeprom_get_prev_offset(eeprom));
 
        /* Offset length 1 */
        sandbox_i2c_eeprom_set_offset_len(eeprom, 1);
        ut_assertok(i2c_set_chip_offset_len(dev, 1));
        ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2));
+       ut_asserteq(2, sanbox_i2c_eeprom_get_prev_offset(eeprom));
        ut_assertok(dm_i2c_read(dev, 0, buf, 5));
-       ut_assertok(memcmp(buf, "ABAB\0", sizeof(buf)));
+       ut_asserteq_mem("ABAB\0", buf, sizeof(buf));
+       ut_asserteq(0, sanbox_i2c_eeprom_get_prev_offset(eeprom));
 
-       /* Offset length 2 */
+       /* Offset length 2 boundary - check model wrapping */
        sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
        ut_assertok(i2c_set_chip_offset_len(dev, 2));
-       ut_assertok(dm_i2c_write(dev, 0x210, (uint8_t *)"AB", 2));
-       ut_assertok(dm_i2c_read(dev, 0x210, buf, 5));
-       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+       ut_assertok(dm_i2c_write(dev, 0xFF, (uint8_t *)"A", 1));
+       ut_asserteq(0xFF, sanbox_i2c_eeprom_get_prev_offset(eeprom));
+       ut_assertok(dm_i2c_write(dev, 0x100, (uint8_t *)"B", 1));
+       ut_asserteq(0x100, sanbox_i2c_eeprom_get_prev_offset(eeprom));
+       ut_assertok(dm_i2c_write(dev, 0x101, (uint8_t *)"C", 1));
+       ut_asserteq(0x101, sanbox_i2c_eeprom_get_prev_offset(eeprom));
+       ut_assertok(dm_i2c_read(dev, 0xFF, buf, 5));
+       ut_asserteq_mem("ABCAB", buf, sizeof(buf));
+       ut_asserteq(0xFF, sanbox_i2c_eeprom_get_prev_offset(eeprom));
 
-       /* Offset length 3 */
+       /* Offset length 2 */
        sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
        ut_assertok(i2c_set_chip_offset_len(dev, 2));
-       ut_assertok(dm_i2c_write(dev, 0x410, (uint8_t *)"AB", 2));
-       ut_assertok(dm_i2c_read(dev, 0x410, buf, 5));
-       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+       ut_assertok(dm_i2c_write(dev, 0x2020, (uint8_t *)"AB", 2));
+       ut_assertok(dm_i2c_read(dev, 0x2020, buf, 5));
+       ut_asserteq_mem("AB\0\0\0", buf, sizeof(buf));
+       ut_asserteq(0x2020, sanbox_i2c_eeprom_get_prev_offset(eeprom));
+
+       /* Offset length 3 */
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 3);
+       ut_assertok(i2c_set_chip_offset_len(dev, 3));
+       ut_assertok(dm_i2c_write(dev, 0x303030, (uint8_t *)"AB", 2));
+       ut_assertok(dm_i2c_read(dev, 0x303030, buf, 5));
+       ut_asserteq_mem("AB\0\0\0", buf, sizeof(buf));
+       ut_asserteq(0x303030, sanbox_i2c_eeprom_get_prev_offset(eeprom));
 
        /* Offset length 4 */
-       sandbox_i2c_eeprom_set_offset_len(eeprom, 2);
-       ut_assertok(i2c_set_chip_offset_len(dev, 2));
-       ut_assertok(dm_i2c_write(dev, 0x420, (uint8_t *)"AB", 2));
-       ut_assertok(dm_i2c_read(dev, 0x420, buf, 5));
-       ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf)));
+       sandbox_i2c_eeprom_set_offset_len(eeprom, 4);
+       ut_assertok(i2c_set_chip_offset_len(dev, 4));
+       ut_assertok(dm_i2c_write(dev, 0x40404040, (uint8_t *)"AB", 2));
+       ut_assertok(dm_i2c_read(dev, 0x40404040, buf, 5));
+       ut_asserteq_mem("AB\0\0\0", buf, sizeof(buf));
+       ut_asserteq(0x40404040, sanbox_i2c_eeprom_get_prev_offset(eeprom));
 
        /* Restore defaults */
        sandbox_i2c_eeprom_set_offset_len(eeprom, 1);