/*
 * (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
 */

/*
 * Modified 4/5/2001
 * Wait for completion of each sector erase command issued
 * 4/5/2001
 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
 */

#include <common.h>
#include <ppc4xx.h>
#include <asm/processor.h>

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

#undef DEBUG
#ifdef DEBUG
#define DEBUGF(x...) printf(x)
#else
#define DEBUGF(x...)
#endif				/* DEBUG */

/*
 * include common flash code (for amcc boards)
 */
#include "../common/flash.c"

/*-----------------------------------------------------------------------
 * Functions
 */
static ulong flash_get_size(vu_long * addr, flash_info_t * info);
static void flash_get_offsets(ulong base, flash_info_t * info);

unsigned long flash_init(void)
{
	unsigned long size_b0, size_b1;
	int i;
	uint pbcr;
	unsigned long base_b0, base_b1;

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

	/* Static FLASH Bank configuration here - FIXME XXX */

	size_b0 =
	    flash_get_size((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);

	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
		printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
		       size_b0, size_b0 << 20);
	}

	/* Only one bank */
	if (CFG_MAX_FLASH_BANKS == 1) {
		/* Setup offsets */
		flash_get_offsets(FLASH_BASE0_PRELIM, &flash_info[0]);

		/* Monitor protection ON by default */
		(void)flash_protect(FLAG_PROTECT_SET,
				    CFG_MONITOR_BASE,
				    CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
				    &flash_info[0]);
#ifdef CFG_ENV_IS_IN_FLASH
		(void)flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR,
				    CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
				    &flash_info[0]);
		(void)flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR_REDUND,
				    CFG_ENV_ADDR_REDUND + CFG_ENV_SECT_SIZE - 1,
				    &flash_info[0]);
#endif

		size_b1 = 0;
		flash_info[0].size = size_b0;
	}

	/* 2 banks */
	else {
		size_b1 =
		    flash_get_size((vu_long *) FLASH_BASE1_PRELIM,
				   &flash_info[1]);

		/* Re-do sizing to get full correct info */

		if (size_b1) {
			mtdcr(ebccfga, pb0cr);
			pbcr = mfdcr(ebccfgd);
			mtdcr(ebccfga, pb0cr);
			base_b1 = -size_b1;
			pbcr = (pbcr & 0x0001ffff) | base_b1 |
			    (((size_b1 / 1024 / 1024) - 1) << 17);
			mtdcr(ebccfgd, pbcr);
			/*          printf("pb1cr = %x\n", pbcr); */
		}

		if (size_b0) {
			mtdcr(ebccfga, pb1cr);
			pbcr = mfdcr(ebccfgd);
			mtdcr(ebccfga, pb1cr);
			base_b0 = base_b1 - size_b0;
			pbcr = (pbcr & 0x0001ffff) | base_b0 |
			    (((size_b0 / 1024 / 1024) - 1) << 17);
			mtdcr(ebccfgd, pbcr);
			/*            printf("pb0cr = %x\n", pbcr); */
		}

		size_b0 = flash_get_size((vu_long *) base_b0, &flash_info[0]);

		flash_get_offsets(base_b0, &flash_info[0]);

		/* monitor protection ON by default */
		(void)flash_protect(FLAG_PROTECT_SET,
				    base_b0 + size_b0 - CFG_MONITOR_LEN,
				    base_b0 + size_b0 - 1, &flash_info[0]);
		/* Also protect sector containing initial power-up instruction */
		/* (flash_protect() checks address range - other call ignored) */
		(void)flash_protect(FLAG_PROTECT_SET,
				    0xFFFFFFFC, 0xFFFFFFFF, &flash_info[0]);
		(void)flash_protect(FLAG_PROTECT_SET,
				    0xFFFFFFFC, 0xFFFFFFFF, &flash_info[1]);

		if (size_b1) {
			/* Re-do sizing to get full correct info */
			size_b1 =
			    flash_get_size((vu_long *) base_b1, &flash_info[1]);

			flash_get_offsets(base_b1, &flash_info[1]);

			/* monitor protection ON by default */
			(void)flash_protect(FLAG_PROTECT_SET,
					    base_b1 + size_b1 - CFG_MONITOR_LEN,
					    base_b1 + size_b1 - 1,
					    &flash_info[1]);
			/* monitor protection OFF by default (one is enough) */
			(void)flash_protect(FLAG_PROTECT_CLEAR,
					    base_b0 + size_b0 - CFG_MONITOR_LEN,
					    base_b0 + size_b0 - 1,
					    &flash_info[0]);
		} else {
			flash_info[1].flash_id = FLASH_UNKNOWN;
			flash_info[1].sector_count = -1;
		}

		flash_info[0].size = size_b0;
		flash_info[1].size = size_b1;
	}			/* else 2 banks */
	return (size_b0 + size_b1);
}

static void flash_get_offsets(ulong base, flash_info_t * info)
{
	int i;

	/* set up sector start address table */
	if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
	    (info->flash_id == FLASH_AM040)) {
		for (i = 0; i < info->sector_count; i++)
			info->start[i] = base + (i * 0x00010000);
	} else {
		if (info->flash_id & FLASH_BTYPE) {
			/* set sector offsets for bottom boot block type        */
			info->start[0] = base + 0x00000000;
			info->start[1] = base + 0x00004000;
			info->start[2] = base + 0x00006000;
			info->start[3] = base + 0x00008000;
			for (i = 4; i < info->sector_count; i++) {
				info->start[i] =
				    base + (i * 0x00010000) - 0x00030000;
			}
		} else {
			/* set sector offsets for top boot block type           */
			i = info->sector_count - 1;
			info->start[i--] = base + info->size - 0x00004000;
			info->start[i--] = base + info->size - 0x00006000;
			info->start[i--] = base + info->size - 0x00008000;
			for (; i >= 0; i--) {
				info->start[i] = base + i * 0x00010000;
			}
		}
	}
}
