/*
 * flash.c: Support code for the flash chips on the Xilinx ML2 board
 *
 * Copyright 2002 Mind NV
 *
 * http://www.mind.be/
 *
 * Author : Peter De Schrijver (p2@mind.be)
 *
 * This software may be used and distributed according to the terms of
 * the GNU General Public License (GPL) version 2, incorporated herein by
 * reference. Drivers based on or derived from this code fall under the GPL
 * and must retain the authorship, copyright and this license notice. This
 * file is not a complete program and may only be used when the entire program
 * is licensed under the GPL.
 *
 */

#include <common.h>
#include <asm/u-boot.h>
#include <configs/ML2.h>

#define FLASH_BANK_SIZE (64*1024*1024)

flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];

#define SECT_SIZE		(512*1024)

#define CMD_READ_ARRAY	0x00FF00FF00FF00FULL
#define CMD_IDENTIFY        0x0090009000900090ULL
#define CMD_ERASE_SETUP     0x0020002000200020ULL
#define CMD_ERASE_CONFIRM   0x00D000D000D000D0ULL
#define CMD_PROGRAM     0x0040004000400040ULL
#define CMD_RESUME      0x00D000D000D000D0ULL
#define CMD_SUSPEND     0x00B000B000B000B0ULL
#define CMD_STATUS_READ     0x0070007000700070ULL
#define CMD_STATUS_RESET    0x0050005000500050ULL

#define BIT_BUSY        0x0080008000800080ULL
#define BIT_ERASE_SUSPEND   0x004000400400040ULL
#define BIT_ERASE_ERROR     0x0020002000200020ULL
#define BIT_PROGRAM_ERROR   0x0010001000100010ULL
#define BIT_VPP_RANGE_ERROR 0x0008000800080008ULL
#define BIT_PROGRAM_SUSPEND 0x0004000400040004ULL
#define BIT_PROTECT_ERROR   0x0002000200020002ULL
#define BIT_UNDEFINED       0x0001000100010001ULL

#define BIT_SEQUENCE_ERROR  0x0030003000300030ULL

#define BIT_TIMEOUT     0x80000000


inline void eieio(void) {

	__asm__ __volatile__ ("eieio" : : : "memory");

}

ulong flash_init(void) {

	int i, j;
	ulong size = 0;

	for(i=0;i<CFG_MAX_FLASH_BANKS;i++) {
		ulong flashbase = 0;

		flash_info[i].flash_id = (INTEL_MANUFACT & FLASH_VENDMASK) |
								 (INTEL_ID_28F128J3A & FLASH_TYPEMASK);
		flash_info[i].size = FLASH_BANK_SIZE;
		flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
		memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
		if (i==0)
			flashbase = CFG_FLASH_BASE;
		else
			panic("configured to many flash banks!\n");
		for (j = 0; j < flash_info[i].sector_count; j++)
				flash_info[i].start[j]=flashbase + j * SECT_SIZE;

		size += flash_info[i].size;
	}

	return size;
}

void flash_print_info  (flash_info_t *info) {

	int i;

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

	switch (info->flash_id & FLASH_TYPEMASK) {
		case (INTEL_ID_28F128J3A & FLASH_TYPEMASK):
			printf("4x 28F128J3A (128Mbit)\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 % 5) == 0)
			printf("\n   ");
		printf (" %08lX%s", info->start[i],
				 info->protect[i] ? " (RO)" : "     ");
	}
	printf ("\n");
}

int flash_error (unsigned long long code) {

	if (code & BIT_TIMEOUT) {
		printf ("Timeout\n");
		return ERR_TIMOUT;
	}

	if (~code & BIT_BUSY) {
		printf ("Busy\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_VPP_RANGE_ERROR) {
		printf ("Vpp range error\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_PROTECT_ERROR) {
		printf ("Device protect error\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_SEQUENCE_ERROR) {
		printf ("Command seqence error\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_ERASE_ERROR) {
		printf ("Block erase error\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_PROGRAM_ERROR) {
		printf ("Program error\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_ERASE_SUSPEND) {
		printf ("Block erase suspended\n");
		return ERR_PROG_ERROR;
	}

	if (code & BIT_PROGRAM_SUSPEND) {
		printf ("Program suspended\n");
		return ERR_PROG_ERROR;
	}

	return ERR_OK;

}

int flash_erase (flash_info_t *info, int s_first, int s_last) {

	int rc = ERR_OK;
	int sect;
	unsigned long long result;

	if (info->flash_id == FLASH_UNKNOWN)
		return ERR_UNKNOWN_FLASH_TYPE;

	if ((s_first < 0) || (s_first > s_last))
		return ERR_INVAL;

	if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
		return ERR_UNKNOWN_FLASH_VENDOR;

	for (sect=s_first; sect<=s_last; ++sect)
		if (info->protect[sect])
			return ERR_PROTECTED;

	for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
		volatile unsigned long long *addr=
									(unsigned long long *)(info->start[sect]);

		printf("Erasing sector %2d ... ", sect);

		*addr=CMD_STATUS_RESET;
		eieio();
		*addr=CMD_ERASE_SETUP;
		eieio();
		*addr=CMD_ERASE_CONFIRM;
		eieio();

		do {
			result = *addr;
		} while(~result & BIT_BUSY);

		*addr=CMD_READ_ARRAY;

		if ((rc = flash_error(result)) == ERR_OK)
			printf("ok.\n");
		else
			break;
	}

	if (ctrlc())
		printf("User Interrupt!\n");

	return rc;
}

volatile static int write_word (flash_info_t *info, ulong dest, unsigned long long data) {

	volatile unsigned long long *addr=(unsigned long long *)dest;
	unsigned long long result;
	int rc = ERR_OK;

	result=*addr;
	if ((result & data) != data)
		return ERR_NOT_ERASED;

	*addr=CMD_STATUS_RESET;
	eieio();
	*addr=CMD_PROGRAM;
	eieio();
	*addr=data;
	eieio();

	do {
		result=*addr;
	} while(~result & BIT_BUSY);

	*addr=CMD_READ_ARRAY;

	rc = flash_error(result);

	return rc;

}

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) {

	ulong cp, wp;
	unsigned long long data;
	int l;
	int i,rc;

	wp=(addr & ~7);

	if((l=addr-wp) != 0) {
		data=0;
		for(i=0,cp=wp;i<l;++i,++cp)
			data = (data >> 8) | (*(uchar *)cp << 24);

		for (; i<8 && cnt>0; ++i) {
			data = (data >> 8) | (*src++ << 24);
			--cnt;
			++cp;
		}

		for (; i<8; ++i, ++cp)
			data = (data >> 8) | (*(uchar *)cp << 24);

		if ((rc = write_word(info, wp, data)) != 0)
			return rc;

		wp+=8;
	}

	while(cnt>=8) {
		data=*((unsigned long long *)src);
		if ((rc = write_word(info, wp, data)) != 0)
			return rc;
		src+=8;
		wp+=8;
		cnt-=8;
	}

	if(cnt == 0)
		return ERR_OK;

	data = 0;
	for (i=0, cp=wp; i<8 && cnt>0; ++i, ++cp) {
		data = (data >> 8) | (*src++ << 24);
		--cnt;
	}
	for (; i<8; ++i, ++cp) {
		data = (data >> 8) | (*(uchar *)cp << 24);
	}

	return write_word(info, wp, data);

}

