/*
 * (C) Copyright 2009
 * Magnus Lilja <lilja.magnus@gmail.com>
 *
 * (C) Copyright 2008
 * Maxim Artamonov, <scn1874 at yandex.ru>
 *
 * (C) Copyright 2006-2008
 * Stefan Roese, DENX Software Engineering, sr at 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/arch/imx-regs.h>
#include <asm/io.h>
#include <fsl_nfc.h>

static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR;

static void nfc_wait_ready(void)
{
	uint32_t tmp;

	while (!(readw(&nfc->config2) & NFC_INT))
		;

	/* Reset interrupt flag */
	tmp = readw(&nfc->config2);
	tmp &= ~NFC_INT;
	writew(tmp, &nfc->config2);
}

static void nfc_nand_init(void)
{
#if defined(MXC_NFC_V2_1)
	int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512;
	int config1;

	writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size);

	/* unlocking RAM Buff */
	writew(0x2, &nfc->config);

	/* hardware ECC checking and correct */
	config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK |
			NFC_ONE_CYCLE | NFC_FP_INT;
	/*
	 * if spare size is larger that 16 bytes per 512 byte hunk
	 * then use 8 symbol correction instead of 4
	 */
	if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16)
		config1 &= ~NFC_4_8N_ECC;
	else
		config1 |= NFC_4_8N_ECC;
	writew(config1, &nfc->config1);
#elif defined(MXC_NFC_V1)
	/* unlocking RAM Buff */
	writew(0x2, &nfc->config);

	/* hardware ECC checking and correct */
	writew(NFC_ECC_EN | NFC_INT_MSK, &nfc->config1);
#endif
}

static void nfc_nand_command(unsigned short command)
{
	writew(command, &nfc->flash_cmd);
	writew(NFC_CMD, &nfc->config2);
	nfc_wait_ready();
}

static void nfc_nand_address(unsigned short address)
{
	writew(address, &nfc->flash_addr);
	writew(NFC_ADDR, &nfc->config2);
	nfc_wait_ready();
}

static void nfc_nand_page_address(unsigned int page_address)
{
	unsigned int page_count;

	nfc_nand_address(0x00);

	/* code only for large page flash */
	if (CONFIG_SYS_NAND_PAGE_SIZE > 512)
		nfc_nand_address(0x00);

	page_count = CONFIG_SYS_NAND_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;

	if (page_address <= page_count) {
		page_count--; /* transform 0x01000000 to 0x00ffffff */
		do {
			nfc_nand_address(page_address & 0xff);
			page_address = page_address >> 8;
			page_count = page_count >> 8;
		} while (page_count);
	}

	nfc_nand_address(0x00);
}

static void nfc_nand_data_output(void)
{
#ifdef NAND_MXC_2K_MULTI_CYCLE
	int i;
#endif

	writew(0, &nfc->buf_addr);
	writew(NFC_OUTPUT, &nfc->config2);
	nfc_wait_ready();
#ifdef NAND_MXC_2K_MULTI_CYCLE
	/*
	 * This NAND controller requires multiple input commands
	 * for pages larger than 512 bytes.
	 */
	for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) {
		writew(i, &nfc->buf_addr);
		writew(NFC_OUTPUT, &nfc->config2);
		nfc_wait_ready();
	}
#endif
}

static int nfc_nand_check_ecc(void)
{
#if defined(MXC_NFC_V1)
	u16 ecc_status = readw(&nfc->ecc_status_result);
	return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2;
#elif defined(MXC_NFC_V2_1)
	u32 ecc_status = readl(&nfc->ecc_status_result);
	int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512;
	int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4;
	int subpages = CONFIG_SYS_NAND_PAGE_SIZE / 512;

	do {
		if ((ecc_status & 0xf) > err_limit)
			return 1;
		ecc_status >>= 4;
	} while (--subpages);

	return 0;
#endif
}

