mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-27 01:58:19 +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 */
 |