diff options
Diffstat (limited to 'common/cmd_onenand.c')
| -rw-r--r-- | common/cmd_onenand.c | 155 | 
1 files changed, 155 insertions, 0 deletions
| diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c new file mode 100644 index 000000000..dcda099c8 --- /dev/null +++ b/common/cmd_onenand.c @@ -0,0 +1,155 @@ +/* + *  U-Boot command for OneNAND support + * + *  Copyright (C) 2005-2007 Samsung Electronics + *  Kyungmin Park <kyungmin.park@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> +#include <command.h> + +#ifdef CONFIG_CMD_ONENAND + +#include <linux/mtd/compat.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/onenand.h> + +#include <asm/io.h> + +extern struct mtd_info onenand_mtd; +extern struct onenand_chip onenand_chip; + +int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +	int ret = 0; + +	switch (argc) { +	case 0: +	case 1: +		printf("Usage:\n%s\n", cmdtp->usage); +		return 1; + +	case 2: +		if (strncmp(argv[1], "open", 4) == 0) { +			onenand_init(); +			return 0; +		} +		onenand_print_device_info(onenand_chip.device_id, 1); +		return 0; + +	default: +		/* At least 4 args */ +		if (strncmp(argv[1], "erase", 5) == 0) { +			struct erase_info instr; +			ulong start, end; +			ulong block; + +			start = simple_strtoul(argv[2], NULL, 10); +			end = simple_strtoul(argv[3], NULL, 10); +			start -= (unsigned long)onenand_chip.base; +			end -= (unsigned long)onenand_chip.base; + +			if (!end || end < 0) +				end = start; + +			printf("Erase block from %d to %d\n", start, end); + +			for (block = start; block <= end; block++) { +				instr.addr = block << onenand_chip.erase_shift; +				instr.len = 1 << onenand_chip.erase_shift; +				ret = onenand_erase(&onenand_mtd, &instr); +				if (ret) { +					printf("erase failed %d\n", block); +					break; +				} +			} + +			return 0; +		} + +		if (strncmp(argv[1], "read", 4) == 0) { +			ulong addr = simple_strtoul(argv[2], NULL, 16); +			ulong ofs = simple_strtoul(argv[3], NULL, 16); +			size_t len = simple_strtoul(argv[4], NULL, 16); +			size_t retlen = 0; +			int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1; + +			ofs -= (unsigned long)onenand_chip.base; + +			if (oob) +				onenand_read_oob(&onenand_mtd, ofs, len, +						 &retlen, (u_char *) addr); +			else +				onenand_read(&onenand_mtd, ofs, len, &retlen, +					     (u_char *) addr); +			printf("Done\n"); + +			return 0; +		} + +		if (strncmp(argv[1], "write", 5) == 0) { +			ulong addr = simple_strtoul(argv[2], NULL, 16); +			ulong ofs = simple_strtoul(argv[3], NULL, 16); +			size_t len = simple_strtoul(argv[4], NULL, 16); +			size_t retlen = 0; + +			ofs -= (unsigned long)onenand_chip.base; + +			onenand_write(&onenand_mtd, ofs, len, &retlen, +				      (u_char *) addr); +			printf("Done\n"); + +			return 0; +		} + +		if (strncmp(argv[1], "block", 5) == 0) { +			ulong addr = simple_strtoul(argv[2], NULL, 16); +			ulong block = simple_strtoul(argv[3], NULL, 10); +			ulong page = simple_strtoul(argv[4], NULL, 10); +			size_t len = simple_strtol(argv[5], NULL, 10); +			size_t retlen = 0; +			ulong ofs; +			int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1; + +			ofs = block << onenand_chip.erase_shift; +			if (page) +				ofs += page << onenand_chip.page_shift; + +			if (!len) { +				if (oob) +					len = 64; +				else +					len = 512; +			} + +			if (oob) +				onenand_read_oob(&onenand_mtd, ofs, len, +						 &retlen, (u_char *) addr); +			else +				onenand_read(&onenand_mtd, ofs, len, &retlen, +					     (u_char *) addr); +			return 0; +		} + +		break; +	} + +	return 0; +} + +U_BOOT_CMD( +	onenand,	6,	1,	do_onenand, +	"onenand - OneNAND sub-system\n", +	"info   - show available OneNAND devices\n" +	"onenand read[.oob] addr ofs len - read data at ofs with len to addr\n" +	"onenand write addr ofs len - write data at ofs with len from addr\n" +	"onenand erase saddr eaddr - erase block start addr to end addr\n" +	"onenand block[.oob] addr block [page] [len] - " +		"read data with (block [, page]) to addr" +); + +#endif /* CONFIG_CMD_ONENAND */ |