/*
 * (C) Copyright 2000
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include "flash.h"
#include <linux/compiler.h>

flash_info_t	flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips	*/

#if defined(CONFIG_ENV_IS_IN_FLASH)
# ifndef  CONFIG_ENV_ADDR
#  define CONFIG_ENV_ADDR	(CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
# endif
# ifndef  CONFIG_ENV_SIZE
#  define CONFIG_ENV_SIZE	CONFIG_ENV_SECT_SIZE
# endif
# ifndef  CONFIG_ENV_SECT_SIZE
#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
# endif
#endif

/*-----------------------------------------------------------------------
 * Functions
 */
static int write_word (flash_info_t *info, ulong dest, ulong data);

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


#if defined(CONFIG_CMA302)

/*
 * probe for the existence of flash at address "addr"
 * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id
 */
static int
c302f_probe_word(c302f_addr_t addr)
{
	/* reset the flash */
	*addr = C302F_BNK_CMD_RST;

	/* check the manufacturer id */
	*addr = C302F_BNK_CMD_RD_ID;
	if (*C302F_BNK_ADDR_MAN(addr) != C302F_BNK_RD_ID_MAN)
		return 1;

	/* check the device id */
	*addr = C302F_BNK_CMD_RD_ID;
	if (*C302F_BNK_ADDR_DEV(addr) != C302F_BNK_RD_ID_DEV)
		return 2;

#ifdef FLASH_DEBUG
	{
		int i;

		printf("\nMaster Lock Config = 0x%08lx\n",
			*C302F_BNK_ADDR_CFGM(addr));
		for (i = 0; i < C302F_BNK_NBLOCKS; i++)
			printf("Block %2d Lock Config = 0x%08lx\n",
				i, *C302F_BNK_ADDR_CFG(i, addr));
	}
#endif

	/* reset the flash again */
	*addr = C302F_BNK_CMD_RST;

	return 0;
}

/*
 * probe for Cogent CMA302 flash module at address "base" and store
 * info for any found into flash_info entry "fip". Must find at least
 * one bank.
 */
static void
c302f_probe(flash_info_t *fip, c302f_addr_t base)
{
	c302f_addr_t addr, eaddr;
	int nbanks;

	fip->size = 0L;
	fip->sector_count = 0;

	addr = base;
	eaddr = C302F_BNK_ADDR_BASE(addr, C302F_MAX_BANKS);
	nbanks = 0;

	while (addr < eaddr) {
		c302f_addr_t addrw, eaddrw, addrb;
		int i, osc, nsc;

		addrw = addr;
		eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);

		while (addrw < eaddrw)
			if (c302f_probe_word(addrw++) != 0)
				goto out;

		/* bank exists - append info for this bank to *fip */
		fip->flash_id = FLASH_MAN_INTEL|FLASH_28F008S5;
		fip->size += C302F_BNK_SIZE;
		osc = fip->sector_count;
		fip->sector_count += C302F_BNK_NBLOCKS;
		if ((nsc = fip->sector_count) >= CONFIG_SYS_MAX_FLASH_SECT)
			panic("Too many sectors in flash at address 0x%08lx\n",
				(unsigned long)base);

		addrb = addr;
		for (i = osc; i < nsc; i++) {
			fip->start[i] = (ulong)addrb;
			fip->protect[i] = 0;
			addrb = C302F_BNK_ADDR_NEXT_BLK(addrb);
		}

		addr = C302F_BNK_ADDR_NEXT_BNK(addr);
		nbanks++;
	}

out:
	if (nbanks == 0)
		panic("ERROR: no flash found at address 0x%08lx\n",
			(unsigned long)base);
}

static void
c302f_reset(flash_info_t *info, int sect)
{
	c302f_addr_t addrw, eaddrw;

	addrw = (c302f_addr_t)info->start[sect];
	eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);

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

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

