mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			447 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			447 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (C) Copyright 2007
 | 
						|
 * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier:	GPL-2.0+
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <asm/io.h>
 | 
						|
#include <spartan2.h>
 | 
						|
#include <spartan3.h>
 | 
						|
#include <command.h>
 | 
						|
#include "fpga.h"
 | 
						|
#include "pmc440.h"
 | 
						|
 | 
						|
DECLARE_GLOBAL_DATA_PTR;
 | 
						|
 | 
						|
#if defined(CONFIG_FPGA)
 | 
						|
 | 
						|
#define USE_SP_CODE
 | 
						|
 | 
						|
#ifdef USE_SP_CODE
 | 
						|
xilinx_spartan3_slave_parallel_fns pmc440_fpga_fns = {
 | 
						|
	fpga_pre_config_fn,
 | 
						|
	fpga_pgm_fn,
 | 
						|
	fpga_init_fn,
 | 
						|
	NULL, /* err */
 | 
						|
	fpga_done_fn,
 | 
						|
	fpga_clk_fn,
 | 
						|
	fpga_cs_fn,
 | 
						|
	fpga_wr_fn,
 | 
						|
	NULL, /* rdata */
 | 
						|
	fpga_wdata_fn,
 | 
						|
	fpga_busy_fn,
 | 
						|
	fpga_abort_fn,
 | 
						|
	fpga_post_config_fn,
 | 
						|
};
 | 
						|
#else
 | 
						|
