"Das U-Boot" Source Tree
at master 577 lines 14 kB view raw
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 * Set CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS to 0 19 * 20 */ 21 22#include <config.h> 23#include <command.h> 24#include <dm.h> 25#include <eeprom.h> 26#include <i2c.h> 27#include <i2c_eeprom.h> 28#include <eeprom_layout.h> 29#include <vsprintf.h> 30#include <linux/delay.h> 31 32#ifndef I2C_RXTX_LEN 33#define I2C_RXTX_LEN 128 34#endif 35 36#define EEPROM_PAGE_SIZE (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS) 37#define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1)) 38 39#if CONFIG_IS_ENABLED(DM_I2C) 40static int eeprom_i2c_bus; 41#endif 42 43__weak int eeprom_write_enable(unsigned dev_addr, int state) 44{ 45 return 0; 46} 47 48void eeprom_init(int bus) 49{ 50 /* I2C EEPROM */ 51#if CONFIG_IS_ENABLED(DM_I2C) 52 eeprom_i2c_bus = bus; 53#elif CONFIG_IS_ENABLED(SYS_I2C_LEGACY) 54 if (bus >= 0) 55 i2c_set_bus_num(bus); 56 i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 57#endif 58} 59 60/* 61 * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is 62 * 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM. 63 * 64 * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is 65 * 0x00000nxx for EEPROM address selectors and page number at n. 66 */ 67static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr) 68{ 69 unsigned blk_off; 70 int alen; 71 72 blk_off = offset & 0xff; /* block offset */ 73#if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 74 addr[0] = offset >> 8; /* block number */ 75 addr[1] = blk_off; /* block offset */ 76 alen = 2; 77#else 78 addr[0] = offset >> 16; /* block number */ 79 addr[1] = offset >> 8; /* upper address octet */ 80 addr[2] = blk_off; /* lower address octet */ 81 alen = 3; 82#endif /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN */ 83 84 addr[0] |= dev_addr; /* insert device address */ 85 86 return alen; 87} 88 89static int eeprom_len(unsigned offset, unsigned end) 90{ 91 unsigned len = end - offset; 92 93 /* 94 * For a FRAM device there is no limit on the number of the 95 * bytes that can be accessed with the single read or write 96 * operation. 97 */ 98#if !defined(CONFIG_SYS_I2C_FRAM) 99 unsigned blk_off = offset & 0xff; 100 unsigned maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off); 101 102 if (maxlen > I2C_RXTX_LEN) 103 maxlen = I2C_RXTX_LEN; 104 105 if (len > maxlen) 106 len = maxlen; 107#endif 108 109 return len; 110} 111 112static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen, 113 uchar *buffer, unsigned len, bool read) 114{ 115 int ret = 0; 116 117#if CONFIG_IS_ENABLED(DM_I2C) 118 struct udevice *dev; 119 120 ret = i2c_get_chip_for_busnum(eeprom_i2c_bus, addr[0], 121 alen - 1, &dev); 122 if (ret) { 123 printf("%s: Cannot find udev for a bus %d\n", __func__, 124 eeprom_i2c_bus); 125 return CMD_RET_FAILURE; 126 } 127 128 if (read) 129 ret = dm_i2c_read(dev, offset, buffer, len); 130 else 131 ret = dm_i2c_write(dev, offset, buffer, len); 132 133#else /* Non DM I2C support - will be removed */ 134 135 if (read) 136 ret = i2c_read(addr[0], offset, alen - 1, buffer, len); 137 else 138 ret = i2c_write(addr[0], offset, alen - 1, buffer, len); 139#endif /* CONFIG_DM_I2C */ 140 if (ret) 141 ret = CMD_RET_FAILURE; 142 143 return ret; 144} 145 146static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer, 147 unsigned cnt, bool read) 148{ 149 unsigned end = offset + cnt; 150 unsigned alen, len; 151 int rcode = 0; 152 uchar addr[3]; 153 154#if !CONFIG_IS_ENABLED(DM_I2C) && defined(CONFIG_SYS_I2C_EEPROM_BUS) 155 eeprom_init(CONFIG_SYS_I2C_EEPROM_BUS); 156#endif 157 158 while (offset < end) { 159 alen = eeprom_addr(dev_addr, offset, addr); 160 161 len = eeprom_len(offset, end); 162 163 rcode = eeprom_rw_block(offset, addr, alen, buffer, len, read); 164 165 buffer += len; 166 offset += len; 167 168#if CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS > 0 169 if (!read) 170 udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000); 171#endif 172 } 173 174 return rcode; 175} 176 177int eeprom_read(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt) 178{ 179 /* 180 * Read data until done or would cross a page boundary. 181 * We must write the address again when changing pages 182 * because the next page may be in a different device. 183 */ 184 return eeprom_rw(dev_addr, offset, buffer, cnt, 1); 185} 186 187int eeprom_write(unsigned dev_addr, unsigned offset, 188 uchar *buffer, unsigned cnt) 189{ 190 int ret; 191 192 eeprom_write_enable(dev_addr, 1); 193 194 /* 195 * Write data until done or would cross a write page boundary. 196 * We must write the address again when changing pages 197 * because the address counter only increments within a page. 198 */ 199 ret = eeprom_rw(dev_addr, offset, buffer, cnt, 0); 200 201 eeprom_write_enable(dev_addr, 0); 202 return ret; 203} 204 205static long parse_numeric_param(char *str) 206{ 207 char *endptr; 208 long value = simple_strtol(str, &endptr, 16); 209 210 return (*endptr != '\0') ? -1 : value; 211} 212 213struct eeprom_dev_spec { 214#if CONFIG_IS_ENABLED(I2C_EEPROM) 215 struct udevice *dev; 216#endif 217 int i2c_bus; 218 ulong i2c_addr; 219}; 220 221static void eeprom_dev_spec_init(struct eeprom_dev_spec *dev) 222{ 223#if CONFIG_IS_ENABLED(I2C_EEPROM) 224 if (!dev->dev) 225#endif 226 eeprom_init(dev->i2c_bus); 227} 228 229static int eeprom_dev_spec_read(struct eeprom_dev_spec *dev, 230 unsigned offset, uchar *buffer, unsigned cnt) 231{ 232#if CONFIG_IS_ENABLED(I2C_EEPROM) 233 if (dev->dev) 234 return i2c_eeprom_read(dev->dev, offset, buffer, cnt); 235#endif 236 return eeprom_read(dev->i2c_addr, offset, buffer, cnt); 237} 238 239static int eeprom_dev_spec_write(struct eeprom_dev_spec *dev, 240 unsigned offset, uchar *buffer, unsigned cnt) 241{ 242#if CONFIG_IS_ENABLED(I2C_EEPROM) 243 if (dev->dev) 244 return i2c_eeprom_write(dev->dev, offset, buffer, cnt); 245#endif 246 return eeprom_write(dev->i2c_addr, offset, buffer, cnt); 247} 248 249/** 250 * parse_eeprom_dev_spec - parse the eeprom device specifier 251 * 252 * @dev: pointer to eeprom device specifier 253 * @argc: count of command line arguments that can be used to parse 254 * the device specifier 255 * @argv: command line arguments left to parse 256 * 257 * @returns: number of arguments parsed or CMD_RET_USAGE if error 258 */ 259static int parse_eeprom_dev_spec(struct eeprom_dev_spec *dev, int argc, 260 char *const argv[]) 261{ 262#if CONFIG_IS_ENABLED(I2C_EEPROM) 263 if (argc == 0) { 264 if (!uclass_first_device_err(UCLASS_I2C_EEPROM, &dev->dev)) 265 return 0; 266 } 267 268 if (argc == 1) { 269 if (!uclass_get_device_by_name(UCLASS_I2C_EEPROM, argv[0], 270 &dev->dev)) 271 return 1; 272 273 /* 274 * If we could not find the device by name and the parameter is 275 * not numeric (and so won't be handled later), fail. 276 */ 277 if (parse_numeric_param(argv[0]) == -1) { 278 printf("Can't get eeprom device: %s\n", argv[0]); 279 return CMD_RET_USAGE; 280 } 281 } 282#endif 283 284#ifdef CONFIG_SYS_I2C_EEPROM_ADDR 285 if (argc == 0) { 286 dev->i2c_bus = -1; 287 dev->i2c_addr = CONFIG_SYS_I2C_EEPROM_ADDR; 288 289 return 0; 290 } 291#endif 292 if (argc == 1) { 293 dev->i2c_bus = -1; 294 dev->i2c_addr = parse_numeric_param(argv[0]); 295 296 return 1; 297 } 298 299 if (argc == 2) { 300 dev->i2c_bus = parse_numeric_param(argv[0]); 301 dev->i2c_addr = parse_numeric_param(argv[1]); 302 303 return 2; 304 } 305 306 return CMD_RET_USAGE; 307} 308 309#ifdef CONFIG_CMD_EEPROM_LAYOUT 310 311#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS 312__weak int eeprom_parse_layout_version(char *str) 313{ 314 return LAYOUT_VERSION_UNRECOGNIZED; 315} 316#endif 317 318static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE]; 319 320#endif 321 322enum eeprom_action { 323 EEPROM_LIST, 324 EEPROM_READ, 325 EEPROM_WRITE, 326 EEPROM_PRINT, 327 EEPROM_UPDATE, 328 EEPROM_ACTION_INVALID, 329}; 330 331static enum eeprom_action parse_action(char *cmd) 332{ 333#if CONFIG_IS_ENABLED(I2C_EEPROM) 334 if (!strncmp(cmd, "list", 4)) 335 return EEPROM_LIST; 336#endif 337 if (!strncmp(cmd, "read", 4)) 338 return EEPROM_READ; 339 if (!strncmp(cmd, "write", 5)) 340 return EEPROM_WRITE; 341#ifdef CONFIG_CMD_EEPROM_LAYOUT 342 if (!strncmp(cmd, "print", 5)) 343 return EEPROM_PRINT; 344 if (!strncmp(cmd, "update", 6)) 345 return EEPROM_UPDATE; 346#endif 347 348 return EEPROM_ACTION_INVALID; 349} 350 351#if CONFIG_IS_ENABLED(I2C_EEPROM) 352static int do_eeprom_list(void) 353{ 354 struct udevice *dev; 355 struct uclass *uc; 356 int err; 357 358 err = uclass_get(UCLASS_I2C_EEPROM, &uc); 359 if (err) 360 return CMD_RET_FAILURE; 361 362 uclass_foreach_dev(dev, uc) 363 printf("%s (%s)\n", dev->name, dev->driver->name); 364 365 return CMD_RET_SUCCESS; 366} 367#endif 368 369static int do_eeprom_rw(struct eeprom_dev_spec *dev, bool read, 370 ulong addr, ulong off, ulong cnt) 371{ 372 const char *const fmt = 373 "\nEEPROM @0x%lX %s: addr 0x%08lx off 0x%04lx count %ld ... "; 374 uchar *memloc = (uchar *)addr; 375 int ret; 376 377 printf(fmt, dev->i2c_addr, read ? "read" : "write", addr, off, cnt); 378 if (read) 379 ret = eeprom_dev_spec_read(dev, off, memloc, cnt); 380 else 381 ret = eeprom_dev_spec_write(dev, off, memloc, cnt); 382 puts("done\n"); 383 384 return ret; 385} 386 387#ifdef CONFIG_CMD_EEPROM_LAYOUT 388 389static int do_eeprom_layout(struct eeprom_dev_spec *dev, int layout_ver, 390 struct eeprom_layout *layout) 391{ 392 eeprom_layout_setup(layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE, 393 layout_ver); 394 395 return eeprom_dev_spec_read(dev, 0, eeprom_buf, layout->data_size); 396} 397 398static int do_eeprom_print(struct eeprom_dev_spec *dev, int layout_ver) 399{ 400 struct eeprom_layout layout; 401 int ret; 402 403 ret = do_eeprom_layout(dev, layout_ver, &layout); 404 if (ret) 405 return ret; 406 407 layout.print(&layout); 408 409 return 0; 410} 411 412static int do_eeprom_update(struct eeprom_dev_spec *dev, int layout_ver, 413 char *key, char *value) 414{ 415 struct eeprom_layout layout; 416 int ret; 417 418 ret = do_eeprom_layout(dev, layout_ver, &layout); 419 if (ret) 420 return ret; 421 422 ret = layout.update(&layout, key, value); 423 if (ret) 424 return CMD_RET_FAILURE; 425 426 return eeprom_dev_spec_write(dev, 0, layout.data, layout.data_size); 427} 428 429#endif 430 431static int eeprom_action_expected_argc(enum eeprom_action action) 432{ 433 switch (action) { 434 case EEPROM_LIST: 435 return 0; 436 case EEPROM_READ: 437 case EEPROM_WRITE: 438 return 3; 439 case EEPROM_PRINT: 440 return 0; 441 case EEPROM_UPDATE: 442 return 2; 443 default: 444 return CMD_RET_USAGE; 445 } 446} 447 448#define NEXT_PARAM(argc, index) { (argc)--; (index)++; } 449int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 450{ 451 enum eeprom_action action = EEPROM_ACTION_INVALID; 452 struct eeprom_dev_spec dev; 453 ulong addr = 0, cnt = 0, off = 0; 454 int ret, index = 0; 455#ifdef CONFIG_CMD_EEPROM_LAYOUT 456 char *field_name = ""; 457 char *field_value = ""; 458 int layout_ver = LAYOUT_VERSION_AUTODETECT; 459#endif 460 461 if (argc <= 1) 462 return CMD_RET_USAGE; 463 464 NEXT_PARAM(argc, index); /* Skip program name */ 465 466 action = parse_action(argv[index]); 467 NEXT_PARAM(argc, index); 468 469 if (action == EEPROM_ACTION_INVALID) 470 return CMD_RET_USAGE; 471 472#if CONFIG_IS_ENABLED(I2C_EEPROM) 473 if (action == EEPROM_LIST) 474 return do_eeprom_list(); 475#endif 476 477#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS 478 if (action == EEPROM_PRINT || action == EEPROM_UPDATE) { 479 if (!strcmp(argv[index], "-l")) { 480 NEXT_PARAM(argc, index); 481 layout_ver = eeprom_parse_layout_version(argv[index]); 482 NEXT_PARAM(argc, index); 483 } 484 } 485#endif 486 487 ret = parse_eeprom_dev_spec(&dev, 488 argc - eeprom_action_expected_argc(action), 489 argv + index); 490 if (ret == CMD_RET_USAGE) 491 return ret; 492 493 while (ret--) 494 NEXT_PARAM(argc, index); 495 496 if (action == EEPROM_READ || action == EEPROM_WRITE) { 497 addr = parse_numeric_param(argv[index]); 498 NEXT_PARAM(argc, index); 499 off = parse_numeric_param(argv[index]); 500 NEXT_PARAM(argc, index); 501 cnt = parse_numeric_param(argv[index]); 502 } 503 504#ifdef CONFIG_CMD_EEPROM_LAYOUT 505 if (action == EEPROM_UPDATE) { 506 field_name = argv[index]; 507 NEXT_PARAM(argc, index); 508 field_value = argv[index]; 509 NEXT_PARAM(argc, index); 510 } 511#endif 512 513 eeprom_dev_spec_init(&dev); 514 515 switch (action) { 516 case EEPROM_READ: 517 case EEPROM_WRITE: 518 return do_eeprom_rw(&dev, action == EEPROM_READ, 519 addr, off, cnt); 520#ifdef CONFIG_CMD_EEPROM_LAYOUT 521 case EEPROM_PRINT: 522 return do_eeprom_print(&dev, layout_ver); 523 case EEPROM_UPDATE: 524 return do_eeprom_update(&dev, layout_ver, 525 field_name, field_value); 526#endif 527 default: 528 return CMD_RET_USAGE; 529 } 530} 531 532#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS 533#define EEPROM_LAYOUT_SPEC "[-l <layout_version>] " 534#else 535#define EEPROM_LAYOUT_SPEC "" 536#endif 537 538#if CONFIG_IS_ENABLED(I2C_EEPROM) 539# define EEPROM_DEV_SPEC "[device_specifier]" 540#else 541# define EEPROM_DEV_SPEC "[[bus] devaddr]" 542#endif 543 544U_BOOT_CMD( 545 eeprom, 8, 1, do_eeprom, 546 "EEPROM sub-system", 547#if CONFIG_IS_ENABLED(I2C_EEPROM) 548 "list\n" 549 "eeprom " 550#endif 551 "read " EEPROM_DEV_SPEC " addr off cnt\n" 552 "eeprom write " EEPROM_DEV_SPEC " addr off cnt\n" 553 " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" 554#ifdef CONFIG_CMD_EEPROM_LAYOUT 555 "\n" 556 "eeprom print " EEPROM_LAYOUT_SPEC EEPROM_DEV_SPEC "\n" 557 " - Print layout fields and their data in human readable format\n" 558 "eeprom update " EEPROM_LAYOUT_SPEC EEPROM_DEV_SPEC " field_name field_value\n" 559 " - Update a specific eeprom field with new data.\n" 560 " The new data must be written in the same human readable format as shown by the print command." 561#endif 562#if CONFIG_IS_ENABLED(I2C_EEPROM) 563 "\n\n" 564 "DEVICE SPECIFIER - the eeprom device can be specified\n" 565 " [dev_name] - by device name (devices can listed with the eeprom list command)\n" 566 " [[bus] devaddr] - or by I2C bus and I2C device address\n" 567 "If no device specifier is given, the first driver-model found device is used." 568#endif 569#ifdef CONFIG_EEPROM_LAYOUT_VERSIONS 570 "\n\n" 571 "LAYOUT VERSIONS\n" 572 "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n" 573 "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n" 574 "The values which can be provided with the -l option are:\n" 575 CONFIG_EEPROM_LAYOUT_HELP_STRING"\n" 576#endif 577);