/*
 * (C) Copyright 2000
 * Wolfgang Denk, DENX Software Engineering, wd@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
 *
 * Hacked for the marvell db64360 eval board by
 * Ingo Assmus <ingo.assmus@keymile.com>
 */

#include <common.h>
#include <mpc8xx.h>
#include "../include/mv_gen_reg.h"
#include "../include/memory.h"
#include "intel_flash.h"


/*-----------------------------------------------------------------------
 * Protection Flags:
 */
#define FLAG_PROTECT_SET	0x01
#define FLAG_PROTECT_CLEAR	0x02

static void bank_reset (flash_info_t * info, int sect)
{
	bank_addr_t addrw, eaddrw;

	addrw = (bank_addr_t) info->start[sect];
	eaddrw = BANK_ADDR_NEXT_WORD (addrw);

	while (addrw < eaddrw) {
#ifdef FLASH_DEBUG
		printf ("  writing reset cmd to addr 0x%08lx\n",
			(unsigned long) addrw);
#endif
		*addrw = BANK_CMD_RST;
		addrw++;
	}
}

static void bank_erase_init (flash_info_t * info, int sect)
{
	bank_addr_t addrw, saddrw, eaddrw;
	int flag;

#ifdef FLASH_DEBUG
	printf ("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG);
	printf ("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
	printf ("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
	printf ("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
	printf ("0x%08x BANK_CMD_RST\n", BANK_CMD_RST);
	printf ("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY);
	printf ("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR);
#endif

	saddrw = (bank_addr_t) info->start[sect];
	eaddrw = BANK_ADDR_NEXT_WORD (saddrw);

#ifdef FLASH_DEBUG
	printf ("erasing sector %d, start addr = 0x%08lx "
		"(bank next word addr = 0x%08lx)\n", sect,
		(unsigned long) saddrw, (unsigned long) eaddrw);
#endif

	/* Disable intrs which might cause a timeout here */
	flag = disable_interrupts ();

	for (addrw = saddrw; addrw < eaddrw; addrw++) {
#ifdef FLASH_DEBUG
		printf ("  writing erase cmd to addr 0x%08lx\n",
			(unsigned long) addrw);
#endif
		*addrw = BANK_CMD_ERASE1;
		*addrw = BANK_CMD_ERASE2;
	}

	/* re-enable interrupts if necessary */
	if (flag)
		enable_interrupts ();
}

static int bank_erase_poll (flash_info_t * info, int sect)
{
	bank_addr_t addrw, saddrw, eaddrw;
	int sectdone, haderr;

	saddrw = (bank_addr_t) info->start[sect];
	eaddrw = BANK_ADDR_NEXT_WORD (saddrw);

	sectdone = 1;
	haderr = 0;

	for (addrw = saddrw; addrw < eaddrw; addrw++) {
		bank_word_t stat = *addrw;

#ifdef FLASH_DEBUG
		printf ("  checking status at addr "
			"0x%08x [0x%08x]\n", (unsigned long) addrw, stat);
#endif
		if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
			sectdone = 0;
		else if ((stat & BANK_STAT_ERR) != 0) {
			printf (" failed on sector %d "
				"(stat = 0x%08x) at "
				"address 0x%p\n", sect, stat, addrw);
			*addrw = BANK_CMD_CLR_STAT;
			haderr = 1;
		}
	}

	if (haderr)
		return (-1);
	else
		return (sectdone);
}

int write_word_intel (bank_addr_t addr, bank_word_t value)
{
	bank_word_t stat;
	ulong start;
	int flag, retval;

	/* Disable interrupts which might cause a timeout here */
	flag = disable_interrupts ();

	*addr = BANK_CMD_PROG;

	*addr = value;

	/* re-enable interrupts if necessary */
	if (flag)
		enable_interrupts ();

	retval = 0;

	/* data polling for D7 */
	start = get_timer (0);
	do {
		if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
			retval = 1;
			goto done;
		}
		stat = *addr;
	} while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);

	if ((stat & BANK_STAT_ERR) != 0) {
		printf ("flash program failed (stat = 0x%08lx) "
			"at address 0x%08lx\n", (ulong) stat, (ulong) addr);
		*addr = BANK_CMD_CLR_STAT;
		retval = 3;
	}

      done:
	/* reset to read mode */
	*addr = BANK_CMD_RST;

	return (retval);
}

/*-----------------------------------------------------------------------
 */

int flash_erase_intel (flash_info_t * info, int s_first, int s_last)
{
	int prot, sect, haderr;
	ulong start, now, last;

#ifdef FLASH_DEBUG
	printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
		"  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
		(info - flash_info) + 1);
	flash_print_info (info);
#endif

	if ((s_first < 0) || (s_first > s_last)) {
		if (info->flash_id == FLASH_UNKNOWN) {
			printf ("- missing\n");
		} else {
			printf ("- no sectors to erase\n");
		}
		return 1;
	}

	prot = 0;
	for (sect = s_first; sect <= s_last; ++sect) {
		if (info->protect[sect]) {
			prot++;
		}
	}

	if (prot) {
		printf ("- Warning: %d protected sector%s will not be erased!\n", prot, (prot > 1 ? "s" : ""));
	}

	start = get_timer (0);
	last = 0;
	haderr = 0;

	for (sect = s_first; sect <= s_last; sect++) {
		if (info->protect[sect] == 0) {	/* not protected */
			ulong estart;
			int sectdone;

			bank_erase_init (info, sect);

			/* wait at least 80us - let's wait 1 ms */
			udelay (1000);

			estart = get_timer (start);

			do {
				now = get_timer (start);

				if (now - estart > CFG_FLASH_ERASE_TOUT) {
					printf ("Timeout (sect %d)\n", sect);
					haderr = 1;
					break;
				}
#ifndef FLASH_DEBUG
				/* show that we're waiting */
				if ((now - last) > 1000) {	/* every second */
					putc ('.');
					last = now;
				}
#endif

				sectdone = bank_erase_poll (info, sect);

				if (sectdone < 0) {
					haderr = 1;
					break;
				}

			} while (!sectdone);

			if (haderr)
				break;
		}
	}

	if (haderr > 0)
		printf (" failed\n");
	else
		printf (" done\n");

	/* reset to read mode */
	for (sect = s_first; sect <= s_last; sect++) {
		if (info->protect[sect] == 0) {	/* not protected */
			bank_reset (info, sect);
		}
	}
	return haderr;
}
