How to use I2C in U-Boot SPL

Thomas Thielemann th.thielemann at web.de
Wed Nov 22 21:57:18 CET 2023


Hello U-Boot,

I was able to use the I2C commands from within U-Boot to control my I2C device:

Configured the Processor GPIOs for the I2C bus in device tree
Enabled the I2C bus in device tree
Added my device to the I2C bus in device tree
Wrote my script into a U-Boot variable
Run my script
Now I want to do the same from within the U-Boot SPL. I extended int board_early_init_f(void) in board.c for my hardware. The debug output is printed at run time. But the I2C device is not found.

How do I review whether the I2C bus is using the right GPIOs and whether my device is configured right?

static int i2c_get_dev(uint bus_num, uint dev_num, struct udevice **i2c_dev)
{
    int ret;

    if (!i2c_led_bus) {
        ret = uclass_get_device_by_seq(UCLASS_I2C, bus_num, &i2c_led_bus);
        if (ret) {
            printf("I2C bus %i not found (%d)\n", dev_num, ret);
            return -ENODEV;
        }
    }

    return i2c_get_chip(i2c_led_bus, dev_num, bus_num, i2c_dev);
}
#endif

static int i2c_enable_leds(void)
{
    log_info("i2c_enable_leds\n");
    const uint  bus_num = 1;    // i2c bus
    const uint  dev_num = 0x28;     // i2c chip address
    const uint  dev_addr = 0x00;    // write all bytes in one junk from start
    const uint  dev_addr_len = 1;
    int     ret;
    const uint  cmd_len = 29;       // cmd_len is the number of bytes.
    uchar   cmd[29] = {
        0x40, 0x3c, // init
        0x00, 0x00, 0x00, 0x00, 0x00, // unused
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // set intensitiy to max
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // unused
        0xff, 0x00, 0x00, // RGB LED
        0xff, 0x00, 0x00 // RGB LED
    };
#if CONFIG_IS_ENABLED(DM_I2C)
    struct udevice *i2c_dev;
    struct dm_i2c_chip *i2c_chip;
#endif

#if CONFIG_IS_ENABLED(DM_I2C)
    ret = i2c_get_dev(bus_num, dev_num, &i2c_dev);
    if (!ret)
        ret = i2c_set_chip_offset_len(i2c_dev, dev_addr_len);
    if (ret) {
        log_err("Failed to write to 0x28 (%d)\n", ret);
        return ret;
    }
    i2c_chip = dev_get_parent_plat(i2c_dev);
    if (!i2c_chip) {
        log_err("Failed to write to 0x28 (%d)\n", ret);
        return ret;
    }
#endif

#if CONFIG_IS_ENABLED(DM_I2C)
        i2c_chip->flags &= ~DM_I2C_CHIP_WR_ADDRESS;
        ret = dm_i2c_write(i2c_dev, dev_addr, cmd, cmd_len);
#else
        ret = i2c_write(dev_num, dev_addr, dev_addr_len, cmd, cmd_len);
#endif
        if (ret)
            log_err("Failed to write to 0x28 (%d)\n", ret);

    return 0;
}
int board_early_init_f(void)
{
    i2c_enable_leds();

    return 0;
}


Regards,
Thomas


More information about the U-Boot mailing list