1 /* 2 * Command for accessing SPI flash. 3 * 4 * Copyright (C) 2008 Atmel Corporation 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <div64.h> 11 #include <dm.h> 12 #include <malloc.h> 13 #include <mapmem.h> 14 #include <spi.h> 15 #include <spi_flash.h> 16 #include <jffs2/jffs2.h> 17 #include <linux/mtd/mtd.h> 18 19 #include <asm/io.h> 20 #include <dm/device-internal.h> 21 22 static struct spi_flash *flash; 23 24 /* 25 * This function computes the length argument for the erase command. 26 * The length on which the command is to operate can be given in two forms: 27 * 1. <cmd> offset len - operate on <'offset', 'len') 28 * 2. <cmd> offset +len - operate on <'offset', 'round_up(len)') 29 * If the second form is used and the length doesn't fall on the 30 * sector boundary, than it will be adjusted to the next sector boundary. 31 * If it isn't in the flash, the function will fail (return -1). 32 * Input: 33 * arg: length specification (i.e. both command arguments) 34 * Output: 35 * len: computed length for operation 36 * Return: 37 * 1: success 38 * -1: failure (bad format, bad address). 39 */ 40 static int sf_parse_len_arg(char *arg, ulong *len) 41 { 42 char *ep; 43 char round_up_len; /* indicates if the "+length" form used */ 44 ulong len_arg; 45 46 round_up_len = 0; 47 if (*arg == '+') { 48 round_up_len = 1; 49 ++arg; 50 } 51 52 len_arg = simple_strtoul(arg, &ep, 16); 53 if (ep == arg || *ep != '\0') 54 return -1; 55 56 if (round_up_len && flash->sector_size > 0) 57 *len = ROUND(len_arg, flash->sector_size); 58 else 59 *len = len_arg; 60 61 return 1; 62 } 63 64 /** 65 * This function takes a byte length and a delta unit of time to compute the 66 * approximate bytes per second 67 * 68 * @param len amount of bytes currently processed 69 * @param start_ms start time of processing in ms 70 * @return bytes per second if OK, 0 on error 71 */ 72 static ulong bytes_per_second(unsigned int len, ulong start_ms) 73 { 74 /* less accurate but avoids overflow */ 75 if (len >= ((unsigned int) -1) / 1024) 76 return len / (max(get_timer(start_ms) / 1024, 1UL)); 77 else 78 return 1024 * len / max(get_timer(start_ms), 1UL); 79 } 80 81 static int do_spi_flash_probe(int argc, char * const argv[]) 82 { 83 unsigned int bus = CONFIG_SF_DEFAULT_BUS; 84 unsigned int cs = CONFIG_SF_DEFAULT_CS; 85 unsigned int speed = CONFIG_SF_DEFAULT_SPEED; 86 unsigned int mode = CONFIG_SF_DEFAULT_MODE; 87 char *endp; 88 #ifdef CONFIG_DM_SPI_FLASH 89 struct udevice *new, *bus_dev; 90 int ret; 91 /* In DM mode defaults will be taken from DT */ 92 speed = 0, mode = 0; 93 #else 94 struct spi_flash *new; 95 #endif 96 97 if (argc >= 2) { 98 cs = simple_strtoul(argv[1], &endp, 0); 99 if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) 100 return -1; 101 if (*endp == ':') { 102 if (endp[1] == 0) 103 return -1; 104 105 bus = cs; 106 cs = simple_strtoul(endp + 1, &endp, 0); 107 if (*endp != 0) 108 return -1; 109 } 110 } 111 112 if (argc >= 3) { 113 speed = simple_strtoul(argv[2], &endp, 0); 114 if (*argv[2] == 0 || *endp != 0) 115 return -1; 116 } 117 if (argc >= 4) { 118 mode = simple_strtoul(argv[3], &endp, 16); 119 if (*argv[3] == 0 || *endp != 0) 120 return -1; 121 } 122 123 #ifdef CONFIG_DM_SPI_FLASH 124 /* Remove the old device, otherwise probe will just be a nop */ 125 ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); 126 if (!ret) { 127 device_remove(new); 128 } 129 flash = NULL; 130 ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new); 131 if (ret) { 132 printf("Failed to initialize SPI flash at %u:%u (error %d)\n", 133 bus, cs, ret); 134 return 1; 135 } 136 137 flash = dev_get_uclass_priv(new); 138 #else 139 if (flash) 140 spi_flash_free(flash); 141 142 new = spi_flash_probe(bus, cs, speed, mode); 143 flash = new; 144 145 if (!new) { 146 printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); 147 return 1; 148 } 149 150 flash = new; 151 #endif 152 153 return 0; 154 } 155 156 /** 157 * Write a block of data to SPI flash, first checking if it is different from 158 * what is already there. 159 * 160 * If the data being written is the same, then *skipped is incremented by len. 161 * 162 * @param flash flash context pointer 163 * @param offset flash offset to write 164 * @param len number of bytes to write 165 * @param buf buffer to write from 166 * @param cmp_buf read buffer to use to compare data 167 * @param skipped Count of skipped data (incremented by this function) 168 * @return NULL if OK, else a string containing the stage which failed 169 */ 170 static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, 171 size_t len, const char *buf, char *cmp_buf, size_t *skipped) 172 { 173 char *ptr = (char *)buf; 174 175 debug("offset=%#x, sector_size=%#x, len=%#zx\n", 176 offset, flash->sector_size, len); 177 /* Read the entire sector so to allow for rewriting */ 178 if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf)) 179 return "read"; 180 /* Compare only what is meaningful (len) */ 181 if (memcmp(cmp_buf, buf, len) == 0) { 182 debug("Skip region %x size %zx: no change\n", 183 offset, len); 184 *skipped += len; 185 return NULL; 186 } 187 /* Erase the entire sector */ 188 if (spi_flash_erase(flash, offset, flash->sector_size)) 189 return "erase"; 190 /* If it's a partial sector, copy the data into the temp-buffer */ 191 if (len != flash->sector_size) { 192 memcpy(cmp_buf, buf, len); 193 ptr = cmp_buf; 194 } 195 /* Write one complete sector */ 196 if (spi_flash_write(flash, offset, flash->sector_size, ptr)) 197 return "write"; 198 199 return NULL; 200 } 201 202 /** 203 * Update an area of SPI flash by erasing and writing any blocks which need 204 * to change. Existing blocks with the correct data are left unchanged. 205 * 206 * @param flash flash context pointer 207 * @param offset flash offset to write 208 * @param len number of bytes to write 209 * @param buf buffer to write from 210 * @return 0 if ok, 1 on error 211 */ 212 static int spi_flash_update(struct spi_flash *flash, u32 offset, 213 size_t len, const char *buf) 214 { 215 const char *err_oper = NULL; 216 char *cmp_buf; 217 const char *end = buf + len; 218 size_t todo; /* number of bytes to do in this pass */ 219 size_t skipped = 0; /* statistics */ 220 const ulong start_time = get_timer(0); 221 size_t scale = 1; 222 const char *start_buf = buf; 223 ulong delta; 224 225 if (end - buf >= 200) 226 scale = (end - buf) / 100; 227 cmp_buf = memalign(ARCH_DMA_MINALIGN, flash->sector_size); 228 if (cmp_buf) { 229 ulong last_update = get_timer(0); 230 231 for (; buf < end && !err_oper; buf += todo, offset += todo) { 232 todo = min_t(size_t, end - buf, flash->sector_size); 233 if (get_timer(last_update) > 100) { 234 printf(" \rUpdating, %zu%% %lu B/s", 235 100 - (end - buf) / scale, 236 bytes_per_second(buf - start_buf, 237 start_time)); 238 last_update = get_timer(0); 239 } 240 err_oper = spi_flash_update_block(flash, offset, todo, 241 buf, cmp_buf, &skipped); 242 } 243 } else { 244 err_oper = "malloc"; 245 } 246 free(cmp_buf); 247 putc('\r'); 248 if (err_oper) { 249 printf("SPI flash failed in %s step\n", err_oper); 250 return 1; 251 } 252 253 delta = get_timer(start_time); 254 printf("%zu bytes written, %zu bytes skipped", len - skipped, 255 skipped); 256 printf(" in %ld.%lds, speed %ld B/s\n", 257 delta / 1000, delta % 1000, bytes_per_second(len, start_time)); 258 259 return 0; 260 } 261 262 static int do_spi_flash_read_write(int argc, char * const argv[]) 263 { 264 unsigned long addr; 265 void *buf; 266 char *endp; 267 int ret = 1; 268 int dev = 0; 269 loff_t offset, len, maxsize; 270 271 if (argc < 3) 272 return -1; 273 274 addr = simple_strtoul(argv[1], &endp, 16); 275 if (*argv[1] == 0 || *endp != 0) 276 return -1; 277 278 if (mtd_arg_off_size(argc - 2, &argv[2], &dev, &offset, &len, 279 &maxsize, MTD_DEV_TYPE_NOR, flash->size)) 280 return -1; 281 282 /* Consistency checking */ 283 if (offset + len > flash->size) { 284 printf("ERROR: attempting %s past flash size (%#x)\n", 285 argv[0], flash->size); 286 return 1; 287 } 288 289 buf = map_physmem(addr, len, MAP_WRBACK); 290 if (!buf) { 291 puts("Failed to map physical memory\n"); 292 return 1; 293 } 294 295 if (strcmp(argv[0], "update") == 0) { 296 ret = spi_flash_update(flash, offset, len, buf); 297 } else if (strncmp(argv[0], "read", 4) == 0 || 298 strncmp(argv[0], "write", 5) == 0) { 299 int read; 300 301 read = strncmp(argv[0], "read", 4) == 0; 302 if (read) 303 ret = spi_flash_read(flash, offset, len, buf); 304 else 305 ret = spi_flash_write(flash, offset, len, buf); 306 307 printf("SF: %zu bytes @ %#x %s: ", (size_t)len, (u32)offset, 308 read ? "Read" : "Written"); 309 if (ret) 310 printf("ERROR %d\n", ret); 311 else 312 printf("OK\n"); 313 } 314 315 unmap_physmem(buf, len); 316 317 return ret == 0 ? 0 : 1; 318 } 319 320 static int do_spi_flash_erase(int argc, char * const argv[]) 321 { 322 int ret; 323 int dev = 0; 324 loff_t offset, len, maxsize; 325 ulong size; 326 327 if (argc < 3) 328 return -1; 329 330 if (mtd_arg_off(argv[1], &dev, &offset, &len, &maxsize, 331 MTD_DEV_TYPE_NOR, flash->size)) 332 return -1; 333 334 ret = sf_parse_len_arg(argv[2], &size); 335 if (ret != 1) 336 return -1; 337 338 /* Consistency checking */ 339 if (offset + size > flash->size) { 340 printf("ERROR: attempting %s past flash size (%#x)\n", 341 argv[0], flash->size); 342 return 1; 343 } 344 345 ret = spi_flash_erase(flash, offset, size); 346 printf("SF: %zu bytes @ %#x Erased: %s\n", (size_t)size, (u32)offset, 347 ret ? "ERROR" : "OK"); 348 349 return ret == 0 ? 0 : 1; 350 } 351 352 static int do_spi_protect(int argc, char * const argv[]) 353 { 354 int ret = 0; 355 loff_t start, len; 356 bool prot = false; 357 358 if (argc != 4) 359 return -1; 360 361 if (!str2off(argv[2], &start)) { 362 puts("start sector is not a valid number\n"); 363 return 1; 364 } 365 366 if (!str2off(argv[3], &len)) { 367 puts("len is not a valid number\n"); 368 return 1; 369 } 370 371 if (strcmp(argv[1], "lock") == 0) 372 prot = true; 373 else if (strcmp(argv[1], "unlock") == 0) 374 prot = false; 375 else 376 return -1; /* Unknown parameter */ 377 378 ret = spi_flash_protect(flash, start, len, prot); 379 380 return ret == 0 ? 0 : 1; 381 } 382 383 #ifdef CONFIG_CMD_SF_TEST 384 enum { 385 STAGE_ERASE, 386 STAGE_CHECK, 387 STAGE_WRITE, 388 STAGE_READ, 389 390 STAGE_COUNT, 391 }; 392 393 static char *stage_name[STAGE_COUNT] = { 394 "erase", 395 "check", 396 "write", 397 "read", 398 }; 399 400 struct test_info { 401 int stage; 402 int bytes; 403 unsigned base_ms; 404 unsigned time_ms[STAGE_COUNT]; 405 }; 406 407 static void show_time(struct test_info *test, int stage) 408 { 409 uint64_t speed; /* KiB/s */ 410 int bps; /* Bits per second */ 411 412 speed = (long long)test->bytes * 1000; 413 if (test->time_ms[stage]) 414 do_div(speed, test->time_ms[stage] * 1024); 415 bps = speed * 8; 416 417 printf("%d %s: %d ticks, %d KiB/s %d.%03d Mbps\n", stage, 418 stage_name[stage], test->time_ms[stage], 419 (int)speed, bps / 1000, bps % 1000); 420 } 421 422 static void spi_test_next_stage(struct test_info *test) 423 { 424 test->time_ms[test->stage] = get_timer(test->base_ms); 425 show_time(test, test->stage); 426 test->base_ms = get_timer(0); 427 test->stage++; 428 } 429 430 /** 431 * Run a test on the SPI flash 432 * 433 * @param flash SPI flash to use 434 * @param buf Source buffer for data to write 435 * @param len Size of data to read/write 436 * @param offset Offset within flash to check 437 * @param vbuf Verification buffer 438 * @return 0 if ok, -1 on error 439 */ 440 static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len, 441 ulong offset, uint8_t *vbuf) 442 { 443 struct test_info test; 444 int i; 445 446 printf("SPI flash test:\n"); 447 memset(&test, '\0', sizeof(test)); 448 test.base_ms = get_timer(0); 449 test.bytes = len; 450 if (spi_flash_erase(flash, offset, len)) { 451 printf("Erase failed\n"); 452 return -1; 453 } 454 spi_test_next_stage(&test); 455 456 if (spi_flash_read(flash, offset, len, vbuf)) { 457 printf("Check read failed\n"); 458 return -1; 459 } 460 for (i = 0; i < len; i++) { 461 if (vbuf[i] != 0xff) { 462 printf("Check failed at %d\n", i); 463 print_buffer(i, vbuf + i, 1, 464 min_t(uint, len - i, 0x40), 0); 465 return -1; 466 } 467 } 468 spi_test_next_stage(&test); 469 470 if (spi_flash_write(flash, offset, len, buf)) { 471 printf("Write failed\n"); 472 return -1; 473 } 474 memset(vbuf, '\0', len); 475 spi_test_next_stage(&test); 476 477 if (spi_flash_read(flash, offset, len, vbuf)) { 478 printf("Read failed\n"); 479 return -1; 480 } 481 spi_test_next_stage(&test); 482 483 for (i = 0; i < len; i++) { 484 if (buf[i] != vbuf[i]) { 485 printf("Verify failed at %d, good data:\n", i); 486 print_buffer(i, buf + i, 1, 487 min_t(uint, len - i, 0x40), 0); 488 printf("Bad data:\n"); 489 print_buffer(i, vbuf + i, 1, 490 min_t(uint, len - i, 0x40), 0); 491 return -1; 492 } 493 } 494 printf("Test passed\n"); 495 for (i = 0; i < STAGE_COUNT; i++) 496 show_time(&test, i); 497 498 return 0; 499 } 500 501 static int do_spi_flash_test(int argc, char * const argv[]) 502 { 503 unsigned long offset; 504 unsigned long len; 505 uint8_t *buf, *from; 506 char *endp; 507 uint8_t *vbuf; 508 int ret; 509 510 if (argc < 3) 511 return -1; 512 offset = simple_strtoul(argv[1], &endp, 16); 513 if (*argv[1] == 0 || *endp != 0) 514 return -1; 515 len = simple_strtoul(argv[2], &endp, 16); 516 if (*argv[2] == 0 || *endp != 0) 517 return -1; 518 519 vbuf = memalign(ARCH_DMA_MINALIGN, len); 520 if (!vbuf) { 521 printf("Cannot allocate memory (%lu bytes)\n", len); 522 return 1; 523 } 524 buf = memalign(ARCH_DMA_MINALIGN, len); 525 if (!buf) { 526 free(vbuf); 527 printf("Cannot allocate memory (%lu bytes)\n", len); 528 return 1; 529 } 530 531 from = map_sysmem(CONFIG_SYS_TEXT_BASE, 0); 532 memcpy(buf, from, len); 533 ret = spi_flash_test(flash, buf, len, offset, vbuf); 534 free(vbuf); 535 free(buf); 536 if (ret) { 537 printf("Test failed\n"); 538 return 1; 539 } 540 541 return 0; 542 } 543 #endif /* CONFIG_CMD_SF_TEST */ 544 545 static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, 546 char * const argv[]) 547 { 548 const char *cmd; 549 int ret; 550 551 /* need at least two arguments */ 552 if (argc < 2) 553 goto usage; 554 555 cmd = argv[1]; 556 --argc; 557 ++argv; 558 559 if (strcmp(cmd, "probe") == 0) { 560 ret = do_spi_flash_probe(argc, argv); 561 goto done; 562 } 563 564 /* The remaining commands require a selected device */ 565 if (!flash) { 566 puts("No SPI flash selected. Please run `sf probe'\n"); 567 return 1; 568 } 569 570 if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0 || 571 strcmp(cmd, "update") == 0) 572 ret = do_spi_flash_read_write(argc, argv); 573 else if (strcmp(cmd, "erase") == 0) 574 ret = do_spi_flash_erase(argc, argv); 575 else if (strcmp(cmd, "protect") == 0) 576 ret = do_spi_protect(argc, argv); 577 #ifdef CONFIG_CMD_SF_TEST 578 else if (!strcmp(cmd, "test")) 579 ret = do_spi_flash_test(argc, argv); 580 #endif 581 else 582 ret = -1; 583 584 done: 585 if (ret != -1) 586 return ret; 587 588 usage: 589 return CMD_RET_USAGE; 590 } 591 592 #ifdef CONFIG_CMD_SF_TEST 593 #define SF_TEST_HELP "\nsf test offset len " \ 594 "- run a very basic destructive test" 595 #else 596 #define SF_TEST_HELP 597 #endif 598 599 U_BOOT_CMD( 600 sf, 5, 1, do_spi_flash, 601 "SPI flash sub-system", 602 "probe [[bus:]cs] [hz] [mode] - init flash device on given SPI bus\n" 603 " and chip select\n" 604 "sf read addr offset|partition len - read `len' bytes starting at\n" 605 " `offset' or from start of mtd\n" 606 " `partition'to memory at `addr'\n" 607 "sf write addr offset|partition len - write `len' bytes from memory\n" 608 " at `addr' to flash at `offset'\n" 609 " or to start of mtd `partition'\n" 610 "sf erase offset|partition [+]len - erase `len' bytes from `offset'\n" 611 " or from start of mtd `partition'\n" 612 " `+len' round up `len' to block size\n" 613 "sf update addr offset|partition len - erase and write `len' bytes from memory\n" 614 " at `addr' to flash at `offset'\n" 615 " or to start of mtd `partition'\n" 616 "sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" 617 " at address 'sector'\n" 618 SF_TEST_HELP 619 ); 620