/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2008 Wang Qingpei <Qingpei.Wang@amd.com>
 * Copyright (C) 2008 Joe Bao <Zheng.Bao@amd.com>
 * Copyright (C) 2008 Advanced Micro Devices, Inc.
 *
 * 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
 */

#include <string.h>
#include <sys/mman.h>
#include "flash.h"
#include "spi.h"

struct sb600_spi_controller {
	unsigned int spi_cntrl0;	/* 00h */
	unsigned int restrictedcmd1;	/* 04h */
	unsigned int restrictedcmd2;	/* 08h */
	unsigned int spi_cntrl1;	/* 0ch */
	unsigned int spi_cmdvalue0;	/* 10h */
	unsigned int spi_cmdvalue1;	/* 14h */
	unsigned int spi_cmdvalue2;	/* 18h */
	unsigned int spi_fakeid;	/* 1Ch */
};

struct sb600_spi_controller *spi_bar = NULL;
uint8_t *sb600_spibar;

int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
	/* Maximum read length is 8 bytes. */
	return spi_read_chunked(flash, buf, start, len, 8);
}

uint8_t sb600_read_status_register(void)
{
	const unsigned char cmd[0x02] = { JEDEC_RDSR, 0x00 };
	unsigned char readarr[JEDEC_RDSR_INSIZE];

	/* Read Status Register */
	spi_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
	return readarr[0];
}

int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf)
{
	int rc = 0, i;
	int total_size = flash->total_size * 1024;
	int result;

	/* Erase first */
	printf("Erasing flash before programming... ");
	if (flash->erase(flash)) {
		fprintf(stderr, "ERASE FAILED!\n");
		return -1;
	}
	printf("done.\n");

	printf("Programming flash");
	for (i = 0; i < total_size; i++, buf++) {
		spi_disable_blockprotect();
		result = spi_write_enable();
		if (result)
			return result;
		spi_byte_program(i, *buf);
		/* wait program complete. */
		if (i % 0x8000 == 0)
			printf(".");
		while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
			;
	}
	printf(" done.\n");
	return rc;
}

void reset_internal_fifo_pointer(void)
{
	mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);

	while (mmio_readb(sb600_spibar + 0xD) & 0x7)
		printf("reset\n");
}

void execute_command(void)
{
	mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2);

	while (mmio_readb(sb600_spibar + 2) & 1)
		;
}

int sb600_spi_command(unsigned int writecnt, unsigned int readcnt,
		      const unsigned char *writearr, unsigned char *readarr)
{
	int count;
	/* First byte is cmd which can not being sent through FIFO. */
	unsigned char cmd = *writearr++;

	writecnt--;

	spi_bar = (struct sb600_spi_controller *) sb600_spibar;

	printf_debug("%s, cmd=%x, writecnt=%x, readcnt=%x\n",
		     __func__, cmd, writecnt, readcnt);

	if (readcnt > 8) {
		printf("%s, SB600 SPI controller can not receive %d bytes, "
		       "which is limited with 8 bytes\n", __func__, readcnt);
		return 1;
	}

	if (writecnt > 8) {
		printf("%s, SB600 SPI controller can not sent %d bytes, "
		       "which is limited with 8 bytes\n", __func__, writecnt);
		return 1;
	}

	mmio_writeb(cmd, sb600_spibar + 0);
	mmio_writeb(readcnt << 4 | (writecnt), sb600_spibar + 1);

	/* Before we use the FIFO, reset it first. */
	reset_internal_fifo_pointer();

	/* Send the write byte to FIFO. */
	for (count = 0; count < writecnt; count++, writearr++) {
		printf_debug(" [%x]", *writearr);
		mmio_writeb(*writearr, sb600_spibar + 0xC);
	}
	printf_debug("\n");

	/*
	 * We should send the data by sequence, which means we need to reset
	 * the FIFO pointer to the first byte we want to send.
	 */
	reset_internal_fifo_pointer();

	execute_command();

	/*
	 * After the command executed, we should find out the index of the
	 * received byte. Here we just reset the FIFO pointer, skip the
	 * writecnt, is there anyone who have anther method to replace it?
	 */
	reset_internal_fifo_pointer();

	for (count = 0; count < writecnt; count++) {
		cmd = mmio_readb(sb600_spibar + 0xC);	/* Skip the byte we send. */
		printf_debug("[ %2x]", cmd);
	}

	printf_debug("The FIFO pointer 6 is %d.\n", mmio_readb(sb600_spibar + 0xd) & 0x07);
	for (count = 0; count < readcnt; count++, readarr++) {
		*readarr = mmio_readb(sb600_spibar + 0xC);
		printf_debug("[%02x]", *readarr);
	}
	printf_debug("\n");

	return 0;
}