static void nfc_nand_read_page(unsigned int page_address)
{
	writew(0, &nfc->buf_addr); /* read in first 0 buffer */
	nfc_nand_command(NAND_CMD_READ0);
	nfc_nand_page_address(page_address);

	if (CONFIG_SYS_NAND_PAGE_SIZE > 512)
		nfc_nand_command(NAND_CMD_READSTART);

	nfc_nand_data_output(); /* fill the main buffer 0 */
}

static int nfc_read_page(unsigned int page_address, unsigned char *buf)
{
	int i;
	u32 *src;
	u32 *dst;

	nfc_nand_read_page(page_address);

	if (nfc_nand_check_ecc())
		return -1;

	src = (u32 *)&nfc->main_area[0][0];
	dst = (u32 *)buf;

	/* main copy loop from NAND-buffer to SDRAM memory */
	for (i = 0; i < CONFIG_SYS_NAND_PAGE_SIZE / 4; i++) {
		writel(readl(src), dst);
		src++;
		dst++;
	}

	return 0;
}

static int is_badblock(int pagenumber)
{
	int page = pagenumber;
	u32 badblock;
	u32 *src;

	/* Check the first two pages for bad block markers */
	for (page = pagenumber; page < pagenumber + 2; page++) {
		nfc_nand_read_page(page);

		src = (u32 *)&nfc->spare_area[0][0];

		/*
		 * IMPORTANT NOTE: The nand flash controller uses a non-
		 * standard layout for large page devices. This can
		 * affect the position of the bad block marker.
		 */
		/* Get the bad block marker */
		badblock = readl(&src[CONFIG_SYS_NAND_BAD_BLOCK_POS / 4]);
		badblock >>= 8 * (CONFIG_SYS_NAND_BAD_BLOCK_POS % 4);
		badblock &= 0xff;

		/* bad block marker verify */
		if (badblock != 0xff)
			return 1; /* potential bad block */
	}

	return 0;
}

static int nand_load(unsigned int from, unsigned int size, unsigned char *buf)
{
	int i;
	unsigned int page;
	unsigned int maxpages = CONFIG_SYS_NAND_SIZE /
				CONFIG_SYS_NAND_PAGE_SIZE;

	nfc_nand_init();

	/* Convert to page number */
	page = from / CONFIG_SYS_NAND_PAGE_SIZE;
	i = 0;

	while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) {
		if (nfc_read_page(page, buf) < 0)
			return -1;

		page++;
		i++;
		buf = buf + CONFIG_SYS_NAND_PAGE_SIZE;

		/*
		 * Check if we have crossed a block boundary, and if so
		 * check for bad block.
		 */
		if (!(page % CONFIG_SYS_NAND_PAGE_COUNT)) {
			/*
			 * Yes, new block. See if this block is good. If not,
			 * loop until we find a good block.
			 */
			while (is_badblock(page)) {
				page = page + CONFIG_SYS_NAND_PAGE_COUNT;
				/* Check i we've reached the end of flash. */
				if (page >= maxpages)
					return -1;
			}
		}
	}

	return 0;
}

#if defined(CONFIG_ARM)
void board_init_f (ulong bootflag)
{
	relocate_code (CONFIG_SYS_TEXT_BASE - TOTAL_MALLOC_LEN, NULL,
		       CONFIG_SYS_TEXT_BASE);
}
#endif

/*
 * 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)
{
	__attribute__((noreturn)) void (*uboot)(void);

	/*
	 * CONFIG_SYS_NAND_U_BOOT_OFFS and CONFIG_SYS_NAND_U_BOOT_SIZE must
	 * be aligned to full pages
	 */
	if (!nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
		       (uchar *)CONFIG_SYS_NAND_U_BOOT_DST)) {
		/* Copy from NAND successful, start U-boot */
		uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
		uboot();
	} else {
		/* Unrecoverable error when copying from NAND */
		hang();
	}
}

/*
 * Called in case of an exception.
 */
void hang(void)
{
	/* Loop forever */
	while (1) ;
}
