/*
 * Copyright (C) 2003 ETC s.r.o.
 *
 * This code was inspired by Marius Groeger and Kyle Harris code
 * available in other board ports for U-Boot
 *
 * SPDX-License-Identifier:	GPL-2.0+
 *
 * Written by Peter Figuli <peposh@etc.sk>, 2003.
 */

#include <common.h>
#include "intel.h"


/*
 * This code should handle CFI FLASH memory device. This code is very
 * minimalistic approach without many essential error handling code as well.
 * Because U-Boot actually is missing smart handling of FLASH device,
 * we just set flash_id to anything else to FLASH_UNKNOW, so common code
 * can call us without any restrictions.
 * TODO: Add CFI Query, to be able to determine FLASH device.
 * TODO: Add error handling code
 * NOTE: This code was tested with BUS_WIDTH 4 and ITERLEAVE 2 only, but
 *       hopefully may work with other configurations.
 */

#if ( SCB9328_FLASH_BUS_WIDTH == 1 )
#  define FLASH_BUS vu_char
#  define FLASH_BUS_RET u_char
#  if ( SCB9328_FLASH_INTERLEAVE == 1 )
#    define FLASH_CMD( x ) x
#  else
#    error "With 8bit bus only one chip is allowed"
#  endif


#elif ( SCB9328_FLASH_BUS_WIDTH == 2 )
#  define FLASH_BUS vu_short
#  define FLASH_BUS_RET u_short
#  if ( SCB9328_FLASH_INTERLEAVE == 1 )
#    define FLASH_CMD( x ) x
#  elif ( SCB9328_FLASH_INTERLEAVE == 2 )
#    define FLASH_CMD( x ) (( x << 8 )| x )
#  else
#    error "With 16bit bus only 1 or 2 chip(s) are allowed"
#  endif


#elif ( SCB9328_FLASH_BUS_WIDTH == 4 )
#  define FLASH_BUS vu_long
#  define FLASH_BUS_RET u_long
#  if ( SCB9328_FLASH_INTERLEAVE == 1 )
#    define FLASH_CMD( x ) x
#  elif ( SCB9328_FLASH_INTERLEAVE == 2 )
#    define FLASH_CMD( x ) (( x << 16 )| x )
#  elif ( SCB9328_FLASH_INTERLEAVE == 4 )
#    define FLASH_CMD( x ) (( x << 24 )|( x << 16 ) ( x << 8 )| x )
#  else
#    error "With 32bit bus only 1,2 or 4 chip(s) are allowed"
#  endif

#else
#  error "Flash bus width might be 1,2,4 for 8,16,32 bit configuration"
#endif


flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];

static FLASH_BUS_RET flash_status_reg (void)
{

	FLASH_BUS *addr = (FLASH_BUS *) 0;

	/* cppcheck-suppress nullPointer */
	*addr = FLASH_CMD (CFI_INTEL_CMD_READ_STATUS_REGISTER);

	/* cppcheck-suppress nullPointer */
	return *addr;
}

static int flash_ready (ulong timeout)
{
	int ok = 1;
	ulong start;

	start = get_timer(0);
	while ((flash_status_reg () & FLASH_CMD (CFI_INTEL_SR_READY)) !=
		   FLASH_CMD (CFI_INTEL_SR_READY)) {
		if (get_timer(start) > timeout && timeout != 0) {
			ok = 0;
			break;
		}
	}
	return ok;
}

#if ( CONFIG_SYS_MAX_FLASH_BANKS != 1 )
#  error "SCB9328 platform has only one flash bank!"
#endif


ulong flash_init (void)
{
	int i;
	unsigned long address = SCB9328_FLASH_BASE;

	flash_info[0].size = SCB9328_FLASH_BANK_SIZE;
	flash_info[0].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
	flash_info[0].flash_id = INTEL_MANUFACT;
	memset (flash_info[0].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);

	for (i = 0; i < CONFIG_SYS_MAX_FLASH_SECT; i++) {
		flash_info[0].start[i] = address;
#ifdef SCB9328_FLASH_UNLOCK
		/* Some devices are hw locked after start. */
		*((FLASH_BUS *) address) = FLASH_CMD (CFI_INTEL_CMD_LOCK_SETUP);
		*((FLASH_BUS *) address) = FLASH_CMD (CFI_INTEL_CMD_UNLOCK_BLOCK);
		flash_ready (0);
		*((FLASH_BUS *) address) = FLASH_CMD (CFI_INTEL_CMD_READ_ARRAY);
#endif
		address += SCB9328_FLASH_SECT_SIZE;
	}

	flash_protect (FLAG_PROTECT_SET,
				   CONFIG_SYS_FLASH_BASE,
				   CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
				   &flash_info[0]);

	flash_protect (FLAG_PROTECT_SET,
				   CONFIG_ENV_ADDR,
				   CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);

	return SCB9328_FLASH_BANK_SIZE;
}

