12e192b24SSimon Glass /* 22e192b24SSimon Glass * (C) Copyright 2000, 2001 32e192b24SSimon Glass * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 42e192b24SSimon Glass * 52e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 62e192b24SSimon Glass */ 72e192b24SSimon Glass 82e192b24SSimon Glass /* 92e192b24SSimon Glass * Support for read and write access to EEPROM like memory devices. This 102e192b24SSimon Glass * includes regular EEPROM as well as FRAM (ferroelectic nonvolaile RAM). 112e192b24SSimon Glass * FRAM devices read and write data at bus speed. In particular, there is no 122e192b24SSimon Glass * write delay. Also, there is no limit imposed on the number of bytes that can 132e192b24SSimon Glass * be transferred with a single read or write. 142e192b24SSimon Glass * 152e192b24SSimon Glass * Use the following configuration options to ensure no unneeded performance 162e192b24SSimon Glass * degradation (typical for EEPROM) is incured for FRAM memory: 172e192b24SSimon Glass * 182e192b24SSimon Glass * #define CONFIG_SYS_I2C_FRAM 192e192b24SSimon Glass * #undef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 202e192b24SSimon Glass * 212e192b24SSimon Glass */ 222e192b24SSimon Glass 232e192b24SSimon Glass #include <common.h> 242e192b24SSimon Glass #include <config.h> 252e192b24SSimon Glass #include <command.h> 262e192b24SSimon Glass #include <i2c.h> 272e192b24SSimon Glass 282e192b24SSimon Glass #ifndef CONFIG_SYS_I2C_SPEED 292e192b24SSimon Glass #define CONFIG_SYS_I2C_SPEED 50000 302e192b24SSimon Glass #endif 312e192b24SSimon Glass 322e192b24SSimon Glass #ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 332e192b24SSimon Glass #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 0 342e192b24SSimon Glass #endif 352e192b24SSimon Glass 362e192b24SSimon Glass #ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 372e192b24SSimon Glass #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 8 382e192b24SSimon Glass #endif 392e192b24SSimon Glass 40a6e7b774SMario Six #ifndef I2C_RXTX_LEN 41a6e7b774SMario Six #define I2C_RXTX_LEN 128 42a6e7b774SMario Six #endif 43a6e7b774SMario Six 442e192b24SSimon Glass #define EEPROM_PAGE_SIZE (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS) 452e192b24SSimon Glass #define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1)) 462e192b24SSimon Glass 472e192b24SSimon Glass /* 482e192b24SSimon Glass * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is 492e192b24SSimon Glass * 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM. 502e192b24SSimon Glass * 512e192b24SSimon Glass * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is 522e192b24SSimon Glass * 0x00000nxx for EEPROM address selectors and page number at n. 532e192b24SSimon Glass */ 542e192b24SSimon Glass #if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C) 552e192b24SSimon Glass #if !defined(CONFIG_SYS_I2C_EEPROM_ADDR_LEN) || \ 562e192b24SSimon Glass (CONFIG_SYS_I2C_EEPROM_ADDR_LEN < 1) || \ 572e192b24SSimon Glass (CONFIG_SYS_I2C_EEPROM_ADDR_LEN > 2) 582e192b24SSimon Glass #error CONFIG_SYS_I2C_EEPROM_ADDR_LEN must be 1 or 2 592e192b24SSimon Glass #endif 602e192b24SSimon Glass #endif 612e192b24SSimon Glass 622e192b24SSimon Glass __weak int eeprom_write_enable(unsigned dev_addr, int state) 632e192b24SSimon Glass { 642e192b24SSimon Glass return 0; 652e192b24SSimon Glass } 662e192b24SSimon Glass 672e192b24SSimon Glass void eeprom_init(int bus) 682e192b24SSimon Glass { 692e192b24SSimon Glass /* SPI EEPROM */ 702e192b24SSimon Glass #if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) 712e192b24SSimon Glass spi_init_f(); 722e192b24SSimon Glass #endif 732e192b24SSimon Glass 742e192b24SSimon Glass /* I2C EEPROM */ 752636ac65SNikita Kiryanov #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) 762e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) 772e192b24SSimon Glass if (bus >= 0) 782e192b24SSimon Glass i2c_set_bus_num(bus); 792e192b24SSimon Glass #endif 802e192b24SSimon Glass i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 812e192b24SSimon Glass #endif 822e192b24SSimon Glass } 832e192b24SSimon Glass 842e192b24SSimon Glass static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr) 852e192b24SSimon Glass { 862e192b24SSimon Glass unsigned blk_off; 872e192b24SSimon Glass int alen; 882e192b24SSimon Glass 892e192b24SSimon Glass blk_off = offset & 0xff; /* block offset */ 902e192b24SSimon Glass #if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 912e192b24SSimon Glass addr[0] = offset >> 8; /* block number */ 922e192b24SSimon Glass addr[1] = blk_off; /* block offset */ 932e192b24SSimon Glass alen = 2; 942e192b24SSimon Glass #else 952e192b24SSimon Glass addr[0] = offset >> 16; /* block number */ 962e192b24SSimon Glass addr[1] = offset >> 8; /* upper address octet */ 972e192b24SSimon Glass addr[2] = blk_off; /* lower address octet */ 982e192b24SSimon Glass alen = 3; 992e192b24SSimon Glass #endif /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN */ 1002e192b24SSimon Glass 1012e192b24SSimon Glass addr[0] |= dev_addr; /* insert device address */ 1022e192b24SSimon Glass 1032e192b24SSimon Glass return alen; 1042e192b24SSimon Glass } 1052e192b24SSimon Glass 1062e192b24SSimon Glass static int eeprom_len(unsigned offset, unsigned end) 1072e192b24SSimon Glass { 1082e192b24SSimon Glass unsigned len = end - offset; 1092e192b24SSimon Glass 1102e192b24SSimon Glass /* 1112e192b24SSimon Glass * For a FRAM device there is no limit on the number of the 1122e192b24SSimon Glass * bytes that can be ccessed with the single read or write 1132e192b24SSimon Glass * operation. 1142e192b24SSimon Glass */ 1152e192b24SSimon Glass #if !defined(CONFIG_SYS_I2C_FRAM) 1162e192b24SSimon Glass unsigned blk_off = offset & 0xff; 1172e192b24SSimon Glass unsigned maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off); 1182e192b24SSimon Glass 1192e192b24SSimon Glass if (maxlen > I2C_RXTX_LEN) 1202e192b24SSimon Glass maxlen = I2C_RXTX_LEN; 1212e192b24SSimon Glass 1222e192b24SSimon Glass if (len > maxlen) 1232e192b24SSimon Glass len = maxlen; 1242e192b24SSimon Glass #endif 1252e192b24SSimon Glass 1262e192b24SSimon Glass return len; 1272e192b24SSimon Glass } 1282e192b24SSimon Glass 1292e192b24SSimon Glass static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen, 1302e192b24SSimon Glass uchar *buffer, unsigned len, bool read) 1312e192b24SSimon Glass { 1322e192b24SSimon Glass int ret = 0; 1332e192b24SSimon Glass 1342e192b24SSimon Glass /* SPI */ 1352e192b24SSimon Glass #if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) 1362e192b24SSimon Glass if (read) 1372e192b24SSimon Glass spi_read(addr, alen, buffer, len); 1382e192b24SSimon Glass else 1392e192b24SSimon Glass spi_write(addr, alen, buffer, len); 1402e192b24SSimon Glass #else /* I2C */ 1412e192b24SSimon Glass 1422e192b24SSimon Glass #if defined(CONFIG_SYS_I2C_EEPROM_BUS) 1432e192b24SSimon Glass i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS); 1442e192b24SSimon Glass #endif 1452e192b24SSimon Glass 1462e192b24SSimon Glass if (read) 1472e192b24SSimon Glass ret = i2c_read(addr[0], offset, alen - 1, buffer, len); 1482e192b24SSimon Glass else 1492e192b24SSimon Glass ret = i2c_write(addr[0], offset, alen - 1, buffer, len); 1502e192b24SSimon Glass 1512e192b24SSimon Glass if (ret) 1522e192b24SSimon Glass ret = 1; 1532e192b24SSimon Glass #endif 1542e192b24SSimon Glass return ret; 1552e192b24SSimon Glass } 1562e192b24SSimon Glass 1572e192b24SSimon Glass static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer, 1582e192b24SSimon Glass unsigned cnt, bool read) 1592e192b24SSimon Glass { 1602e192b24SSimon Glass unsigned end = offset + cnt; 1612e192b24SSimon Glass unsigned alen, len; 1622e192b24SSimon Glass int rcode = 0; 1632e192b24SSimon Glass uchar addr[3]; 1642e192b24SSimon Glass 1652e192b24SSimon Glass while (offset < end) { 1662e192b24SSimon Glass alen = eeprom_addr(dev_addr, offset, addr); 1672e192b24SSimon Glass 1682e192b24SSimon Glass len = eeprom_len(offset, end); 1692e192b24SSimon Glass 1702e192b24SSimon Glass rcode = eeprom_rw_block(offset, addr, alen, buffer, len, read); 1712e192b24SSimon Glass 1722e192b24SSimon Glass buffer += len; 1732e192b24SSimon Glass offset += len; 1742e192b24SSimon Glass 1752e192b24SSimon Glass if (!read) 1762e192b24SSimon Glass udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); 1772e192b24SSimon Glass } 1782e192b24SSimon Glass 1792e192b24SSimon Glass return rcode; 1802e192b24SSimon Glass } 1812e192b24SSimon Glass 1822e192b24SSimon Glass int eeprom_read(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt) 1832e192b24SSimon Glass { 1842e192b24SSimon Glass /* 1852e192b24SSimon Glass * Read data until done or would cross a page boundary. 1862e192b24SSimon Glass * We must write the address again when changing pages 1872e192b24SSimon Glass * because the next page may be in a different device. 1882e192b24SSimon Glass */ 1892e192b24SSimon Glass return eeprom_rw(dev_addr, offset, buffer, cnt, 1); 1902e192b24SSimon Glass } 1912e192b24SSimon Glass 1922e192b24SSimon Glass int eeprom_write(unsigned dev_addr, unsigned offset, 1932e192b24SSimon Glass uchar *buffer, unsigned cnt) 1942e192b24SSimon Glass { 1952e192b24SSimon Glass int ret; 1962e192b24SSimon Glass 1972e192b24SSimon Glass eeprom_write_enable(dev_addr, 1); 1982e192b24SSimon Glass 1992e192b24SSimon Glass /* 2002e192b24SSimon Glass * Write data until done or would cross a write page boundary. 2012e192b24SSimon Glass * We must write the address again when changing pages 2022e192b24SSimon Glass * because the address counter only increments within a page. 2032e192b24SSimon Glass */ 2042e192b24SSimon Glass ret = eeprom_rw(dev_addr, offset, buffer, cnt, 0); 2052e192b24SSimon Glass 2062e192b24SSimon Glass eeprom_write_enable(dev_addr, 0); 2072e192b24SSimon Glass return ret; 2082e192b24SSimon Glass } 2092e192b24SSimon Glass 210*aa9e6044SNikita Kiryanov #ifdef CONFIG_CMD_EEPROM_LAYOUT 211*aa9e6044SNikita Kiryanov #include <eeprom_layout.h> 212*aa9e6044SNikita Kiryanov 213*aa9e6044SNikita Kiryanov __weak int eeprom_parse_layout_version(char *str) 214*aa9e6044SNikita Kiryanov { 215*aa9e6044SNikita Kiryanov return LAYOUT_VERSION_UNRECOGNIZED; 216*aa9e6044SNikita Kiryanov } 217*aa9e6044SNikita Kiryanov 218*aa9e6044SNikita Kiryanov static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; 219*aa9e6044SNikita Kiryanov 220*aa9e6044SNikita Kiryanov #ifndef CONFIG_EEPROM_LAYOUT_HELP_STRING 221*aa9e6044SNikita Kiryanov #define CONFIG_EEPROM_LAYOUT_HELP_STRING "<not defined>" 222*aa9e6044SNikita Kiryanov #endif 223*aa9e6044SNikita Kiryanov 224*aa9e6044SNikita Kiryanov enum eeprom_action { 225*aa9e6044SNikita Kiryanov EEPROM_PRINT, 226*aa9e6044SNikita Kiryanov EEPROM_UPDATE, 227*aa9e6044SNikita Kiryanov EEPROM_ACTION_INVALID, 228*aa9e6044SNikita Kiryanov }; 229*aa9e6044SNikita Kiryanov 230*aa9e6044SNikita Kiryanov static enum eeprom_action parse_action(char *cmd) 231*aa9e6044SNikita Kiryanov { 232*aa9e6044SNikita Kiryanov if (!strncmp(cmd, "print", 5)) 233*aa9e6044SNikita Kiryanov return EEPROM_PRINT; 234*aa9e6044SNikita Kiryanov if (!strncmp(cmd, "update", 6)) 235*aa9e6044SNikita Kiryanov return EEPROM_UPDATE; 236*aa9e6044SNikita Kiryanov 237*aa9e6044SNikita Kiryanov return EEPROM_ACTION_INVALID; 238*aa9e6044SNikita Kiryanov } 239*aa9e6044SNikita Kiryanov 240*aa9e6044SNikita Kiryanov static int parse_numeric_param(char *str) 241*aa9e6044SNikita Kiryanov { 242*aa9e6044SNikita Kiryanov char *endptr; 243*aa9e6044SNikita Kiryanov int value = simple_strtol(str, &endptr, 16); 244*aa9e6044SNikita Kiryanov 245*aa9e6044SNikita Kiryanov return (*endptr != '\0') ? -1 : value; 246*aa9e6044SNikita Kiryanov } 247*aa9e6044SNikita Kiryanov 248*aa9e6044SNikita Kiryanov static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, 249*aa9e6044SNikita Kiryanov int i2c_addr, int layout_ver, char *key, 250*aa9e6044SNikita Kiryanov char *value) 251*aa9e6044SNikita Kiryanov { 252*aa9e6044SNikita Kiryanov int rcode; 253*aa9e6044SNikita Kiryanov struct eeprom_layout layout; 254*aa9e6044SNikita Kiryanov 255*aa9e6044SNikita Kiryanov if (action == EEPROM_ACTION_INVALID) 256*aa9e6044SNikita Kiryanov return CMD_RET_USAGE; 257*aa9e6044SNikita Kiryanov 258*aa9e6044SNikita Kiryanov eeprom_init(i2c_bus); 259*aa9e6044SNikita Kiryanov rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE); 260*aa9e6044SNikita Kiryanov if (rcode < 0) 261*aa9e6044SNikita Kiryanov return rcode; 262*aa9e6044SNikita Kiryanov 263*aa9e6044SNikita Kiryanov eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE, 264*aa9e6044SNikita Kiryanov layout_ver); 265*aa9e6044SNikita Kiryanov 266*aa9e6044SNikita Kiryanov if (action == EEPROM_PRINT) { 267*aa9e6044SNikita Kiryanov layout.print(&layout); 268*aa9e6044SNikita Kiryanov return 0; 269*aa9e6044SNikita Kiryanov } 270*aa9e6044SNikita Kiryanov 271*aa9e6044SNikita Kiryanov layout.update(&layout, key, value); 272*aa9e6044SNikita Kiryanov 273*aa9e6044SNikita Kiryanov rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE); 274*aa9e6044SNikita Kiryanov 275*aa9e6044SNikita Kiryanov return rcode; 276*aa9e6044SNikita Kiryanov } 277*aa9e6044SNikita Kiryanov 278*aa9e6044SNikita Kiryanov #define NEXT_PARAM(argc, index) { (argc)--; (index)++; } 279*aa9e6044SNikita Kiryanov static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc, 280*aa9e6044SNikita Kiryanov char * const argv[]) 281*aa9e6044SNikita Kiryanov { 282*aa9e6044SNikita Kiryanov int layout_ver = LAYOUT_VERSION_AUTODETECT; 283*aa9e6044SNikita Kiryanov enum eeprom_action action = EEPROM_ACTION_INVALID; 284*aa9e6044SNikita Kiryanov int i2c_bus = -1, i2c_addr = -1, index = 0; 285*aa9e6044SNikita Kiryanov char *field_name = ""; 286*aa9e6044SNikita Kiryanov char *field_value = ""; 287*aa9e6044SNikita Kiryanov 288*aa9e6044SNikita Kiryanov if (argc <= 1) 289*aa9e6044SNikita Kiryanov return CMD_RET_USAGE; 290*aa9e6044SNikita Kiryanov 291*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); /* Skip program name */ 292*aa9e6044SNikita Kiryanov 293*aa9e6044SNikita Kiryanov action = parse_action(argv[index]); 294*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 295*aa9e6044SNikita Kiryanov 296*aa9e6044SNikita Kiryanov if (argc <= 1) 297*aa9e6044SNikita Kiryanov return CMD_RET_USAGE; 298*aa9e6044SNikita Kiryanov 299*aa9e6044SNikita Kiryanov if (!strcmp(argv[index], "-l")) { 300*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 301*aa9e6044SNikita Kiryanov 302*aa9e6044SNikita Kiryanov layout_ver = eeprom_parse_layout_version(argv[index]); 303*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 304*aa9e6044SNikita Kiryanov } 305*aa9e6044SNikita Kiryanov 306*aa9e6044SNikita Kiryanov if (argc <= 1) 307*aa9e6044SNikita Kiryanov return CMD_RET_USAGE; 308*aa9e6044SNikita Kiryanov 309*aa9e6044SNikita Kiryanov i2c_bus = parse_numeric_param(argv[index]); 310*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 311*aa9e6044SNikita Kiryanov 312*aa9e6044SNikita Kiryanov i2c_addr = parse_numeric_param(argv[index]); 313*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 314*aa9e6044SNikita Kiryanov 315*aa9e6044SNikita Kiryanov if (action == EEPROM_PRINT) 316*aa9e6044SNikita Kiryanov goto done; 317*aa9e6044SNikita Kiryanov 318*aa9e6044SNikita Kiryanov if (argc) { 319*aa9e6044SNikita Kiryanov field_name = argv[index]; 320*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 321*aa9e6044SNikita Kiryanov } 322*aa9e6044SNikita Kiryanov 323*aa9e6044SNikita Kiryanov if (argc) { 324*aa9e6044SNikita Kiryanov field_value = argv[index]; 325*aa9e6044SNikita Kiryanov NEXT_PARAM(argc, index); 326*aa9e6044SNikita Kiryanov } 327*aa9e6044SNikita Kiryanov 328*aa9e6044SNikita Kiryanov done: 329*aa9e6044SNikita Kiryanov return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, 330*aa9e6044SNikita Kiryanov field_name, field_value); 331*aa9e6044SNikita Kiryanov } 332*aa9e6044SNikita Kiryanov 333*aa9e6044SNikita Kiryanov #endif 334*aa9e6044SNikita Kiryanov 3352e192b24SSimon Glass static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 3362e192b24SSimon Glass { 3372e192b24SSimon Glass const char *const fmt = 3382e192b24SSimon Glass "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; 3392e192b24SSimon Glass char * const *args = &argv[2]; 3402e192b24SSimon Glass int rcode; 3412e192b24SSimon Glass ulong dev_addr, addr, off, cnt; 3422e192b24SSimon Glass int bus_addr; 3432e192b24SSimon Glass 344*aa9e6044SNikita Kiryanov #ifdef CONFIG_CMD_EEPROM_LAYOUT 345*aa9e6044SNikita Kiryanov if (argc >= 2) { 346*aa9e6044SNikita Kiryanov if (!strcmp(argv[1], "update") || !strcmp(argv[1], "print")) 347*aa9e6044SNikita Kiryanov return do_eeprom_layout(cmdtp, flag, argc, argv); 348*aa9e6044SNikita Kiryanov } 349*aa9e6044SNikita Kiryanov #endif 350*aa9e6044SNikita Kiryanov 3512e192b24SSimon Glass switch (argc) { 3522e192b24SSimon Glass #ifdef CONFIG_SYS_DEF_EEPROM_ADDR 3532e192b24SSimon Glass case 5: 3542e192b24SSimon Glass bus_addr = -1; 3552e192b24SSimon Glass dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR; 3562e192b24SSimon Glass break; 3572e192b24SSimon Glass #endif 3582e192b24SSimon Glass case 6: 3592e192b24SSimon Glass bus_addr = -1; 3602e192b24SSimon Glass dev_addr = simple_strtoul(*args++, NULL, 16); 3612e192b24SSimon Glass break; 3622e192b24SSimon Glass case 7: 3632e192b24SSimon Glass bus_addr = simple_strtoul(*args++, NULL, 16); 3642e192b24SSimon Glass dev_addr = simple_strtoul(*args++, NULL, 16); 3652e192b24SSimon Glass break; 3662e192b24SSimon Glass default: 3672e192b24SSimon Glass return CMD_RET_USAGE; 3682e192b24SSimon Glass } 3692e192b24SSimon Glass 3702e192b24SSimon Glass addr = simple_strtoul(*args++, NULL, 16); 3712e192b24SSimon Glass off = simple_strtoul(*args++, NULL, 16); 3722e192b24SSimon Glass cnt = simple_strtoul(*args++, NULL, 16); 3732e192b24SSimon Glass 3742e192b24SSimon Glass eeprom_init(bus_addr); 3752e192b24SSimon Glass 3762e192b24SSimon Glass if (strcmp(argv[1], "read") == 0) { 3772e192b24SSimon Glass printf(fmt, dev_addr, argv[1], addr, off, cnt); 3782e192b24SSimon Glass 3792e192b24SSimon Glass rcode = eeprom_read(dev_addr, off, (uchar *)addr, cnt); 3802e192b24SSimon Glass 3812e192b24SSimon Glass puts("done\n"); 3822e192b24SSimon Glass return rcode; 3832e192b24SSimon Glass } else if (strcmp(argv[1], "write") == 0) { 3842e192b24SSimon Glass printf(fmt, dev_addr, argv[1], addr, off, cnt); 3852e192b24SSimon Glass 3862e192b24SSimon Glass rcode = eeprom_write(dev_addr, off, (uchar *)addr, cnt); 3872e192b24SSimon Glass 3882e192b24SSimon Glass puts("done\n"); 3892e192b24SSimon Glass return rcode; 3902e192b24SSimon Glass } 3912e192b24SSimon Glass 3922e192b24SSimon Glass return CMD_RET_USAGE; 3932e192b24SSimon Glass } 3942e192b24SSimon Glass 3952e192b24SSimon Glass U_BOOT_CMD( 396*aa9e6044SNikita Kiryanov eeprom, 8, 1, do_eeprom, 3972e192b24SSimon Glass "EEPROM sub-system", 3982e192b24SSimon Glass "read <bus> <devaddr> addr off cnt\n" 3992e192b24SSimon Glass "eeprom write <bus> <devaddr> addr off cnt\n" 4002e192b24SSimon Glass " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" 401*aa9e6044SNikita Kiryanov #ifdef CONFIG_CMD_EEPROM_LAYOUT 402*aa9e6044SNikita Kiryanov "\n" 403*aa9e6044SNikita Kiryanov "eeprom print [-l <layout_version>] bus devaddr\n" 404*aa9e6044SNikita Kiryanov " - Print layout fields and their data in human readable format\n" 405*aa9e6044SNikita Kiryanov "eeprom update [-l <layout_version>] bus devaddr <field_name> <field_value>\n" 406*aa9e6044SNikita Kiryanov " - Update a specific eeprom field with new data.\n" 407*aa9e6044SNikita Kiryanov " The new data must be written in the same human readable format as shown by the print command.\n" 408*aa9e6044SNikita Kiryanov "\n" 409*aa9e6044SNikita Kiryanov "LAYOUT VERSIONS\n" 410*aa9e6044SNikita Kiryanov "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n" 411*aa9e6044SNikita Kiryanov "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n" 412*aa9e6044SNikita Kiryanov "The values which can be provided with the -l option are:\n" 413*aa9e6044SNikita Kiryanov CONFIG_EEPROM_LAYOUT_HELP_STRING"\n" 414*aa9e6044SNikita Kiryanov #endif 4152e192b24SSimon Glass ) 416