/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2007, 2008, 2009, 2010, 2011 Carl-Daniel Hailfinger
 * Copyright (C) 2008 coresystems GmbH
 *
 * 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; version 2 of the License.
 *
 * 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.
 */

/*
 * Contains the generic SPI framework
 */

#include <strings.h>
#include <string.h>
#include "flash.h"
#include "flashchips.h"
#include "chipdrivers.h"
#include "programmer.h"
#include "spi.h"

int spi_send_command(const struct flashctx *flash, unsigned int writecnt,
		     unsigned int readcnt, const unsigned char *writearr,
		     unsigned char *readarr)
{
	return flash->mst.spi->command(flash, writecnt, readcnt, writearr,
				       readarr);
}

int spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds)
{
	return flash->mst.spi->multicommand(flash, cmds);
}

int default_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
			     unsigned int readcnt,
			     const unsigned char *writearr,
			     unsigned char *readarr)
{
	struct spi_command cmd[] = {
	{
		.writecnt = writecnt,
		.readcnt = readcnt,
		.writearr = writearr,
		.readarr = readarr,
	}, {
		.writecnt = 0,
		.writearr = NULL,
		.readcnt = 0,
		.readarr = NULL,
	}};

	return spi_send_multicommand(flash, cmd);
}

int default_spi_send_multicommand(const struct flashctx *flash,
				  struct spi_command *cmds)
{
	int result = 0;
	for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) {
		result = spi_send_command(flash, cmds->writecnt, cmds->readcnt,
					  cmds->writearr, cmds->readarr);
	}
	return result;
}

int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
		     unsigned int len)
{
	unsigned int max_data = flash->mst.spi->max_data_read;
	if (max_data == MAX_DATA_UNSPECIFIED) {
		msg_perr("%s called, but SPI read chunk size not defined on this hardware.\n"
			 "Please report a bug at flashprog@flashprog.org\n", __func__);
		return 1;
	}
	return flashprog_read_chunked(flash, buf, start, len, max_data, spi_nbyte_read);
}

int default_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
{
	unsigned int max_data = flash->mst.spi->max_data_write;
	if (max_data == MAX_DATA_UNSPECIFIED) {
		msg_perr("%s called, but SPI write chunk size not defined on this hardware.\n"
			 "Please report a bug at flashprog@flashprog.org\n", __func__);
		return 1;
	}
	return spi_write_chunked(flash, buf, start, len, max_data);
}

int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
		  unsigned int len)
{
	int ret;
	size_t to_read;
	for (; len; len -= to_read, buf += to_read, start += to_read) {
		/* Do not cross 16MiB boundaries in a single transfer.
		   This helps with
		   o multi-die 4-byte-addressing chips,
		   o dediprog that has a protocol limit of 32MiB-512B. */
		to_read = min(ALIGN_DOWN(start + 16*MiB, 16*MiB) - start, len);
		ret = flash->mst.spi->read(flash, buf, start, to_read);
		if (ret)
			return ret;
	}
	return 0;
}

/*
 * Program chip using page (256 bytes) programming.
 * Some SPI masters can't do this, they use single byte programming instead.
 * The redirect to single byte programming is achieved by setting
 * .write_256 = spi_chip_write_1
 */
/* real chunksize is up to 256, logical chunksize is 256 */
int spi_chip_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
{
	return flash->mst.spi->write_256(flash, buf, start, len);
}

int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
{
	if (flash->mst.spi->write_aai)
		return flash->mst.spi->write_aai(flash, buf, start, len);
	return default_spi_write_aai(flash, buf, start, len);
}

bool default_spi_probe_opcode(const struct flashctx *flash, uint8_t opcode)
{
	return true;
}

int register_spi_master(const struct spi_master *mst, size_t max_rom_decode, void *data)
{
	struct registered_master rmst;

	if (mst->shutdown) {
		if (register_shutdown(mst->shutdown, data)) {
			mst->shutdown(data); /* cleanup */
			return 1;
		}
	}

	if (!mst->write_256 || !mst->read || !mst->command ||
	    !mst->multicommand || !mst->probe_opcode ||
	    ((mst->command == default_spi_send_command) &&
	     (mst->multicommand == default_spi_send_multicommand))) {
		msg_perr("%s called with incomplete master definition.\n"
			 "Please report a bug at flashprog@flashprog.org\n",
			 __func__);
		return ERROR_FLASHPROG_BUG;
	}

	if (max_rom_decode)
		rmst.max_rom_decode = max_rom_decode;
	else
		rmst.max_rom_decode = MAX_ROM_DECODE_UNLIMITED;
	rmst.buses_supported = BUS_SPI;
	rmst.spi = *mst;
	if (data)
		rmst.spi.data = data;
	return register_master(&rmst);
}

/*
 * The following array has erasefn and opcode list pair. The opcode list pair is
 * 0 termintated and must have size one more than the maximum number of opcodes
 * used by any erasefn. Also the opcodes must be in increasing order.
 */
static const struct {
	erasefunc_t *func;
	uint8_t opcode[3];
	bool native_4ba;
} function_opcode_list[] = {
	{spi_block_erase_20, {0x20}, false},
	{spi_block_erase_21, {0x21}, true},
	{spi_block_erase_50, {0x50}, false},
	{spi_block_erase_52, {0x52}, false},
	{spi_block_erase_53, {0x53}, true},
	{spi_block_erase_5c, {0x5c}, true},
	{spi_block_erase_60, {0x60}, false},
	{spi_block_erase_62, {0x62}, false},
	{spi_block_erase_81, {0x81}, false},
	{spi_block_erase_c4, {0xc4}, false},
	{spi_block_erase_c7, {0xc7}, false},
	{spi_block_erase_d7, {0xd7}, false},
	{spi_block_erase_d8, {0xd8}, false},
	{spi_block_erase_db, {0xdb}, false},
	{spi_block_erase_dc, {0xdc}, true},
	//AT45CS1282
	{spi_erase_at45cs_sector, {0x50, 0x7c, 0}, false},
	//AT45DB**
	{spi_erase_at45db_page, {0x81}, false},
	{spi_erase_at45db_block, {0x50}, false},
	{spi_erase_at45db_sector, {0x7c}, false},
	{spi_erase_at45db_chip, {0xc7}, false},
};

const uint8_t *spi_get_opcode_from_erasefn(erasefunc_t *func, bool *native_4ba)
{
	size_t i;
	for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) {
		if (function_opcode_list[i].func == func) {
			if (native_4ba)
				*native_4ba = function_opcode_list[i].native_4ba;
			return function_opcode_list[i].opcode;
		}
	}
	msg_cinfo("%s: unknown erase function (0x%p). Please report "
			"this at flashprog@flashprog.org\n", __func__, func);
	return NULL;
}
