blob: 684a21aa582203915918d70cc0683fbe7970c3e5 [file] [log] [blame]
#include <common.h>
#include <command.h>
#include <errno.h>
#include <fs.h>
#ifdef CONFIG_COMCERTO_NAND_ERASE_FBB
#include <getopt.h>
#include <linux/stat.h>
#include <fcntl.h>
#include <ioctl.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/mtd-abi.h>
#endif /* CONFIG_COMCERTO_NAND_ERASE_FBB */
#define NANDDEVNAME "nand0"
#ifdef CONFIG_COMCERTO_NAND_ERASE_FBB
extern int erase_old_nand_fmt(struct mtd_info *mtd, u8 bb_old_layout);
static int do_erase_old_nand_fmt(struct command *cmdtp, int argc, char *argv[])
{
struct mtd_info_user user;
int fd, ret = 0;
char *filename = NULL;
struct stat s;
unsigned long start = 0, size = ~0;
if (argc != 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return COMMAND_ERROR_USAGE;
}
filename = argv[1];
if (stat(filename, &s)) {
printf("stat %s: %s\n", filename, errno_str());
return 1;
}
size = s.st_size;
if (!filename) {
printf("missing filename\n");
return 1;
}
fd = open(filename, O_RDWR);
if (fd < 0) {
printf("open %s: %s", filename, errno_str());
return 1;
}
ret = ioctl(fd, MEMGETINFO, &user);
/* Change ecc layout to HW BCH-8 */
erase_old_nand_fmt(user.mtd, 0);
if (erase(fd, size, start)) {
perror("erase");
ret = 1;
}
/* Change ecc layout to SW BCH */
erase_old_nand_fmt(user.mtd, 1);
if (erase(fd, size, start)) {
perror("erase");
ret = 1;
}
printf("\t\t\t\t!!Erasure of old NAND format completed!!\n");
printf("\t\t\t\t!!!! Please reboot the system now !!!!\n");
return 0;
}
static const __maybe_unused char cmd_erase_old_nand_fmt_help[] =
"Usage: erase_old_nand_fmt <mtddev>\n"
"Example: erase_old_nand_fmt /dev/nand0 \n"
"Erase old NAND format on <mtddev>\n";
BAREBOX_CMD_START(erase_old_nand_fmt)
.cmd = do_erase_old_nand_fmt,
.usage = "Erase old NAND format",
BAREBOX_CMD_HELP(cmd_erase_old_nand_fmt_help)
BAREBOX_CMD_END
#endif /* CONFIG_COMCERTO_NAND_ERASE_FBB */
#ifdef CONFIG_NAND_WRITE
int erase_nand(ulong offset, ulong count)
{
struct cdev *cdev;
int err;
cdev = cdev_by_name(NANDDEVNAME);
printf("Erasing from offset 0x%lx count 0x%lx ...\n", offset, count);
err = cdev->ops->erase(cdev, count, offset);
if (err) {
perror("erase failed\n");
perror("erase");
return -1;
} else {
printf("Erase completed\n");
}
printf("Done\n");
return 0;
}
EXPORT_SYMBOL(erase_nand);
static int do_erase_nand(struct command *cmdtp, int argc, char *argv[])
{
ulong offset, count;
if (argc != 3) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
offset = simple_strtoul(argv[1], NULL, 16);
count = simple_strtoul(argv[2], NULL, 16);
if (count == 0) {
puts ("Zero length ???\n");
return 1;
}
if(erase_nand(offset, count) < 0)
{
printf("ERROR: NAND Erase FAIL !!\n");
return -1;
}
return 0;
}
static const __maybe_unused char cmd_nand_erase_help[] =
"Usage: erase_nand <nand offset> <count>\n"
"Erase memory at nand offset\n";
BAREBOX_CMD_START(erase_nand)
.cmd = do_erase_nand,
.usage = "Erase the NAND",
BAREBOX_CMD_HELP(cmd_nand_erase_help)
BAREBOX_CMD_END
int update_nand(ulong src, ulong offset, ulong count)
{
struct cdev *cdev;
int err;
cdev = cdev_by_name(NANDDEVNAME);
printf("Erasing from offset 0x%lx count 0x%lx ...\n", offset, count);
err = cdev->ops->erase(cdev, count, offset);
if (err) {
perror("erase failed\n");
perror("erase");
return -1;
} else {
printf("Erase completed\n");
}
#if 1
printf("Writing ...\n");
err = cdev->ops->write(cdev, (char *)src, count, offset, 0);
if(err == -1)
{
perror("write failed\n");
perror("write");
return -1;
}
#endif
printf("Done\n");
return 0;
}
EXPORT_SYMBOL(update_nand);
static int do_update_nand(struct command *cmdtp, int argc, char *argv[])
{
ulong src, offset, count;
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
src = simple_strtoul(argv[1], NULL, 16);
offset = simple_strtoul(argv[2], NULL, 16);
count = simple_strtoul(argv[3], NULL, 16);
if (count == 0) {
puts ("Zero length ???\n");
return 1;
}
if(update_nand(src, offset, count) < 0)
{
printf("ERROR: NAND Update FAIL !!\n");
return -1;
}
return 0;
}
static const __maybe_unused char cmd_nand_help[] =
"Usage: update_nand <ddr src> <nand offset> <count>\n"
"Copy memory at <src> of <count> bytes to <dst>\n";
BAREBOX_CMD_START(update_nand)
.cmd = do_update_nand,
.usage = "Flash the NAND",
BAREBOX_CMD_HELP(cmd_nand_help)
BAREBOX_CMD_END
#endif /* CONFIG_NAND_WRITE */
int read_nand(ulong src, ulong offset, ulong count)
{
struct cdev *cdev;
int err;
cdev = cdev_by_name(NANDDEVNAME);
printf("Reading ...\n");
err = cdev->ops->read(cdev, (char *)src, count, offset, 0);
if(err < 0)
{
perror("read failed %d\n");
return -1;
}
printf("Done...Bytes read 0x%x\n", err);
return 0;
}
EXPORT_SYMBOL(read_nand);
static int do_read_nand(struct command *cmdtp, int argc, char *argv[])
{
ulong src, offset, count;
if (argc != 4) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
src = simple_strtoul(argv[1], NULL, 16);
offset = simple_strtoul(argv[2], NULL, 16);
count = simple_strtoul(argv[3], NULL, 16);
if (count == 0) {
puts ("Zero length ???\n");
return 1;
}
if(read_nand(src, offset, count) < 0)
{
printf("ERROR: NAND Read FAIL !!\n");
return -1;
}
return 0;
}
static const __maybe_unused char cmd_nand_read_help[] =
"Usage: read_nand <ddr src> <nand offset> <count>\n"
"Read NAND to <src> of <count> bytes from <offset>\n";
BAREBOX_CMD_START(read_nand)
.cmd = do_read_nand,
.usage = "Read the NAND",
BAREBOX_CMD_HELP(cmd_nand_read_help)
BAREBOX_CMD_END