diff options
Diffstat (limited to 'common/cmd_sf.c')
| -rw-r--r-- | common/cmd_sf.c | 191 | 
1 files changed, 191 insertions, 0 deletions
| diff --git a/common/cmd_sf.c b/common/cmd_sf.c new file mode 100644 index 000000000..8c0a7514d --- /dev/null +++ b/common/cmd_sf.c @@ -0,0 +1,191 @@ +/* + * Command for accessing SPI flash. + * + * Copyright (C) 2008 Atmel Corporation + */ +#include <common.h> +#include <spi_flash.h> + +#include <asm/io.h> + +#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 + +static struct spi_flash *flash; + +static int do_spi_flash_probe(int argc, char *argv[]) +{ +	unsigned int bus = 0; +	unsigned int cs; +	unsigned int speed = CONFIG_SF_DEFAULT_SPEED; +	unsigned int mode = CONFIG_SF_DEFAULT_MODE; +	char *endp; +	struct spi_flash *new; + +	if (argc < 2) +		goto usage; + +	cs = simple_strtoul(argv[1], &endp, 0); +	if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) +		goto usage; +	if (*endp == ':') { +		if (endp[1] == 0) +			goto usage; + +		bus = cs; +		cs = simple_strtoul(endp + 1, &endp, 0); +		if (*endp != 0) +			goto usage; +	} + +	if (argc >= 3) { +		speed = simple_strtoul(argv[2], &endp, 0); +		if (*argv[2] == 0 || *endp != 0) +			goto usage; +	} +	if (argc >= 4) { +		mode = simple_strtoul(argv[3], &endp, 0); +		if (*argv[3] == 0 || *endp != 0) +			goto usage; +	} + +	new = spi_flash_probe(bus, cs, speed, mode); +	if (!new) { +		printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); +		return 1; +	} + +	if (flash) +		spi_flash_free(flash); +	flash = new; + +	printf("%u KiB %s at %u:%u is now current device\n", +			flash->size >> 10, flash->name, bus, cs); + +	return 0; + +usage: +	puts("Usage: sf probe [bus:]cs [hz] [mode]\n"); +	return 1; +} + +static int do_spi_flash_read_write(int argc, char *argv[]) +{ +	unsigned long addr; +	unsigned long offset; +	unsigned long len; +	void *buf; +	char *endp; +	int ret; + +	if (argc < 4) +		goto usage; + +	addr = simple_strtoul(argv[1], &endp, 16); +	if (*argv[1] == 0 || *endp != 0) +		goto usage; +	offset = simple_strtoul(argv[2], &endp, 16); +	if (*argv[2] == 0 || *endp != 0) +		goto usage; +	len = simple_strtoul(argv[3], &endp, 16); +	if (*argv[3] == 0 || *endp != 0) +		goto usage; + +	buf = map_physmem(addr, len, MAP_WRBACK); +	if (!buf) { +		puts("Failed to map physical memory\n"); +		return 1; +	} + +	if (strcmp(argv[0], "read") == 0) +		ret = spi_flash_read(flash, offset, len, buf); +	else +		ret = spi_flash_write(flash, offset, len, buf); + +	unmap_physmem(buf, len); + +	if (ret) { +		printf("SPI flash %s failed\n", argv[0]); +		return 1; +	} + +	return 0; + +usage: +	printf("Usage: sf %s addr offset len\n", argv[0]); +	return 1; +} + +static int do_spi_flash_erase(int argc, char *argv[]) +{ +	unsigned long offset; +	unsigned long len; +	char *endp; +	int ret; + +	if (argc < 3) +		goto usage; + +	offset = simple_strtoul(argv[1], &endp, 16); +	if (*argv[1] == 0 || *endp != 0) +		goto usage; +	len = simple_strtoul(argv[2], &endp, 16); +	if (*argv[2] == 0 || *endp != 0) +		goto usage; + +	ret = spi_flash_erase(flash, offset, len); +	if (ret) { +		printf("SPI flash %s failed\n", argv[0]); +		return 1; +	} + +	return 0; + +usage: +	puts("Usage: sf erase offset len\n"); +	return 1; +} + +static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	const char *cmd; + +	/* need at least two arguments */ +	if (argc < 2) +		goto usage; + +	cmd = argv[1]; + +	if (strcmp(cmd, "probe") == 0) +		return do_spi_flash_probe(argc - 1, argv + 1); + +	/* The remaining commands require a selected device */ +	if (!flash) { +		puts("No SPI flash selected. Please run `sf probe'\n"); +		return 1; +	} + +	if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0) +		return do_spi_flash_read_write(argc - 1, argv + 1); +	if (strcmp(cmd, "erase") == 0) +		return do_spi_flash_erase(argc - 1, argv + 1); + +usage: +	printf("Usage:\n%s\n", cmdtp->usage); +	return 1; +} + +U_BOOT_CMD( +	sf,	5,	1,	do_spi_flash, +	"sf	- SPI flash sub-system\n", +	"probe [bus:]cs [hz] [mode]	- init flash device on given SPI bus\n" +	"				  and chip select\n" +	"sf read addr offset len 	- read `len' bytes starting at\n" +	"				  `offset' to memory at `addr'\n" +	"sf write addr offset len	- write `len' bytes from memory\n" +	"				  at `addr' to flash at `offset'\n" +	"sf erase offset len		- erase `len' bytes from `offset'\n"); |