/*
 * FM3 On-Chip Flash memory lowlevel driver
 * Copyright (C) 2012 Yoshinori Sato <ysato@users.sourceforge.jp>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <flash.h>
#include <asm/io.h>

#define FASZR	0x40000000

int erase_sector_low(unsigned long addr) __attribute__((section(".ram_text")));
int write_sector_low(unsigned long addr, uchar *src, int size)
	__attribute__((section(".ram_text")));
int erase_sector_low(unsigned long addr)
{
	unsigned char status;
	int ret = ERR_OK;
	int i;

	writel(0x01, FASZR);
	readl(FASZR);
	for(i = 0; i < 2; i++) {
		writew(0x00aa, (addr + (i * 4)) | 0x1550);
		writew(0x0055, (addr + (i * 4)) | 0x0aa8);
		writew(0x0080, (addr + (i * 4)) | 0x1550);
		writew(0x00aa, (addr + (i * 4)) | 0x1550);
		writew(0x0055, (addr + (i * 4)) | 0x0aa8);
		writew(0x0030, (addr + (i * 4)));
	}
	readb(addr + (i * 4));
	while ((readb(addr + (i * 4)) & 0x08) == 0);
	while (((status = readb(addr + (i * 4))) & 0x80) == 0) {
		if (status & 0x20) {
			writew(0xf0, addr + (i * 4));
			ret = ERR_TIMOUT;
			goto out;
		}
	}
out:
	writel(0x02, FASZR);
	readl(FASZR);
	return ret;
}

int write_sector_low(unsigned long addr, uchar *src, int size)
{
	unsigned short *p = (unsigned short *)src;
	unsigned short status;
	int ret = ERR_OK;

	writeb(0x01, FASZR);
	readb(FASZR);
	for(; size > 0; p++, addr += 2, size -= 2) {
		if (*p == 0xffff)
			continue;
		writew(0x00aa, 0x00001550);
		writew(0x0055, 0x00000aa8);
		writew(0x00a0, 0x00001550);
		writew(*p, addr);
		readw(addr);
		while(((status = readw(addr)) ^ *p) & 0x0080) {
			if(status & 0x0020) {
				writew(0xf0, addr);
				ret = ERR_TIMOUT;
				goto done;
			}
		}
	}
done:
	writeb(0x02, FASZR);
	readb(FASZR);
	return ret;
}
