/*
 * (C) Copyright 2010
 * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.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
 */

/*
 * this driver supports the enhanced embedded flash in the Atmel
 * AT91SAM9XE devices with the following geometry:
 *
 * AT91SAM9XE128: 1 plane of  8 regions of 32 pages (total  256 pages)
 * AT91SAM9XE256: 1 plane of 16 regions of 32 pages (total  512 pages)
 * AT91SAM9XE512: 1 plane of 32 regions of 32 pages (total 1024 pages)
 * (the exact geometry is read from the flash at runtime, so any
 *  future devices should already be covered)
 *
 * Regions can be write/erase protected.
 * Whole (!) pages can be individually written with erase on the fly.
 * Writing partial pages will corrupt the rest of the page.
 *
 * The flash is presented to u-boot with each region being a sector,
 * having the following effects:
 * Each sector can be hardware protected (protect on/off).
 * Each page in a sector can be rewritten anytime.
 * Since pages are erased when written, the "erase" does nothing.
 * The first "CONFIG_EFLASH_PROTSECTORS" cannot be unprotected
 * by u-Boot commands.
 *
 * Note: Redundant environment will not work in this flash since
 * it does use partial page writes. Make sure the environent spans
 * whole pages!
 */

/*
 * optional TODOs (nice to have features):
 *
 * make the driver coexist with other NOR flash drivers
 *	(use an index into flash_info[], requires work
 *	in those other drivers, too)
 * Make the erase command fill the sectors with 0xff
 *	(if the flashes grow larger in the future and
 *	someone puts a jffs2 into them)
 * do a read-modify-write for partially programmed pages
 */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/at91_common.h>
#include <asm/arch/at91_eefc.h>
#include <asm/arch/at91_dbu.h>

/* checks to detect configuration errors */
#if CONFIG_SYS_MAX_FLASH_BANKS!=1
#error eflash: this driver can only handle 1 bank
#endif

/* global structure */
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
static u32 pagesize;

unsigned long flash_init (void)
{
	at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
	at91_dbu_t *dbu = (at91_dbu_t *) ATMEL_BASE_DBGU;
	u32 id, size, nplanes, planesize, nlocks;
	u32 addr, i, tmp=0;

	debug("eflash: init\n");

	flash_info[0].flash_id = FLASH_UNKNOWN;

	/* check if its an AT91ARM9XE SoC */
	if ((readl(&dbu->cidr) & AT91_DBU_CID_ARCH_MASK) != AT91_DBU_CID_ARCH_9XExx) {
		puts("eflash: not an AT91SAM9XE\n");
		return 0;
	}

	/* now query the eflash for its structure */
	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GETD, &eefc->fcr);
	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
		;
	id = readl(&eefc->frr);		/* word 0 */
	size = readl(&eefc->frr);	/* word 1 */
	pagesize = readl(&eefc->frr);	/* word 2 */
	nplanes = readl(&eefc->frr);	/* word 3 */
	planesize = readl(&eefc->frr);	/* word 4 */
	debug("id=%08x size=%u pagesize=%u planes=%u planesize=%u\n",
		id, size, pagesize, nplanes, planesize);
	for (i=1; i<nplanes; i++) {
		tmp = readl(&eefc->frr);	/* words 5..4+nplanes-1 */
	};
	nlocks = readl(&eefc->frr);	/* word 4+nplanes */
	debug("nlocks=%u\n", nlocks);
	/* since we are going to use the lock regions as sectors, check count */
	if (nlocks > CONFIG_SYS_MAX_FLASH_SECT) {
		printf("eflash: number of lock regions(%u) "\
			"> CONFIG_SYS_MAX_FLASH_SECT. reducing...\n",
			nlocks);
		nlocks = CONFIG_SYS_MAX_FLASH_SECT;
	}
	flash_info[0].size = size;
	flash_info[0].sector_count = nlocks;
	flash_info[0].flash_id = id;

	addr = ATMEL_BASE_FLASH;
	for (i=0; i<nlocks; i++) {
		tmp = readl(&eefc->frr);	/* words 4+nplanes+1.. */
		flash_info[0].start[i] = addr;
		flash_info[0].protect[i] = 0;
		addr += tmp;
	};

	/* now read the protection information for all regions */
	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
		;
	for (i=0; i<flash_info[0].sector_count; i++) {
		if (i%32 == 0)
			tmp = readl(&eefc->frr);
		flash_info[0].protect[i] = (tmp >> (i%32)) & 1;
#if defined(CONFIG_EFLASH_PROTSECTORS)
		if (i < CONFIG_EFLASH_PROTSECTORS)
			flash_info[0].protect[i] = 1;
#endif
	}

	return size;
}

