/*
 * (C) Copyright 2006-2008
 * Stefan Roese, DENX Software Engineering, sr@denx.de.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <nand.h>
#include <asm/io.h>

#define CFG_NAND_READ_DELAY \
	{ volatile int dummy; int i; for (i=0; i<10000; i++) dummy = i; }

static int nand_ecc_pos[] = CFG_NAND_ECCPOS;

extern void board_nand_init(struct nand_chip *nand);

#if (CFG_NAND_PAGE_SIZE <= 512)
/*
 * NAND command for small page NAND devices (512)
 */
static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 cmd)
{
	struct nand_chip *this = mtd->priv;
	int page_addr = page + block * CFG_NAND_PAGE_COUNT;
	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;

	if (this->dev_ready)
		while (!this->dev_ready(mtd))
			;
	else
		CFG_NAND_READ_DELAY;

	/* Begin command latch cycle */
	this->cmd_ctrl(mtd, cmd, ctrl);
	/* Set ALE and clear CLE to start address cycle */
	ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
	/* Column address */
	this->cmd_ctrl(mtd, offs, ctrl);
	ctrl &= ~NAND_CTRL_CHANGE;
	this->cmd_ctrl(mtd, (u8)(page_addr & 0xff), ctrl);	/* A[16:9] */
	ctrl &= ~NAND_CTRL_CHANGE;
	this->cmd_ctrl(mtd, (u8)((page_addr >> 8) & 0xff), ctrl); /* A[24:17] */
#ifdef CFG_NAND_4_ADDR_CYCLE
	/* One more address cycle for devices > 32MiB */
	this->cmd_ctrl(mtd, (u8)((page_addr >> 16) & 0x0f), ctrl); /* A[xx:25] */
#endif
	/* Latch in address */
	this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);

	/*
	 * Wait a while for the data to be ready
	 */
	if (this->dev_ready)
		while (!this->dev_ready(mtd))
			;
	else
		CFG_NAND_READ_DELAY;

	return 0;
}
#else
/*
 * NAND command for large page NAND devices (2k)
 */
static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8 cmd)
{
	struct nand_chip *this = mtd->priv;
	int page_offs = offs;
	int page_addr = page + block * CFG_NAND_PAGE_COUNT;

	if (this->dev_ready)
		this->dev_ready(mtd);
	else
		CFG_NAND_READ_DELAY;

	/* Emulate NAND_CMD_READOOB */
	if (cmd == NAND_CMD_READOOB) {
		page_offs += CFG_NAND_PAGE_SIZE;
		cmd = NAND_CMD_READ0;
	}

	/* Begin command latch cycle */
	this->hwcontrol(mtd, NAND_CTL_SETCLE);
	this->write_byte(mtd, cmd);
	/* Set ALE and clear CLE to start address cycle */
	this->hwcontrol(mtd, NAND_CTL_CLRCLE);
	this->hwcontrol(mtd, NAND_CTL_SETALE);
	/* Column address */
	this->write_byte(mtd, page_offs & 0xff);			/* A[7:0] */
	this->write_byte(mtd, (uchar)((page_offs >> 8) & 0xff));	/* A[11:9] */
	/* Row address */
	this->write_byte(mtd, (uchar)(page_addr & 0xff));		/* A[19:12] */
	this->write_byte(mtd, (uchar)((page_addr >> 8) & 0xff));	/* A[27:20] */
#ifdef CFG_NAND_5_ADDR_CYCLE
	/* One more address cycle for devices > 128MiB */
	this->write_byte(mtd, (uchar)((page_addr >> 16) & 0x0f));	/* A[xx:28] */
#endif
	/* Latch in address */
	this->hwcontrol(mtd, NAND_CTL_CLRALE);

	/* Begin command latch cycle */
	this->hwcontrol(mtd, NAND_CTL_SETCLE);
	/* Write out the start read command */
	this->write_byte(mtd, NAND_CMD_READSTART);
	/* End command latch cycle */
	this->hwcontrol(mtd, NAND_CTL_CLRCLE);

	/*
	 * Wait a while for the data to be ready
	 */
	if (this->dev_ready)
		this->dev_ready(mtd);
	else
		CFG_NAND_READ_DELAY;

	return 0;
}
#endif

