/*
 * 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

extern 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, 16);
		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;
}
#ifdef CONFIG_SPI_FLASH_PROTECTION
static int do_spi_flash_protect(int argc, char *argv[])
{
	int ret;
	const char *cmd;

	if (argc < 2)
		goto usage;

	cmd = argv[1];
	
	if (strcmp(cmd, "on") == 0)
		ret = spi_flash_protect(flash, 1);
	if (strcmp(cmd, "off") == 0)
		ret = spi_flash_protect(flash, 0);
	if (strcmp(cmd, "all_off") == 0)
		ret = spi_flash_protect(flash, -1);
	if (ret) {
		printf("SPI flash %s failed\n", argv[0]);
		return 1;
	}

	return 0;

usage:
	puts("Usage: sf protect on/off/all_off\n");
	return 1;
}

static int do_spi_flash_lock(int argc, char *argv[])
{
	int ret;
	int lock;
	char *endp;
	unsigned long offset;

	if (argc < 2)
		goto usage;

	offset = simple_strtoul(argv[1], &endp, 0);
	if (*endp)
		goto usage;

	if (argc < 3)
		ret = spi_flash_read_lock(flash, offset, &lock);
	else {
		if (!strcmp(argv[2], "off"))
			lock = SPI_FLASH_LOCK_NONE;
		else if (!strcmp(argv[2], "on"))
			lock = SPI_FLASH_LOCK_WRITE;
		else if (!strcmp(argv[2], "never"))
			lock = SPI_FLASH_LOCK_DOWN;
		else if (!strcmp(argv[2], "forever"))
			lock = SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN;
		else
			goto usage;

		ret = spi_flash_write_lock(flash, offset, lock);
	}

	if (ret) {
		printf("SPI flash %s failed, error %d\n", argv[0], ret);
		return 1;
	}
	else if (argc < 3) {
		switch (lock) {
		case SPI_FLASH_LOCK_NONE:
			puts("off\n");
			break;
		case SPI_FLASH_LOCK_WRITE:
			puts("on\n");
			break;
		case SPI_FLASH_LOCK_DOWN:
			puts("never\n");
			break;
		case SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN:
			puts("forever\n");
			break;
		default:
			printf("? (%x)\n", lock);
			break;
		}
	}

	return 0;

usage:
	puts("Usage: sf lock offset [mode]\n"
		" modes:\n"
		"  'off' - unlocked\n"
		"  'on' - locked\n"
		"  'never' - unlock until power cycle\n"
		"  'forever' - lock until power cycle\n");

	return 1;
}

static int do_spi_flash_lock_range(int argc, char *argv[])
{
	int ret;
	int lock;
	char *endp;
	unsigned long offset;
	unsigned long len;

	if (argc < 4)
		goto usage;

	offset = simple_strtoul(argv[1], &endp, 0);
	if (*endp)
		goto usage;

	len = simple_strtoul(argv[2], &endp, 0);
	if (*endp)
		goto usage;

	if (!strcmp(argv[3], "off"))
		lock = SPI_FLASH_LOCK_NONE;
	else if (!strcmp(argv[3], "on"))
		lock = SPI_FLASH_LOCK_WRITE;
	else if (!strcmp(argv[3], "never"))
		lock = SPI_FLASH_LOCK_DOWN;
	else if (!strcmp(argv[3], "forever"))
		lock = SPI_FLASH_LOCK_WRITE|SPI_FLASH_LOCK_DOWN;
	else
		goto usage;

	ret = spi_flash_lock(flash, offset, len, lock);
	if (ret) {
		printf("SPI flash %s failed, error %d\n", argv[0], ret);
		return 1;
	}

	return 0;

usage:
	puts("Usage: sf lock-range offset len mode\n"
		" modes:\n"
		"  'off' - unlocked\n"
		"  'on' - locked\n"
		"  'never' - unlock until power cycle\n"
		"  'forever' - lock until power cycle\n");

	return 1;
}
#endif

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);
#ifdef CONFIG_SPI_FLASH_PROTECTION
	if (strcmp(cmd, "protect") == 0)
		return do_spi_flash_protect(argc - 1, argv + 1);
	if (strcmp(cmd, "lock") == 0)
		return do_spi_flash_lock(argc - 1, argv + 1);
	if (strcmp(cmd, "lock-range") == 0)
		return do_spi_flash_lock_range(argc - 1, argv + 1);
#endif

usage:
	cmd_usage(cmdtp);
	return 1;
}

U_BOOT_CMD(
	sf,	5,	1,	do_spi_flash,
	"SPI flash sub-system",
	"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"
#ifdef CONFIG_SPI_FLASH_PROTECTION
	"sf protect on			- protect spi flash\n"
	"sf protect off			- unprotect spi flash\n"
	"sf lock offset [mode]		- get sector lock or set to `mode'\n"
	"sf lock-range offset len mode	- set address range lock to `mode'\n"
#endif
);
