/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2000 Silicon Integrated System Corporation
 *
 * 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
 */

/*
 * Datasheet:
 *  - Name: Intel 82802AB/82802AC Firmware Hub (FWH)
 *  - URL: http://www.intel.com/design/chipsets/datashts/290658.htm
 *  - PDF: http://download.intel.com/design/chipsets/datashts/29065804.pdf
 *  - Order number: 290658-004
 */

#include "flash.h"
#include "chipdrivers.h"

// I need that Berkeley bit-map printer
void print_status_82802ab(uint8_t status)
{
	msg_cdbg("%s", status & 0x80 ? "Ready:" : "Busy:");
	msg_cdbg("%s", status & 0x40 ? "BE SUSPEND:" : "BE RUN/FINISH:");
	msg_cdbg("%s", status & 0x20 ? "BE ERROR:" : "BE OK:");
	msg_cdbg("%s", status & 0x10 ? "PROG ERR:" : "PROG OK:");
	msg_cdbg("%s", status & 0x8 ? "VP ERR:" : "VPP OK:");
	msg_cdbg("%s", status & 0x4 ? "PROG SUSPEND:" : "PROG RUN/FINISH:");
	msg_cdbg("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:");
}

int probe_82802ab(struct flashchip *flash)
{
	chipaddr bios = flash->virtual_memory;
	uint8_t id1, id2;
	uint8_t flashcontent1, flashcontent2;
	int shifted = (flash->feature_bits & FEATURE_ADDR_SHIFTED) != 0;

	/* Reset to get a clean state */
	chip_writeb(0xFF, bios);
	programmer_delay(10);

	/* Enter ID mode */
	chip_writeb(0x90, bios);
	programmer_delay(10);

	id1 = chip_readb(bios + (0x00 << shifted));
	id2 = chip_readb(bios + (0x01 << shifted));

	/* Leave ID mode */
	chip_writeb(0xFF, bios);

	programmer_delay(10);

	msg_cdbg("%s: id1 0x%02x, id2 0x%02x", __func__, id1, id2);

	if (!oddparity(id1))
		msg_cdbg(", id1 parity violation");

	/* Read the product ID location again. We should now see normal flash contents. */
	flashcontent1 = chip_readb(bios + (0x00 << shifted));
	flashcontent2 = chip_readb(bios + (0x01 << shifted));

	if (id1 == flashcontent1)
		msg_cdbg(", id1 is normal flash content");
	if (id2 == flashcontent2)
		msg_cdbg(", id2 is normal flash content");

	msg_cdbg("\n");
	if (id1 != flash->manufacture_id || id2 != flash->model_id)
		return 0;

	if (flash->feature_bits & FEATURE_REGISTERMAP)
		map_flash_registers(flash);

	return 1;
}

uint8_t wait_82802ab(chipaddr bios)
{
	uint8_t status;

	chip_writeb(0x70, bios);
	if ((chip_readb(bios) & 0x80) == 0) {	// it's busy
		while ((chip_readb(bios) & 0x80) == 0) ;
	}

	status = chip_readb(bios);

	/* Reset to get a clean state */
	chip_writeb(0xFF, bios);

	return status;
}

int unlock_82802ab(struct flashchip *flash)
{
	int i;
	//chipaddr wrprotect = flash->virtual_registers + page + 2;

	for (i = 0; i < flash->total_size * 1024; i+= flash->page_size)
	{
		chip_writeb(0, flash->virtual_registers + i + 2);
	}

	return 0;
}

int erase_block_82802ab(struct flashchip *flash, unsigned int page, unsigned int pagesize)
{
	chipaddr bios = flash->virtual_memory;
	uint8_t status;

	// clear status register
	chip_writeb(0x50, bios + page);

	// now start it
	chip_writeb(0x20, bios + page);
	chip_writeb(0xd0, bios + page);
	programmer_delay(10);

	// now let's see what the register is
	status = wait_82802ab(bios);
	print_status_82802ab(status);

	if (check_erased_range(flash, page, pagesize)) {
		msg_cerr("ERASE FAILED!\n");
		return -1;
	}
	msg_cinfo("DONE BLOCK 0x%x\n", page);

	return 0;
}

int erase_82802ab(struct flashchip *flash)
{
	int i;
	unsigned int total_size = flash->total_size * 1024;

	msg_cspew("total_size is %d; flash->page_size is %d\n",
	       total_size, flash->page_size);
	for (i = 0; i < total_size; i += flash->page_size)
		if (erase_block_82802ab(flash, i, flash->page_size)) {
			msg_cerr("ERASE FAILED!\n");
			return -1;
		}
	msg_cinfo("DONE ERASE\n");

	return 0;
}

void write_page_82802ab(chipaddr bios, uint8_t *src,
			chipaddr dst, int page_size)
{
	int i;

	for (i = 0; i < page_size; i++) {
		/* transfer data from source to destination */
		chip_writeb(0x40, dst);
		chip_writeb(*src++, dst++);
		wait_82802ab(bios);
	}
}

int write_82802ab(struct flashchip *flash, uint8_t *buf)
{
	int i;
	chipaddr bios = flash->virtual_memory;

	if (erase_flash(flash)) {
		msg_cerr("ERASE FAILED!\n");
		return -1;
	}

	msg_cinfo("Programming at: ");
	for (i = 0; i < flash->total_size; i++) {
		if ((i & 0x3) == 0)
			msg_cinfo("address: 0x%08lx", (unsigned long)i * 1024);

                write_page_82802ab(bios, buf + i * 1024, bios + i * 1024, 1024);

		if ((i & 0x3) == 0)
			msg_cinfo("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
	}

	msg_cinfo("DONE!\n");
	return 0;
}

int unlock_28f004s5(struct flashchip *flash)
{
	chipaddr bios = flash->virtual_memory;
	uint8_t mcfg, bcfg, need_unlock = 0, can_unlock = 0;
	int i;

	/* Clear status register */
	chip_writeb(0x50, bios);

	/* Read identifier codes */
	chip_writeb(0x90, bios);

	/* Read master lock-bit */
	mcfg = chip_readb(bios + 0x3);
	msg_cdbg("master lock is ");
	if (mcfg) {
		msg_cdbg("locked!\n");
	} else {
		msg_cdbg("unlocked!\n");
		can_unlock = 1;
	}
	
	/* Read block lock-bits */
	for (i = 0; i < flash->total_size * 1024; i+= (64 * 1024)) {
		bcfg = chip_readb(bios + i + 2); // read block lock config
		msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un");
		if (bcfg) {
			need_unlock = 1;
		}
	}

	/* Reset chip */
	chip_writeb(0xFF, bios);

	/* Unlock: clear block lock-bits, if needed */
	if (can_unlock && need_unlock) {
		msg_cdbg("Unlock: ");
		chip_writeb(0x60, bios);
		chip_writeb(0xD0, bios);
		chip_writeb(0xFF, bios);
		msg_cdbg("Done!\n");
	}

	/* Error: master locked or a block is locked */
	if (!can_unlock && need_unlock) {
		msg_cerr("At least one block is locked and lockdown is active!\n");
		return -1;
	}

	return 0;
}
