mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
cmd_i2c: Provide option for bulk 'i2c write' in one transaction
I2C chips do exist that require a write of some multi-byte data to occur in a single bus transaction (aka atomic transfer), otherwise either the write does not come into effect at all, or normal operation of internal circuitry cannot be guaranteed. The current implementation of the 'i2c write' command (transfer of multiple bytes from a memory buffer) in fact performs a separate transaction for each byte to be written and thus cannot support such types of I2C slave devices. This patch provides an alternative by allowing 'i2c write' to execute the write transfer of the given number of bytes in a single bus transaction if the '-s' option is specified as a final command argument. Else the current re-addressing method is used. Signed-off-by: Lubomir Popov <l-popov@ti.com> hs: adapt to CONFIG_DM_I2C
This commit is contained in:
parent
9e533cb046
commit
ed16f14689
1 changed files with 36 additions and 9 deletions
|
@ -342,9 +342,10 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
|
||||||
int ret;
|
int ret;
|
||||||
#ifdef CONFIG_DM_I2C
|
#ifdef CONFIG_DM_I2C
|
||||||
struct udevice *dev;
|
struct udevice *dev;
|
||||||
|
struct dm_i2c_chip *i2c_chip;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (argc != 5)
|
if ((argc < 5) || (argc > 6))
|
||||||
return cmd_usage(cmdtp);
|
return cmd_usage(cmdtp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -367,7 +368,7 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
|
||||||
return cmd_usage(cmdtp);
|
return cmd_usage(cmdtp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Length is the number of objects, not number of bytes.
|
* Length is the number of bytes.
|
||||||
*/
|
*/
|
||||||
length = simple_strtoul(argv[4], NULL, 16);
|
length = simple_strtoul(argv[4], NULL, 16);
|
||||||
|
|
||||||
|
@ -377,22 +378,47 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
|
||||||
ret = i2c_set_chip_offset_len(dev, alen);
|
ret = i2c_set_chip_offset_len(dev, alen);
|
||||||
if (ret)
|
if (ret)
|
||||||
return i2c_report_err(ret, I2C_ERR_WRITE);
|
return i2c_report_err(ret, I2C_ERR_WRITE);
|
||||||
|
i2c_chip = dev_get_parent_platdata(dev);
|
||||||
|
if (!i2c_chip)
|
||||||
|
return i2c_report_err(ret, I2C_ERR_WRITE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (length-- > 0) {
|
if (argc == 6 && !strcmp(argv[5], "-s")) {
|
||||||
|
/*
|
||||||
|
* Write all bytes in a single I2C transaction. If the target
|
||||||
|
* device is an EEPROM, it is your responsibility to not cross
|
||||||
|
* a page boundary. No write delay upon completion, take this
|
||||||
|
* into account if linking commands.
|
||||||
|
*/
|
||||||
#ifdef CONFIG_DM_I2C
|
#ifdef CONFIG_DM_I2C
|
||||||
ret = dm_i2c_write(dev, devaddr++, memaddr++, 1);
|
i2c_chip->flags &= ~DM_I2C_CHIP_WR_ADDRESS;
|
||||||
|
ret = dm_i2c_write(dev, devaddr, memaddr, length);
|
||||||
#else
|
#else
|
||||||
ret = i2c_write(chip, devaddr++, alen, memaddr++, 1);
|
ret = i2c_write(chip, devaddr, alen, memaddr, length);
|
||||||
#endif
|
#endif
|
||||||
if (ret)
|
if (ret)
|
||||||
return i2c_report_err(ret, I2C_ERR_WRITE);
|
return i2c_report_err(ret, I2C_ERR_WRITE);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Repeated addressing - perform <length> separate
|
||||||
|
* write transactions of one byte each
|
||||||
|
*/
|
||||||
|
while (length-- > 0) {
|
||||||
|
#ifdef CONFIG_DM_I2C
|
||||||
|
i2c_chip->flags |= DM_I2C_CHIP_WR_ADDRESS;
|
||||||
|
ret = dm_i2c_write(dev, devaddr++, memaddr++, 1);
|
||||||
|
#else
|
||||||
|
ret = i2c_write(chip, devaddr++, alen, memaddr++, 1);
|
||||||
|
#endif
|
||||||
|
if (ret)
|
||||||
|
return i2c_report_err(ret, I2C_ERR_WRITE);
|
||||||
/*
|
/*
|
||||||
* No write delay with FRAM devices.
|
* No write delay with FRAM devices.
|
||||||
*/
|
*/
|
||||||
#if !defined(CONFIG_SYS_I2C_FRAM)
|
#if !defined(CONFIG_SYS_I2C_FRAM)
|
||||||
udelay(11000);
|
udelay(11000);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1827,7 +1853,7 @@ static cmd_tbl_t cmd_i2c_sub[] = {
|
||||||
U_BOOT_CMD_MKENT(nm, 2, 1, do_i2c_nm, "", ""),
|
U_BOOT_CMD_MKENT(nm, 2, 1, do_i2c_nm, "", ""),
|
||||||
U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""),
|
U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""),
|
||||||
U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""),
|
U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""),
|
||||||
U_BOOT_CMD_MKENT(write, 5, 0, do_i2c_write, "", ""),
|
U_BOOT_CMD_MKENT(write, 6, 0, do_i2c_write, "", ""),
|
||||||
#ifdef CONFIG_DM_I2C
|
#ifdef CONFIG_DM_I2C
|
||||||
U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""),
|
U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""),
|
||||||
#endif
|
#endif
|
||||||
|
@ -1894,7 +1920,8 @@ static char i2c_help_text[] =
|
||||||
"i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n"
|
"i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n"
|
||||||
"i2c probe [address] - test for and show device(s) on the I2C bus\n"
|
"i2c probe [address] - test for and show device(s) on the I2C bus\n"
|
||||||
"i2c read chip address[.0, .1, .2] length memaddress - read to memory\n"
|
"i2c read chip address[.0, .1, .2] length memaddress - read to memory\n"
|
||||||
"i2c write memaddress chip address[.0, .1, .2] length - write memory to i2c\n"
|
"i2c write memaddress chip address[.0, .1, .2] length [-s] - write memory\n"
|
||||||
|
" to I2C; the -s option selects bulk write in a single transaction\n"
|
||||||
#ifdef CONFIG_DM_I2C
|
#ifdef CONFIG_DM_I2C
|
||||||
"i2c flags chip [flags] - set or get chip flags\n"
|
"i2c flags chip [flags] - set or get chip flags\n"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1906,7 +1933,7 @@ static char i2c_help_text[] =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
U_BOOT_CMD(
|
U_BOOT_CMD(
|
||||||
i2c, 6, 1, do_i2c,
|
i2c, 7, 1, do_i2c,
|
||||||
"I2C sub-system",
|
"I2C sub-system",
|
||||||
i2c_help_text
|
i2c_help_text
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue