1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2000, 2001 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7 /* 8 * Support for read and write access to EEPROM like memory devices. This 9 * includes regular EEPROM as well as FRAM (ferroelectic nonvolaile RAM). 10 * FRAM devices read and write data at bus speed. In particular, there is no 11 * write delay. Also, there is no limit imposed on the number of bytes that can 12 * be transferred with a single read or write. 13 * 14 * Use the following configuration options to ensure no unneeded performance 15 * degradation (typical for EEPROM) is incured for FRAM memory: 16 * 17 * #define CONFIG_SYS_I2C_FRAM 18 * #undef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 19 * 20 */ 21 22 #include <common.h> 23 #include <config.h> 24 #include <command.h> 25 #include <i2c.h> 26 #include <eeprom_layout.h> 27 28 #ifndef CONFIG_SYS_I2C_SPEED 29 #define CONFIG_SYS_I2C_SPEED 50000 30 #endif 31 32 #ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 33 #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 0 34 #endif 35 36 #ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 37 #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 8 38 #endif 39 40 #ifndef I2C_RXTX_LEN 41 #define I2C_RXTX_LEN 128 42 #endif 43 44 #define EEPROM_PAGE_SIZE (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS) 45 #define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1)) 46 47 /* 48 * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is 49 * 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM. 50 * 51 * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is 52 * 0x00000nxx for EEPROM address selectors and page number at n. 53 */ 54 #if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C) 55 #if !defined(CONFIG_SYS_I2C_EEPROM_ADDR_LEN) || \ 56 (CONFIG_SYS_I2C_EEPROM_ADDR_LEN < 1) || \ 57 (CONFIG_SYS_I2C_EEPROM_ADDR_LEN > 2) 58 #error CONFIG_SYS_I2C_EEPROM_ADDR_LEN must be 1 or 2 59 #endif 60 #endif 61 62 __weak int eeprom_write_enable(unsigned dev_addr, int state) 63 { 64 return 0; 65 } 66 67 void eeprom_init(int bus) 68 { 69 /* I2C EEPROM */ 70 #if defined(CONFIG_SYS_I2C) 71 if (bus >= 0) 72 i2c_set_bus_num(bus); 73 i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 74 #endif 75 } 76 77 static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr) 78 { 79 unsigned blk_off; 80 int alen; 81 82 blk_off = offset & 0xff; /* block offset */ 83 #if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 84 addr[0] = offset >> 8; /* block number */ 85 addr[1] = blk_off; /* block offset */ 86 alen = 2; 87 #else 88 addr[0] = offset >> 16; /* block number */ 89 addr[1] = offset >> 8; /* upper address octet */ 90 addr[2] = blk_off; /* lower address octet */ 91 alen = 3; 92 #endif /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN */ 93 94 addr[0] |= dev_addr; /* insert device address */ 95 96 return alen; 97 } 98 99 static int eeprom_len(unsigned offset, unsigned end) 100 { 101 unsigned len = end - offset; 102 103 /* 104 * For a FRAM device there is no limit on the number of the 105 * bytes that can be ccessed with the single read or write 106 * operation. 107 */ 108 #if !defined(CONFIG_SYS_I2C_FRAM) 109 unsigned blk_off = offset & 0xff; 110 unsigned maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off); 111 112 if (maxlen > I2C_RXTX_LEN) 113 maxlen = I2C_RXTX_LEN; 114 115 if (len > maxlen) 116 len = maxlen; 117 #endif 118 119 return len; 120 } 121 122 static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen, 123 uchar *buffer, unsigned len, bool read) 124 { 125 int ret = 0; 126 127 #if defined(CONFIG_SYS_I2C_EEPROM_BUS) 128 i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS); 129 #endif 130 131 if (read) 132 ret = i2c_read(addr[0], offset, alen - 1, buffer, len); 133 else 134 ret = i2c_write(addr[0], offset, alen - 1, buffer, len); 135 136 if (ret) 137 ret = 1; 138 139 return ret; 140 } 141 142 static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer, 143 unsigned cnt, bool read) 144 { 145 unsigned end = offset + cnt; 146 unsigned alen, len; 147 int rcode = 0; 148 uchar addr[3]; 149 150 while (offset < end) { 151 alen = eeprom_addr(dev_addr, offset, addr); 152 153 len = eeprom_len(offset, end); 154 155 rcode = eeprom_rw_block(offset, addr, alen, buffer, len, read); 156 157 buffer += len; 158 offset += len; 159 160 if (!read) 161 udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); 162 } 163 164 return rcode; 165 } 166 167 int eeprom_read(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt) 168 { 169 /* 170 * Read data until done or would cross a page boundary. 171 * We must write the address again when changing pages 172 * because the next page may be in a different device. 173 */ 174 return eeprom_rw(dev_addr, offset, buffer, cnt, 1); 175 } 176 177 int eeprom_write(unsigned dev_addr, unsigned offset, 178 uchar *buffer, unsigned cnt) 179 { 180 int ret; 181 182 eeprom_write_enable(dev_addr, 1); 183 184 /* 185 * Write data until done or would cross a write page boundary. 186 * We must write the address again when changing pages 187 * because the address counter only increments within a page. 188 */ 189 ret = eeprom_rw(dev_addr, offset, buffer, cnt, 0); 190 191 eeprom_write_enable(dev_addr, 0); 192 return ret; 193 } 194 195 static int parse_numeric_param(char *str) 196 { 197 char *endptr; 198 int value = simple_strtol(str, &endptr, 16); 199 200 return (*endptr != '\0') ? -1 : value; 201 } 202 203 /** 204 * parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters 205 * 206 * @i2c_bus: address to store the i2c bus 207 * @i2c_addr: address to store the device i2c address 208 * @argc: count of command line arguments left to parse 209 * @argv: command line arguments left to parse 210 * @argc_no_bus_addr: argc value we expect to see when bus & addr aren't given 211 * 212 * @returns: number of arguments parsed or CMD_RET_USAGE if error 213 */ 214 static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc, 215 char * const argv[], int argc_no_bus_addr) 216 { 217 int argc_no_bus = argc_no_bus_addr + 1; 218 int argc_bus_addr = argc_no_bus_addr + 2; 219 220 #ifdef CONFIG_SYS_DEF_EEPROM_ADDR 221 if (argc == argc_no_bus_addr) { 222 *i2c_bus = -1; 223 *i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR; 224 225 return 0; 226 } 227 #endif 228 if (argc == argc_no_bus) { 229 *i2c_bus = -1; 230 *i2c_addr = parse_numeric_param(argv[0]); 231 232 return 1; 233 } 234 235 if (argc == argc_bus_addr) { 236 *i2c_bus = parse_numeric_param(argv[0]); 237 *i2c_addr = parse_numeric_param(argv[1]); 238 239 return 2; 240 } 241 242 return CMD_RET_USAGE; 243 } 244 245 #ifdef CONFIG_CMD_EEPROM_LAYOUT 246 247 __weak int eeprom_parse_layout_version(char *str) 248 { 249 return LAYOUT_VERSION_UNRECOGNIZED; 250 } 251 252 static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; 253 254 #endif 255 256 enum eeprom_action { 257 EEPROM_READ, 258 EEPROM_WRITE, 259 EEPROM_PRINT, 260 EEPROM_UPDATE, 261 EEPROM_ACTION_INVALID, 262 }; 263 264 static enum eeprom_action parse_action(char *cmd) 265 { 266 if (!strncmp(cmd, "read", 4)) 267 return EEPROM_READ; 268 if (!strncmp(cmd, "write", 5)) 269 return EEPROM_WRITE; 270 #ifdef CONFIG_CMD_EEPROM_LAYOUT 271 if (!strncmp(cmd, "print", 5)) 272 return EEPROM_PRINT; 273 if (!strncmp(cmd, "update", 6)) 274 return EEPROM_UPDATE; 275 #endif 276 277 return EEPROM_ACTION_INVALID; 278 } 279 280 static int eeprom_execute_command(enum eeprom_action action, int i2c_bus, 281 ulong i2c_addr, int layout_ver, char *key, 282 char *value, ulong addr, ulong off, ulong cnt) 283 { 284 int rcode = 0; 285 const char *const fmt = 286 "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; 287 #ifdef CONFIG_CMD_EEPROM_LAYOUT 288 struct eeprom_layout layout; 289 #endif 290 291 if (action == EEPROM_ACTION_INVALID) 292 return CMD_RET_USAGE; 293 294 eeprom_init(i2c_bus); 295 if (action == EEPROM_READ) { 296 printf(fmt, i2c_addr, "read", addr, off, cnt); 297 298 rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt); 299 300 puts("done\n"); 301 return rcode; 302 } else if (action == EEPROM_WRITE) { 303 printf(fmt, i2c_addr, "write", addr, off, cnt); 304 305 rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt); 306 307 puts("done\n"); 308 return rcode; 309 } 310 311 #ifdef CONFIG_CMD_EEPROM_LAYOUT 312 rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE); 313 if (rcode < 0) 314 return rcode; 315 316 eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE, 317 layout_ver); 318 319 if (action == EEPROM_PRINT) { 320 layout.print(&layout); 321 return 0; 322 } 323 324 layout.update(&layout, key, value); 325 326 rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE); 327 #endif 328 329 return rcode; 330 } 331 332 #define NEXT_PARAM(argc, index) { (argc)--; (index)++; } 333 int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 334 { 335 int layout_ver = LAYOUT_VERSION_AUTODETECT; 336 enum eeprom_action action = EEPROM_ACTION_INVALID; 337 int i2c_bus = -1, index = 0; 338 ulong i2c_addr = -1, addr = 0, cnt = 0, off = 0; 339 int ret; 340 char *field_name = ""; 341 char *field_value = ""; 342 343 if (argc <= 1) 344 return CMD_RET_USAGE; 345 346 NEXT_PARAM(argc, index); /* Skip program name */ 347 348 action = parse_action(argv[index]); 349 NEXT_PARAM(argc, index); 350 351 if (action == EEPROM_ACTION_INVALID) 352 return CMD_RET_USAGE; 353 354 #ifdef CONFIG_CMD_EEPROM_LAYOUT 355 if (action == EEPROM_PRINT || action == EEPROM_UPDATE) { 356 if (!strcmp(argv[index], "-l")) { 357 NEXT_PARAM(argc, index); 358 layout_ver = eeprom_parse_layout_version(argv[index]); 359 NEXT_PARAM(argc, index); 360 } 361 } 362 #endif 363 364 switch (action) { 365 case EEPROM_READ: 366 case EEPROM_WRITE: 367 ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, 368 argv + index, 3); 369 break; 370 case EEPROM_PRINT: 371 ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, 372 argv + index, 0); 373 break; 374 case EEPROM_UPDATE: 375 ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc, 376 argv + index, 2); 377 break; 378 default: 379 /* Get compiler to stop whining */ 380 return CMD_RET_USAGE; 381 } 382 383 if (ret == CMD_RET_USAGE) 384 return ret; 385 386 while (ret--) 387 NEXT_PARAM(argc, index); 388 389 if (action == EEPROM_READ || action == EEPROM_WRITE) { 390 addr = parse_numeric_param(argv[index]); 391 NEXT_PARAM(argc, index); 392 off = parse_numeric_param(argv[index]); 393 NEXT_PARAM(argc, index); 394 cnt = parse_numeric_param(argv[index]); 395 } 396 397 #ifdef CONFIG_CMD_EEPROM_LAYOUT 398 if (action == EEPROM_UPDATE) { 399 field_name = argv[index]; 400 NEXT_PARAM(argc, index); 401 field_value = argv[index]; 402 NEXT_PARAM(argc, index); 403 } 404 #endif 405 406 return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver, 407 field_name, field_value, addr, off, cnt); 408 } 409 410 U_BOOT_CMD( 411 eeprom, 8, 1, do_eeprom, 412 "EEPROM sub-system", 413 "read <bus> <devaddr> addr off cnt\n" 414 "eeprom write <bus> <devaddr> addr off cnt\n" 415 " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" 416 #ifdef CONFIG_CMD_EEPROM_LAYOUT 417 "\n" 418 "eeprom print [-l <layout_version>] <bus> <devaddr>\n" 419 " - Print layout fields and their data in human readable format\n" 420 "eeprom update [-l <layout_version>] <bus> <devaddr> field_name field_value\n" 421 " - Update a specific eeprom field with new data.\n" 422 " The new data must be written in the same human readable format as shown by the print command.\n" 423 "\n" 424 "LAYOUT VERSIONS\n" 425 "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n" 426 "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n" 427 "The values which can be provided with the -l option are:\n" 428 CONFIG_EEPROM_LAYOUT_HELP_STRING"\n" 429 #endif 430 ) 431