12e192b24SSimon Glass /* 22e192b24SSimon Glass * (C) Copyright 2009 32e192b24SSimon Glass * Sergey Kubushyn, himself, ksi@koi8.net 42e192b24SSimon Glass * 52e192b24SSimon Glass * Changes for unified multibus/multiadapter I2C support. 62e192b24SSimon Glass * 72e192b24SSimon Glass * (C) Copyright 2001 82e192b24SSimon Glass * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 92e192b24SSimon Glass * 102e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 112e192b24SSimon Glass */ 122e192b24SSimon Glass 132e192b24SSimon Glass /* 142e192b24SSimon Glass * I2C Functions similar to the standard memory functions. 152e192b24SSimon Glass * 162e192b24SSimon Glass * There are several parameters in many of the commands that bear further 172e192b24SSimon Glass * explanations: 182e192b24SSimon Glass * 192e192b24SSimon Glass * {i2c_chip} is the I2C chip address (the first byte sent on the bus). 202e192b24SSimon Glass * Each I2C chip on the bus has a unique address. On the I2C data bus, 212e192b24SSimon Glass * the address is the upper seven bits and the LSB is the "read/write" 222e192b24SSimon Glass * bit. Note that the {i2c_chip} address specified on the command 232e192b24SSimon Glass * line is not shifted up: e.g. a typical EEPROM memory chip may have 242e192b24SSimon Glass * an I2C address of 0x50, but the data put on the bus will be 0xA0 252e192b24SSimon Glass * for write and 0xA1 for read. This "non shifted" address notation 262e192b24SSimon Glass * matches at least half of the data sheets :-/. 272e192b24SSimon Glass * 282e192b24SSimon Glass * {addr} is the address (or offset) within the chip. Small memory 292e192b24SSimon Glass * chips have 8 bit addresses. Large memory chips have 16 bit 302e192b24SSimon Glass * addresses. Other memory chips have 9, 10, or 11 bit addresses. 312e192b24SSimon Glass * Many non-memory chips have multiple registers and {addr} is used 322e192b24SSimon Glass * as the register index. Some non-memory chips have only one register 332e192b24SSimon Glass * and therefore don't need any {addr} parameter. 342e192b24SSimon Glass * 352e192b24SSimon Glass * The default {addr} parameter is one byte (.1) which works well for 362e192b24SSimon Glass * memories and registers with 8 bits of address space. 372e192b24SSimon Glass * 382e192b24SSimon Glass * You can specify the length of the {addr} field with the optional .0, 392e192b24SSimon Glass * .1, or .2 modifier (similar to the .b, .w, .l modifier). If you are 402e192b24SSimon Glass * manipulating a single register device which doesn't use an address 412e192b24SSimon Glass * field, use "0.0" for the address and the ".0" length field will 422e192b24SSimon Glass * suppress the address in the I2C data stream. This also works for 432e192b24SSimon Glass * successive reads using the I2C auto-incrementing memory pointer. 442e192b24SSimon Glass * 452e192b24SSimon Glass * If you are manipulating a large memory with 2-byte addresses, use 462e192b24SSimon Glass * the .2 address modifier, e.g. 210.2 addresses location 528 (decimal). 472e192b24SSimon Glass * 482e192b24SSimon Glass * Then there are the unfortunate memory chips that spill the most 492e192b24SSimon Glass * significant 1, 2, or 3 bits of address into the chip address byte. 502e192b24SSimon Glass * This effectively makes one chip (logically) look like 2, 4, or 512e192b24SSimon Glass * 8 chips. This is handled (awkwardly) by #defining 522e192b24SSimon Glass * CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW and using the .1 modifier on the 532e192b24SSimon Glass * {addr} field (since .1 is the default, it doesn't actually have to 542e192b24SSimon Glass * be specified). Examples: given a memory chip at I2C chip address 552e192b24SSimon Glass * 0x50, the following would happen... 562e192b24SSimon Glass * i2c md 50 0 10 display 16 bytes starting at 0x000 572e192b24SSimon Glass * On the bus: <S> A0 00 <E> <S> A1 <rd> ... <rd> 582e192b24SSimon Glass * i2c md 50 100 10 display 16 bytes starting at 0x100 592e192b24SSimon Glass * On the bus: <S> A2 00 <E> <S> A3 <rd> ... <rd> 602e192b24SSimon Glass * i2c md 50 210 10 display 16 bytes starting at 0x210 612e192b24SSimon Glass * On the bus: <S> A4 10 <E> <S> A5 <rd> ... <rd> 622e192b24SSimon Glass * This is awfully ugly. It would be nice if someone would think up 632e192b24SSimon Glass * a better way of handling this. 642e192b24SSimon Glass * 652e192b24SSimon Glass * Adapted from cmd_mem.c which is copyright Wolfgang Denk (wd@denx.de). 662e192b24SSimon Glass */ 672e192b24SSimon Glass 682e192b24SSimon Glass #include <common.h> 692e192b24SSimon Glass #include <bootretry.h> 702e192b24SSimon Glass #include <cli.h> 712e192b24SSimon Glass #include <command.h> 722e192b24SSimon Glass #include <console.h> 732e192b24SSimon Glass #include <dm.h> 742e192b24SSimon Glass #include <edid.h> 752e192b24SSimon Glass #include <environment.h> 762e192b24SSimon Glass #include <errno.h> 772e192b24SSimon Glass #include <i2c.h> 782e192b24SSimon Glass #include <malloc.h> 792e192b24SSimon Glass #include <asm/byteorder.h> 802e192b24SSimon Glass #include <linux/compiler.h> 812e192b24SSimon Glass 822e192b24SSimon Glass DECLARE_GLOBAL_DATA_PTR; 832e192b24SSimon Glass 842e192b24SSimon Glass /* Display values from last command. 852e192b24SSimon Glass * Memory modify remembered values are different from display memory. 862e192b24SSimon Glass */ 872e192b24SSimon Glass static uint i2c_dp_last_chip; 882e192b24SSimon Glass static uint i2c_dp_last_addr; 892e192b24SSimon Glass static uint i2c_dp_last_alen; 902e192b24SSimon Glass static uint i2c_dp_last_length = 0x10; 912e192b24SSimon Glass 922e192b24SSimon Glass static uint i2c_mm_last_chip; 932e192b24SSimon Glass static uint i2c_mm_last_addr; 942e192b24SSimon Glass static uint i2c_mm_last_alen; 952e192b24SSimon Glass 962e192b24SSimon Glass /* If only one I2C bus is present, the list of devices to ignore when 972e192b24SSimon Glass * the probe command is issued is represented by a 1D array of addresses. 982e192b24SSimon Glass * When multiple buses are present, the list is an array of bus-address 992e192b24SSimon Glass * pairs. The following macros take care of this */ 1002e192b24SSimon Glass 1012e192b24SSimon Glass #if defined(CONFIG_SYS_I2C_NOPROBES) 1022e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS) 1032e192b24SSimon Glass static struct 1042e192b24SSimon Glass { 1052e192b24SSimon Glass uchar bus; 1062e192b24SSimon Glass uchar addr; 1072e192b24SSimon Glass } i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES; 1082e192b24SSimon Glass #define GET_BUS_NUM i2c_get_bus_num() 1092e192b24SSimon Glass #define COMPARE_BUS(b,i) (i2c_no_probes[(i)].bus == (b)) 1102e192b24SSimon Glass #define COMPARE_ADDR(a,i) (i2c_no_probes[(i)].addr == (a)) 1112e192b24SSimon Glass #define NO_PROBE_ADDR(i) i2c_no_probes[(i)].addr 1122e192b24SSimon Glass #else /* single bus */ 1132e192b24SSimon Glass static uchar i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES; 1142e192b24SSimon Glass #define GET_BUS_NUM 0 1152e192b24SSimon Glass #define COMPARE_BUS(b,i) ((b) == 0) /* Make compiler happy */ 1162e192b24SSimon Glass #define COMPARE_ADDR(a,i) (i2c_no_probes[(i)] == (a)) 1172e192b24SSimon Glass #define NO_PROBE_ADDR(i) i2c_no_probes[(i)] 1182e192b24SSimon Glass #endif /* defined(CONFIG_SYS_I2C) */ 1192e192b24SSimon Glass #endif 1202e192b24SSimon Glass 1212e192b24SSimon Glass #define DISP_LINE_LEN 16 1222e192b24SSimon Glass 1232e192b24SSimon Glass /* 1242e192b24SSimon Glass * Default for driver model is to use the chip's existing address length. 1252e192b24SSimon Glass * For legacy code, this is not stored, so we need to use a suitable 1262e192b24SSimon Glass * default. 1272e192b24SSimon Glass */ 1282e192b24SSimon Glass #ifdef CONFIG_DM_I2C 1292e192b24SSimon Glass #define DEFAULT_ADDR_LEN (-1) 1302e192b24SSimon Glass #else 1312e192b24SSimon Glass #define DEFAULT_ADDR_LEN 1 1322e192b24SSimon Glass #endif 1332e192b24SSimon Glass 1342e192b24SSimon Glass #ifdef CONFIG_DM_I2C 1352e192b24SSimon Glass static struct udevice *i2c_cur_bus; 1362e192b24SSimon Glass 1372e192b24SSimon Glass static int cmd_i2c_set_bus_num(unsigned int busnum) 1382e192b24SSimon Glass { 1392e192b24SSimon Glass struct udevice *bus; 1402e192b24SSimon Glass int ret; 1412e192b24SSimon Glass 1422e192b24SSimon Glass ret = uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus); 1432e192b24SSimon Glass if (ret) { 1442e192b24SSimon Glass debug("%s: No bus %d\n", __func__, busnum); 1452e192b24SSimon Glass return ret; 1462e192b24SSimon Glass } 1472e192b24SSimon Glass i2c_cur_bus = bus; 1482e192b24SSimon Glass 1492e192b24SSimon Glass return 0; 1502e192b24SSimon Glass } 1512e192b24SSimon Glass 1522e192b24SSimon Glass static int i2c_get_cur_bus(struct udevice **busp) 1532e192b24SSimon Glass { 1542e192b24SSimon Glass if (!i2c_cur_bus) { 1552e192b24SSimon Glass puts("No I2C bus selected\n"); 1562e192b24SSimon Glass return -ENODEV; 1572e192b24SSimon Glass } 1582e192b24SSimon Glass *busp = i2c_cur_bus; 1592e192b24SSimon Glass 1602e192b24SSimon Glass return 0; 1612e192b24SSimon Glass } 1622e192b24SSimon Glass 1632e192b24SSimon Glass static int i2c_get_cur_bus_chip(uint chip_addr, struct udevice **devp) 1642e192b24SSimon Glass { 1652e192b24SSimon Glass struct udevice *bus; 1662e192b24SSimon Glass int ret; 1672e192b24SSimon Glass 1682e192b24SSimon Glass ret = i2c_get_cur_bus(&bus); 1692e192b24SSimon Glass if (ret) 1702e192b24SSimon Glass return ret; 1712e192b24SSimon Glass 1722e192b24SSimon Glass return i2c_get_chip(bus, chip_addr, 1, devp); 1732e192b24SSimon Glass } 1742e192b24SSimon Glass 1752e192b24SSimon Glass #endif 1762e192b24SSimon Glass 1772e192b24SSimon Glass /** 1782e192b24SSimon Glass * i2c_init_board() - Board-specific I2C bus init 1792e192b24SSimon Glass * 1802e192b24SSimon Glass * This function is the default no-op implementation of I2C bus 1812e192b24SSimon Glass * initialization. This function can be overriden by board-specific 1822e192b24SSimon Glass * implementation if needed. 1832e192b24SSimon Glass */ 1842e192b24SSimon Glass __weak 1852e192b24SSimon Glass void i2c_init_board(void) 1862e192b24SSimon Glass { 1872e192b24SSimon Glass } 1882e192b24SSimon Glass 1892e192b24SSimon Glass /* TODO: Implement architecture-specific get/set functions */ 1902e192b24SSimon Glass 1912e192b24SSimon Glass /** 1922e192b24SSimon Glass * i2c_get_bus_speed() - Return I2C bus speed 1932e192b24SSimon Glass * 1942e192b24SSimon Glass * This function is the default implementation of function for retrieveing 1952e192b24SSimon Glass * the current I2C bus speed in Hz. 1962e192b24SSimon Glass * 1972e192b24SSimon Glass * A driver implementing runtime switching of I2C bus speed must override 1982e192b24SSimon Glass * this function to report the speed correctly. Simple or legacy drivers 1992e192b24SSimon Glass * can use this fallback. 2002e192b24SSimon Glass * 2012e192b24SSimon Glass * Returns I2C bus speed in Hz. 2022e192b24SSimon Glass */ 2032e192b24SSimon Glass #if !defined(CONFIG_SYS_I2C) && !defined(CONFIG_DM_I2C) 2042e192b24SSimon Glass /* 2052e192b24SSimon Glass * TODO: Implement architecture-specific get/set functions 2062e192b24SSimon Glass * Should go away, if we switched completely to new multibus support 2072e192b24SSimon Glass */ 2082e192b24SSimon Glass __weak 2092e192b24SSimon Glass unsigned int i2c_get_bus_speed(void) 2102e192b24SSimon Glass { 2112e192b24SSimon Glass return CONFIG_SYS_I2C_SPEED; 2122e192b24SSimon Glass } 2132e192b24SSimon Glass 2142e192b24SSimon Glass /** 2152e192b24SSimon Glass * i2c_set_bus_speed() - Configure I2C bus speed 2162e192b24SSimon Glass * @speed: Newly set speed of the I2C bus in Hz 2172e192b24SSimon Glass * 2182e192b24SSimon Glass * This function is the default implementation of function for setting 2192e192b24SSimon Glass * the I2C bus speed in Hz. 2202e192b24SSimon Glass * 2212e192b24SSimon Glass * A driver implementing runtime switching of I2C bus speed must override 2222e192b24SSimon Glass * this function to report the speed correctly. Simple or legacy drivers 2232e192b24SSimon Glass * can use this fallback. 2242e192b24SSimon Glass * 2252e192b24SSimon Glass * Returns zero on success, negative value on error. 2262e192b24SSimon Glass */ 2272e192b24SSimon Glass __weak 2282e192b24SSimon Glass int i2c_set_bus_speed(unsigned int speed) 2292e192b24SSimon Glass { 2302e192b24SSimon Glass if (speed != CONFIG_SYS_I2C_SPEED) 2312e192b24SSimon Glass return -1; 2322e192b24SSimon Glass 2332e192b24SSimon Glass return 0; 2342e192b24SSimon Glass } 2352e192b24SSimon Glass #endif 2362e192b24SSimon Glass 2372e192b24SSimon Glass /** 2382e192b24SSimon Glass * get_alen() - Small parser helper function to get address length 2392e192b24SSimon Glass * 2402e192b24SSimon Glass * Returns the address length. 2412e192b24SSimon Glass */ 2422e192b24SSimon Glass static uint get_alen(char *arg, int default_len) 2432e192b24SSimon Glass { 2442e192b24SSimon Glass int j; 2452e192b24SSimon Glass int alen; 2462e192b24SSimon Glass 2472e192b24SSimon Glass alen = default_len; 2482e192b24SSimon Glass for (j = 0; j < 8; j++) { 2492e192b24SSimon Glass if (arg[j] == '.') { 2502e192b24SSimon Glass alen = arg[j+1] - '0'; 2512e192b24SSimon Glass break; 2522e192b24SSimon Glass } else if (arg[j] == '\0') 2532e192b24SSimon Glass break; 2542e192b24SSimon Glass } 2552e192b24SSimon Glass return alen; 2562e192b24SSimon Glass } 2572e192b24SSimon Glass 2582e192b24SSimon Glass enum i2c_err_op { 2592e192b24SSimon Glass I2C_ERR_READ, 2602e192b24SSimon Glass I2C_ERR_WRITE, 2612e192b24SSimon Glass }; 2622e192b24SSimon Glass 2632e192b24SSimon Glass static int i2c_report_err(int ret, enum i2c_err_op op) 2642e192b24SSimon Glass { 2652e192b24SSimon Glass printf("Error %s the chip: %d\n", 2662e192b24SSimon Glass op == I2C_ERR_READ ? "reading" : "writing", ret); 2672e192b24SSimon Glass 2682e192b24SSimon Glass return CMD_RET_FAILURE; 2692e192b24SSimon Glass } 2702e192b24SSimon Glass 2712e192b24SSimon Glass /** 2722e192b24SSimon Glass * do_i2c_read() - Handle the "i2c read" command-line command 2732e192b24SSimon Glass * @cmdtp: Command data struct pointer 2742e192b24SSimon Glass * @flag: Command flag 2752e192b24SSimon Glass * @argc: Command-line argument count 2762e192b24SSimon Glass * @argv: Array of command-line arguments 2772e192b24SSimon Glass * 2782e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 2792e192b24SSimon Glass * on error. 2802e192b24SSimon Glass * 2812e192b24SSimon Glass * Syntax: 2822e192b24SSimon Glass * i2c read {i2c_chip} {devaddr}{.0, .1, .2} {len} {memaddr} 2832e192b24SSimon Glass */ 2842e192b24SSimon Glass static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 2852e192b24SSimon Glass { 2862e192b24SSimon Glass uint chip; 2872e192b24SSimon Glass uint devaddr, length; 2882e192b24SSimon Glass int alen; 2892e192b24SSimon Glass u_char *memaddr; 2902e192b24SSimon Glass int ret; 2912e192b24SSimon Glass #ifdef CONFIG_DM_I2C 2922e192b24SSimon Glass struct udevice *dev; 2932e192b24SSimon Glass #endif 2942e192b24SSimon Glass 2952e192b24SSimon Glass if (argc != 5) 2962e192b24SSimon Glass return CMD_RET_USAGE; 2972e192b24SSimon Glass 2982e192b24SSimon Glass /* 2992e192b24SSimon Glass * I2C chip address 3002e192b24SSimon Glass */ 3012e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 3022e192b24SSimon Glass 3032e192b24SSimon Glass /* 3042e192b24SSimon Glass * I2C data address within the chip. This can be 1 or 3052e192b24SSimon Glass * 2 bytes long. Some day it might be 3 bytes long :-). 3062e192b24SSimon Glass */ 3072e192b24SSimon Glass devaddr = simple_strtoul(argv[2], NULL, 16); 3082e192b24SSimon Glass alen = get_alen(argv[2], DEFAULT_ADDR_LEN); 3092e192b24SSimon Glass if (alen > 3) 3102e192b24SSimon Glass return CMD_RET_USAGE; 3112e192b24SSimon Glass 3122e192b24SSimon Glass /* 3132e192b24SSimon Glass * Length is the number of objects, not number of bytes. 3142e192b24SSimon Glass */ 3152e192b24SSimon Glass length = simple_strtoul(argv[3], NULL, 16); 3162e192b24SSimon Glass 3172e192b24SSimon Glass /* 3182e192b24SSimon Glass * memaddr is the address where to store things in memory 3192e192b24SSimon Glass */ 3202e192b24SSimon Glass memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16); 3212e192b24SSimon Glass 3222e192b24SSimon Glass #ifdef CONFIG_DM_I2C 3232e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 3242e192b24SSimon Glass if (!ret && alen != -1) 3252e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 3262e192b24SSimon Glass if (!ret) 3272e192b24SSimon Glass ret = dm_i2c_read(dev, devaddr, memaddr, length); 3282e192b24SSimon Glass #else 3292e192b24SSimon Glass ret = i2c_read(chip, devaddr, alen, memaddr, length); 3302e192b24SSimon Glass #endif 3312e192b24SSimon Glass if (ret) 3322e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 3332e192b24SSimon Glass 3342e192b24SSimon Glass return 0; 3352e192b24SSimon Glass } 3362e192b24SSimon Glass 3372e192b24SSimon Glass static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 3382e192b24SSimon Glass { 3392e192b24SSimon Glass uint chip; 3402e192b24SSimon Glass uint devaddr, length; 3412e192b24SSimon Glass int alen; 3422e192b24SSimon Glass u_char *memaddr; 3432e192b24SSimon Glass int ret; 3442e192b24SSimon Glass #ifdef CONFIG_DM_I2C 3452e192b24SSimon Glass struct udevice *dev; 3462e192b24SSimon Glass struct dm_i2c_chip *i2c_chip; 3472e192b24SSimon Glass #endif 3482e192b24SSimon Glass 3492e192b24SSimon Glass if ((argc < 5) || (argc > 6)) 3502e192b24SSimon Glass return cmd_usage(cmdtp); 3512e192b24SSimon Glass 3522e192b24SSimon Glass /* 3532e192b24SSimon Glass * memaddr is the address where to store things in memory 3542e192b24SSimon Glass */ 3552e192b24SSimon Glass memaddr = (u_char *)simple_strtoul(argv[1], NULL, 16); 3562e192b24SSimon Glass 3572e192b24SSimon Glass /* 3582e192b24SSimon Glass * I2C chip address 3592e192b24SSimon Glass */ 3602e192b24SSimon Glass chip = simple_strtoul(argv[2], NULL, 16); 3612e192b24SSimon Glass 3622e192b24SSimon Glass /* 3632e192b24SSimon Glass * I2C data address within the chip. This can be 1 or 3642e192b24SSimon Glass * 2 bytes long. Some day it might be 3 bytes long :-). 3652e192b24SSimon Glass */ 3662e192b24SSimon Glass devaddr = simple_strtoul(argv[3], NULL, 16); 3672e192b24SSimon Glass alen = get_alen(argv[3], DEFAULT_ADDR_LEN); 3682e192b24SSimon Glass if (alen > 3) 3692e192b24SSimon Glass return cmd_usage(cmdtp); 3702e192b24SSimon Glass 3712e192b24SSimon Glass /* 3722e192b24SSimon Glass * Length is the number of bytes. 3732e192b24SSimon Glass */ 3742e192b24SSimon Glass length = simple_strtoul(argv[4], NULL, 16); 3752e192b24SSimon Glass 3762e192b24SSimon Glass #ifdef CONFIG_DM_I2C 3772e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 3782e192b24SSimon Glass if (!ret && alen != -1) 3792e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 3802e192b24SSimon Glass if (ret) 3812e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 3822e192b24SSimon Glass i2c_chip = dev_get_parent_platdata(dev); 3832e192b24SSimon Glass if (!i2c_chip) 3842e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 3852e192b24SSimon Glass #endif 3862e192b24SSimon Glass 3872e192b24SSimon Glass if (argc == 6 && !strcmp(argv[5], "-s")) { 3882e192b24SSimon Glass /* 3892e192b24SSimon Glass * Write all bytes in a single I2C transaction. If the target 3902e192b24SSimon Glass * device is an EEPROM, it is your responsibility to not cross 3912e192b24SSimon Glass * a page boundary. No write delay upon completion, take this 3922e192b24SSimon Glass * into account if linking commands. 3932e192b24SSimon Glass */ 3942e192b24SSimon Glass #ifdef CONFIG_DM_I2C 3952e192b24SSimon Glass i2c_chip->flags &= ~DM_I2C_CHIP_WR_ADDRESS; 3962e192b24SSimon Glass ret = dm_i2c_write(dev, devaddr, memaddr, length); 3972e192b24SSimon Glass #else 3982e192b24SSimon Glass ret = i2c_write(chip, devaddr, alen, memaddr, length); 3992e192b24SSimon Glass #endif 4002e192b24SSimon Glass if (ret) 4012e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 4022e192b24SSimon Glass } else { 4032e192b24SSimon Glass /* 4042e192b24SSimon Glass * Repeated addressing - perform <length> separate 4052e192b24SSimon Glass * write transactions of one byte each 4062e192b24SSimon Glass */ 4072e192b24SSimon Glass while (length-- > 0) { 4082e192b24SSimon Glass #ifdef CONFIG_DM_I2C 4092e192b24SSimon Glass i2c_chip->flags |= DM_I2C_CHIP_WR_ADDRESS; 4102e192b24SSimon Glass ret = dm_i2c_write(dev, devaddr++, memaddr++, 1); 4112e192b24SSimon Glass #else 4122e192b24SSimon Glass ret = i2c_write(chip, devaddr++, alen, memaddr++, 1); 4132e192b24SSimon Glass #endif 4142e192b24SSimon Glass if (ret) 4152e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 4162e192b24SSimon Glass /* 4172e192b24SSimon Glass * No write delay with FRAM devices. 4182e192b24SSimon Glass */ 4192e192b24SSimon Glass #if !defined(CONFIG_SYS_I2C_FRAM) 4202e192b24SSimon Glass udelay(11000); 4212e192b24SSimon Glass #endif 4222e192b24SSimon Glass } 4232e192b24SSimon Glass } 4242e192b24SSimon Glass return 0; 4252e192b24SSimon Glass } 4262e192b24SSimon Glass 4272e192b24SSimon Glass #ifdef CONFIG_DM_I2C 4282e192b24SSimon Glass static int do_i2c_flags(cmd_tbl_t *cmdtp, int flag, int argc, 4292e192b24SSimon Glass char *const argv[]) 4302e192b24SSimon Glass { 4312e192b24SSimon Glass struct udevice *dev; 4322e192b24SSimon Glass uint flags; 4332e192b24SSimon Glass int chip; 4342e192b24SSimon Glass int ret; 4352e192b24SSimon Glass 4362e192b24SSimon Glass if (argc < 2) 4372e192b24SSimon Glass return CMD_RET_USAGE; 4382e192b24SSimon Glass 4392e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 4402e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 4412e192b24SSimon Glass if (ret) 4422e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 4432e192b24SSimon Glass 4442e192b24SSimon Glass if (argc > 2) { 4452e192b24SSimon Glass flags = simple_strtoul(argv[2], NULL, 16); 4462e192b24SSimon Glass ret = i2c_set_chip_flags(dev, flags); 4472e192b24SSimon Glass } else { 4482e192b24SSimon Glass ret = i2c_get_chip_flags(dev, &flags); 4492e192b24SSimon Glass if (!ret) 4502e192b24SSimon Glass printf("%x\n", flags); 4512e192b24SSimon Glass } 4522e192b24SSimon Glass if (ret) 4532e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 4542e192b24SSimon Glass 4552e192b24SSimon Glass return 0; 4562e192b24SSimon Glass } 4572e192b24SSimon Glass 4582e192b24SSimon Glass static int do_i2c_olen(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 4592e192b24SSimon Glass { 4602e192b24SSimon Glass struct udevice *dev; 4612e192b24SSimon Glass uint olen; 4622e192b24SSimon Glass int chip; 4632e192b24SSimon Glass int ret; 4642e192b24SSimon Glass 4652e192b24SSimon Glass if (argc < 2) 4662e192b24SSimon Glass return CMD_RET_USAGE; 4672e192b24SSimon Glass 4682e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 4692e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 4702e192b24SSimon Glass if (ret) 4712e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 4722e192b24SSimon Glass 4732e192b24SSimon Glass if (argc > 2) { 4742e192b24SSimon Glass olen = simple_strtoul(argv[2], NULL, 16); 4752e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, olen); 4762e192b24SSimon Glass } else { 4772e192b24SSimon Glass ret = i2c_get_chip_offset_len(dev); 4782e192b24SSimon Glass if (ret >= 0) { 4792e192b24SSimon Glass printf("%x\n", ret); 4802e192b24SSimon Glass ret = 0; 4812e192b24SSimon Glass } 4822e192b24SSimon Glass } 4832e192b24SSimon Glass if (ret) 4842e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 4852e192b24SSimon Glass 4862e192b24SSimon Glass return 0; 4872e192b24SSimon Glass } 4882e192b24SSimon Glass #endif 4892e192b24SSimon Glass 4902e192b24SSimon Glass /** 4912e192b24SSimon Glass * do_i2c_md() - Handle the "i2c md" command-line command 4922e192b24SSimon Glass * @cmdtp: Command data struct pointer 4932e192b24SSimon Glass * @flag: Command flag 4942e192b24SSimon Glass * @argc: Command-line argument count 4952e192b24SSimon Glass * @argv: Array of command-line arguments 4962e192b24SSimon Glass * 4972e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 4982e192b24SSimon Glass * on error. 4992e192b24SSimon Glass * 5002e192b24SSimon Glass * Syntax: 5012e192b24SSimon Glass * i2c md {i2c_chip} {addr}{.0, .1, .2} {len} 5022e192b24SSimon Glass */ 5032e192b24SSimon Glass static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 5042e192b24SSimon Glass { 5052e192b24SSimon Glass uint chip; 5062e192b24SSimon Glass uint addr, length; 5072e192b24SSimon Glass int alen; 5082e192b24SSimon Glass int j, nbytes, linebytes; 5092e192b24SSimon Glass int ret; 5102e192b24SSimon Glass #ifdef CONFIG_DM_I2C 5112e192b24SSimon Glass struct udevice *dev; 5122e192b24SSimon Glass #endif 5132e192b24SSimon Glass 5142e192b24SSimon Glass /* We use the last specified parameters, unless new ones are 5152e192b24SSimon Glass * entered. 5162e192b24SSimon Glass */ 5172e192b24SSimon Glass chip = i2c_dp_last_chip; 5182e192b24SSimon Glass addr = i2c_dp_last_addr; 5192e192b24SSimon Glass alen = i2c_dp_last_alen; 5202e192b24SSimon Glass length = i2c_dp_last_length; 5212e192b24SSimon Glass 5222e192b24SSimon Glass if (argc < 3) 5232e192b24SSimon Glass return CMD_RET_USAGE; 5242e192b24SSimon Glass 5252e192b24SSimon Glass if ((flag & CMD_FLAG_REPEAT) == 0) { 5262e192b24SSimon Glass /* 5272e192b24SSimon Glass * New command specified. 5282e192b24SSimon Glass */ 5292e192b24SSimon Glass 5302e192b24SSimon Glass /* 5312e192b24SSimon Glass * I2C chip address 5322e192b24SSimon Glass */ 5332e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 5342e192b24SSimon Glass 5352e192b24SSimon Glass /* 5362e192b24SSimon Glass * I2C data address within the chip. This can be 1 or 5372e192b24SSimon Glass * 2 bytes long. Some day it might be 3 bytes long :-). 5382e192b24SSimon Glass */ 5392e192b24SSimon Glass addr = simple_strtoul(argv[2], NULL, 16); 5402e192b24SSimon Glass alen = get_alen(argv[2], DEFAULT_ADDR_LEN); 5412e192b24SSimon Glass if (alen > 3) 5422e192b24SSimon Glass return CMD_RET_USAGE; 5432e192b24SSimon Glass 5442e192b24SSimon Glass /* 5452e192b24SSimon Glass * If another parameter, it is the length to display. 5462e192b24SSimon Glass * Length is the number of objects, not number of bytes. 5472e192b24SSimon Glass */ 5482e192b24SSimon Glass if (argc > 3) 5492e192b24SSimon Glass length = simple_strtoul(argv[3], NULL, 16); 5502e192b24SSimon Glass } 5512e192b24SSimon Glass 5522e192b24SSimon Glass #ifdef CONFIG_DM_I2C 5532e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 5542e192b24SSimon Glass if (!ret && alen != -1) 5552e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 5562e192b24SSimon Glass if (ret) 5572e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 5582e192b24SSimon Glass #endif 5592e192b24SSimon Glass 5602e192b24SSimon Glass /* 5612e192b24SSimon Glass * Print the lines. 5622e192b24SSimon Glass * 5632e192b24SSimon Glass * We buffer all read data, so we can make sure data is read only 5642e192b24SSimon Glass * once. 5652e192b24SSimon Glass */ 5662e192b24SSimon Glass nbytes = length; 5672e192b24SSimon Glass do { 5682e192b24SSimon Glass unsigned char linebuf[DISP_LINE_LEN]; 5692e192b24SSimon Glass unsigned char *cp; 5702e192b24SSimon Glass 5712e192b24SSimon Glass linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; 5722e192b24SSimon Glass 5732e192b24SSimon Glass #ifdef CONFIG_DM_I2C 5742e192b24SSimon Glass ret = dm_i2c_read(dev, addr, linebuf, linebytes); 5752e192b24SSimon Glass #else 5762e192b24SSimon Glass ret = i2c_read(chip, addr, alen, linebuf, linebytes); 5772e192b24SSimon Glass #endif 5782e192b24SSimon Glass if (ret) 5792e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 5802e192b24SSimon Glass else { 5812e192b24SSimon Glass printf("%04x:", addr); 5822e192b24SSimon Glass cp = linebuf; 5832e192b24SSimon Glass for (j=0; j<linebytes; j++) { 5842e192b24SSimon Glass printf(" %02x", *cp++); 5852e192b24SSimon Glass addr++; 5862e192b24SSimon Glass } 5872e192b24SSimon Glass puts (" "); 5882e192b24SSimon Glass cp = linebuf; 5892e192b24SSimon Glass for (j=0; j<linebytes; j++) { 5902e192b24SSimon Glass if ((*cp < 0x20) || (*cp > 0x7e)) 5912e192b24SSimon Glass puts ("."); 5922e192b24SSimon Glass else 5932e192b24SSimon Glass printf("%c", *cp); 5942e192b24SSimon Glass cp++; 5952e192b24SSimon Glass } 5962e192b24SSimon Glass putc ('\n'); 5972e192b24SSimon Glass } 5982e192b24SSimon Glass nbytes -= linebytes; 5992e192b24SSimon Glass } while (nbytes > 0); 6002e192b24SSimon Glass 6012e192b24SSimon Glass i2c_dp_last_chip = chip; 6022e192b24SSimon Glass i2c_dp_last_addr = addr; 6032e192b24SSimon Glass i2c_dp_last_alen = alen; 6042e192b24SSimon Glass i2c_dp_last_length = length; 6052e192b24SSimon Glass 6062e192b24SSimon Glass return 0; 6072e192b24SSimon Glass } 6082e192b24SSimon Glass 6092e192b24SSimon Glass /** 6102e192b24SSimon Glass * do_i2c_mw() - Handle the "i2c mw" command-line command 6112e192b24SSimon Glass * @cmdtp: Command data struct pointer 6122e192b24SSimon Glass * @flag: Command flag 6132e192b24SSimon Glass * @argc: Command-line argument count 6142e192b24SSimon Glass * @argv: Array of command-line arguments 6152e192b24SSimon Glass * 6162e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 6172e192b24SSimon Glass * on error. 6182e192b24SSimon Glass * 6192e192b24SSimon Glass * Syntax: 6202e192b24SSimon Glass * i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}] 6212e192b24SSimon Glass */ 6222e192b24SSimon Glass static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 6232e192b24SSimon Glass { 6242e192b24SSimon Glass uint chip; 6252e192b24SSimon Glass ulong addr; 6262e192b24SSimon Glass int alen; 6272e192b24SSimon Glass uchar byte; 6282e192b24SSimon Glass int count; 6292e192b24SSimon Glass int ret; 6302e192b24SSimon Glass #ifdef CONFIG_DM_I2C 6312e192b24SSimon Glass struct udevice *dev; 6322e192b24SSimon Glass #endif 6332e192b24SSimon Glass 6342e192b24SSimon Glass if ((argc < 4) || (argc > 5)) 6352e192b24SSimon Glass return CMD_RET_USAGE; 6362e192b24SSimon Glass 6372e192b24SSimon Glass /* 6382e192b24SSimon Glass * Chip is always specified. 6392e192b24SSimon Glass */ 6402e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 6412e192b24SSimon Glass 6422e192b24SSimon Glass /* 6432e192b24SSimon Glass * Address is always specified. 6442e192b24SSimon Glass */ 6452e192b24SSimon Glass addr = simple_strtoul(argv[2], NULL, 16); 6462e192b24SSimon Glass alen = get_alen(argv[2], DEFAULT_ADDR_LEN); 6472e192b24SSimon Glass if (alen > 3) 6482e192b24SSimon Glass return CMD_RET_USAGE; 6492e192b24SSimon Glass 6502e192b24SSimon Glass #ifdef CONFIG_DM_I2C 6512e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 6522e192b24SSimon Glass if (!ret && alen != -1) 6532e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 6542e192b24SSimon Glass if (ret) 6552e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 6562e192b24SSimon Glass #endif 6572e192b24SSimon Glass /* 6582e192b24SSimon Glass * Value to write is always specified. 6592e192b24SSimon Glass */ 6602e192b24SSimon Glass byte = simple_strtoul(argv[3], NULL, 16); 6612e192b24SSimon Glass 6622e192b24SSimon Glass /* 6632e192b24SSimon Glass * Optional count 6642e192b24SSimon Glass */ 6652e192b24SSimon Glass if (argc == 5) 6662e192b24SSimon Glass count = simple_strtoul(argv[4], NULL, 16); 6672e192b24SSimon Glass else 6682e192b24SSimon Glass count = 1; 6692e192b24SSimon Glass 6702e192b24SSimon Glass while (count-- > 0) { 6712e192b24SSimon Glass #ifdef CONFIG_DM_I2C 6722e192b24SSimon Glass ret = dm_i2c_write(dev, addr++, &byte, 1); 6732e192b24SSimon Glass #else 6742e192b24SSimon Glass ret = i2c_write(chip, addr++, alen, &byte, 1); 6752e192b24SSimon Glass #endif 6762e192b24SSimon Glass if (ret) 6772e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 6782e192b24SSimon Glass /* 6792e192b24SSimon Glass * Wait for the write to complete. The write can take 6802e192b24SSimon Glass * up to 10mSec (we allow a little more time). 6812e192b24SSimon Glass */ 6822e192b24SSimon Glass /* 6832e192b24SSimon Glass * No write delay with FRAM devices. 6842e192b24SSimon Glass */ 6852e192b24SSimon Glass #if !defined(CONFIG_SYS_I2C_FRAM) 6862e192b24SSimon Glass udelay(11000); 6872e192b24SSimon Glass #endif 6882e192b24SSimon Glass } 6892e192b24SSimon Glass 6902e192b24SSimon Glass return 0; 6912e192b24SSimon Glass } 6922e192b24SSimon Glass 6932e192b24SSimon Glass /** 6942e192b24SSimon Glass * do_i2c_crc() - Handle the "i2c crc32" command-line command 6952e192b24SSimon Glass * @cmdtp: Command data struct pointer 6962e192b24SSimon Glass * @flag: Command flag 6972e192b24SSimon Glass * @argc: Command-line argument count 6982e192b24SSimon Glass * @argv: Array of command-line arguments 6992e192b24SSimon Glass * 7002e192b24SSimon Glass * Calculate a CRC on memory 7012e192b24SSimon Glass * 7022e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 7032e192b24SSimon Glass * on error. 7042e192b24SSimon Glass * 7052e192b24SSimon Glass * Syntax: 7062e192b24SSimon Glass * i2c crc32 {i2c_chip} {addr}{.0, .1, .2} {count} 7072e192b24SSimon Glass */ 7082e192b24SSimon Glass static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 7092e192b24SSimon Glass { 7102e192b24SSimon Glass uint chip; 7112e192b24SSimon Glass ulong addr; 7122e192b24SSimon Glass int alen; 7132e192b24SSimon Glass int count; 7142e192b24SSimon Glass uchar byte; 7152e192b24SSimon Glass ulong crc; 7162e192b24SSimon Glass ulong err; 7172e192b24SSimon Glass int ret = 0; 7182e192b24SSimon Glass #ifdef CONFIG_DM_I2C 7192e192b24SSimon Glass struct udevice *dev; 7202e192b24SSimon Glass #endif 7212e192b24SSimon Glass 7222e192b24SSimon Glass if (argc < 4) 7232e192b24SSimon Glass return CMD_RET_USAGE; 7242e192b24SSimon Glass 7252e192b24SSimon Glass /* 7262e192b24SSimon Glass * Chip is always specified. 7272e192b24SSimon Glass */ 7282e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 7292e192b24SSimon Glass 7302e192b24SSimon Glass /* 7312e192b24SSimon Glass * Address is always specified. 7322e192b24SSimon Glass */ 7332e192b24SSimon Glass addr = simple_strtoul(argv[2], NULL, 16); 7342e192b24SSimon Glass alen = get_alen(argv[2], DEFAULT_ADDR_LEN); 7352e192b24SSimon Glass if (alen > 3) 7362e192b24SSimon Glass return CMD_RET_USAGE; 7372e192b24SSimon Glass 7382e192b24SSimon Glass #ifdef CONFIG_DM_I2C 7392e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 7402e192b24SSimon Glass if (!ret && alen != -1) 7412e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 7422e192b24SSimon Glass if (ret) 7432e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 7442e192b24SSimon Glass #endif 7452e192b24SSimon Glass /* 7462e192b24SSimon Glass * Count is always specified 7472e192b24SSimon Glass */ 7482e192b24SSimon Glass count = simple_strtoul(argv[3], NULL, 16); 7492e192b24SSimon Glass 7502e192b24SSimon Glass printf ("CRC32 for %08lx ... %08lx ==> ", addr, addr + count - 1); 7512e192b24SSimon Glass /* 7522e192b24SSimon Glass * CRC a byte at a time. This is going to be slooow, but hey, the 7532e192b24SSimon Glass * memories are small and slow too so hopefully nobody notices. 7542e192b24SSimon Glass */ 7552e192b24SSimon Glass crc = 0; 7562e192b24SSimon Glass err = 0; 7572e192b24SSimon Glass while (count-- > 0) { 7582e192b24SSimon Glass #ifdef CONFIG_DM_I2C 7592e192b24SSimon Glass ret = dm_i2c_read(dev, addr, &byte, 1); 7602e192b24SSimon Glass #else 7612e192b24SSimon Glass ret = i2c_read(chip, addr, alen, &byte, 1); 7622e192b24SSimon Glass #endif 7632e192b24SSimon Glass if (ret) 7642e192b24SSimon Glass err++; 7652e192b24SSimon Glass crc = crc32 (crc, &byte, 1); 7662e192b24SSimon Glass addr++; 7672e192b24SSimon Glass } 7682e192b24SSimon Glass if (err > 0) 7692e192b24SSimon Glass i2c_report_err(ret, I2C_ERR_READ); 7702e192b24SSimon Glass else 7712e192b24SSimon Glass printf ("%08lx\n", crc); 7722e192b24SSimon Glass 7732e192b24SSimon Glass return 0; 7742e192b24SSimon Glass } 7752e192b24SSimon Glass 7762e192b24SSimon Glass /** 7772e192b24SSimon Glass * mod_i2c_mem() - Handle the "i2c mm" and "i2c nm" command-line command 7782e192b24SSimon Glass * @cmdtp: Command data struct pointer 7792e192b24SSimon Glass * @flag: Command flag 7802e192b24SSimon Glass * @argc: Command-line argument count 7812e192b24SSimon Glass * @argv: Array of command-line arguments 7822e192b24SSimon Glass * 7832e192b24SSimon Glass * Modify memory. 7842e192b24SSimon Glass * 7852e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 7862e192b24SSimon Glass * on error. 7872e192b24SSimon Glass * 7882e192b24SSimon Glass * Syntax: 7892e192b24SSimon Glass * i2c mm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2} 7902e192b24SSimon Glass * i2c nm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2} 7912e192b24SSimon Glass */ 7922e192b24SSimon Glass static int 7932e192b24SSimon Glass mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) 7942e192b24SSimon Glass { 7952e192b24SSimon Glass uint chip; 7962e192b24SSimon Glass ulong addr; 7972e192b24SSimon Glass int alen; 7982e192b24SSimon Glass ulong data; 7992e192b24SSimon Glass int size = 1; 8002e192b24SSimon Glass int nbytes; 8012e192b24SSimon Glass int ret; 8022e192b24SSimon Glass #ifdef CONFIG_DM_I2C 8032e192b24SSimon Glass struct udevice *dev; 8042e192b24SSimon Glass #endif 8052e192b24SSimon Glass 8062e192b24SSimon Glass if (argc != 3) 8072e192b24SSimon Glass return CMD_RET_USAGE; 8082e192b24SSimon Glass 8092e192b24SSimon Glass bootretry_reset_cmd_timeout(); /* got a good command to get here */ 8102e192b24SSimon Glass /* 8112e192b24SSimon Glass * We use the last specified parameters, unless new ones are 8122e192b24SSimon Glass * entered. 8132e192b24SSimon Glass */ 8142e192b24SSimon Glass chip = i2c_mm_last_chip; 8152e192b24SSimon Glass addr = i2c_mm_last_addr; 8162e192b24SSimon Glass alen = i2c_mm_last_alen; 8172e192b24SSimon Glass 8182e192b24SSimon Glass if ((flag & CMD_FLAG_REPEAT) == 0) { 8192e192b24SSimon Glass /* 8202e192b24SSimon Glass * New command specified. Check for a size specification. 8212e192b24SSimon Glass * Defaults to byte if no or incorrect specification. 8222e192b24SSimon Glass */ 8232e192b24SSimon Glass size = cmd_get_data_size(argv[0], 1); 8242e192b24SSimon Glass 8252e192b24SSimon Glass /* 8262e192b24SSimon Glass * Chip is always specified. 8272e192b24SSimon Glass */ 8282e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 8292e192b24SSimon Glass 8302e192b24SSimon Glass /* 8312e192b24SSimon Glass * Address is always specified. 8322e192b24SSimon Glass */ 8332e192b24SSimon Glass addr = simple_strtoul(argv[2], NULL, 16); 8342e192b24SSimon Glass alen = get_alen(argv[2], DEFAULT_ADDR_LEN); 8352e192b24SSimon Glass if (alen > 3) 8362e192b24SSimon Glass return CMD_RET_USAGE; 8372e192b24SSimon Glass } 8382e192b24SSimon Glass 8392e192b24SSimon Glass #ifdef CONFIG_DM_I2C 8402e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 8412e192b24SSimon Glass if (!ret && alen != -1) 8422e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 8432e192b24SSimon Glass if (ret) 8442e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 8452e192b24SSimon Glass #endif 8462e192b24SSimon Glass 8472e192b24SSimon Glass /* 8482e192b24SSimon Glass * Print the address, followed by value. Then accept input for 8492e192b24SSimon Glass * the next value. A non-converted value exits. 8502e192b24SSimon Glass */ 8512e192b24SSimon Glass do { 8522e192b24SSimon Glass printf("%08lx:", addr); 8532e192b24SSimon Glass #ifdef CONFIG_DM_I2C 8542e192b24SSimon Glass ret = dm_i2c_read(dev, addr, (uchar *)&data, size); 8552e192b24SSimon Glass #else 8562e192b24SSimon Glass ret = i2c_read(chip, addr, alen, (uchar *)&data, size); 8572e192b24SSimon Glass #endif 8582e192b24SSimon Glass if (ret) 8592e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 8602e192b24SSimon Glass 8612e192b24SSimon Glass data = cpu_to_be32(data); 8622e192b24SSimon Glass if (size == 1) 8632e192b24SSimon Glass printf(" %02lx", (data >> 24) & 0x000000FF); 8642e192b24SSimon Glass else if (size == 2) 8652e192b24SSimon Glass printf(" %04lx", (data >> 16) & 0x0000FFFF); 8662e192b24SSimon Glass else 8672e192b24SSimon Glass printf(" %08lx", data); 8682e192b24SSimon Glass 8692e192b24SSimon Glass nbytes = cli_readline(" ? "); 8702e192b24SSimon Glass if (nbytes == 0) { 8712e192b24SSimon Glass /* 8722e192b24SSimon Glass * <CR> pressed as only input, don't modify current 8732e192b24SSimon Glass * location and move to next. 8742e192b24SSimon Glass */ 8752e192b24SSimon Glass if (incrflag) 8762e192b24SSimon Glass addr += size; 8772e192b24SSimon Glass nbytes = size; 8782e192b24SSimon Glass /* good enough to not time out */ 8792e192b24SSimon Glass bootretry_reset_cmd_timeout(); 8802e192b24SSimon Glass } 8812e192b24SSimon Glass #ifdef CONFIG_BOOT_RETRY_TIME 8822e192b24SSimon Glass else if (nbytes == -2) 8832e192b24SSimon Glass break; /* timed out, exit the command */ 8842e192b24SSimon Glass #endif 8852e192b24SSimon Glass else { 8862e192b24SSimon Glass char *endp; 8872e192b24SSimon Glass 8882e192b24SSimon Glass data = simple_strtoul(console_buffer, &endp, 16); 8892e192b24SSimon Glass if (size == 1) 8902e192b24SSimon Glass data = data << 24; 8912e192b24SSimon Glass else if (size == 2) 8922e192b24SSimon Glass data = data << 16; 8932e192b24SSimon Glass data = be32_to_cpu(data); 8942e192b24SSimon Glass nbytes = endp - console_buffer; 8952e192b24SSimon Glass if (nbytes) { 8962e192b24SSimon Glass /* 8972e192b24SSimon Glass * good enough to not time out 8982e192b24SSimon Glass */ 8992e192b24SSimon Glass bootretry_reset_cmd_timeout(); 9002e192b24SSimon Glass #ifdef CONFIG_DM_I2C 9012e192b24SSimon Glass ret = dm_i2c_write(dev, addr, (uchar *)&data, 9022e192b24SSimon Glass size); 9032e192b24SSimon Glass #else 9042e192b24SSimon Glass ret = i2c_write(chip, addr, alen, 9052e192b24SSimon Glass (uchar *)&data, size); 9062e192b24SSimon Glass #endif 9072e192b24SSimon Glass if (ret) 9082e192b24SSimon Glass return i2c_report_err(ret, 9092e192b24SSimon Glass I2C_ERR_WRITE); 9102e192b24SSimon Glass #ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 9112e192b24SSimon Glass udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); 9122e192b24SSimon Glass #endif 9132e192b24SSimon Glass if (incrflag) 9142e192b24SSimon Glass addr += size; 9152e192b24SSimon Glass } 9162e192b24SSimon Glass } 9172e192b24SSimon Glass } while (nbytes); 9182e192b24SSimon Glass 9192e192b24SSimon Glass i2c_mm_last_chip = chip; 9202e192b24SSimon Glass i2c_mm_last_addr = addr; 9212e192b24SSimon Glass i2c_mm_last_alen = alen; 9222e192b24SSimon Glass 9232e192b24SSimon Glass return 0; 9242e192b24SSimon Glass } 9252e192b24SSimon Glass 9262e192b24SSimon Glass /** 9272e192b24SSimon Glass * do_i2c_probe() - Handle the "i2c probe" command-line command 9282e192b24SSimon Glass * @cmdtp: Command data struct pointer 9292e192b24SSimon Glass * @flag: Command flag 9302e192b24SSimon Glass * @argc: Command-line argument count 9312e192b24SSimon Glass * @argv: Array of command-line arguments 9322e192b24SSimon Glass * 9332e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 9342e192b24SSimon Glass * on error. 9352e192b24SSimon Glass * 9362e192b24SSimon Glass * Syntax: 9372e192b24SSimon Glass * i2c probe {addr} 9382e192b24SSimon Glass * 9392e192b24SSimon Glass * Returns zero (success) if one or more I2C devices was found 9402e192b24SSimon Glass */ 9412e192b24SSimon Glass static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 9422e192b24SSimon Glass { 9432e192b24SSimon Glass int j; 9442e192b24SSimon Glass int addr = -1; 9452e192b24SSimon Glass int found = 0; 9462e192b24SSimon Glass #if defined(CONFIG_SYS_I2C_NOPROBES) 9472e192b24SSimon Glass int k, skip; 9482e192b24SSimon Glass unsigned int bus = GET_BUS_NUM; 9492e192b24SSimon Glass #endif /* NOPROBES */ 9502e192b24SSimon Glass int ret; 9512e192b24SSimon Glass #ifdef CONFIG_DM_I2C 9522e192b24SSimon Glass struct udevice *bus, *dev; 9532e192b24SSimon Glass 9542e192b24SSimon Glass if (i2c_get_cur_bus(&bus)) 9552e192b24SSimon Glass return CMD_RET_FAILURE; 9562e192b24SSimon Glass #endif 9572e192b24SSimon Glass 9582e192b24SSimon Glass if (argc == 2) 9592e192b24SSimon Glass addr = simple_strtol(argv[1], 0, 16); 9602e192b24SSimon Glass 9612e192b24SSimon Glass puts ("Valid chip addresses:"); 9622e192b24SSimon Glass for (j = 0; j < 128; j++) { 9632e192b24SSimon Glass if ((0 <= addr) && (j != addr)) 9642e192b24SSimon Glass continue; 9652e192b24SSimon Glass 9662e192b24SSimon Glass #if defined(CONFIG_SYS_I2C_NOPROBES) 9672e192b24SSimon Glass skip = 0; 9682e192b24SSimon Glass for (k = 0; k < ARRAY_SIZE(i2c_no_probes); k++) { 9692e192b24SSimon Glass if (COMPARE_BUS(bus, k) && COMPARE_ADDR(j, k)) { 9702e192b24SSimon Glass skip = 1; 9712e192b24SSimon Glass break; 9722e192b24SSimon Glass } 9732e192b24SSimon Glass } 9742e192b24SSimon Glass if (skip) 9752e192b24SSimon Glass continue; 9762e192b24SSimon Glass #endif 9772e192b24SSimon Glass #ifdef CONFIG_DM_I2C 9782e192b24SSimon Glass ret = dm_i2c_probe(bus, j, 0, &dev); 9792e192b24SSimon Glass #else 9802e192b24SSimon Glass ret = i2c_probe(j); 9812e192b24SSimon Glass #endif 9822e192b24SSimon Glass if (ret == 0) { 9832e192b24SSimon Glass printf(" %02X", j); 9842e192b24SSimon Glass found++; 9852e192b24SSimon Glass } 9862e192b24SSimon Glass } 9872e192b24SSimon Glass putc ('\n'); 9882e192b24SSimon Glass 9892e192b24SSimon Glass #if defined(CONFIG_SYS_I2C_NOPROBES) 9902e192b24SSimon Glass puts ("Excluded chip addresses:"); 9912e192b24SSimon Glass for (k = 0; k < ARRAY_SIZE(i2c_no_probes); k++) { 9922e192b24SSimon Glass if (COMPARE_BUS(bus,k)) 9932e192b24SSimon Glass printf(" %02X", NO_PROBE_ADDR(k)); 9942e192b24SSimon Glass } 9952e192b24SSimon Glass putc ('\n'); 9962e192b24SSimon Glass #endif 9972e192b24SSimon Glass 9982e192b24SSimon Glass return (0 == found); 9992e192b24SSimon Glass } 10002e192b24SSimon Glass 10012e192b24SSimon Glass /** 10022e192b24SSimon Glass * do_i2c_loop() - Handle the "i2c loop" command-line command 10032e192b24SSimon Glass * @cmdtp: Command data struct pointer 10042e192b24SSimon Glass * @flag: Command flag 10052e192b24SSimon Glass * @argc: Command-line argument count 10062e192b24SSimon Glass * @argv: Array of command-line arguments 10072e192b24SSimon Glass * 10082e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 10092e192b24SSimon Glass * on error. 10102e192b24SSimon Glass * 10112e192b24SSimon Glass * Syntax: 10122e192b24SSimon Glass * i2c loop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}] 10132e192b24SSimon Glass * {length} - Number of bytes to read 10142e192b24SSimon Glass * {delay} - A DECIMAL number and defaults to 1000 uSec 10152e192b24SSimon Glass */ 10162e192b24SSimon Glass static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 10172e192b24SSimon Glass { 10182e192b24SSimon Glass uint chip; 10192e192b24SSimon Glass int alen; 10202e192b24SSimon Glass uint addr; 10212e192b24SSimon Glass uint length; 10222e192b24SSimon Glass u_char bytes[16]; 10232e192b24SSimon Glass int delay; 10242e192b24SSimon Glass int ret; 10252e192b24SSimon Glass #ifdef CONFIG_DM_I2C 10262e192b24SSimon Glass struct udevice *dev; 10272e192b24SSimon Glass #endif 10282e192b24SSimon Glass 10292e192b24SSimon Glass if (argc < 3) 10302e192b24SSimon Glass return CMD_RET_USAGE; 10312e192b24SSimon Glass 10322e192b24SSimon Glass /* 10332e192b24SSimon Glass * Chip is always specified. 10342e192b24SSimon Glass */ 10352e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 10362e192b24SSimon Glass 10372e192b24SSimon Glass /* 10382e192b24SSimon Glass * Address is always specified. 10392e192b24SSimon Glass */ 10402e192b24SSimon Glass addr = simple_strtoul(argv[2], NULL, 16); 10412e192b24SSimon Glass alen = get_alen(argv[2], DEFAULT_ADDR_LEN); 10422e192b24SSimon Glass if (alen > 3) 10432e192b24SSimon Glass return CMD_RET_USAGE; 10442e192b24SSimon Glass #ifdef CONFIG_DM_I2C 10452e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 10462e192b24SSimon Glass if (!ret && alen != -1) 10472e192b24SSimon Glass ret = i2c_set_chip_offset_len(dev, alen); 10482e192b24SSimon Glass if (ret) 10492e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_WRITE); 10502e192b24SSimon Glass #endif 10512e192b24SSimon Glass 10522e192b24SSimon Glass /* 10532e192b24SSimon Glass * Length is the number of objects, not number of bytes. 10542e192b24SSimon Glass */ 10552e192b24SSimon Glass length = 1; 10562e192b24SSimon Glass length = simple_strtoul(argv[3], NULL, 16); 10572e192b24SSimon Glass if (length > sizeof(bytes)) 10582e192b24SSimon Glass length = sizeof(bytes); 10592e192b24SSimon Glass 10602e192b24SSimon Glass /* 10612e192b24SSimon Glass * The delay time (uSec) is optional. 10622e192b24SSimon Glass */ 10632e192b24SSimon Glass delay = 1000; 10642e192b24SSimon Glass if (argc > 3) 10652e192b24SSimon Glass delay = simple_strtoul(argv[4], NULL, 10); 10662e192b24SSimon Glass /* 10672e192b24SSimon Glass * Run the loop... 10682e192b24SSimon Glass */ 10692e192b24SSimon Glass while (1) { 10702e192b24SSimon Glass #ifdef CONFIG_DM_I2C 10712e192b24SSimon Glass ret = dm_i2c_read(dev, addr, bytes, length); 10722e192b24SSimon Glass #else 10732e192b24SSimon Glass ret = i2c_read(chip, addr, alen, bytes, length); 10742e192b24SSimon Glass #endif 10752e192b24SSimon Glass if (ret) 10762e192b24SSimon Glass i2c_report_err(ret, I2C_ERR_READ); 10772e192b24SSimon Glass udelay(delay); 10782e192b24SSimon Glass } 10792e192b24SSimon Glass 10802e192b24SSimon Glass /* NOTREACHED */ 10812e192b24SSimon Glass return 0; 10822e192b24SSimon Glass } 10832e192b24SSimon Glass 10842e192b24SSimon Glass /* 10852e192b24SSimon Glass * The SDRAM command is separately configured because many 10862e192b24SSimon Glass * (most?) embedded boards don't use SDRAM DIMMs. 10872e192b24SSimon Glass * 10882e192b24SSimon Glass * FIXME: Document and probably move elsewhere! 10892e192b24SSimon Glass */ 10902e192b24SSimon Glass #if defined(CONFIG_CMD_SDRAM) 10912e192b24SSimon Glass static void print_ddr2_tcyc (u_char const b) 10922e192b24SSimon Glass { 10932e192b24SSimon Glass printf ("%d.", (b >> 4) & 0x0F); 10942e192b24SSimon Glass switch (b & 0x0F) { 10952e192b24SSimon Glass case 0x0: 10962e192b24SSimon Glass case 0x1: 10972e192b24SSimon Glass case 0x2: 10982e192b24SSimon Glass case 0x3: 10992e192b24SSimon Glass case 0x4: 11002e192b24SSimon Glass case 0x5: 11012e192b24SSimon Glass case 0x6: 11022e192b24SSimon Glass case 0x7: 11032e192b24SSimon Glass case 0x8: 11042e192b24SSimon Glass case 0x9: 11052e192b24SSimon Glass printf ("%d ns\n", b & 0x0F); 11062e192b24SSimon Glass break; 11072e192b24SSimon Glass case 0xA: 11082e192b24SSimon Glass puts ("25 ns\n"); 11092e192b24SSimon Glass break; 11102e192b24SSimon Glass case 0xB: 11112e192b24SSimon Glass puts ("33 ns\n"); 11122e192b24SSimon Glass break; 11132e192b24SSimon Glass case 0xC: 11142e192b24SSimon Glass puts ("66 ns\n"); 11152e192b24SSimon Glass break; 11162e192b24SSimon Glass case 0xD: 11172e192b24SSimon Glass puts ("75 ns\n"); 11182e192b24SSimon Glass break; 11192e192b24SSimon Glass default: 11202e192b24SSimon Glass puts ("?? ns\n"); 11212e192b24SSimon Glass break; 11222e192b24SSimon Glass } 11232e192b24SSimon Glass } 11242e192b24SSimon Glass 11252e192b24SSimon Glass static void decode_bits (u_char const b, char const *str[], int const do_once) 11262e192b24SSimon Glass { 11272e192b24SSimon Glass u_char mask; 11282e192b24SSimon Glass 11292e192b24SSimon Glass for (mask = 0x80; mask != 0x00; mask >>= 1, ++str) { 11302e192b24SSimon Glass if (b & mask) { 11312e192b24SSimon Glass puts (*str); 11322e192b24SSimon Glass if (do_once) 11332e192b24SSimon Glass return; 11342e192b24SSimon Glass } 11352e192b24SSimon Glass } 11362e192b24SSimon Glass } 11372e192b24SSimon Glass 11382e192b24SSimon Glass /* 11392e192b24SSimon Glass * Syntax: 11402e192b24SSimon Glass * i2c sdram {i2c_chip} 11412e192b24SSimon Glass */ 11422e192b24SSimon Glass static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) 11432e192b24SSimon Glass { 1144*18c4e7f7SMichal Simek enum { unknown, EDO, SDRAM, DDR, DDR2, DDR3, DDR4 } type; 11452e192b24SSimon Glass 11462e192b24SSimon Glass uint chip; 11472e192b24SSimon Glass u_char data[128]; 11482e192b24SSimon Glass u_char cksum; 11492e192b24SSimon Glass int j; 11502e192b24SSimon Glass 11512e192b24SSimon Glass static const char *decode_CAS_DDR2[] = { 11522e192b24SSimon Glass " TBD", " 6", " 5", " 4", " 3", " 2", " TBD", " TBD" 11532e192b24SSimon Glass }; 11542e192b24SSimon Glass 11552e192b24SSimon Glass static const char *decode_CAS_default[] = { 11562e192b24SSimon Glass " TBD", " 7", " 6", " 5", " 4", " 3", " 2", " 1" 11572e192b24SSimon Glass }; 11582e192b24SSimon Glass 11592e192b24SSimon Glass static const char *decode_CS_WE_default[] = { 11602e192b24SSimon Glass " TBD", " 6", " 5", " 4", " 3", " 2", " 1", " 0" 11612e192b24SSimon Glass }; 11622e192b24SSimon Glass 11632e192b24SSimon Glass static const char *decode_byte21_default[] = { 11642e192b24SSimon Glass " TBD (bit 7)\n", 11652e192b24SSimon Glass " Redundant row address\n", 11662e192b24SSimon Glass " Differential clock input\n", 11672e192b24SSimon Glass " Registerd DQMB inputs\n", 11682e192b24SSimon Glass " Buffered DQMB inputs\n", 11692e192b24SSimon Glass " On-card PLL\n", 11702e192b24SSimon Glass " Registered address/control lines\n", 11712e192b24SSimon Glass " Buffered address/control lines\n" 11722e192b24SSimon Glass }; 11732e192b24SSimon Glass 11742e192b24SSimon Glass static const char *decode_byte22_DDR2[] = { 11752e192b24SSimon Glass " TBD (bit 7)\n", 11762e192b24SSimon Glass " TBD (bit 6)\n", 11772e192b24SSimon Glass " TBD (bit 5)\n", 11782e192b24SSimon Glass " TBD (bit 4)\n", 11792e192b24SSimon Glass " TBD (bit 3)\n", 11802e192b24SSimon Glass " Supports partial array self refresh\n", 11812e192b24SSimon Glass " Supports 50 ohm ODT\n", 11822e192b24SSimon Glass " Supports weak driver\n" 11832e192b24SSimon Glass }; 11842e192b24SSimon Glass 11852e192b24SSimon Glass static const char *decode_row_density_DDR2[] = { 11862e192b24SSimon Glass "512 MiB", "256 MiB", "128 MiB", "16 GiB", 11872e192b24SSimon Glass "8 GiB", "4 GiB", "2 GiB", "1 GiB" 11882e192b24SSimon Glass }; 11892e192b24SSimon Glass 11902e192b24SSimon Glass static const char *decode_row_density_default[] = { 11912e192b24SSimon Glass "512 MiB", "256 MiB", "128 MiB", "64 MiB", 11922e192b24SSimon Glass "32 MiB", "16 MiB", "8 MiB", "4 MiB" 11932e192b24SSimon Glass }; 11942e192b24SSimon Glass 11952e192b24SSimon Glass if (argc < 2) 11962e192b24SSimon Glass return CMD_RET_USAGE; 11972e192b24SSimon Glass 11982e192b24SSimon Glass /* 11992e192b24SSimon Glass * Chip is always specified. 12002e192b24SSimon Glass */ 12012e192b24SSimon Glass chip = simple_strtoul (argv[1], NULL, 16); 12022e192b24SSimon Glass 12032e192b24SSimon Glass if (i2c_read (chip, 0, 1, data, sizeof (data)) != 0) { 12042e192b24SSimon Glass puts ("No SDRAM Serial Presence Detect found.\n"); 12052e192b24SSimon Glass return 1; 12062e192b24SSimon Glass } 12072e192b24SSimon Glass 12082e192b24SSimon Glass cksum = 0; 12092e192b24SSimon Glass for (j = 0; j < 63; j++) { 12102e192b24SSimon Glass cksum += data[j]; 12112e192b24SSimon Glass } 12122e192b24SSimon Glass if (cksum != data[63]) { 12132e192b24SSimon Glass printf ("WARNING: Configuration data checksum failure:\n" 12142e192b24SSimon Glass " is 0x%02x, calculated 0x%02x\n", data[63], cksum); 12152e192b24SSimon Glass } 12162e192b24SSimon Glass printf ("SPD data revision %d.%d\n", 12172e192b24SSimon Glass (data[62] >> 4) & 0x0F, data[62] & 0x0F); 12182e192b24SSimon Glass printf ("Bytes used 0x%02X\n", data[0]); 12192e192b24SSimon Glass printf ("Serial memory size 0x%02X\n", 1 << data[1]); 12202e192b24SSimon Glass 12212e192b24SSimon Glass puts ("Memory type "); 12222e192b24SSimon Glass switch (data[2]) { 12232e192b24SSimon Glass case 2: 12242e192b24SSimon Glass type = EDO; 12252e192b24SSimon Glass puts ("EDO\n"); 12262e192b24SSimon Glass break; 12272e192b24SSimon Glass case 4: 12282e192b24SSimon Glass type = SDRAM; 12292e192b24SSimon Glass puts ("SDRAM\n"); 12302e192b24SSimon Glass break; 1231*18c4e7f7SMichal Simek case 7: 1232*18c4e7f7SMichal Simek type = DDR; 1233*18c4e7f7SMichal Simek puts("DDR\n"); 1234*18c4e7f7SMichal Simek break; 12352e192b24SSimon Glass case 8: 12362e192b24SSimon Glass type = DDR2; 12372e192b24SSimon Glass puts ("DDR2\n"); 12382e192b24SSimon Glass break; 1239*18c4e7f7SMichal Simek case 11: 1240*18c4e7f7SMichal Simek type = DDR3; 1241*18c4e7f7SMichal Simek puts("DDR3\n"); 1242*18c4e7f7SMichal Simek break; 1243*18c4e7f7SMichal Simek case 12: 1244*18c4e7f7SMichal Simek type = DDR4; 1245*18c4e7f7SMichal Simek puts("DDR4\n"); 1246*18c4e7f7SMichal Simek break; 12472e192b24SSimon Glass default: 12482e192b24SSimon Glass type = unknown; 12492e192b24SSimon Glass puts ("unknown\n"); 12502e192b24SSimon Glass break; 12512e192b24SSimon Glass } 12522e192b24SSimon Glass 12532e192b24SSimon Glass puts ("Row address bits "); 12542e192b24SSimon Glass if ((data[3] & 0x00F0) == 0) 12552e192b24SSimon Glass printf ("%d\n", data[3] & 0x0F); 12562e192b24SSimon Glass else 12572e192b24SSimon Glass printf ("%d/%d\n", data[3] & 0x0F, (data[3] >> 4) & 0x0F); 12582e192b24SSimon Glass 12592e192b24SSimon Glass puts ("Column address bits "); 12602e192b24SSimon Glass if ((data[4] & 0x00F0) == 0) 12612e192b24SSimon Glass printf ("%d\n", data[4] & 0x0F); 12622e192b24SSimon Glass else 12632e192b24SSimon Glass printf ("%d/%d\n", data[4] & 0x0F, (data[4] >> 4) & 0x0F); 12642e192b24SSimon Glass 12652e192b24SSimon Glass switch (type) { 12662e192b24SSimon Glass case DDR2: 12672e192b24SSimon Glass printf ("Number of ranks %d\n", 12682e192b24SSimon Glass (data[5] & 0x07) + 1); 12692e192b24SSimon Glass break; 12702e192b24SSimon Glass default: 12712e192b24SSimon Glass printf ("Module rows %d\n", data[5]); 12722e192b24SSimon Glass break; 12732e192b24SSimon Glass } 12742e192b24SSimon Glass 12752e192b24SSimon Glass switch (type) { 12762e192b24SSimon Glass case DDR2: 12772e192b24SSimon Glass printf ("Module data width %d bits\n", data[6]); 12782e192b24SSimon Glass break; 12792e192b24SSimon Glass default: 12802e192b24SSimon Glass printf ("Module data width %d bits\n", 12812e192b24SSimon Glass (data[7] << 8) | data[6]); 12822e192b24SSimon Glass break; 12832e192b24SSimon Glass } 12842e192b24SSimon Glass 12852e192b24SSimon Glass puts ("Interface signal levels "); 12862e192b24SSimon Glass switch(data[8]) { 12872e192b24SSimon Glass case 0: puts ("TTL 5.0 V\n"); break; 12882e192b24SSimon Glass case 1: puts ("LVTTL\n"); break; 12892e192b24SSimon Glass case 2: puts ("HSTL 1.5 V\n"); break; 12902e192b24SSimon Glass case 3: puts ("SSTL 3.3 V\n"); break; 12912e192b24SSimon Glass case 4: puts ("SSTL 2.5 V\n"); break; 12922e192b24SSimon Glass case 5: puts ("SSTL 1.8 V\n"); break; 12932e192b24SSimon Glass default: puts ("unknown\n"); break; 12942e192b24SSimon Glass } 12952e192b24SSimon Glass 12962e192b24SSimon Glass switch (type) { 12972e192b24SSimon Glass case DDR2: 12982e192b24SSimon Glass printf ("SDRAM cycle time "); 12992e192b24SSimon Glass print_ddr2_tcyc (data[9]); 13002e192b24SSimon Glass break; 13012e192b24SSimon Glass default: 13022e192b24SSimon Glass printf ("SDRAM cycle time %d.%d ns\n", 13032e192b24SSimon Glass (data[9] >> 4) & 0x0F, data[9] & 0x0F); 13042e192b24SSimon Glass break; 13052e192b24SSimon Glass } 13062e192b24SSimon Glass 13072e192b24SSimon Glass switch (type) { 13082e192b24SSimon Glass case DDR2: 13092e192b24SSimon Glass printf ("SDRAM access time 0.%d%d ns\n", 13102e192b24SSimon Glass (data[10] >> 4) & 0x0F, data[10] & 0x0F); 13112e192b24SSimon Glass break; 13122e192b24SSimon Glass default: 13132e192b24SSimon Glass printf ("SDRAM access time %d.%d ns\n", 13142e192b24SSimon Glass (data[10] >> 4) & 0x0F, data[10] & 0x0F); 13152e192b24SSimon Glass break; 13162e192b24SSimon Glass } 13172e192b24SSimon Glass 13182e192b24SSimon Glass puts ("EDC configuration "); 13192e192b24SSimon Glass switch (data[11]) { 13202e192b24SSimon Glass case 0: puts ("None\n"); break; 13212e192b24SSimon Glass case 1: puts ("Parity\n"); break; 13222e192b24SSimon Glass case 2: puts ("ECC\n"); break; 13232e192b24SSimon Glass default: puts ("unknown\n"); break; 13242e192b24SSimon Glass } 13252e192b24SSimon Glass 13262e192b24SSimon Glass if ((data[12] & 0x80) == 0) 13272e192b24SSimon Glass puts ("No self refresh, rate "); 13282e192b24SSimon Glass else 13292e192b24SSimon Glass puts ("Self refresh, rate "); 13302e192b24SSimon Glass 13312e192b24SSimon Glass switch(data[12] & 0x7F) { 13322e192b24SSimon Glass case 0: puts ("15.625 us\n"); break; 13332e192b24SSimon Glass case 1: puts ("3.9 us\n"); break; 13342e192b24SSimon Glass case 2: puts ("7.8 us\n"); break; 13352e192b24SSimon Glass case 3: puts ("31.3 us\n"); break; 13362e192b24SSimon Glass case 4: puts ("62.5 us\n"); break; 13372e192b24SSimon Glass case 5: puts ("125 us\n"); break; 13382e192b24SSimon Glass default: puts ("unknown\n"); break; 13392e192b24SSimon Glass } 13402e192b24SSimon Glass 13412e192b24SSimon Glass switch (type) { 13422e192b24SSimon Glass case DDR2: 13432e192b24SSimon Glass printf ("SDRAM width (primary) %d\n", data[13]); 13442e192b24SSimon Glass break; 13452e192b24SSimon Glass default: 13462e192b24SSimon Glass printf ("SDRAM width (primary) %d\n", data[13] & 0x7F); 13472e192b24SSimon Glass if ((data[13] & 0x80) != 0) { 13482e192b24SSimon Glass printf (" (second bank) %d\n", 13492e192b24SSimon Glass 2 * (data[13] & 0x7F)); 13502e192b24SSimon Glass } 13512e192b24SSimon Glass break; 13522e192b24SSimon Glass } 13532e192b24SSimon Glass 13542e192b24SSimon Glass switch (type) { 13552e192b24SSimon Glass case DDR2: 13562e192b24SSimon Glass if (data[14] != 0) 13572e192b24SSimon Glass printf ("EDC width %d\n", data[14]); 13582e192b24SSimon Glass break; 13592e192b24SSimon Glass default: 13602e192b24SSimon Glass if (data[14] != 0) { 13612e192b24SSimon Glass printf ("EDC width %d\n", 13622e192b24SSimon Glass data[14] & 0x7F); 13632e192b24SSimon Glass 13642e192b24SSimon Glass if ((data[14] & 0x80) != 0) { 13652e192b24SSimon Glass printf (" (second bank) %d\n", 13662e192b24SSimon Glass 2 * (data[14] & 0x7F)); 13672e192b24SSimon Glass } 13682e192b24SSimon Glass } 13692e192b24SSimon Glass break; 13702e192b24SSimon Glass } 13712e192b24SSimon Glass 13722e192b24SSimon Glass if (DDR2 != type) { 13732e192b24SSimon Glass printf ("Min clock delay, back-to-back random column addresses " 13742e192b24SSimon Glass "%d\n", data[15]); 13752e192b24SSimon Glass } 13762e192b24SSimon Glass 13772e192b24SSimon Glass puts ("Burst length(s) "); 13782e192b24SSimon Glass if (data[16] & 0x80) puts (" Page"); 13792e192b24SSimon Glass if (data[16] & 0x08) puts (" 8"); 13802e192b24SSimon Glass if (data[16] & 0x04) puts (" 4"); 13812e192b24SSimon Glass if (data[16] & 0x02) puts (" 2"); 13822e192b24SSimon Glass if (data[16] & 0x01) puts (" 1"); 13832e192b24SSimon Glass putc ('\n'); 13842e192b24SSimon Glass printf ("Number of banks %d\n", data[17]); 13852e192b24SSimon Glass 13862e192b24SSimon Glass switch (type) { 13872e192b24SSimon Glass case DDR2: 13882e192b24SSimon Glass puts ("CAS latency(s) "); 13892e192b24SSimon Glass decode_bits (data[18], decode_CAS_DDR2, 0); 13902e192b24SSimon Glass putc ('\n'); 13912e192b24SSimon Glass break; 13922e192b24SSimon Glass default: 13932e192b24SSimon Glass puts ("CAS latency(s) "); 13942e192b24SSimon Glass decode_bits (data[18], decode_CAS_default, 0); 13952e192b24SSimon Glass putc ('\n'); 13962e192b24SSimon Glass break; 13972e192b24SSimon Glass } 13982e192b24SSimon Glass 13992e192b24SSimon Glass if (DDR2 != type) { 14002e192b24SSimon Glass puts ("CS latency(s) "); 14012e192b24SSimon Glass decode_bits (data[19], decode_CS_WE_default, 0); 14022e192b24SSimon Glass putc ('\n'); 14032e192b24SSimon Glass } 14042e192b24SSimon Glass 14052e192b24SSimon Glass if (DDR2 != type) { 14062e192b24SSimon Glass puts ("WE latency(s) "); 14072e192b24SSimon Glass decode_bits (data[20], decode_CS_WE_default, 0); 14082e192b24SSimon Glass putc ('\n'); 14092e192b24SSimon Glass } 14102e192b24SSimon Glass 14112e192b24SSimon Glass switch (type) { 14122e192b24SSimon Glass case DDR2: 14132e192b24SSimon Glass puts ("Module attributes:\n"); 14142e192b24SSimon Glass if (data[21] & 0x80) 14152e192b24SSimon Glass puts (" TBD (bit 7)\n"); 14162e192b24SSimon Glass if (data[21] & 0x40) 14172e192b24SSimon Glass puts (" Analysis probe installed\n"); 14182e192b24SSimon Glass if (data[21] & 0x20) 14192e192b24SSimon Glass puts (" TBD (bit 5)\n"); 14202e192b24SSimon Glass if (data[21] & 0x10) 14212e192b24SSimon Glass puts (" FET switch external enable\n"); 14222e192b24SSimon Glass printf (" %d PLLs on DIMM\n", (data[21] >> 2) & 0x03); 14232e192b24SSimon Glass if (data[20] & 0x11) { 14242e192b24SSimon Glass printf (" %d active registers on DIMM\n", 14252e192b24SSimon Glass (data[21] & 0x03) + 1); 14262e192b24SSimon Glass } 14272e192b24SSimon Glass break; 14282e192b24SSimon Glass default: 14292e192b24SSimon Glass puts ("Module attributes:\n"); 14302e192b24SSimon Glass if (!data[21]) 14312e192b24SSimon Glass puts (" (none)\n"); 14322e192b24SSimon Glass else 14332e192b24SSimon Glass decode_bits (data[21], decode_byte21_default, 0); 14342e192b24SSimon Glass break; 14352e192b24SSimon Glass } 14362e192b24SSimon Glass 14372e192b24SSimon Glass switch (type) { 14382e192b24SSimon Glass case DDR2: 14392e192b24SSimon Glass decode_bits (data[22], decode_byte22_DDR2, 0); 14402e192b24SSimon Glass break; 14412e192b24SSimon Glass default: 14422e192b24SSimon Glass puts ("Device attributes:\n"); 14432e192b24SSimon Glass if (data[22] & 0x80) puts (" TBD (bit 7)\n"); 14442e192b24SSimon Glass if (data[22] & 0x40) puts (" TBD (bit 6)\n"); 14452e192b24SSimon Glass if (data[22] & 0x20) puts (" Upper Vcc tolerance 5%\n"); 14462e192b24SSimon Glass else puts (" Upper Vcc tolerance 10%\n"); 14472e192b24SSimon Glass if (data[22] & 0x10) puts (" Lower Vcc tolerance 5%\n"); 14482e192b24SSimon Glass else puts (" Lower Vcc tolerance 10%\n"); 14492e192b24SSimon Glass if (data[22] & 0x08) puts (" Supports write1/read burst\n"); 14502e192b24SSimon Glass if (data[22] & 0x04) puts (" Supports precharge all\n"); 14512e192b24SSimon Glass if (data[22] & 0x02) puts (" Supports auto precharge\n"); 14522e192b24SSimon Glass if (data[22] & 0x01) puts (" Supports early RAS# precharge\n"); 14532e192b24SSimon Glass break; 14542e192b24SSimon Glass } 14552e192b24SSimon Glass 14562e192b24SSimon Glass switch (type) { 14572e192b24SSimon Glass case DDR2: 14582e192b24SSimon Glass printf ("SDRAM cycle time (2nd highest CAS latency) "); 14592e192b24SSimon Glass print_ddr2_tcyc (data[23]); 14602e192b24SSimon Glass break; 14612e192b24SSimon Glass default: 14622e192b24SSimon Glass printf ("SDRAM cycle time (2nd highest CAS latency) %d." 14632e192b24SSimon Glass "%d ns\n", (data[23] >> 4) & 0x0F, data[23] & 0x0F); 14642e192b24SSimon Glass break; 14652e192b24SSimon Glass } 14662e192b24SSimon Glass 14672e192b24SSimon Glass switch (type) { 14682e192b24SSimon Glass case DDR2: 14692e192b24SSimon Glass printf ("SDRAM access from clock (2nd highest CAS latency) 0." 14702e192b24SSimon Glass "%d%d ns\n", (data[24] >> 4) & 0x0F, data[24] & 0x0F); 14712e192b24SSimon Glass break; 14722e192b24SSimon Glass default: 14732e192b24SSimon Glass printf ("SDRAM access from clock (2nd highest CAS latency) %d." 14742e192b24SSimon Glass "%d ns\n", (data[24] >> 4) & 0x0F, data[24] & 0x0F); 14752e192b24SSimon Glass break; 14762e192b24SSimon Glass } 14772e192b24SSimon Glass 14782e192b24SSimon Glass switch (type) { 14792e192b24SSimon Glass case DDR2: 14802e192b24SSimon Glass printf ("SDRAM cycle time (3rd highest CAS latency) "); 14812e192b24SSimon Glass print_ddr2_tcyc (data[25]); 14822e192b24SSimon Glass break; 14832e192b24SSimon Glass default: 14842e192b24SSimon Glass printf ("SDRAM cycle time (3rd highest CAS latency) %d." 14852e192b24SSimon Glass "%d ns\n", (data[25] >> 4) & 0x0F, data[25] & 0x0F); 14862e192b24SSimon Glass break; 14872e192b24SSimon Glass } 14882e192b24SSimon Glass 14892e192b24SSimon Glass switch (type) { 14902e192b24SSimon Glass case DDR2: 14912e192b24SSimon Glass printf ("SDRAM access from clock (3rd highest CAS latency) 0." 14922e192b24SSimon Glass "%d%d ns\n", (data[26] >> 4) & 0x0F, data[26] & 0x0F); 14932e192b24SSimon Glass break; 14942e192b24SSimon Glass default: 14952e192b24SSimon Glass printf ("SDRAM access from clock (3rd highest CAS latency) %d." 14962e192b24SSimon Glass "%d ns\n", (data[26] >> 4) & 0x0F, data[26] & 0x0F); 14972e192b24SSimon Glass break; 14982e192b24SSimon Glass } 14992e192b24SSimon Glass 15002e192b24SSimon Glass switch (type) { 15012e192b24SSimon Glass case DDR2: 15022e192b24SSimon Glass printf ("Minimum row precharge %d.%02d ns\n", 15032e192b24SSimon Glass (data[27] >> 2) & 0x3F, 25 * (data[27] & 0x03)); 15042e192b24SSimon Glass break; 15052e192b24SSimon Glass default: 15062e192b24SSimon Glass printf ("Minimum row precharge %d ns\n", data[27]); 15072e192b24SSimon Glass break; 15082e192b24SSimon Glass } 15092e192b24SSimon Glass 15102e192b24SSimon Glass switch (type) { 15112e192b24SSimon Glass case DDR2: 15122e192b24SSimon Glass printf ("Row active to row active min %d.%02d ns\n", 15132e192b24SSimon Glass (data[28] >> 2) & 0x3F, 25 * (data[28] & 0x03)); 15142e192b24SSimon Glass break; 15152e192b24SSimon Glass default: 15162e192b24SSimon Glass printf ("Row active to row active min %d ns\n", data[28]); 15172e192b24SSimon Glass break; 15182e192b24SSimon Glass } 15192e192b24SSimon Glass 15202e192b24SSimon Glass switch (type) { 15212e192b24SSimon Glass case DDR2: 15222e192b24SSimon Glass printf ("RAS to CAS delay min %d.%02d ns\n", 15232e192b24SSimon Glass (data[29] >> 2) & 0x3F, 25 * (data[29] & 0x03)); 15242e192b24SSimon Glass break; 15252e192b24SSimon Glass default: 15262e192b24SSimon Glass printf ("RAS to CAS delay min %d ns\n", data[29]); 15272e192b24SSimon Glass break; 15282e192b24SSimon Glass } 15292e192b24SSimon Glass 15302e192b24SSimon Glass printf ("Minimum RAS pulse width %d ns\n", data[30]); 15312e192b24SSimon Glass 15322e192b24SSimon Glass switch (type) { 15332e192b24SSimon Glass case DDR2: 15342e192b24SSimon Glass puts ("Density of each row "); 15352e192b24SSimon Glass decode_bits (data[31], decode_row_density_DDR2, 1); 15362e192b24SSimon Glass putc ('\n'); 15372e192b24SSimon Glass break; 15382e192b24SSimon Glass default: 15392e192b24SSimon Glass puts ("Density of each row "); 15402e192b24SSimon Glass decode_bits (data[31], decode_row_density_default, 1); 15412e192b24SSimon Glass putc ('\n'); 15422e192b24SSimon Glass break; 15432e192b24SSimon Glass } 15442e192b24SSimon Glass 15452e192b24SSimon Glass switch (type) { 15462e192b24SSimon Glass case DDR2: 15472e192b24SSimon Glass puts ("Command and Address setup "); 15482e192b24SSimon Glass if (data[32] >= 0xA0) { 15492e192b24SSimon Glass printf ("1.%d%d ns\n", 15502e192b24SSimon Glass ((data[32] >> 4) & 0x0F) - 10, data[32] & 0x0F); 15512e192b24SSimon Glass } else { 15522e192b24SSimon Glass printf ("0.%d%d ns\n", 15532e192b24SSimon Glass ((data[32] >> 4) & 0x0F), data[32] & 0x0F); 15542e192b24SSimon Glass } 15552e192b24SSimon Glass break; 15562e192b24SSimon Glass default: 15572e192b24SSimon Glass printf ("Command and Address setup %c%d.%d ns\n", 15582e192b24SSimon Glass (data[32] & 0x80) ? '-' : '+', 15592e192b24SSimon Glass (data[32] >> 4) & 0x07, data[32] & 0x0F); 15602e192b24SSimon Glass break; 15612e192b24SSimon Glass } 15622e192b24SSimon Glass 15632e192b24SSimon Glass switch (type) { 15642e192b24SSimon Glass case DDR2: 15652e192b24SSimon Glass puts ("Command and Address hold "); 15662e192b24SSimon Glass if (data[33] >= 0xA0) { 15672e192b24SSimon Glass printf ("1.%d%d ns\n", 15682e192b24SSimon Glass ((data[33] >> 4) & 0x0F) - 10, data[33] & 0x0F); 15692e192b24SSimon Glass } else { 15702e192b24SSimon Glass printf ("0.%d%d ns\n", 15712e192b24SSimon Glass ((data[33] >> 4) & 0x0F), data[33] & 0x0F); 15722e192b24SSimon Glass } 15732e192b24SSimon Glass break; 15742e192b24SSimon Glass default: 15752e192b24SSimon Glass printf ("Command and Address hold %c%d.%d ns\n", 15762e192b24SSimon Glass (data[33] & 0x80) ? '-' : '+', 15772e192b24SSimon Glass (data[33] >> 4) & 0x07, data[33] & 0x0F); 15782e192b24SSimon Glass break; 15792e192b24SSimon Glass } 15802e192b24SSimon Glass 15812e192b24SSimon Glass switch (type) { 15822e192b24SSimon Glass case DDR2: 15832e192b24SSimon Glass printf ("Data signal input setup 0.%d%d ns\n", 15842e192b24SSimon Glass (data[34] >> 4) & 0x0F, data[34] & 0x0F); 15852e192b24SSimon Glass break; 15862e192b24SSimon Glass default: 15872e192b24SSimon Glass printf ("Data signal input setup %c%d.%d ns\n", 15882e192b24SSimon Glass (data[34] & 0x80) ? '-' : '+', 15892e192b24SSimon Glass (data[34] >> 4) & 0x07, data[34] & 0x0F); 15902e192b24SSimon Glass break; 15912e192b24SSimon Glass } 15922e192b24SSimon Glass 15932e192b24SSimon Glass switch (type) { 15942e192b24SSimon Glass case DDR2: 15952e192b24SSimon Glass printf ("Data signal input hold 0.%d%d ns\n", 15962e192b24SSimon Glass (data[35] >> 4) & 0x0F, data[35] & 0x0F); 15972e192b24SSimon Glass break; 15982e192b24SSimon Glass default: 15992e192b24SSimon Glass printf ("Data signal input hold %c%d.%d ns\n", 16002e192b24SSimon Glass (data[35] & 0x80) ? '-' : '+', 16012e192b24SSimon Glass (data[35] >> 4) & 0x07, data[35] & 0x0F); 16022e192b24SSimon Glass break; 16032e192b24SSimon Glass } 16042e192b24SSimon Glass 16052e192b24SSimon Glass puts ("Manufacturer's JEDEC ID "); 16062e192b24SSimon Glass for (j = 64; j <= 71; j++) 16072e192b24SSimon Glass printf ("%02X ", data[j]); 16082e192b24SSimon Glass putc ('\n'); 16092e192b24SSimon Glass printf ("Manufacturing Location %02X\n", data[72]); 16102e192b24SSimon Glass puts ("Manufacturer's Part Number "); 16112e192b24SSimon Glass for (j = 73; j <= 90; j++) 16122e192b24SSimon Glass printf ("%02X ", data[j]); 16132e192b24SSimon Glass putc ('\n'); 16142e192b24SSimon Glass printf ("Revision Code %02X %02X\n", data[91], data[92]); 16152e192b24SSimon Glass printf ("Manufacturing Date %02X %02X\n", data[93], data[94]); 16162e192b24SSimon Glass puts ("Assembly Serial Number "); 16172e192b24SSimon Glass for (j = 95; j <= 98; j++) 16182e192b24SSimon Glass printf ("%02X ", data[j]); 16192e192b24SSimon Glass putc ('\n'); 16202e192b24SSimon Glass 16212e192b24SSimon Glass if (DDR2 != type) { 16222e192b24SSimon Glass printf ("Speed rating PC%d\n", 16232e192b24SSimon Glass data[126] == 0x66 ? 66 : data[126]); 16242e192b24SSimon Glass } 16252e192b24SSimon Glass return 0; 16262e192b24SSimon Glass } 16272e192b24SSimon Glass #endif 16282e192b24SSimon Glass 16292e192b24SSimon Glass /* 16302e192b24SSimon Glass * Syntax: 16312e192b24SSimon Glass * i2c edid {i2c_chip} 16322e192b24SSimon Glass */ 16332e192b24SSimon Glass #if defined(CONFIG_I2C_EDID) 16342e192b24SSimon Glass int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 16352e192b24SSimon Glass { 16362e192b24SSimon Glass uint chip; 16372e192b24SSimon Glass struct edid1_info edid; 16382e192b24SSimon Glass int ret; 16392e192b24SSimon Glass #ifdef CONFIG_DM_I2C 16402e192b24SSimon Glass struct udevice *dev; 16412e192b24SSimon Glass #endif 16422e192b24SSimon Glass 16432e192b24SSimon Glass if (argc < 2) { 16442e192b24SSimon Glass cmd_usage(cmdtp); 16452e192b24SSimon Glass return 1; 16462e192b24SSimon Glass } 16472e192b24SSimon Glass 16482e192b24SSimon Glass chip = simple_strtoul(argv[1], NULL, 16); 16492e192b24SSimon Glass #ifdef CONFIG_DM_I2C 16502e192b24SSimon Glass ret = i2c_get_cur_bus_chip(chip, &dev); 16512e192b24SSimon Glass if (!ret) 16522e192b24SSimon Glass ret = dm_i2c_read(dev, 0, (uchar *)&edid, sizeof(edid)); 16532e192b24SSimon Glass #else 16542e192b24SSimon Glass ret = i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)); 16552e192b24SSimon Glass #endif 16562e192b24SSimon Glass if (ret) 16572e192b24SSimon Glass return i2c_report_err(ret, I2C_ERR_READ); 16582e192b24SSimon Glass 16592e192b24SSimon Glass if (edid_check_info(&edid)) { 16602e192b24SSimon Glass puts("Content isn't valid EDID.\n"); 16612e192b24SSimon Glass return 1; 16622e192b24SSimon Glass } 16632e192b24SSimon Glass 16642e192b24SSimon Glass edid_print_info(&edid); 16652e192b24SSimon Glass return 0; 16662e192b24SSimon Glass 16672e192b24SSimon Glass } 16682e192b24SSimon Glass #endif /* CONFIG_I2C_EDID */ 16692e192b24SSimon Glass 16702e192b24SSimon Glass #ifdef CONFIG_DM_I2C 16712e192b24SSimon Glass static void show_bus(struct udevice *bus) 16722e192b24SSimon Glass { 16732e192b24SSimon Glass struct udevice *dev; 16742e192b24SSimon Glass 16752e192b24SSimon Glass printf("Bus %d:\t%s", bus->req_seq, bus->name); 16762e192b24SSimon Glass if (device_active(bus)) 16772e192b24SSimon Glass printf(" (active %d)", bus->seq); 16782e192b24SSimon Glass printf("\n"); 16792e192b24SSimon Glass for (device_find_first_child(bus, &dev); 16802e192b24SSimon Glass dev; 16812e192b24SSimon Glass device_find_next_child(&dev)) { 16822e192b24SSimon Glass struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); 16832e192b24SSimon Glass 16842e192b24SSimon Glass printf(" %02x: %s, offset len %x, flags %x\n", 16852e192b24SSimon Glass chip->chip_addr, dev->name, chip->offset_len, 16862e192b24SSimon Glass chip->flags); 16872e192b24SSimon Glass } 16882e192b24SSimon Glass } 16892e192b24SSimon Glass #endif 16902e192b24SSimon Glass 16912e192b24SSimon Glass /** 16922e192b24SSimon Glass * do_i2c_show_bus() - Handle the "i2c bus" command-line command 16932e192b24SSimon Glass * @cmdtp: Command data struct pointer 16942e192b24SSimon Glass * @flag: Command flag 16952e192b24SSimon Glass * @argc: Command-line argument count 16962e192b24SSimon Glass * @argv: Array of command-line arguments 16972e192b24SSimon Glass * 16982e192b24SSimon Glass * Returns zero always. 16992e192b24SSimon Glass */ 17002e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) 17012e192b24SSimon Glass static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, 17022e192b24SSimon Glass char * const argv[]) 17032e192b24SSimon Glass { 17042e192b24SSimon Glass if (argc == 1) { 17052e192b24SSimon Glass /* show all busses */ 17062e192b24SSimon Glass #ifdef CONFIG_DM_I2C 17072e192b24SSimon Glass struct udevice *bus; 17082e192b24SSimon Glass struct uclass *uc; 17092e192b24SSimon Glass int ret; 17102e192b24SSimon Glass 17112e192b24SSimon Glass ret = uclass_get(UCLASS_I2C, &uc); 17122e192b24SSimon Glass if (ret) 17132e192b24SSimon Glass return CMD_RET_FAILURE; 17142e192b24SSimon Glass uclass_foreach_dev(bus, uc) 17152e192b24SSimon Glass show_bus(bus); 17162e192b24SSimon Glass #else 17172e192b24SSimon Glass int i; 17182e192b24SSimon Glass 17192e192b24SSimon Glass for (i = 0; i < CONFIG_SYS_NUM_I2C_BUSES; i++) { 17202e192b24SSimon Glass printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name); 17212e192b24SSimon Glass #ifndef CONFIG_SYS_I2C_DIRECT_BUS 17222e192b24SSimon Glass int j; 17232e192b24SSimon Glass 17242e192b24SSimon Glass for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) { 17252e192b24SSimon Glass if (i2c_bus[i].next_hop[j].chip == 0) 17262e192b24SSimon Glass break; 17272e192b24SSimon Glass printf("->%s@0x%2x:%d", 17282e192b24SSimon Glass i2c_bus[i].next_hop[j].mux.name, 17292e192b24SSimon Glass i2c_bus[i].next_hop[j].chip, 17302e192b24SSimon Glass i2c_bus[i].next_hop[j].channel); 17312e192b24SSimon Glass } 17322e192b24SSimon Glass #endif 17332e192b24SSimon Glass printf("\n"); 17342e192b24SSimon Glass } 17352e192b24SSimon Glass #endif 17362e192b24SSimon Glass } else { 17372e192b24SSimon Glass int i; 17382e192b24SSimon Glass 17392e192b24SSimon Glass /* show specific bus */ 17402e192b24SSimon Glass i = simple_strtoul(argv[1], NULL, 10); 17412e192b24SSimon Glass #ifdef CONFIG_DM_I2C 17422e192b24SSimon Glass struct udevice *bus; 17432e192b24SSimon Glass int ret; 17442e192b24SSimon Glass 17452e192b24SSimon Glass ret = uclass_get_device_by_seq(UCLASS_I2C, i, &bus); 17462e192b24SSimon Glass if (ret) { 17472e192b24SSimon Glass printf("Invalid bus %d: err=%d\n", i, ret); 17482e192b24SSimon Glass return CMD_RET_FAILURE; 17492e192b24SSimon Glass } 17502e192b24SSimon Glass show_bus(bus); 17512e192b24SSimon Glass #else 17522e192b24SSimon Glass if (i >= CONFIG_SYS_NUM_I2C_BUSES) { 17532e192b24SSimon Glass printf("Invalid bus %d\n", i); 17542e192b24SSimon Glass return -1; 17552e192b24SSimon Glass } 17562e192b24SSimon Glass printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name); 17572e192b24SSimon Glass #ifndef CONFIG_SYS_I2C_DIRECT_BUS 17582e192b24SSimon Glass int j; 17592e192b24SSimon Glass for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) { 17602e192b24SSimon Glass if (i2c_bus[i].next_hop[j].chip == 0) 17612e192b24SSimon Glass break; 17622e192b24SSimon Glass printf("->%s@0x%2x:%d", 17632e192b24SSimon Glass i2c_bus[i].next_hop[j].mux.name, 17642e192b24SSimon Glass i2c_bus[i].next_hop[j].chip, 17652e192b24SSimon Glass i2c_bus[i].next_hop[j].channel); 17662e192b24SSimon Glass } 17672e192b24SSimon Glass #endif 17682e192b24SSimon Glass printf("\n"); 17692e192b24SSimon Glass #endif 17702e192b24SSimon Glass } 17712e192b24SSimon Glass 17722e192b24SSimon Glass return 0; 17732e192b24SSimon Glass } 17742e192b24SSimon Glass #endif 17752e192b24SSimon Glass 17762e192b24SSimon Glass /** 17772e192b24SSimon Glass * do_i2c_bus_num() - Handle the "i2c dev" command-line command 17782e192b24SSimon Glass * @cmdtp: Command data struct pointer 17792e192b24SSimon Glass * @flag: Command flag 17802e192b24SSimon Glass * @argc: Command-line argument count 17812e192b24SSimon Glass * @argv: Array of command-line arguments 17822e192b24SSimon Glass * 17832e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 17842e192b24SSimon Glass * on error. 17852e192b24SSimon Glass */ 17862e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS) || \ 17872e192b24SSimon Glass defined(CONFIG_DM_I2C) 17882e192b24SSimon Glass static int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc, 17892e192b24SSimon Glass char * const argv[]) 17902e192b24SSimon Glass { 17912e192b24SSimon Glass int ret = 0; 17922e192b24SSimon Glass int bus_no; 17932e192b24SSimon Glass 17942e192b24SSimon Glass if (argc == 1) { 17952e192b24SSimon Glass /* querying current setting */ 17962e192b24SSimon Glass #ifdef CONFIG_DM_I2C 17972e192b24SSimon Glass struct udevice *bus; 17982e192b24SSimon Glass 17992e192b24SSimon Glass if (!i2c_get_cur_bus(&bus)) 18002e192b24SSimon Glass bus_no = bus->seq; 18012e192b24SSimon Glass else 18022e192b24SSimon Glass bus_no = -1; 18032e192b24SSimon Glass #else 18042e192b24SSimon Glass bus_no = i2c_get_bus_num(); 18052e192b24SSimon Glass #endif 18062e192b24SSimon Glass printf("Current bus is %d\n", bus_no); 18072e192b24SSimon Glass } else { 18082e192b24SSimon Glass bus_no = simple_strtoul(argv[1], NULL, 10); 18092e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) 18102e192b24SSimon Glass if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES) { 18112e192b24SSimon Glass printf("Invalid bus %d\n", bus_no); 18122e192b24SSimon Glass return -1; 18132e192b24SSimon Glass } 18142e192b24SSimon Glass #endif 18152e192b24SSimon Glass printf("Setting bus to %d\n", bus_no); 18162e192b24SSimon Glass #ifdef CONFIG_DM_I2C 18172e192b24SSimon Glass ret = cmd_i2c_set_bus_num(bus_no); 18182e192b24SSimon Glass #else 18192e192b24SSimon Glass ret = i2c_set_bus_num(bus_no); 18202e192b24SSimon Glass #endif 18212e192b24SSimon Glass if (ret) 18222e192b24SSimon Glass printf("Failure changing bus number (%d)\n", ret); 18232e192b24SSimon Glass } 18242e192b24SSimon Glass 18252e192b24SSimon Glass return ret ? CMD_RET_FAILURE : 0; 18262e192b24SSimon Glass } 18272e192b24SSimon Glass #endif /* defined(CONFIG_SYS_I2C) */ 18282e192b24SSimon Glass 18292e192b24SSimon Glass /** 18302e192b24SSimon Glass * do_i2c_bus_speed() - Handle the "i2c speed" command-line command 18312e192b24SSimon Glass * @cmdtp: Command data struct pointer 18322e192b24SSimon Glass * @flag: Command flag 18332e192b24SSimon Glass * @argc: Command-line argument count 18342e192b24SSimon Glass * @argv: Array of command-line arguments 18352e192b24SSimon Glass * 18362e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 18372e192b24SSimon Glass * on error. 18382e192b24SSimon Glass */ 18392e192b24SSimon Glass static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) 18402e192b24SSimon Glass { 18412e192b24SSimon Glass int speed, ret=0; 18422e192b24SSimon Glass 18432e192b24SSimon Glass #ifdef CONFIG_DM_I2C 18442e192b24SSimon Glass struct udevice *bus; 18452e192b24SSimon Glass 18462e192b24SSimon Glass if (i2c_get_cur_bus(&bus)) 18472e192b24SSimon Glass return 1; 18482e192b24SSimon Glass #endif 18492e192b24SSimon Glass if (argc == 1) { 18502e192b24SSimon Glass #ifdef CONFIG_DM_I2C 18512e192b24SSimon Glass speed = dm_i2c_get_bus_speed(bus); 18522e192b24SSimon Glass #else 18532e192b24SSimon Glass speed = i2c_get_bus_speed(); 18542e192b24SSimon Glass #endif 18552e192b24SSimon Glass /* querying current speed */ 18562e192b24SSimon Glass printf("Current bus speed=%d\n", speed); 18572e192b24SSimon Glass } else { 18582e192b24SSimon Glass speed = simple_strtoul(argv[1], NULL, 10); 18592e192b24SSimon Glass printf("Setting bus speed to %d Hz\n", speed); 18602e192b24SSimon Glass #ifdef CONFIG_DM_I2C 18612e192b24SSimon Glass ret = dm_i2c_set_bus_speed(bus, speed); 18622e192b24SSimon Glass #else 18632e192b24SSimon Glass ret = i2c_set_bus_speed(speed); 18642e192b24SSimon Glass #endif 18652e192b24SSimon Glass if (ret) 18662e192b24SSimon Glass printf("Failure changing bus speed (%d)\n", ret); 18672e192b24SSimon Glass } 18682e192b24SSimon Glass 18692e192b24SSimon Glass return ret ? CMD_RET_FAILURE : 0; 18702e192b24SSimon Glass } 18712e192b24SSimon Glass 18722e192b24SSimon Glass /** 18732e192b24SSimon Glass * do_i2c_mm() - Handle the "i2c mm" command-line command 18742e192b24SSimon Glass * @cmdtp: Command data struct pointer 18752e192b24SSimon Glass * @flag: Command flag 18762e192b24SSimon Glass * @argc: Command-line argument count 18772e192b24SSimon Glass * @argv: Array of command-line arguments 18782e192b24SSimon Glass * 18792e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 18802e192b24SSimon Glass * on error. 18812e192b24SSimon Glass */ 18822e192b24SSimon Glass static int do_i2c_mm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) 18832e192b24SSimon Glass { 18842e192b24SSimon Glass return mod_i2c_mem (cmdtp, 1, flag, argc, argv); 18852e192b24SSimon Glass } 18862e192b24SSimon Glass 18872e192b24SSimon Glass /** 18882e192b24SSimon Glass * do_i2c_nm() - Handle the "i2c nm" command-line command 18892e192b24SSimon Glass * @cmdtp: Command data struct pointer 18902e192b24SSimon Glass * @flag: Command flag 18912e192b24SSimon Glass * @argc: Command-line argument count 18922e192b24SSimon Glass * @argv: Array of command-line arguments 18932e192b24SSimon Glass * 18942e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 18952e192b24SSimon Glass * on error. 18962e192b24SSimon Glass */ 18972e192b24SSimon Glass static int do_i2c_nm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) 18982e192b24SSimon Glass { 18992e192b24SSimon Glass return mod_i2c_mem (cmdtp, 0, flag, argc, argv); 19002e192b24SSimon Glass } 19012e192b24SSimon Glass 19022e192b24SSimon Glass /** 19032e192b24SSimon Glass * do_i2c_reset() - Handle the "i2c reset" command-line command 19042e192b24SSimon Glass * @cmdtp: Command data struct pointer 19052e192b24SSimon Glass * @flag: Command flag 19062e192b24SSimon Glass * @argc: Command-line argument count 19072e192b24SSimon Glass * @argv: Array of command-line arguments 19082e192b24SSimon Glass * 19092e192b24SSimon Glass * Returns zero always. 19102e192b24SSimon Glass */ 19112e192b24SSimon Glass static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) 19122e192b24SSimon Glass { 19132e192b24SSimon Glass #if defined(CONFIG_DM_I2C) 19142e192b24SSimon Glass struct udevice *bus; 19152e192b24SSimon Glass 19162e192b24SSimon Glass if (i2c_get_cur_bus(&bus)) 19172e192b24SSimon Glass return CMD_RET_FAILURE; 19182e192b24SSimon Glass if (i2c_deblock(bus)) { 19192e192b24SSimon Glass printf("Error: Not supported by the driver\n"); 19202e192b24SSimon Glass return CMD_RET_FAILURE; 19212e192b24SSimon Glass } 19222e192b24SSimon Glass #elif defined(CONFIG_SYS_I2C) 19232e192b24SSimon Glass i2c_init(I2C_ADAP->speed, I2C_ADAP->slaveaddr); 19242e192b24SSimon Glass #else 19252e192b24SSimon Glass i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 19262e192b24SSimon Glass #endif 19272e192b24SSimon Glass return 0; 19282e192b24SSimon Glass } 19292e192b24SSimon Glass 19302e192b24SSimon Glass static cmd_tbl_t cmd_i2c_sub[] = { 19312e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) 19322e192b24SSimon Glass U_BOOT_CMD_MKENT(bus, 1, 1, do_i2c_show_bus, "", ""), 19332e192b24SSimon Glass #endif 19342e192b24SSimon Glass U_BOOT_CMD_MKENT(crc32, 3, 1, do_i2c_crc, "", ""), 19352e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || \ 19362e192b24SSimon Glass defined(CONFIG_I2C_MULTI_BUS) || defined(CONFIG_DM_I2C) 19372e192b24SSimon Glass U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""), 19382e192b24SSimon Glass #endif /* CONFIG_I2C_MULTI_BUS */ 19392e192b24SSimon Glass #if defined(CONFIG_I2C_EDID) 19402e192b24SSimon Glass U_BOOT_CMD_MKENT(edid, 1, 1, do_edid, "", ""), 19412e192b24SSimon Glass #endif /* CONFIG_I2C_EDID */ 19422e192b24SSimon Glass U_BOOT_CMD_MKENT(loop, 3, 1, do_i2c_loop, "", ""), 19432e192b24SSimon Glass U_BOOT_CMD_MKENT(md, 3, 1, do_i2c_md, "", ""), 19442e192b24SSimon Glass U_BOOT_CMD_MKENT(mm, 2, 1, do_i2c_mm, "", ""), 19452e192b24SSimon Glass U_BOOT_CMD_MKENT(mw, 3, 1, do_i2c_mw, "", ""), 19462e192b24SSimon Glass U_BOOT_CMD_MKENT(nm, 2, 1, do_i2c_nm, "", ""), 19472e192b24SSimon Glass U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""), 19482e192b24SSimon Glass U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""), 19492e192b24SSimon Glass U_BOOT_CMD_MKENT(write, 6, 0, do_i2c_write, "", ""), 19502e192b24SSimon Glass #ifdef CONFIG_DM_I2C 19512e192b24SSimon Glass U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""), 19522e192b24SSimon Glass U_BOOT_CMD_MKENT(olen, 2, 1, do_i2c_olen, "", ""), 19532e192b24SSimon Glass #endif 19542e192b24SSimon Glass U_BOOT_CMD_MKENT(reset, 0, 1, do_i2c_reset, "", ""), 19552e192b24SSimon Glass #if defined(CONFIG_CMD_SDRAM) 19562e192b24SSimon Glass U_BOOT_CMD_MKENT(sdram, 1, 1, do_sdram, "", ""), 19572e192b24SSimon Glass #endif 19582e192b24SSimon Glass U_BOOT_CMD_MKENT(speed, 1, 1, do_i2c_bus_speed, "", ""), 19592e192b24SSimon Glass }; 19602e192b24SSimon Glass 19612e192b24SSimon Glass static __maybe_unused void i2c_reloc(void) 19622e192b24SSimon Glass { 19632e192b24SSimon Glass static int relocated; 19642e192b24SSimon Glass 19652e192b24SSimon Glass if (!relocated) { 19662e192b24SSimon Glass fixup_cmdtable(cmd_i2c_sub, ARRAY_SIZE(cmd_i2c_sub)); 19672e192b24SSimon Glass relocated = 1; 19682e192b24SSimon Glass }; 19692e192b24SSimon Glass } 19702e192b24SSimon Glass 19712e192b24SSimon Glass /** 19722e192b24SSimon Glass * do_i2c() - Handle the "i2c" command-line command 19732e192b24SSimon Glass * @cmdtp: Command data struct pointer 19742e192b24SSimon Glass * @flag: Command flag 19752e192b24SSimon Glass * @argc: Command-line argument count 19762e192b24SSimon Glass * @argv: Array of command-line arguments 19772e192b24SSimon Glass * 19782e192b24SSimon Glass * Returns zero on success, CMD_RET_USAGE in case of misuse and negative 19792e192b24SSimon Glass * on error. 19802e192b24SSimon Glass */ 19812e192b24SSimon Glass static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) 19822e192b24SSimon Glass { 19832e192b24SSimon Glass cmd_tbl_t *c; 19842e192b24SSimon Glass 19852e192b24SSimon Glass #ifdef CONFIG_NEEDS_MANUAL_RELOC 19862e192b24SSimon Glass i2c_reloc(); 19872e192b24SSimon Glass #endif 19882e192b24SSimon Glass 19892e192b24SSimon Glass if (argc < 2) 19902e192b24SSimon Glass return CMD_RET_USAGE; 19912e192b24SSimon Glass 19922e192b24SSimon Glass /* Strip off leading 'i2c' command argument */ 19932e192b24SSimon Glass argc--; 19942e192b24SSimon Glass argv++; 19952e192b24SSimon Glass 19962e192b24SSimon Glass c = find_cmd_tbl(argv[0], &cmd_i2c_sub[0], ARRAY_SIZE(cmd_i2c_sub)); 19972e192b24SSimon Glass 19982e192b24SSimon Glass if (c) 19992e192b24SSimon Glass return c->cmd(cmdtp, flag, argc, argv); 20002e192b24SSimon Glass else 20012e192b24SSimon Glass return CMD_RET_USAGE; 20022e192b24SSimon Glass } 20032e192b24SSimon Glass 20042e192b24SSimon Glass /***************************************************/ 20052e192b24SSimon Glass #ifdef CONFIG_SYS_LONGHELP 20062e192b24SSimon Glass static char i2c_help_text[] = 20072e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || defined(CONFIG_DM_I2C) 20082e192b24SSimon Glass "bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n" 20092e192b24SSimon Glass #endif 20102e192b24SSimon Glass "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n" 20112e192b24SSimon Glass #if defined(CONFIG_SYS_I2C) || \ 20122e192b24SSimon Glass defined(CONFIG_I2C_MULTI_BUS) || defined(CONFIG_DM_I2C) 20132e192b24SSimon Glass "i2c dev [dev] - show or set current I2C bus\n" 20142e192b24SSimon Glass #endif /* CONFIG_I2C_MULTI_BUS */ 20152e192b24SSimon Glass #if defined(CONFIG_I2C_EDID) 20162e192b24SSimon Glass "i2c edid chip - print EDID configuration information\n" 20172e192b24SSimon Glass #endif /* CONFIG_I2C_EDID */ 20182e192b24SSimon Glass "i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device\n" 20192e192b24SSimon Glass "i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n" 20202e192b24SSimon Glass "i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n" 20212e192b24SSimon Glass "i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)\n" 20222e192b24SSimon Glass "i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n" 20232e192b24SSimon Glass "i2c probe [address] - test for and show device(s) on the I2C bus\n" 20242e192b24SSimon Glass "i2c read chip address[.0, .1, .2] length memaddress - read to memory\n" 20252e192b24SSimon Glass "i2c write memaddress chip address[.0, .1, .2] length [-s] - write memory\n" 20262e192b24SSimon Glass " to I2C; the -s option selects bulk write in a single transaction\n" 20272e192b24SSimon Glass #ifdef CONFIG_DM_I2C 20282e192b24SSimon Glass "i2c flags chip [flags] - set or get chip flags\n" 20292e192b24SSimon Glass "i2c olen chip [offset_length] - set or get chip offset length\n" 20302e192b24SSimon Glass #endif 20312e192b24SSimon Glass "i2c reset - re-init the I2C Controller\n" 20322e192b24SSimon Glass #if defined(CONFIG_CMD_SDRAM) 20332e192b24SSimon Glass "i2c sdram chip - print SDRAM configuration information\n" 20342e192b24SSimon Glass #endif 20352e192b24SSimon Glass "i2c speed [speed] - show or set I2C bus speed"; 20362e192b24SSimon Glass #endif 20372e192b24SSimon Glass 20382e192b24SSimon Glass U_BOOT_CMD( 20392e192b24SSimon Glass i2c, 7, 1, do_i2c, 20402e192b24SSimon Glass "I2C sub-system", 20412e192b24SSimon Glass i2c_help_text 20422e192b24SSimon Glass ); 2043