/*
 * (C) Copyright 2000
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
 */

#include <common.h>
#include <mpc8xx.h>
#include <galileo/gt64260R.h>
#include <galileo/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) > CONFIG_SYS_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 > CONFIG_SYS_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;
}
