// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2010
 * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
 */

/*
 * 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 environment 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 <flash.h>
#include <log.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;
}
