/*
 * (C) Copyright 2009
 * Heiko Schocher, DENX Software Engineering, hs@denx.de
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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 CONFIG_NAND_MODE_REG	(void *)(CONFIG_SYS_NAND_BASE + 0x20000)
#define CONFIG_NAND_DATA_REG	(void *)(CONFIG_SYS_NAND_BASE + 0x30000)

#define read_mode()	in_8(CONFIG_NAND_MODE_REG)
#define write_mode(val)	out_8(CONFIG_NAND_MODE_REG, val)
#define read_data()	in_8(CONFIG_NAND_DATA_REG)
#define write_data(val)	out_8(CONFIG_NAND_DATA_REG, val)

#define KPN_RDY2	(1 << 7)
#define KPN_RDY1	(1 << 6)
#define KPN_WPN		(1 << 4)
#define KPN_CE2N	(1 << 3)
#define KPN_CE1N	(1 << 2)
#define KPN_ALE		(1 << 1)
#define KPN_CLE		(1 << 0)

#define KPN_DEFAULT_CHIP_DELAY 50

static int kpn_chip_ready(void)
{
	if (read_mode() & KPN_RDY1)
		return 1;

	return 0;
}

static void kpn_wait_rdy(void)
{
	int cnt = 1000000;

	while (--cnt && !kpn_chip_ready())
		udelay(1);

	if (!cnt)
		printf ("timeout while waiting for RDY\n");
}

static void kpn_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
	u8 reg_val = read_mode();

	if (ctrl & NAND_CTRL_CHANGE) {
		reg_val = reg_val & ~(KPN_ALE + KPN_CLE);

		if (ctrl & NAND_CLE)
			reg_val = reg_val | KPN_CLE;
		if (ctrl & NAND_ALE)
			reg_val = reg_val | KPN_ALE;
		if (ctrl & NAND_NCE)
			reg_val = reg_val & ~KPN_CE1N;
		else
			reg_val = reg_val | KPN_CE1N;

		write_mode(reg_val);
	}
	if (cmd != NAND_CMD_NONE)
		write_data(cmd);

	/* wait until flash is ready */
	kpn_wait_rdy();
}

static u_char kpn_nand_read_byte(struct mtd_info *mtd)
{
	return read_data();
}

static void kpn_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
	int i;

	for (i = 0; i < len; i++) {
		write_data(buf[i]);
		kpn_wait_rdy();
	}
}

static void kpn_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
	int i;

	for (i = 0; i < len; i++)
		buf[i] = read_data();
}

static int kpn_nand_dev_ready(struct mtd_info *mtd)
{
	kpn_wait_rdy();

	return 1;
}

int board_nand_init(struct nand_chip *nand)
{
	nand->ecc.mode = NAND_ECC_SOFT;

	/* Reference hardware control function */
	nand->cmd_ctrl  = kpn_nand_hwcontrol;
	nand->read_byte  = kpn_nand_read_byte;
	nand->write_buf  = kpn_nand_write_buf;
	nand->read_buf   = kpn_nand_read_buf;
	nand->dev_ready  = kpn_nand_dev_ready;
	nand->chip_delay = KPN_DEFAULT_CHIP_DELAY;

	/* reset mode register */
	write_mode(KPN_CE1N + KPN_CE2N + KPN_WPN);
	return 0;
}