void flash_print_info (flash_info_t * info)
{
	int i;

	printf (" Intel vendor\n");
	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 % 5)) {
			printf ("\n");
		}

		printf (" %08lX%s", info->start[i],
				info->protect[i] ? " (RO)" : "     ");
	}
	printf ("\n");
}


int flash_erase (flash_info_t * info, int s_first, int s_last)
{
	int flag, non_protected = 0, sector;
	int rc = ERR_OK;

	FLASH_BUS *address;

	for (sector = s_first; sector <= s_last; sector++) {
		if (!info->protect[sector]) {
			non_protected++;
		}
	}

	if (!non_protected) {
		return ERR_PROTECTED;
	}

	/*
	 * Disable interrupts which might cause a timeout
	 * here. Remember that our exception vectors are
	 * at address 0 in the flash, and we don't want a
	 * (ticker) exception to happen while the flash
	 * chip is in programming mode.
	 */
	flag = disable_interrupts ();


	/* Start erase on unprotected sectors */
	for (sector = s_first; sector <= s_last && !ctrlc (); sector++) {
		if (info->protect[sector]) {
			printf ("Protected sector %2d skipping...\n", sector);
			continue;
		} else {
			printf ("Erasing sector %2d ... ", sector);
		}

		address = (FLASH_BUS *) (info->start[sector]);

		*address = FLASH_CMD (CFI_INTEL_CMD_BLOCK_ERASE);
		*address = FLASH_CMD (CFI_INTEL_CMD_CONFIRM);
		if (flash_ready (CONFIG_SYS_FLASH_ERASE_TOUT)) {
			*address = FLASH_CMD (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
			printf ("ok.\n");
		} else {
			*address = FLASH_CMD (CFI_INTEL_CMD_SUSPEND);
			rc = ERR_TIMOUT;
			printf ("timeout! Aborting...\n");
			break;
		}
		*address = FLASH_CMD (CFI_INTEL_CMD_READ_ARRAY);
	}
	if (ctrlc ())
		printf ("User Interrupt!\n");

	/* allow flash to settle - wait 10 ms */
	udelay_masked (10000);
	if (flag) {
		enable_interrupts ();
	}

	return rc;
}

static int write_data (flash_info_t * info, ulong dest, FLASH_BUS data)
{
	FLASH_BUS *address = (FLASH_BUS *) dest;
	int rc = ERR_OK;
	int flag;

	/* Check if Flash is (sufficiently) erased */
	if ((*address & data) != data) {
		return ERR_NOT_ERASED;
	}

	/*
	 * Disable interrupts which might cause a timeout
	 * here. Remember that our exception vectors are
	 * at address 0 in the flash, and we don't want a
	 * (ticker) exception to happen while the flash
	 * chip is in programming mode.
	 */

	flag = disable_interrupts ();

	*address = FLASH_CMD (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
	*address = FLASH_CMD (CFI_INTEL_CMD_PROGRAM1);
	*address = data;

	if (!flash_ready (CONFIG_SYS_FLASH_WRITE_TOUT)) {
		*address = FLASH_CMD (CFI_INTEL_CMD_SUSPEND);
		rc = ERR_TIMOUT;
		printf ("timeout! Aborting...\n");
	}

	*address = FLASH_CMD (CFI_INTEL_CMD_READ_ARRAY);
	if (flag) {
		enable_interrupts ();
	}

	return rc;
}

int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
	ulong read_addr, write_addr;
	FLASH_BUS data;
	int i, result = ERR_OK;


	read_addr = addr & ~(sizeof (FLASH_BUS) - 1);
	write_addr = read_addr;
	if (read_addr != addr) {
		data = 0;
		for (i = 0; i < sizeof (FLASH_BUS); i++) {
			if (read_addr < addr || cnt == 0) {
				data |= *((uchar *) read_addr) << i * 8;
			} else {
				data |= (*src++) << i * 8;
				cnt--;
			}
			read_addr++;
		}
		if ((result = write_data (info, write_addr, data)) != ERR_OK) {
			return result;
		}
		write_addr += sizeof (FLASH_BUS);
	}
	for (; cnt >= sizeof (FLASH_BUS); cnt -= sizeof (FLASH_BUS)) {
		if ((result = write_data (info, write_addr,
								  *((FLASH_BUS *) src))) != ERR_OK) {
			return result;
		}
		write_addr += sizeof (FLASH_BUS);
		src += sizeof (FLASH_BUS);
	}
	if (cnt > 0) {
		read_addr = write_addr;
		data = 0;
		for (i = 0; i < sizeof (FLASH_BUS); i++) {
			if (cnt > 0) {
				data |= (*src++) << i * 8;
				cnt--;
			} else {
				data |= *((uchar *) read_addr) << i * 8;
			}
			read_addr++;
		}
		if ((result = write_data (info, write_addr, data)) != 0) {
			return result;
		}
	}
	return ERR_OK;
}
