/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2007 Carl-Daniel Hailfinger
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

/*
 * EN29F512 has 1C,21
 * EN29F010 has 1C,20
 * EN29F040A has 1C,04
 * EN29LV010 has 1C,6E and uses short F0 reset sequence
 * EN29LV040(A) has 1C,4F and uses short F0 reset sequence
 */

#include "flash.h"

int probe_en29f512(struct flashchip *flash)
{
	chipaddr bios = flash->virtual_memory;
	uint8_t id1, id2;

	chip_writeb(0xAA, bios + 0x555);
	chip_writeb(0x55, bios + 0x2AA);
	chip_writeb(0x90, bios + 0x555);

	programmer_delay(10);

	id1 = chip_readb(bios + 0x100);
	id2 = chip_readb(bios + 0x101);

	/* exit by writing F0 anywhere? or the code below */
	chip_writeb(0xAA, bios + 0x555);
	chip_writeb(0x55, bios + 0x2AA);
	chip_writeb(0xF0, bios + 0x555);

	printf_debug("%s: id1 0x%02x, id2 0x%02x\n", __FUNCTION__, id1, id2);

	if (id1 == flash->manufacture_id && id2 == flash->model_id)
		return 1;

	return 0;
}

/*
 * EN29F002AT has 1C,92
 * EN29F002AB has 1C,97
 */

/* This does not seem to function properly for EN29F002NT. */
int probe_en29f002a(struct flashchip *flash)
{
	chipaddr bios = flash->virtual_memory;
	uint8_t id1, id2;

	chip_writeb(0xAA, bios + 0x555);
	chip_writeb(0x55, bios + 0xAAA);
	chip_writeb(0x90, bios + 0x555);

	programmer_delay(10);

	id1 = chip_readb(bios + 0x100);
	id2 = chip_readb(bios + 0x101);

	/* exit by writing F0 anywhere? or the code below */
	chip_writeb(0xAA, bios + 0x555);
	chip_writeb(0x55, bios + 0xAAA);
	chip_writeb(0xF0, bios + 0x555);

	printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);

	if (id1 == flash->manufacture_id && id2 == flash->model_id)
		return 1;

	return 0;
}

/* The EN29F002 chip needs repeated single byte writing, no block writing. */
int write_en29f002a(struct flashchip *flash, uint8_t *buf)
{
	int i;
	int total_size = flash->total_size * 1024;
	chipaddr bios = flash->virtual_memory;
	chipaddr dst = bios;

	//chip_writeb(0xF0, bios);
	programmer_delay(10);
	if (erase_chip_jedec(flash)) {
		fprintf(stderr, "ERASE FAILED!\n");
		return -1;
	}

	printf("Programming page: ");
	for (i = 0; i < total_size; i++) {
		/* write to the sector */
		if ((i & 0xfff) == 0)
			printf("address: 0x%08lx", (unsigned long)i);
		chip_writeb(0xAA, bios + 0x5555);
		chip_writeb(0x55, bios + 0x2AAA);
		chip_writeb(0xA0, bios + 0x5555);
		chip_writeb(*buf++, dst++);

		/* wait for Toggle bit ready */
		toggle_ready_jedec(dst);

		if ((i & 0xfff) == 0)
			printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
	}

	printf("\n");
	return 0;
}
