/*
 * (C) Copyright 2002
 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
 * Keith Outwater, keith_outwater@mvis.com.
 *
 * (C) Copyright 2008
 * Andre Schwarz, Matrix Vision GmbH, andre.schwarz@matrix-vision.de
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <ACEX1K.h>
#include <command.h>
#include "fpga.h"
#include "mvblm7.h"

#ifdef FPGA_DEBUG
#define fpga_debug(fmt, args...)      printf("%s: "fmt, __func__, ##args)
#else
#define fpga_debug(fmt, args...)
#endif

Altera_CYC2_Passive_Serial_fns altera_fns = {
	fpga_null_fn,
	fpga_config_fn,
	fpga_status_fn,
	fpga_done_fn,
	fpga_wr_fn,
	fpga_null_fn,
	fpga_null_fn,
};

Altera_desc cyclone2 = {
	Altera_CYC2,
	passive_serial,
	Altera_EP2C20_SIZE,
	(void *) &altera_fns,
	NULL,
	0
};

DECLARE_GLOBAL_DATA_PTR;

int mvblm7_init_fpga(void)
{
	fpga_debug("Initialize FPGA interface\n");
	fpga_init();
	fpga_add(fpga_altera, &cyclone2);
	fpga_config_fn(0, 1, 0);
	udelay(60);

	return 1;
}

int fpga_null_fn(int cookie)
{
	return 0;
}

int fpga_config_fn(int assert, int flush, int cookie)
{
	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
	volatile gpio83xx_t *gpio = (volatile gpio83xx_t *)&im->gpio[0];
	u32 dvo = gpio->dat;

	fpga_debug("SET config : %s\n", assert ? "low" : "high");
	if (assert)
		dvo |= FPGA_CONFIG;
	else
		dvo &= ~FPGA_CONFIG;

	if (flush)
		gpio->dat = dvo;

	return assert;
}

int fpga_done_fn(int cookie)
{
	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
	volatile gpio83xx_t *gpio = (volatile gpio83xx_t *)&im->gpio[0];
	int result = 0;

	udelay(10);
	fpga_debug("CONF_DONE check ... ");
	if (gpio->dat & FPGA_CONF_DONE)  {
		fpga_debug("high\n");
		result = 1;
	} else
		fpga_debug("low\n");

	return result;
}

int fpga_status_fn(int cookie)
{
	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
	volatile gpio83xx_t *gpio = (volatile gpio83xx_t *)&im->gpio[0];
	int result = 0;

	fpga_debug("STATUS check ... ");
	if (gpio->dat & FPGA_STATUS)  {
		fpga_debug("high\n");
		result = 1;
	} else
		fpga_debug("low\n");

	return result;
}

int fpga_clk_fn(int assert_clk, int flush, int cookie)
{
	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
	volatile gpio83xx_t *gpio = (volatile gpio83xx_t *)&im->gpio[0];
	u32 dvo = gpio->dat;

	fpga_debug("CLOCK %s\n", assert_clk ? "high" : "low");
	if (assert_clk)
		dvo |= FPGA_CCLK;
	else
		dvo &= ~FPGA_CCLK;

	if (flush)
		gpio->dat = dvo;

	return assert_clk;
}

static inline int _write_fpga(u8 val, int dump)
{
	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
	volatile gpio83xx_t *gpio = (volatile gpio83xx_t *)&im->gpio[0];
	int i;
	u32 dvo = gpio->dat;

	if (dump)
		fpga_debug("  %02x -> ", val);
	for (i = 0; i < 8; i++) {
		dvo &= ~FPGA_CCLK;
		gpio->dat = dvo;
		dvo &= ~FPGA_DIN;
		if (dump)
			fpga_debug("%d ", val&1);
		if (val & 1)
			dvo |= FPGA_DIN;
		gpio->dat = dvo;
		dvo |= FPGA_CCLK;
		gpio->dat = dvo;
		val >>= 1;
	}
	if (dump)
		fpga_debug("\n");

	return 0;
}

int fpga_wr_fn(const void *buf, size_t len, int flush, int cookie)
{
	unsigned char *data = (unsigned char *) buf;
	int i;

	fpga_debug("fpga_wr: buf %p / size %d\n", buf, len);
	for (i = 0; i < len; i++)
		_write_fpga(data[i], 0);
	fpga_debug("\n");

	return FPGA_SUCCESS;
}