void flash_print_info (flash_info_t *info)
{
	int i;

	puts("AT91SAM9XE embedded flash\n  Size: ");
	print_size(info->size, " in ");
	printf("%d Sectors\n", 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");
	return;
}

int flash_real_protect (flash_info_t *info, long sector, int prot)
{
	at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;
	u32 pagenum = (info->start[sector]-ATMEL_BASE_FLASH)/pagesize;
	u32 i, tmp=0;

	debug("protect sector=%ld prot=%d\n", sector, prot);

#if defined(CONFIG_EFLASH_PROTSECTORS)
	if (sector < CONFIG_EFLASH_PROTSECTORS) {
		if (!prot) {
			printf("eflash: sector %lu cannot be unprotected\n",
				sector);
		}
		return 1; /* return anyway, caller does not care for result */
	}
#endif
	if (prot) {
		writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_SLB |
			(pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
	} else {
		writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_CLB |
			(pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
	}
	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
		;
	/* now re-read the protection information for all regions */
	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_GLB, &eefc->fcr);
	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
		;
	for (i=0; i<info->sector_count; i++) {
		if (i%32 == 0)
			tmp = readl(&eefc->frr);
		info->protect[i] = (tmp >> (i%32)) & 1;
	}
	return 0;
}

static u32 erase_write_page (u32 pagenum)
{
	at91_eefc_t *eefc = (at91_eefc_t *) ATMEL_BASE_EEFC;

	debug("erase+write page=%u\n", pagenum);

	/* give erase and write page command */
	writel(AT91_EEFC_FCR_KEY | AT91_EEFC_FCR_FCMD_EWP |
		(pagenum << AT91_EEFC_FCR_FARG_SHIFT), &eefc->fcr);
	while ((readl(&eefc->fsr) & AT91_EEFC_FSR_FRDY) == 0)
		;
	/* return status */
	return readl(&eefc->fsr)
		& (AT91_EEFC_FSR_FCMDE | AT91_EEFC_FSR_FLOCKE);
}

int flash_erase (flash_info_t *info, int s_first, int s_last)
{
	debug("erase first=%d last=%d\n", s_first, s_last);
	puts("this flash does not need and support erasing!\n");
	return 0;
}

/*
 * Copy memory to flash, returns:
 * 0 - OK
 * 1 - write timeout
 */

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
	u32 pagenum;
	u32 *src32, *dst32;
	u32 i;

	debug("write src=%08lx addr=%08lx cnt=%lx\n",
		(ulong)src, addr, cnt);

	/* REQUIRE addr to be on a page start, abort if not */
	if (addr % pagesize) {
		printf ("eflash: start %08lx is not on page start\n"\
			"        write aborted\n", addr);
		return 1;
	}

	/* now start copying data */
	pagenum = (addr-ATMEL_BASE_FLASH)/pagesize;
	src32 = (u32 *) src;
	dst32 = (u32 *) addr;
	while (cnt > 0) {
		i = pagesize / 4;
		/* fill page buffer */
		while (i--)
			*dst32++ = *src32++;
		/* write page */
		if (erase_write_page(pagenum))
			return 1;
		pagenum++;
		if (cnt > pagesize)
			cnt -= pagesize;
		else
			cnt = 0;
	}
	return 0;
}