static int nand_is_bad_block(struct mtd_info *mtd, int block)
{
	struct nand_chip *this = mtd->priv;

	nand_command(mtd, block, 0, CFG_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB);

	/*
	 * Read one byte
	 */
	if (in_8(this->IO_ADDR_R) != 0xff)
		return 1;

	return 0;
}

static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
{
	struct nand_chip *this = mtd->priv;
	u_char *ecc_calc;
	u_char *ecc_code;
	u_char *oob_data;
	int i;
	int eccsize = CFG_NAND_ECCSIZE;
	int eccbytes = CFG_NAND_ECCBYTES;
	int eccsteps = CFG_NAND_ECCSTEPS;
	uint8_t *p = dst;
	int stat;

	nand_command(mtd, block, page, 0, NAND_CMD_READ0);

	/* No malloc available for now, just use some temporary locations
	 * in SDRAM
	 */
	ecc_calc = (u_char *)(CFG_SDRAM_BASE + 0x10000);
	ecc_code = ecc_calc + 0x100;
	oob_data = ecc_calc + 0x200;

	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
		this->ecc.hwctl(mtd, NAND_ECC_READ);
		this->read_buf(mtd, p, eccsize);
		this->ecc.calculate(mtd, p, &ecc_calc[i]);
	}
	this->read_buf(mtd, oob_data, CFG_NAND_OOBSIZE);

	/* Pick the ECC bytes out of the oob data */
	for (i = 0; i < CFG_NAND_ECCTOTAL; i++)
		ecc_code[i] = oob_data[nand_ecc_pos[i]];

	eccsteps = CFG_NAND_ECCSTEPS;
	p = dst;

	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
		/* No chance to do something with the possible error message
		 * from correct_data(). We just hope that all possible errors
		 * are corrected by this routine.
		 */
		stat = this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
	}

	return 0;
}

static int nand_load(struct mtd_info *mtd, int offs, int uboot_size, uchar *dst)
{
	int block;
	int blockcopy_count;
	int page;

	/*
	 * offs has to be aligned to a block address!
	 */
	block = offs / CFG_NAND_BLOCK_SIZE;
	blockcopy_count = 0;

	while (blockcopy_count < (uboot_size / CFG_NAND_BLOCK_SIZE)) {
		if (!nand_is_bad_block(mtd, block)) {
			/*
			 * Skip bad blocks
			 */
			for (page = 0; page < CFG_NAND_PAGE_COUNT; page++) {
				nand_read_page(mtd, block, page, dst);
				dst += CFG_NAND_PAGE_SIZE;
			}

			blockcopy_count++;
		}

		block++;
	}

	return 0;
}

/*
 * The main entry for NAND booting. It's necessary that SDRAM is already
 * configured and available since this code loads the main U-Boot image
 * from NAND into SDRAM and starts it from there.
 */
void nand_boot(void)
{
	struct nand_chip nand_chip;
	nand_info_t nand_info;
	int ret;
	void (*uboot)(void);

	/*
	 * Init board specific nand support
	 */
	nand_info.priv = &nand_chip;
	nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W = (void  __iomem *)CFG_NAND_BASE;
	nand_chip.dev_ready = NULL;	/* preset to NULL */
	board_nand_init(&nand_chip);

	/*
	 * Load U-Boot image from NAND into RAM
	 */
	ret = nand_load(&nand_info, CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE,
			(uchar *)CFG_NAND_U_BOOT_DST);

	/*
	 * Jump to U-Boot image
	 */
	uboot = (void (*)(void))CFG_NAND_U_BOOT_START;
	(*uboot)();
}
