text: /*
   * (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;
  }
  