#ifdef FLASH_DEBUG
	printf("0x%08lx C302F_BNK_CMD_PROG\n", C302F_BNK_CMD_PROG);
	printf("0x%08lx C302F_BNK_CMD_ERASE1\n", C302F_BNK_CMD_ERASE1);
	printf("0x%08lx C302F_BNK_CMD_ERASE2\n", C302F_BNK_CMD_ERASE2);
	printf("0x%08lx C302F_BNK_CMD_CLR_STAT\n", C302F_BNK_CMD_CLR_STAT);
	printf("0x%08lx C302F_BNK_CMD_RST\n", C302F_BNK_CMD_RST);
	printf("0x%08lx C302F_BNK_STAT_RDY\n", C302F_BNK_STAT_RDY);
	printf("0x%08lx C302F_BNK_STAT_ERR\n", C302F_BNK_STAT_ERR);
#endif

	saddrw = (c302f_addr_t)info->start[sect];
	eaddrw = C302F_BNK_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 = C302F_BNK_CMD_ERASE1;
		*addrw = C302F_BNK_CMD_ERASE2;
	}

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

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

	saddrw = (c302f_addr_t)info->start[sect];
	eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);

	sectdone = 1;
	haderr = 0;

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

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

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

static int
c302f_write_word(c302f_addr_t addr, c302f_word_t value)
{
	c302f_word_t stat;
	ulong start;
	int flag, retval;

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

	*addr = C302F_BNK_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 & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY);

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

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

	return (retval);
}

#endif	/* CONFIG_CMA302 */

unsigned long
flash_init(void)
{
	unsigned long total;
	int i;
	__maybe_unused flash_info_t *fip;

	/* Init: no FLASHes known */
	for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
		flash_info[i].flash_id = FLASH_UNKNOWN;
	}

	fip = &flash_info[0];
	total = 0L;

#if defined(CONFIG_CMA302)
	c302f_probe(fip, (c302f_addr_t)CONFIG_SYS_FLASH_BASE);
	total += fip->size;
	fip++;
#endif

#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
	/* not yet ...
	cmbf_probe(fip, (cmbf_addr_t)CMA_MB_FLASH_BASE);
	total += fip->size;
	fip++;
	*/
#endif

	/*
	 * protect monitor and environment sectors
	 */

#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
	flash_protect(FLAG_PROTECT_SET,
		      CONFIG_SYS_MONITOR_BASE,
		      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
		      &flash_info[0]);
#endif

#ifdef	CONFIG_ENV_IS_IN_FLASH
	/* ENV protection ON by default */
	flash_protect(FLAG_PROTECT_SET,
		      CONFIG_ENV_ADDR,
		      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
		      &flash_info[0]);
#endif
	return total;
}

/*-----------------------------------------------------------------------
 */
void
flash_print_info(flash_info_t *info)
{
	int i;

	if (info->flash_id == FLASH_UNKNOWN) {
		printf ("missing or unknown FLASH type\n");
		return;
	}

	switch (info->flash_id & FLASH_VENDMASK) {
	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
	default:		printf ("Unknown Vendor ");	break;
	}

	switch (info->flash_id & FLASH_TYPEMASK) {
	case FLASH_28F008S5:	printf ("28F008S5\n");
				break;
	default:		printf ("Unknown Chip Type\n");
				break;
	}

	printf ("  Size: %ld MB in %d Sectors\n",
		info->size >> 20, info->sector_count);

	printf ("  Sector Start Addresses:");
	for (i=0; i<info->sector_count; ++i) {
		if ((i % 4) == 0)
			printf ("\n   ");
		printf (" %2d - %08lX%s", i,
			info->start[i],
			info->protect[i] ? " (RO)" : "     "
		);
	}
	printf ("\n");
	return;
}

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


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

/*
 * The following code cannot be run from FLASH!
 */

