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