/*
 * NAND boot for Freescale Integrated Flash Controller, NAND FCM
 *
 * Copyright 2011 Freescale Semiconductor, Inc.
 * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/io.h>
#include <fsl_ifc.h>
#include <linux/mtd/nand.h>

static inline int is_blank(uchar *addr, int page_size)
{
	int i;

	for (i = 0; i < page_size; i++) {
		if (__raw_readb(&addr[i]) != 0xff)
			return 0;
	}

	/*
	 * For the SPL, don't worry about uncorrectable errors
	 * where the main area is all FFs but shouldn't be.
	 */
	return 1;
}

/* returns nonzero if entire page is blank */
static inline int check_read_ecc(uchar *buf, u32 *eccstat,
				 unsigned int bufnum, int page_size)
{
	u32 reg = eccstat[bufnum / 4];
	int errors = (reg >> ((3 - bufnum % 4) * 8)) & 0xf;

	if (errors == 0xf) { /* uncorrectable */
		/* Blank pages fail hw ECC checks */
		if (is_blank(buf, page_size))
			return 1;

		puts("ecc error\n");
		for (;;)
			;
	}

	return 0;
}

static inline void nand_wait(uchar *buf, int bufnum, int page_size)
{
	struct fsl_ifc *ifc = IFC_BASE_ADDR;
	u32 status;
	u32 eccstat[4];
	int bufperpage = page_size / 512;
	int bufnum_end, i;

	bufnum *= bufperpage;
	bufnum_end = bufnum + bufperpage - 1;

	do {
		status = ifc_in32(&ifc->ifc_nand.nand_evter_stat);
	} while (!(status & IFC_NAND_EVTER_STAT_OPC));

	if (status & IFC_NAND_EVTER_STAT_FTOER) {
		puts("flash time out error\n");
		for (;;)
			;
	}

	for (i = bufnum / 4; i <= bufnum_end / 4; i++)
		eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);

	for (i = bufnum; i <= bufnum_end; i++) {
		if (check_read_ecc(buf, eccstat, i, page_size))
			break;
	}

	ifc_out32(&ifc->ifc_nand.nand_evter_stat, status);
}

static inline int bad_block(uchar *marker, int port_size)
{
	if (port_size == 8)
		return __raw_readb(marker) != 0xff;
	else
		return __raw_readw((u16 *)marker) != 0xffff;
}

int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
{
	struct fsl_ifc *ifc = IFC_BASE_ADDR;
	uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
	int page_size;
	int port_size;
	int pages_per_blk;
	int blk_size;
	int bad_marker = 0;
	int bufnum_mask, bufnum, ver = 0;

	int csor, cspr;
	int pos = 0;
	int j = 0;

	int sram_addr;
	int pg_no;
	uchar *dst = vdst;

	/* Get NAND Flash configuration */
	csor = CONFIG_SYS_NAND_CSOR;
	cspr = CONFIG_SYS_NAND_CSPR;

	port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;

	if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_8K) {
		page_size = 8192;
		bufnum_mask = 0x0;
	} else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_4K) {
		page_size = 4096;
		bufnum_mask = 0x1;
	} else if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) {
		page_size = 2048;
		bufnum_mask = 0x3;
	} else {
		page_size = 512;
		bufnum_mask = 0xf;

		if (port_size == 8)
			bad_marker = 5;
	}

	ver = ifc_in32(&ifc->ifc_rev);
	if (ver >= FSL_IFC_V2_0_0)
		bufnum_mask = (bufnum_mask * 2) + 1;

	pages_per_blk =
		32 << ((csor & CSOR_NAND_PB_MASK) >> CSOR_NAND_PB_SHIFT);

	blk_size = pages_per_blk * page_size;

	/* Open Full SRAM mapping for spare are access */
	ifc_out32(&ifc->ifc_nand.ncfgr, 0x0);

	/* Clear Boot events */
	ifc_out32(&ifc->ifc_nand.nand_evter_stat, 0xffffffff);

	/* Program FIR/FCR for Large/Small page */
	if (page_size > 512) {
		ifc_out32(&ifc->ifc_nand.nand_fir0,
			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
			  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
			  (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
			  (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
			  (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP4_SHIFT));
		ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);

		ifc_out32(&ifc->ifc_nand.nand_fcr0,
			  (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
			  (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
	} else {
		ifc_out32(&ifc->ifc_nand.nand_fir0,
			  (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
			  (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
			  (IFC_FIR_OP_RA0  << IFC_NAND_FIR0_OP2_SHIFT) |
			  (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP3_SHIFT));
		ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0);

		ifc_out32(&ifc->ifc_nand.nand_fcr0,
			  NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
	}

	/* Program FBCR = 0 for full page read */
	ifc_out32(&ifc->ifc_nand.nand_fbcr, 0);

	/* Read and copy u-boot on SDRAM from NAND device, In parallel
	 * check for Bad block if found skip it and read continue to
	 * next Block
	 */
	while (pos < uboot_size) {
		int i = 0;
		do {
			pg_no = offs / page_size;
			bufnum = pg_no & bufnum_mask;
			sram_addr = bufnum * page_size * 2;

			ifc_out32(&ifc->ifc_nand.row0, pg_no);
			ifc_out32(&ifc->ifc_nand.col0, 0);
			/* start read */
			ifc_out32(&ifc->ifc_nand.nandseq_strt,
				  IFC_NAND_SEQ_STRT_FIR_STRT);

			/* wait for read to complete */
			nand_wait(&buf[sram_addr], bufnum, page_size);

			/*
			 * If either of the first two pages are marked bad,
			 * continue to the next block.
			 */
			if (i++ < 2 &&
			    bad_block(&buf[sram_addr + page_size + bad_marker],
				      port_size)) {
				puts("skipping\n");
				offs = (offs + blk_size) & ~(blk_size - 1);
				pos &= ~(blk_size - 1);
				break;
			}

			for (j = 0; j < page_size; j++)
				dst[pos + j] = __raw_readb(&buf[sram_addr + j]);

			pos += page_size;
			offs += page_size;
		} while ((offs & (blk_size - 1)) && (pos < uboot_size));
	}

	return 0;
}

/*
 * Main entrypoint for NAND Boot. 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 from there.
 */
void nand_boot(void)
{
	__attribute__((noreturn)) void (*uboot)(void);
	/*
	 * Load U-Boot image from NAND into RAM
	 */
	nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
			    CONFIG_SYS_NAND_U_BOOT_SIZE,
			    (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);

#ifdef CONFIG_NAND_ENV_DST
	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
			    (uchar *)CONFIG_NAND_ENV_DST);

#ifdef CONFIG_ENV_OFFSET_REDUND
	nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
			    (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
#endif
#endif
	/*
	 * Jump to U-Boot image
	 */
#ifdef CONFIG_SPL_FLUSH_IMAGE
	/*
	 * Clean d-cache and invalidate i-cache, to
	 * make sure that no stale data is executed.
	 */
	flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
#endif
	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
	uboot();
}

#ifndef CONFIG_SPL_NAND_INIT
void nand_init(void)
{
}

void nand_deselect(void)
{
}
#endif