xilinx_spartan3_slave_serial_fns pmc440_fpga_fns = {
 | 
						|
	fpga_pre_config_fn,
 | 
						|
	fpga_pgm_fn,
 | 
						|
	fpga_clk_fn,
 | 
						|
	fpga_init_fn,
 | 
						|
	fpga_done_fn,
 | 
						|
	fpga_wr_fn,
 | 
						|
	fpga_post_config_fn,
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
xilinx_spartan2_slave_serial_fns ngcc_fpga_fns = {
 | 
						|
	ngcc_fpga_pre_config_fn,
 | 
						|
	ngcc_fpga_pgm_fn,
 | 
						|
	ngcc_fpga_clk_fn,
 | 
						|
	ngcc_fpga_init_fn,
 | 
						|
	ngcc_fpga_done_fn,
 | 
						|
	ngcc_fpga_wr_fn,
 | 
						|
	ngcc_fpga_post_config_fn
 | 
						|
};
 | 
						|
 | 
						|
xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
 | 
						|
	XILINX_XC3S1200E_DESC(
 | 
						|
#ifdef USE_SP_CODE
 | 
						|
		slave_parallel,
 | 
						|
#else
 | 
						|
		slave_serial,
 | 
						|
#endif
 | 
						|
		(void *)&pmc440_fpga_fns,
 | 
						|
		0),
 | 
						|
	XILINX_XC2S200_DESC(
 | 
						|
		slave_serial,
 | 
						|
		(void *)&ngcc_fpga_fns,
 | 
						|
		0)
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the active-low FPGA reset signal.
 | 
						|
 */
 | 
						|
void fpga_reset(int assert)
 | 
						|
{
 | 
						|
	debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
 | 
						|
	if (assert) {
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
 | 
						|
		debug("asserted\n");
 | 
						|
	} else {
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
 | 
						|
		debug("deasserted\n");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize the SelectMap interface.  We assume that the mode and the
 | 
						|
 * initial state of all of the port pins have already been set!
 | 
						|
 */
 | 
						|
void fpga_serialslave_init(void)
 | 
						|
{
 | 
						|
	debug("%s:%d: Initialize serial slave interface\n", __FUNCTION__,
 | 
						|
	      __LINE__);
 | 
						|
	fpga_pgm_fn(false, false, 0);	/* make sure program pin is inactive */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the FPGA's active-low SelectMap program line to the specified level
 | 
						|
 */
 | 
						|
int fpga_pgm_fn(int assert, int flush, int cookie)
 | 
						|
{
 | 
						|
	debug("%s:%d: FPGA PROGRAM ",
 | 
						|
	      __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	if (assert) {
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_PRG);
 | 
						|
		debug("asserted\n");
 | 
						|
	} else {
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_PRG);
 | 
						|
		debug("deasserted\n");
 | 
						|
	}
 | 
						|
	return assert;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
 | 
						|
 * asserted (low).
 | 
						|
 */
 | 
						|
int fpga_init_fn(int cookie)
 | 
						|
{
 | 
						|
	if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_INIT)
 | 
						|
		return 0;
 | 
						|
	else
 | 
						|
		return 1;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef USE_SP_CODE
 | 
						|
int fpga_abort_fn(int cookie)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int fpga_cs_fn(int assert_cs, int flush, int cookie)
 | 
						|
{
 | 
						|
	return assert_cs;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int fpga_busy_fn(int cookie)
 | 
						|
{
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Test the state of the active-high FPGA DONE pin
 | 
						|
 */
 | 
						|
int fpga_done_fn(int cookie)
 | 
						|
{
 | 
						|
	if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_DONE)
 | 
						|
		return 1;
 | 
						|
	else
 | 
						|
		return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * FPGA pre-configuration function. Just make sure that
 | 
						|
 * FPGA reset is asserted to keep the FPGA from starting up after
 | 
						|
 * configuration.
 | 
						|
 */
 | 
						|
int fpga_pre_config_fn(int cookie)
 | 
						|
{
 | 
						|
	debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
 | 
						|
	fpga_reset(true);
 | 
						|
 | 
						|
	/* release init# */
 | 
						|
	out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | GPIO0_FPGA_FORCEINIT);
 | 
						|
	/* disable PLD IOs */
 | 
						|
	out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_IOEN_N);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * FPGA post configuration function. Blip the FPGA reset line and then see if
 | 
						|
 * the FPGA appears to be running.
 | 
						|
 */
 | 
						|
int fpga_post_config_fn(int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
	int rc=0;
 | 
						|
	char *s;
 | 
						|
 | 
						|
	debug("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	/* enable PLD0..7 pins */
 | 
						|
	out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_IOEN_N);
 | 
						|
 | 
						|
	fpga_reset(true);
 | 
						|
	udelay (100);
 | 
						|
	fpga_reset(false);
 | 
						|
	udelay (100);
 | 
						|
 | 
						|
	FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK);
 | 
						|
 | 
						|
	/* NGCC/CANDES only: enable ledlink */
 | 
						|
	if ((s = getenv("bd_type")) &&
 | 
						|
	    ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes"))))
 | 
						|
		FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
 | 
						|
 | 
						|
	return rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int fpga_clk_fn(int assert_clk, int flush, int cookie)
 | 
						|
{
 | 
						|
	if (assert_clk)
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
 | 
						|
	else
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
 | 
						|
 | 
						|
	return assert_clk;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int fpga_wr_fn(int assert_write, int flush, int cookie)
 | 
						|
{
 | 
						|
	if (assert_write)
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
 | 
						|
	else
 | 
						|
		out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
 | 
						|
 | 
						|
	return assert_write;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef USE_SP_CODE
 | 
						|
int fpga_wdata_fn(uchar data, int flush, int cookie)
 | 
						|
{
 | 
						|
	uchar val = data;
 | 
						|
	ulong or = in_be32((void*)GPIO1_OR);
 | 
						|
	int i = 7;
 | 
						|
	do {
 | 
						|
		/* Write data */
 | 
						|
		if (val & 0x80)
 | 
						|
			or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
 | 
						|
		else
 | 
						|
			or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
 | 
						|
 | 
						|
		out_be32((void*)GPIO1_OR, or);
 | 
						|
 | 
						|
		/* Assert the clock */
 | 
						|
		or |= GPIO1_FPGA_CLK;
 | 
						|
		out_be32((void*)GPIO1_OR, or);
 | 
						|
		val <<= 1;
 | 
						|
		i --;
 | 
						|
	} while (i > 0);
 | 
						|
 | 
						|
	/* Write last data bit (the 8th clock comes from the sp_load() code */
 | 
						|
	if (val & 0x80)
 | 
						|
		or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
 | 
						|
	else
 | 
						|
		or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
 | 
						|
 | 
						|
	out_be32((void*)GPIO1_OR, or);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#define NGCC_FPGA_PRG  CLOCK_EN
 | 
						|
#define NGCC_FPGA_DATA RESET_OUT
 | 
						|
#define NGCC_FPGA_DONE CLOCK_IN
 | 
						|
#define NGCC_FPGA_INIT IRIGB_R_IN
 | 
						|
#define NGCC_FPGA_CLK  CLOCK_OUT
 | 
						|
 | 
						|
void ngcc_fpga_serialslave_init(void)
 | 
						|
{
 | 
						|
	debug("%s:%d: Initialize serial slave interface\n",
 | 
						|
	      __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	/* make sure program pin is inactive */
 | 
						|
	ngcc_fpga_pgm_fn(false, false, 0);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the active-low FPGA reset signal.
 | 
						|
 */
 | 
						|
void ngcc_fpga_reset(int assert)
 | 
						|
{
 | 
						|
	debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	if (assert) {
 | 
						|
		FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
 | 
						|
		debug("asserted\n");
 | 
						|
	} else {
 | 
						|
		FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
 | 
						|
		debug("deasserted\n");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the FPGA's active-low SelectMap program line to the specified level
 | 
						|
 */
 | 
						|
int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
 | 
						|
	debug("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	if (assert) {
 | 
						|
		FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
 | 
						|
		debug("asserted\n");
 | 
						|
	} else {
 | 
						|
		FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
 | 
						|
		debug("deasserted\n");
 | 
						|
	}
 | 
						|
 | 
						|
	return assert;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
 | 
						|
 * asserted (low).
 | 
						|
 */
 | 
						|
int ngcc_fpga_init_fn(int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
 | 
						|
	debug("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
 | 
						|
	if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
 | 
						|
		debug("high\n");
 | 
						|
		return 0;
 | 
						|
	} else {
 | 
						|
		debug("low\n");
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Test the state of the active-high FPGA DONE pin
 | 
						|
 */
 | 
						|
int ngcc_fpga_done_fn(int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
 | 
						|
	debug("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
 | 
						|
	if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
 | 
						|
		debug("DONE high\n");
 | 
						|
		return 1;
 | 
						|
	} else {
 | 
						|
		debug("low\n");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * FPGA pre-configuration function.
 | 
						|
 */
 | 
						|
int ngcc_fpga_pre_config_fn(int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
	debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	ngcc_fpga_reset(true);
 | 
						|
	FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
 | 
						|
 | 
						|
	ngcc_fpga_reset(true);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * FPGA post configuration function. Blip the FPGA reset line and then see if
 | 
						|
 * the FPGA appears to be running.
 | 
						|
 */
 | 
						|
int ngcc_fpga_post_config_fn(int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
 | 
						|
	debug("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
 | 
						|
 | 
						|
	udelay (100);
 | 
						|
	ngcc_fpga_reset(false);
 | 
						|
 | 
						|
	FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
 | 
						|
	if (assert_clk)
 | 
						|
		FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
 | 
						|
	else
 | 
						|
		FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
 | 
						|
 | 
						|
	return assert_clk;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
 | 
						|
{
 | 
						|
	pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
 | 
						|
 | 
						|
	if (assert_write)
 | 
						|
		FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
 | 
						|
	else
 | 
						|
		FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
 | 
						|
 | 
						|
	return assert_write;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize the fpga.  Return 1 on success, 0 on failure.
 | 
						|
 */
 | 
						|
int pmc440_init_fpga(void)
 | 
						|
{
 | 
						|
	char *s;
 | 
						|
 | 
						|
	debug("%s:%d: Initialize FPGA interface\n",
 | 
						|
	      __FUNCTION__, __LINE__);
 | 
						|
	fpga_init();
 | 
						|
 | 
						|
	fpga_serialslave_init ();
 | 
						|
	debug("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
 | 
						|
	fpga_add (fpga_xilinx, &fpga[0]);
 | 
						|
 | 
						|
	/* NGCC only */
 | 
						|
	if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
 | 
						|
		ngcc_fpga_serialslave_init ();
 | 
						|
		debug("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
 | 
						|
		fpga_add (fpga_xilinx, &fpga[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
#endif /* CONFIG_FPGA */
 |