int
flash_erase(flash_info_t *info, int s_first, int s_last)
{
	int prot, sect, haderr;
	ulong start, now, last;
	void (*erase_init)(flash_info_t *, int);
	int (*erase_poll)(flash_info_t *, int);
	void (*reset)(flash_info_t *, int);
	int rcode = 0;

#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;
	}

	switch (info->flash_id) {

#if defined(CONFIG_CMA302)
	case FLASH_MAN_INTEL|FLASH_28F008S5:
		erase_init = c302f_erase_init;
		erase_poll = c302f_erase_poll;
		reset = c302f_reset;
		break;
#endif

#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
	case FLASH_MAN_INTEL|FLASH_28F800_B:
	case FLASH_MAN_AMD|FLASH_AM29F800B:
		/* not yet ...
		erase_init = cmbf_erase_init;
		erase_poll = cmbf_erase_poll;
		reset = cmbf_reset;
		break;
		*/
#endif

	default:
		printf ("Flash type %08lx not supported - aborted\n",
			info->flash_id);
		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;

			(*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 = (*erase_poll)(info, sect);

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

			} while (!sectdone);

			if (haderr)
				break;
		}
	}

	if (haderr > 0) {
		printf (" failed\n");
		rcode = 1;
	}
	else
		printf (" done\n");

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

/*-----------------------------------------------------------------------
 * Copy memory to flash, returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 * 3 - write error
 */

int
write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
	ulong cp, wp, data;
	int i, l, rc;
	ulong start, now, last;

	wp = (addr & ~3);	/* get lower word aligned address */

	/*
	 * handle unaligned start bytes
	 */
	if ((l = addr - wp) != 0) {
		data = 0;
		for (i=0, cp=wp; i<l; ++i, ++cp) {
			data = (data << 8) | (*(uchar *)cp);
		}
		for (; i<4 && cnt>0; ++i) {
			data = (data << 8) | *src++;
			--cnt;
			++cp;
		}
		for (; cnt==0 && i<4; ++i, ++cp) {
			data = (data << 8) | (*(uchar *)cp);
		}

		if ((rc = write_word(info, wp, data)) != 0) {
			return (rc);
		}
		wp += 4;
	}

	/*
	 * handle word aligned part
	 */
	start = get_timer (0);
	last = 0;
	while (cnt >= 4) {
		data = 0;
		for (i=0; i<4; ++i) {
			data = (data << 8) | *src++;
		}
		if ((rc = write_word(info, wp, data)) != 0) {
			return (rc);
		}
		wp  += 4;
		cnt -= 4;

		/* show that we're waiting */
		now = get_timer(start);
		if ((now - last) > 1000) {	/* every second */
			putc ('.');
			last = now;
		}
	}

	if (cnt == 0) {
		return (0);
	}

	/*
	 * handle unaligned tail bytes
	 */
	data = 0;
	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
		data = (data << 8) | *src++;
		--cnt;
	}
	for (; i<4; ++i, ++cp) {
		data = (data << 8) | (*(uchar *)cp);
	}

	return (write_word(info, wp, data));
}

/*-----------------------------------------------------------------------
 * Write a word to Flash, returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 * 3 - write error
 */
static int
write_word(flash_info_t *info, ulong dest, ulong data)
{
	int retval;

	/* Check if Flash is (sufficiently) erased */
	if ((*(ulong *)dest & data) != data) {
		return (2);
	}

	switch (info->flash_id) {

#if defined(CONFIG_CMA302)
	case FLASH_MAN_INTEL|FLASH_28F008S5:
		retval = c302f_write_word((c302f_addr_t)dest, (c302f_word_t)data);
		break;
#endif

#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
	case FLASH_MAN_INTEL|FLASH_28F800_B:
	case FLASH_MAN_AMD|FLASH_AM29F800B:
		/* not yet ...
		retval = cmbf_write_word((cmbf_addr_t)dest, (cmbf_word_t)data);
		*/
		retval = 3;
		break;
#endif

	default:
		printf ("Flash type %08lx not supported - aborted\n",
			info->flash_id);
		retval = 3;
		break;
	}

	return (retval);
}

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