/*
 * (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>
#ifdef CONFIG_MX31
#include <asm/arch/mx31-regs.h>
#else
#include <asm/arch/imx-regs.h>
#endif
#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->nand_flash_config2) & NFC_INT))
		;

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

void nfc_nand_init(void)
{
#if defined(MXC_NFC_V1_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->configuration);

	/* hardware ECC checking and correct */
	config1 = readw(&nfc->nand_flash_config1) | NFC_ECC_EN | 0x800;
	/*
	 * 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->nand_flash_config1);
#elif defined(MXC_NFC_V1)
	/* unlocking RAM Buff */
	writew(0x2, &nfc->configuration);

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

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

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

	writew(0x00, &nfc->flash_add);
	writew(NFC_ADDR, &nfc->nand_flash_config2);
	nfc_wait_ready();

	/* code only for large page flash */
	if (CONFIG_SYS_NAND_PAGE_SIZE > 512) {
		writew(0x00, &nfc->flash_add);
		writew(NFC_ADDR, &nfc->nand_flash_config2);
		nfc_wait_ready();
	}

	page_count = CONFIG_SYS_NAND_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;

	if (page_address <= page_count) {
		page_count--; /* transform 0x01000000 to 0x00ffffff */
		do {
			writew(page_address & 0xff, &nfc->flash_add);
			writew(NFC_ADDR, &nfc->nand_flash_config2);
			nfc_wait_ready();
			page_address = page_address >> 8;
			page_count = page_count >> 8;
		} while (page_count);
	}

	writew(0x00, &nfc->flash_add);
	writew(NFC_ADDR, &nfc->nand_flash_config2);
	nfc_wait_ready();
}

static void nfc_nand_data_output(void)
{
	int config1 = readw(&nfc->nand_flash_config1);
#ifdef NAND_MXC_2K_MULTI_CYCLE
	int i;
#endif

	config1 |= NFC_ECC_EN | NFC_INT_MSK;
	writew(config1, &nfc->nand_flash_config1);
	writew(0, &nfc->buffer_address);
	writew(NFC_OUTPUT, &nfc->nand_flash_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++) {
		config1 = readw(&nfc->nand_flash_config1);
		config1 |= NFC_ECC_EN | NFC_INT_MSK;
		writew(config1, &nfc->nand_flash_config1);
		writew(i, &nfc->buffer_address);
		writew(NFC_OUTPUT, &nfc->nand_flash_config2);
		nfc_wait_ready();
	}
#endif
}

static int nfc_nand_check_ecc(void)
{
	return readw(&nfc->ecc_status_result);
}

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

	writew(0, &nfc->buffer_address); /* 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 */

	if (nfc_nand_check_ecc())
		return -1;

	src = &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++) {
		writew(0, &nfc->buffer_address); /* read in first 0 buffer */
		nfc_nand_command(NAND_CMD_READ0);
		nfc_nand_page_address(page);

		if (CONFIG_SYS_NAND_PAGE_SIZE > 512)
			nfc_nand_command(NAND_CMD_READSTART);

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

		src = &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) ;
}
