1ecc2ed55SSimon Glass /* 2ecc2ed55SSimon Glass * Copyright (C) 2013 Google, Inc 3ecc2ed55SSimon Glass * 4ecc2ed55SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 5ecc2ed55SSimon Glass * 6ecc2ed55SSimon Glass * Note: Test coverage does not include 10-bit addressing 7ecc2ed55SSimon Glass */ 8ecc2ed55SSimon Glass 9ecc2ed55SSimon Glass #include <common.h> 10ecc2ed55SSimon Glass #include <dm.h> 11ecc2ed55SSimon Glass #include <fdtdec.h> 12ecc2ed55SSimon Glass #include <i2c.h> 13*e721b882SJoe Hershberger #include <asm/state.h> 14*e721b882SJoe Hershberger #include <asm/test.h> 15ecc2ed55SSimon Glass #include <dm/device-internal.h> 16ecc2ed55SSimon Glass #include <dm/test.h> 17ecc2ed55SSimon Glass #include <dm/uclass-internal.h> 18ecc2ed55SSimon Glass #include <dm/util.h> 19*e721b882SJoe Hershberger #include <test/ut.h> 20ecc2ed55SSimon Glass 21ecc2ed55SSimon Glass static const int busnum; 22ecc2ed55SSimon Glass static const int chip = 0x2c; 23ecc2ed55SSimon Glass 24ecc2ed55SSimon Glass /* Test that we can find buses and chips */ 25*e721b882SJoe Hershberger static int dm_test_i2c_find(struct unit_test_state *uts) 26ecc2ed55SSimon Glass { 27ecc2ed55SSimon Glass struct udevice *bus, *dev; 28ecc2ed55SSimon Glass const int no_chip = 0x10; 29ecc2ed55SSimon Glass 30ecc2ed55SSimon Glass ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_I2C, busnum, 31ecc2ed55SSimon Glass false, &bus)); 32ecc2ed55SSimon Glass 33ecc2ed55SSimon Glass /* 34ecc2ed55SSimon Glass * i2c_post_bind() will bind devices to chip selects. Check this then 35ecc2ed55SSimon Glass * remove the emulation and the slave device. 36ecc2ed55SSimon Glass */ 37ecc2ed55SSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); 38f9a4c2daSSimon Glass ut_assertok(dm_i2c_probe(bus, chip, 0, &dev)); 39f9a4c2daSSimon Glass ut_asserteq(-ENODEV, dm_i2c_probe(bus, no_chip, 0, &dev)); 40ecc2ed55SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_I2C, 1, &bus)); 41ecc2ed55SSimon Glass 42ecc2ed55SSimon Glass return 0; 43ecc2ed55SSimon Glass } 44ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_find, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 45ecc2ed55SSimon Glass 46*e721b882SJoe Hershberger static int dm_test_i2c_read_write(struct unit_test_state *uts) 47ecc2ed55SSimon Glass { 48ecc2ed55SSimon Glass struct udevice *bus, *dev; 49ecc2ed55SSimon Glass uint8_t buf[5]; 50ecc2ed55SSimon Glass 51ecc2ed55SSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); 5225ab4b03SSimon Glass ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); 53f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 54ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf))); 55f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); 56f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 57ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\0AB\0", sizeof(buf))); 58ecc2ed55SSimon Glass 59ecc2ed55SSimon Glass return 0; 60ecc2ed55SSimon Glass } 61ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_read_write, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 62ecc2ed55SSimon Glass 63*e721b882SJoe Hershberger static int dm_test_i2c_speed(struct unit_test_state *uts) 64ecc2ed55SSimon Glass { 65ecc2ed55SSimon Glass struct udevice *bus, *dev; 66ecc2ed55SSimon Glass uint8_t buf[5]; 67ecc2ed55SSimon Glass 68ecc2ed55SSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); 69182bf92dSSimon Glass 70182bf92dSSimon Glass /* Use test mode so we create the required errors for invalid speeds */ 71182bf92dSSimon Glass sandbox_i2c_set_test_mode(bus, true); 7225ab4b03SSimon Glass ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); 73ca88b9b9SSimon Glass ut_assertok(dm_i2c_set_bus_speed(bus, 100000)); 74f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 75ca88b9b9SSimon Glass ut_assertok(dm_i2c_set_bus_speed(bus, 400000)); 76ca88b9b9SSimon Glass ut_asserteq(400000, dm_i2c_get_bus_speed(bus)); 77f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 78f9a4c2daSSimon Glass ut_asserteq(-EINVAL, dm_i2c_write(dev, 0, buf, 5)); 79182bf92dSSimon Glass sandbox_i2c_set_test_mode(bus, false); 80ecc2ed55SSimon Glass 81ecc2ed55SSimon Glass return 0; 82ecc2ed55SSimon Glass } 83ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_speed, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 84ecc2ed55SSimon Glass 85*e721b882SJoe Hershberger static int dm_test_i2c_offset_len(struct unit_test_state *uts) 86ecc2ed55SSimon Glass { 87ecc2ed55SSimon Glass struct udevice *bus, *dev; 88ecc2ed55SSimon Glass uint8_t buf[5]; 89ecc2ed55SSimon Glass 90ecc2ed55SSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); 9125ab4b03SSimon Glass ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); 92ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_offset_len(dev, 1)); 93f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 94ecc2ed55SSimon Glass 95ecc2ed55SSimon Glass /* This is not supported by the uclass */ 96ecc2ed55SSimon Glass ut_asserteq(-EINVAL, i2c_set_chip_offset_len(dev, 5)); 97ecc2ed55SSimon Glass 98ecc2ed55SSimon Glass return 0; 99ecc2ed55SSimon Glass } 100ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_offset_len, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 101ecc2ed55SSimon Glass 102*e721b882SJoe Hershberger static int dm_test_i2c_probe_empty(struct unit_test_state *uts) 103ecc2ed55SSimon Glass { 104ecc2ed55SSimon Glass struct udevice *bus, *dev; 105ecc2ed55SSimon Glass 106ecc2ed55SSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); 107182bf92dSSimon Glass 108182bf92dSSimon Glass /* Use test mode so that this chip address will always probe */ 109182bf92dSSimon Glass sandbox_i2c_set_test_mode(bus, true); 110f9a4c2daSSimon Glass ut_assertok(dm_i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev)); 111182bf92dSSimon Glass sandbox_i2c_set_test_mode(bus, false); 112ecc2ed55SSimon Glass 113ecc2ed55SSimon Glass return 0; 114ecc2ed55SSimon Glass } 115ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_probe_empty, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 116ecc2ed55SSimon Glass 117*e721b882SJoe Hershberger static int dm_test_i2c_bytewise(struct unit_test_state *uts) 118ecc2ed55SSimon Glass { 119ecc2ed55SSimon Glass struct udevice *bus, *dev; 120ecc2ed55SSimon Glass struct udevice *eeprom; 121ecc2ed55SSimon Glass uint8_t buf[5]; 122ecc2ed55SSimon Glass 123ecc2ed55SSimon Glass ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); 12425ab4b03SSimon Glass ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); 125f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 126ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf))); 127ecc2ed55SSimon Glass 128ecc2ed55SSimon Glass /* Tell the EEPROM to only read/write one register at a time */ 129ecc2ed55SSimon Glass ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom)); 130ecc2ed55SSimon Glass ut_assertnonnull(eeprom); 131ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_SINGLE_BYTE); 132ecc2ed55SSimon Glass 133ecc2ed55SSimon Glass /* Now we only get the first byte - the rest will be 0xff */ 134f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 135ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf))); 136ecc2ed55SSimon Glass 137ecc2ed55SSimon Glass /* If we do a separate transaction for each byte, it works */ 138ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS)); 139f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 140ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\0\0\0\0", sizeof(buf))); 141ecc2ed55SSimon Glass 142ecc2ed55SSimon Glass /* This will only write A */ 143ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_flags(dev, 0)); 144f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); 145f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 146ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf))); 147ecc2ed55SSimon Glass 148ecc2ed55SSimon Glass /* Check that the B was ignored */ 149ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS)); 150f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 151ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\0A\0\0\0", sizeof(buf))); 152ecc2ed55SSimon Glass 153ecc2ed55SSimon Glass /* Now write it again with the new flags, it should work */ 154ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS)); 155f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); 156f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 157ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\xff\xff\xff\xff", sizeof(buf))); 158ecc2ed55SSimon Glass 159ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_flags(dev, DM_I2C_CHIP_WR_ADDRESS | 160ecc2ed55SSimon Glass DM_I2C_CHIP_RD_ADDRESS)); 161f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 162ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "\0\0AB\0\0", sizeof(buf))); 163ecc2ed55SSimon Glass 164ecc2ed55SSimon Glass /* Restore defaults */ 165ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_test_mode(eeprom, SIE_TEST_MODE_NONE); 166ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_flags(dev, 0)); 167ecc2ed55SSimon Glass 168ecc2ed55SSimon Glass return 0; 169ecc2ed55SSimon Glass } 170ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_bytewise, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 171ecc2ed55SSimon Glass 172*e721b882SJoe Hershberger static int dm_test_i2c_offset(struct unit_test_state *uts) 173ecc2ed55SSimon Glass { 174ecc2ed55SSimon Glass struct udevice *eeprom; 175ecc2ed55SSimon Glass struct udevice *dev; 176ecc2ed55SSimon Glass uint8_t buf[5]; 177ecc2ed55SSimon Glass 17825ab4b03SSimon Glass ut_assertok(i2c_get_chip_for_busnum(busnum, chip, 1, &dev)); 179ecc2ed55SSimon Glass 180ecc2ed55SSimon Glass /* Do a transfer so we can find the emulator */ 181f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 182ecc2ed55SSimon Glass ut_assertok(uclass_first_device(UCLASS_I2C_EMUL, &eeprom)); 183ecc2ed55SSimon Glass 184ecc2ed55SSimon Glass /* Offset length 0 */ 185ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_offset_len(eeprom, 0); 186ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_offset_len(dev, 0)); 187f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 10 /* ignored */, (uint8_t *)"AB", 2)); 188f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 189ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "AB\0\0\0\0", sizeof(buf))); 190ecc2ed55SSimon Glass 191ecc2ed55SSimon Glass /* Offset length 1 */ 192ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_offset_len(eeprom, 1); 193ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_offset_len(dev, 1)); 194f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 2, (uint8_t *)"AB", 2)); 195f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0, buf, 5)); 196ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "ABAB\0", sizeof(buf))); 197ecc2ed55SSimon Glass 198ecc2ed55SSimon Glass /* Offset length 2 */ 199ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_offset_len(eeprom, 2); 200ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_offset_len(dev, 2)); 201f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 0x210, (uint8_t *)"AB", 2)); 202f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0x210, buf, 5)); 203ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf))); 204ecc2ed55SSimon Glass 205ecc2ed55SSimon Glass /* Offset length 3 */ 206ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_offset_len(eeprom, 2); 207ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_offset_len(dev, 2)); 208f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 0x410, (uint8_t *)"AB", 2)); 209f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0x410, buf, 5)); 210ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf))); 211ecc2ed55SSimon Glass 212ecc2ed55SSimon Glass /* Offset length 4 */ 213ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_offset_len(eeprom, 2); 214ecc2ed55SSimon Glass ut_assertok(i2c_set_chip_offset_len(dev, 2)); 215f9a4c2daSSimon Glass ut_assertok(dm_i2c_write(dev, 0x420, (uint8_t *)"AB", 2)); 216f9a4c2daSSimon Glass ut_assertok(dm_i2c_read(dev, 0x420, buf, 5)); 217ecc2ed55SSimon Glass ut_assertok(memcmp(buf, "AB\0\0\0", sizeof(buf))); 218ecc2ed55SSimon Glass 219ecc2ed55SSimon Glass /* Restore defaults */ 220ecc2ed55SSimon Glass sandbox_i2c_eeprom_set_offset_len(eeprom, 1); 221ecc2ed55SSimon Glass 222ecc2ed55SSimon Glass return 0; 223ecc2ed55SSimon Glass } 224ecc2ed55SSimon Glass DM_TEST(dm_test_i2c_offset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 225