/*
 * (C) Copyright 2007
 * Eran Liberty, Extricom , eran.liberty@gmail.com
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 */

#include <common.h>		/* core U-Boot definitions */
#include <altera.h>

#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_STRATIX_II)

int StratixII_ps_fpp_load (Altera_desc * desc, void *buf, size_t bsize,
			   int isSerial, int isSecure);
int StratixII_ps_fpp_dump (Altera_desc * desc, void *buf, size_t bsize);

/****************************************************************/
/* Stratix II Generic Implementation                            */
int StratixII_load (Altera_desc * desc, void *buf, size_t bsize)
{
	int ret_val = FPGA_FAIL;

	switch (desc->iface) {
	case passive_serial:
		ret_val = StratixII_ps_fpp_load (desc, buf, bsize, 1, 0);
		break;
	case fast_passive_parallel:
		ret_val = StratixII_ps_fpp_load (desc, buf, bsize, 0, 0);
		break;
	case fast_passive_parallel_security:
		ret_val = StratixII_ps_fpp_load (desc, buf, bsize, 0, 1);
		break;

		/* Add new interface types here */
	default:
		printf ("%s: Unsupported interface type, %d\n", __FUNCTION__,
			desc->iface);
	}
	return ret_val;
}

int StratixII_dump (Altera_desc * desc, void *buf, size_t bsize)
{
	int ret_val = FPGA_FAIL;

	switch (desc->iface) {
	case passive_serial:
	case fast_passive_parallel:
	case fast_passive_parallel_security:
		ret_val = StratixII_ps_fpp_dump (desc, buf, bsize);
		break;
		/* Add new interface types here */
	default:
		printf ("%s: Unsupported interface type, %d\n", __FUNCTION__,
			desc->iface);
	}
	return ret_val;
}

int StratixII_info (Altera_desc * desc)
{
	return FPGA_SUCCESS;
}

int StratixII_reloc (Altera_desc * desc, ulong reloc_offset)
{
	int i;
	uint32_t dest = (uint32_t) desc & 0xff000000;

	/* we assume a relocated code and non relocated code has different upper 8 bits */
	if (dest != ((uint32_t) desc->iface_fns & 0xff000000)) {
		desc->iface_fns =
		    (void *)((uint32_t) (desc->iface_fns) + reloc_offset);
	}
	for (i = 0; i < sizeof (altera_board_specific_func) / sizeof (void *);
	     i++) {
		if (dest !=
		    ((uint32_t) (((void **)(desc->iface_fns))[i]) & 0xff000000))
		{
			((void **)(desc->iface_fns))[i] =
			    (void
			     *)(((uint32_t) (((void **)(desc->iface_fns))[i])) +
				reloc_offset);
		}
	}
	return FPGA_SUCCESS;
}

int StratixII_ps_fpp_dump (Altera_desc * desc, void *buf, size_t bsize)
{
	printf ("Stratix II Fast Passive Parallel dump is not implemented\n");
	return FPGA_FAIL;
}

int StratixII_ps_fpp_load (Altera_desc * desc, void *buf, size_t bsize,
			   int isSerial, int isSecure)
{
	altera_board_specific_func *fns;
	int cookie;
	int ret_val = FPGA_FAIL;
	int bytecount;
	char *buff = buf;
	int i;

	if (!desc) {
		printf ("%s(%d) Altera_desc missing\n", __FUNCTION__, __LINE__);
		return FPGA_FAIL;
	}
	if (!buff) {
		printf ("%s(%d) buffer is missing\n", __FUNCTION__, __LINE__);
		return FPGA_FAIL;
	}
	if (!bsize) {
		printf ("%s(%d) size is zero\n", __FUNCTION__, __LINE__);
		return FPGA_FAIL;
	}
	if (!desc->iface_fns) {
		printf
		    ("%s(%d) Altera_desc function interface table is missing\n",
		     __FUNCTION__, __LINE__);
		return FPGA_FAIL;
	}
	fns = (altera_board_specific_func *) (desc->iface_fns);
	cookie = desc->cookie;

	if (!
	    (fns->config && fns->status && fns->done && fns->data
	     && fns->abort)) {
		printf
		    ("%s(%d) Missing some function in the function interface table\n",
		     __FUNCTION__, __LINE__);
		return FPGA_FAIL;
	}

	/* 1. give board specific a chance to do anything before we start */
	if (fns->pre) {
		if ((ret_val = fns->pre (cookie)) < 0) {
			return ret_val;
		}
	}

	/* from this point on we must fail gracfully by calling lower layer abort */

	/* 2. Strat burn cycle by deasserting config for t_CFG and waiting t_CF2CK after reaserted */
	fns->config (0, 1, cookie);
	udelay (5);		/* nCONFIG low pulse width 2usec */
	fns->config (1, 1, cookie);
	udelay (100);		/* nCONFIG high to first rising edge on DCLK */

	/* 3. Start the Data cycle with clk deasserted */
	bytecount = 0;
	fns->clk (0, 1, cookie);

	printf ("loading to fpga    ");
	while (bytecount < bsize) {
		/* 3.1 check stratix has not signaled us an error */
		if (fns->status (cookie) != 1) {
			printf
			    ("\n%s(%d) Stratix failed (byte transfered till failure 0x%x)\n",
			     __FUNCTION__, __LINE__, bytecount);
			fns->abort (cookie);
			return FPGA_FAIL;
		}
		if (isSerial) {
			int i;
			uint8_t data = buff[bytecount++];
			for (i = 0; i < 8; i++) {
				/* 3.2(ps) put data on the bus */
				fns->data ((data >> i) & 1, 1, cookie);

				/* 3.3(ps) clock once */
				fns->clk (1, 1, cookie);
				fns->clk (0, 1, cookie);
			}
		} else {
			/* 3.2(fpp) put data on the bus */
			fns->data (buff[bytecount++], 1, cookie);

			/* 3.3(fpp) clock once */
			fns->clk (1, 1, cookie);
			fns->clk (0, 1, cookie);

			/* 3.4(fpp) for secure cycle push 3 more  clocks */
			for (i = 0; isSecure && i < 3; i++) {
				fns->clk (1, 1, cookie);
				fns->clk (0, 1, cookie);
			}
		}

		/* 3.5 while clk is deasserted it is safe to print some progress indication */
		if ((bytecount % (bsize / 100)) == 0) {
			printf ("\b\b\b%02d\%", bytecount * 100 / bsize);
		}
	}

	/* 4. Set one last clock and check conf done signal */
	fns->clk (1, 1, cookie);
	udelay (100);
	if (!fns->done (cookie)) {
		printf (" error!.\n");
		fns->abort (cookie);
		return FPGA_FAIL;
	} else {
		printf ("\b\b\b done.\n");
	}

	/* 5. call lower layer post configuration */
	if (fns->post) {
		if ((ret_val = fns->post (cookie)) < 0) {
			fns->abort (cookie);
			return ret_val;
		}
	}

	return FPGA_SUCCESS;
}

#endif				/* defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ALTERA) && defined(CONFIG_FPGA_STRATIX_II) */
