X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=common%2Fcmd_sf.c;h=6aabf39302ce5e9000d19777a1622b27d1d52189;hb=b45122fdf5d314ef1f492b051fb104a7b48b8079;hp=4af0f0af26bcfa3afbc63708fb019a89cc99d274;hpb=e20cc2ca15b5b0644f51b6e58d530d70acd2bc00;p=u-boot diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 4af0f0af26..6aabf39302 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -2,32 +2,23 @@ * Command for accessing SPI flash. * * Copyright (C) 2008 Atmel Corporation - * Licensed under the GPL-2 or later. + * + * SPDX-License-Identifier: GPL-2.0+ */ #include #include +#include #include +#include +#include #include #include - -#ifndef CONFIG_SF_DEFAULT_SPEED -# define CONFIG_SF_DEFAULT_SPEED 1000000 -#endif -#ifndef CONFIG_SF_DEFAULT_MODE -# define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 -#endif -#ifndef CONFIG_SF_DEFAULT_CS -# define CONFIG_SF_DEFAULT_CS 0 -#endif -#ifndef CONFIG_SF_DEFAULT_BUS -# define CONFIG_SF_DEFAULT_BUS 0 -#endif +#include static struct spi_flash *flash; - /* * This function computes the length argument for the erase command. * The length on which the command is to operate can be given in two forms: @@ -80,9 +71,9 @@ static ulong bytes_per_second(unsigned int len, ulong start_ms) { /* less accurate but avoids overflow */ if (len >= ((unsigned int) -1) / 1024) - return len / (max(get_timer(start_ms) / 1024, 1)); + return len / (max(get_timer(start_ms) / 1024, 1UL)); else - return 1024 * len / max(get_timer(start_ms), 1); + return 1024 * len / max(get_timer(start_ms), 1UL); } static int do_spi_flash_probe(int argc, char * const argv[]) @@ -92,7 +83,12 @@ static int do_spi_flash_probe(int argc, char * const argv[]) unsigned int speed = CONFIG_SF_DEFAULT_SPEED; unsigned int mode = CONFIG_SF_DEFAULT_MODE; char *endp; +#ifdef CONFIG_DM_SPI_FLASH + struct udevice *new, *bus_dev; + int ret; +#else struct spi_flash *new; +#endif if (argc >= 2) { cs = simple_strtoul(argv[1], &endp, 0); @@ -120,6 +116,23 @@ static int do_spi_flash_probe(int argc, char * const argv[]) return -1; } +#ifdef CONFIG_DM_SPI_FLASH + /* Remove the old device, otherwise probe will just be a nop */ + ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new); + if (!ret) { + device_remove(new); + device_unbind(new); + } + flash = NULL; + ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new); + if (ret) { + printf("Failed to initialize SPI flash at %u:%u (error %d)\n", + bus, cs, ret); + return 1; + } + + flash = dev_get_uclass_priv(new); +#else new = spi_flash_probe(bus, cs, speed, mode); if (!new) { printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); @@ -129,6 +142,7 @@ static int do_spi_flash_probe(int argc, char * const argv[]) if (flash) spi_flash_free(flash); flash = new; +#endif return 0; } @@ -152,8 +166,10 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, { debug("offset=%#x, sector_size=%#x, len=%#zx\n", offset, flash->sector_size, len); - if (spi_flash_read(flash, offset, len, cmp_buf)) + /* Read the entire sector so to allow for rewriting */ + if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf)) return "read"; + /* Compare only what is meaningful (len) */ if (memcmp(cmp_buf, buf, len) == 0) { debug("Skip region %x size %zx: no change\n", offset, len); @@ -163,8 +179,17 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset, /* Erase the entire sector */ if (spi_flash_erase(flash, offset, flash->sector_size)) return "erase"; + /* Write the initial part of the block from the source */ if (spi_flash_write(flash, offset, len, buf)) return "write"; + /* If it's a partial sector, rewrite the existing part */ + if (len != flash->sector_size) { + /* Rewrite the original data to the end of the sector */ + if (spi_flash_write(flash, offset + len, + flash->sector_size - len, &cmp_buf[len])) + return "write"; + } + return NULL; } @@ -198,7 +223,7 @@ static int spi_flash_update(struct spi_flash *flash, u32 offset, ulong last_update = get_timer(0); for (; buf < end && !err_oper; buf += todo, offset += todo) { - todo = min(end - buf, flash->sector_size); + todo = min_t(size_t, end - buf, flash->sector_size); if (get_timer(last_update) > 100) { printf(" \rUpdating, %zu%% %lu B/s", 100 - (end - buf) / scale, @@ -346,7 +371,8 @@ static void show_time(struct test_info *test, int stage) int bps; /* Bits per second */ speed = (long long)test->bytes * 1000; - do_div(speed, test->time_ms[stage] * 1024); + if (test->time_ms[stage]) + do_div(speed, test->time_ms[stage] * 1024); bps = speed * 8; printf("%d %s: %d ticks, %d KiB/s %d.%03d Mbps\n", stage, @@ -395,7 +421,8 @@ static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len, for (i = 0; i < len; i++) { if (vbuf[i] != 0xff) { printf("Check failed at %d\n", i); - print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0); + print_buffer(i, vbuf + i, 1, + min_t(uint, len - i, 0x40), 0); return -1; } } @@ -417,9 +444,11 @@ static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len, for (i = 0; i < len; i++) { if (buf[i] != vbuf[i]) { printf("Verify failed at %d, good data:\n", i); - print_buffer(i, buf + i, 1, min(len - i, 0x40), 0); + print_buffer(i, buf + i, 1, + min_t(uint, len - i, 0x40), 0); printf("Bad data:\n"); - print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0); + print_buffer(i, vbuf + i, 1, + min_t(uint, len - i, 0x40), 0); return -1; } } @@ -434,11 +463,13 @@ static int do_spi_flash_test(int argc, char * const argv[]) { unsigned long offset; unsigned long len; - uint8_t *buf = (uint8_t *)CONFIG_SYS_TEXT_BASE; + uint8_t *buf, *from; char *endp; uint8_t *vbuf; int ret; + if (argc < 3) + return -1; offset = simple_strtoul(argv[1], &endp, 16); if (*argv[1] == 0 || *endp != 0) return -1; @@ -448,17 +479,18 @@ static int do_spi_flash_test(int argc, char * const argv[]) vbuf = malloc(len); if (!vbuf) { - printf("Cannot allocate memory\n"); + printf("Cannot allocate memory (%lu bytes)\n", len); return 1; } buf = malloc(len); if (!buf) { free(vbuf); - printf("Cannot allocate memory\n"); + printf("Cannot allocate memory (%lu bytes)\n", len); return 1; } - memcpy(buf, (char *)CONFIG_SYS_TEXT_BASE, len); + from = map_sysmem(CONFIG_SYS_TEXT_BASE, 0); + memcpy(buf, from, len); ret = spi_flash_test(flash, buf, len, offset, vbuf); free(vbuf); free(buf);