mirror of
https://xff.cz/git/u-boot/
synced 2025-10-17 16:02:33 +02:00
FPGA: move fpga drivers to drivers/fpga
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
This commit is contained in:
committed by
Wolfgang Denk
parent
90665e3d97
commit
c8aa7dfc18
362
drivers/fpga/ACEX1K.c
Normal file
362
drivers/fpga/ACEX1K.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.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 <ACEX1K.h> /* ACEX device family */
|
||||
|
||||
/* Define FPGA_DEBUG to get debug printf's */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/* Note: The assumption is that we cannot possibly run fast enough to
|
||||
* overrun the device (the Slave Parallel mode can free run at 50MHz).
|
||||
* If there is a need to operate slower, define CONFIG_FPGA_DELAY in
|
||||
* the board config file to slow things down.
|
||||
*/
|
||||
#ifndef CONFIG_FPGA_DELAY
|
||||
#define CONFIG_FPGA_DELAY()
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT
|
||||
#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10 /* 100 ms */
|
||||
#endif
|
||||
|
||||
static int ACEX1K_ps_load( Altera_desc *desc, void *buf, size_t bsize );
|
||||
static int ACEX1K_ps_dump( Altera_desc *desc, void *buf, size_t bsize );
|
||||
/* static int ACEX1K_ps_info( Altera_desc *desc ); */
|
||||
static int ACEX1K_ps_reloc( Altera_desc *desc, ulong reloc_offset );
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ACEX1K Generic Implementation */
|
||||
int ACEX1K_load (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
|
||||
ret_val = ACEX1K_ps_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
/* Add new interface types here */
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int ACEX1K_dump (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
|
||||
ret_val = ACEX1K_ps_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 ACEX1K_info( Altera_desc *desc )
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int ACEX1K_reloc (Altera_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (desc->family != Altera_ACEX1K) {
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
return FPGA_FAIL;
|
||||
} else
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
ret_val = ACEX1K_ps_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
/* Add new interface types here */
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ACEX1K Passive Serial Generic Implementation */
|
||||
|
||||
static int ACEX1K_ps_load (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
|
||||
int i;
|
||||
|
||||
PRINTF ("%s: start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, fn);
|
||||
|
||||
if (fn) {
|
||||
size_t bytecount = 0;
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
unsigned long ts; /* timestamp */
|
||||
|
||||
PRINTF ("%s: Function Table:\n"
|
||||
"ptr:\t0x%p\n"
|
||||
"struct: 0x%p\n"
|
||||
"config:\t0x%p\n"
|
||||
"status:\t0x%p\n"
|
||||
"clk:\t0x%p\n"
|
||||
"data:\t0x%p\n"
|
||||
"done:\t0x%p\n\n",
|
||||
__FUNCTION__, &fn, fn, fn->config, fn->status,
|
||||
fn->clk, fn->data, fn->done);
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Loading FPGA Device %d...", cookie);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/* Establish the initial state */
|
||||
(*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */
|
||||
|
||||
udelay(2); /* T_cfg > 2us */
|
||||
|
||||
/* nSTATUS should be asserted now */
|
||||
(*fn->done) (cookie);
|
||||
if ( !(*fn->status) (cookie) ) {
|
||||
puts ("** nSTATUS is not asserted.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
(*fn->config) (FALSE, TRUE, cookie); /* Deassert nCONFIG */
|
||||
udelay(2); /* T_cf2st1 < 4us */
|
||||
|
||||
/* Wait for nSTATUS to be released (i.e. deasserted) */
|
||||
ts = get_timer (0); /* get current time */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for STATUS to go high.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
(*fn->done) (cookie);
|
||||
} while ((*fn->status) (cookie));
|
||||
|
||||
/* Get ready for the burn */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
/* Load the data */
|
||||
while (bytecount < bsize) {
|
||||
unsigned char val=0;
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
|
||||
if (ctrlc ()) {
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
#endif
|
||||
/* Altera detects an error if INIT goes low (active)
|
||||
while DONE is low (inactive) */
|
||||
#if 0 /* not yet implemented */
|
||||
if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
|
||||
puts ("** CRC error during FPGA load.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
#endif
|
||||
val = data [bytecount ++ ];
|
||||
i = 8;
|
||||
do {
|
||||
/* Deassert the clock */
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Write data */
|
||||
(*fn->data) ( (val & 0x01), TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Assert the clock */
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
val >>= 1;
|
||||
i --;
|
||||
} while (i > 0);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc (' '); /* terminate the dotted line */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Checking FPGA's CONF_DONE signal - correctly booted ?
|
||||
*/
|
||||
|
||||
if ( ! (*fn->done) (cookie) ) {
|
||||
puts ("** Booting failed! CONF_DONE is still deasserted.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* "DCLK must be clocked an additional 10 times fpr ACEX 1K..."
|
||||
*/
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
puts ("Done.\n");
|
||||
}
|
||||
else {
|
||||
puts ("Fail.\n");
|
||||
}
|
||||
#endif
|
||||
(*fn->post) (cookie);
|
||||
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int ACEX1K_ps_dump (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
/* Readback is only available through the Slave Parallel and */
|
||||
/* boundary-scan interfaces. */
|
||||
printf ("%s: Passive Serial Dumping is unavailable\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
static int ACEX1K_ps_reloc (Altera_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Altera_ACEX1K_Passive_Serial_fns *fn_r, *fn =
|
||||
(Altera_ACEX1K_Passive_Serial_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
ulong addr;
|
||||
|
||||
/* Get the relocated table address */
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Altera_ACEX1K_Passive_Serial_fns *) addr;
|
||||
|
||||
if (!fn_r->relocated) {
|
||||
|
||||
if (memcmp (fn_r, fn,
|
||||
sizeof (Altera_ACEX1K_Passive_Serial_fns))
|
||||
== 0) {
|
||||
/* good copy of the table, fix the descriptor pointer */
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
|
||||
desc);
|
||||
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Altera_pre_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->config) + reloc_offset;
|
||||
fn_r->config = (Altera_config_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->status) + reloc_offset;
|
||||
fn_r->status = (Altera_status_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Altera_done_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->clk) + reloc_offset;
|
||||
fn_r->clk = (Altera_clk_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->data) + reloc_offset;
|
||||
fn_r->data = (Altera_data_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->abort) + reloc_offset;
|
||||
fn_r->abort = (Altera_abort_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Altera_post_fn) addr;
|
||||
|
||||
fn_r->relocated = TRUE;
|
||||
|
||||
} else {
|
||||
/* this table has already been moved */
|
||||
/* XXX - should check to see if the descriptor is correct */
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
||||
}
|
58
drivers/fpga/Makefile
Normal file
58
drivers/fpga/Makefile
Normal file
@@ -0,0 +1,58 @@
|
||||
#
|
||||
# (C) Copyright 2008
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# 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 $(TOPDIR)/config.mk
|
||||
|
||||
LIB := $(obj)libfpga.a
|
||||
|
||||
ifdef CONFIG_FPGA
|
||||
COBJS-y += fpga.o
|
||||
COBJS-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
|
||||
COBJS-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
|
||||
COBJS-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
|
||||
COBJS-$(CONFIG_FPGA_XILINX) += xilinx.o
|
||||
ifdef CONFIG_FPGA_ALTERA
|
||||
COBJS-y += altera.o
|
||||
COBJS-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
|
||||
COBJS-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
|
||||
COBJS-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
|
||||
endif
|
||||
endif
|
||||
|
||||
COBJS := $(COBJS-y)
|
||||
SRCS := $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS))
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(obj).depend $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
283
drivers/fpga/altera.c
Normal file
283
drivers/fpga/altera.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Altera FPGA support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <ACEX1K.h>
|
||||
#include <stratixII.h>
|
||||
|
||||
/* Define FPGA_DEBUG to get debug printf's */
|
||||
/* #define FPGA_DEBUG */
|
||||
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/* Local Static Functions */
|
||||
static int altera_validate (Altera_desc * desc, const char *fn);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int altera_load( Altera_desc *desc, void *buf, size_t bsize )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (!altera_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
} else {
|
||||
switch (desc->family) {
|
||||
case Altera_ACEX1K:
|
||||
case Altera_CYC2:
|
||||
#if defined(CONFIG_FPGA_ACEX1K)
|
||||
PRINTF ("%s: Launching the ACEX1K Loader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = ACEX1K_load (desc, buf, bsize);
|
||||
#elif defined(CONFIG_FPGA_CYCLON2)
|
||||
PRINTF ("%s: Launching the CYCLON II Loader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = CYC2_load (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for ACEX1K devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_FPGA_STRATIX_II)
|
||||
case Altera_StratixII:
|
||||
PRINTF ("%s: Launching the Stratix II Loader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = StratixII_load (desc, buf, bsize);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int altera_dump( Altera_desc *desc, void *buf, size_t bsize )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (!altera_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
} else {
|
||||
switch (desc->family) {
|
||||
case Altera_ACEX1K:
|
||||
#if defined(CONFIG_FPGA_ACEX)
|
||||
PRINTF ("%s: Launching the ACEX1K Reader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = ACEX1K_dump (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for ACEX1K devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_FPGA_STRATIX_II)
|
||||
case Altera_StratixII:
|
||||
PRINTF ("%s: Launching the Stratix II Reader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = StratixII_dump (desc, buf, bsize);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int altera_info( Altera_desc *desc )
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
if (altera_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("Family: \t");
|
||||
switch (desc->family) {
|
||||
case Altera_ACEX1K:
|
||||
printf ("ACEX1K\n");
|
||||
break;
|
||||
case Altera_CYC2:
|
||||
printf ("CYCLON II\n");
|
||||
break;
|
||||
case Altera_StratixII:
|
||||
printf ("Stratix II\n");
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
printf ("Unknown family type, %d\n", desc->family);
|
||||
}
|
||||
|
||||
printf ("Interface type:\t");
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
printf ("Passive Serial (PS)\n");
|
||||
break;
|
||||
case passive_parallel_synchronous:
|
||||
printf ("Passive Parallel Synchronous (PPS)\n");
|
||||
break;
|
||||
case passive_parallel_asynchronous:
|
||||
printf ("Passive Parallel Asynchronous (PPA)\n");
|
||||
break;
|
||||
case passive_serial_asynchronous:
|
||||
printf ("Passive Serial Asynchronous (PSA)\n");
|
||||
break;
|
||||
case altera_jtag_mode: /* Not used */
|
||||
printf ("JTAG Mode\n");
|
||||
break;
|
||||
case fast_passive_parallel:
|
||||
printf ("Fast Passive Parallel (FPP)\n");
|
||||
break;
|
||||
case fast_passive_parallel_security:
|
||||
printf
|
||||
("Fast Passive Parallel with Security (FPPS) \n");
|
||||
break;
|
||||
/* Add new interface types here */
|
||||
default:
|
||||
printf ("Unsupported interface type, %d\n", desc->iface);
|
||||
}
|
||||
|
||||
printf ("Device Size: \t%d bytes\n"
|
||||
"Cookie: \t0x%x (%d)\n",
|
||||
desc->size, desc->cookie, desc->cookie);
|
||||
|
||||
if (desc->iface_fns) {
|
||||
printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
|
||||
switch (desc->family) {
|
||||
case Altera_ACEX1K:
|
||||
case Altera_CYC2:
|
||||
#if defined(CONFIG_FPGA_ACEX1K)
|
||||
ACEX1K_info (desc);
|
||||
#elif defined(CONFIG_FPGA_CYCLON2)
|
||||
CYC2_info (desc);
|
||||
#else
|
||||
/* just in case */
|
||||
printf ("%s: No support for ACEX1K devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
#if defined(CONFIG_FPGA_STRATIX_II)
|
||||
case Altera_StratixII:
|
||||
StratixII_info (desc);
|
||||
break;
|
||||
#endif
|
||||
/* Add new family types here */
|
||||
default:
|
||||
/* we don't need a message here - we give one up above */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf ("No Device Function Table.\n");
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int altera_reloc( Altera_desc *desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (!altera_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
} else {
|
||||
switch (desc->family) {
|
||||
case Altera_ACEX1K:
|
||||
#if defined(CONFIG_FPGA_ACEX1K)
|
||||
ret_val = ACEX1K_reloc (desc, reloc_offset);
|
||||
#else
|
||||
printf ("%s: No support for ACEX devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
#if defined(CONFIG_FPGA_STRATIX_II)
|
||||
case Altera_StratixII:
|
||||
ret_val = StratixII_reloc (desc, reloc_offset);
|
||||
break;
|
||||
#endif
|
||||
case Altera_CYC2:
|
||||
#if defined(CONFIG_FPGA_CYCLON2)
|
||||
ret_val = CYC2_reloc (desc, reloc_offset);
|
||||
#else
|
||||
printf ("%s: No support for CYCLON II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int altera_validate (Altera_desc * desc, const char *fn)
|
||||
{
|
||||
int ret_val = FALSE;
|
||||
|
||||
if (desc) {
|
||||
if ((desc->family > min_altera_type) &&
|
||||
(desc->family < max_altera_type)) {
|
||||
if ((desc->iface > min_altera_iface_type) &&
|
||||
(desc->iface < max_altera_iface_type)) {
|
||||
if (desc->size) {
|
||||
ret_val = TRUE;
|
||||
} else {
|
||||
printf ("%s: NULL part size\n", fn);
|
||||
}
|
||||
} else {
|
||||
printf ("%s: Invalid Interface type, %d\n",
|
||||
fn, desc->iface);
|
||||
}
|
||||
} else {
|
||||
printf ("%s: Invalid family type, %d\n", fn, desc->family);
|
||||
}
|
||||
} else {
|
||||
printf ("%s: NULL descriptor!\n", fn);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
301
drivers/fpga/cyclon2.c
Normal file
301
drivers/fpga/cyclon2.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Heiko Schocher, hs@denx.de
|
||||
* Based on ACE1XK.c
|
||||
*
|
||||
* 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>
|
||||
#include <ACEX1K.h> /* ACEX device family */
|
||||
|
||||
/* Define FPGA_DEBUG to get debug printf's */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/* Note: The assumption is that we cannot possibly run fast enough to
|
||||
* overrun the device (the Slave Parallel mode can free run at 50MHz).
|
||||
* If there is a need to operate slower, define CONFIG_FPGA_DELAY in
|
||||
* the board config file to slow things down.
|
||||
*/
|
||||
#ifndef CONFIG_FPGA_DELAY
|
||||
#define CONFIG_FPGA_DELAY()
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT
|
||||
#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/10 /* 100 ms */
|
||||
#endif
|
||||
|
||||
static int CYC2_ps_load( Altera_desc *desc, void *buf, size_t bsize );
|
||||
static int CYC2_ps_dump( Altera_desc *desc, void *buf, size_t bsize );
|
||||
/* static int CYC2_ps_info( Altera_desc *desc ); */
|
||||
static int CYC2_ps_reloc( Altera_desc *desc, ulong reloc_offset );
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* CYCLON2 Generic Implementation */
|
||||
int CYC2_load (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
|
||||
ret_val = CYC2_ps_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
/* Add new interface types here */
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int CYC2_dump (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
|
||||
ret_val = CYC2_ps_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 CYC2_info( Altera_desc *desc )
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
int CYC2_reloc (Altera_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (desc->family != Altera_CYC2) {
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
return FPGA_FAIL;
|
||||
} else
|
||||
switch (desc->iface) {
|
||||
case passive_serial:
|
||||
ret_val = CYC2_ps_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
/* Add new interface types here */
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* CYCLON2 Passive Serial Generic Implementation */
|
||||
static int CYC2_ps_load (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns;
|
||||
int ret = 0;
|
||||
|
||||
PRINTF ("%s: start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, fn);
|
||||
|
||||
if (fn) {
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
unsigned long ts; /* timestamp */
|
||||
|
||||
PRINTF ("%s: Function Table:\n"
|
||||
"ptr:\t0x%p\n"
|
||||
"struct: 0x%p\n"
|
||||
"config:\t0x%p\n"
|
||||
"status:\t0x%p\n"
|
||||
"write:\t0x%p\n"
|
||||
"done:\t0x%p\n\n",
|
||||
__FUNCTION__, &fn, fn, fn->config, fn->status,
|
||||
fn->write, fn->done);
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Loading FPGA Device %d...", cookie);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/* Establish the initial state */
|
||||
(*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */
|
||||
|
||||
udelay(2); /* T_cfg > 2us */
|
||||
|
||||
/* Wait for nSTATUS to be asserted */
|
||||
ts = get_timer (0); /* get current time */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for STATUS to go high.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while (!(*fn->status) (cookie));
|
||||
|
||||
/* Get ready for the burn */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
ret = (*fn->write) (buf, bsize, TRUE, cookie);
|
||||
if (ret) {
|
||||
puts ("** Write failed.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
puts(" OK? ...");
|
||||
#endif
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc (' '); /* terminate the dotted line */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Checking FPGA's CONF_DONE signal - correctly booted ?
|
||||
*/
|
||||
|
||||
if ( ! (*fn->done) (cookie) ) {
|
||||
puts ("** Booting failed! CONF_DONE is still deasserted.\n");
|
||||
(*fn->abort) (cookie);
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
puts(" OK\n");
|
||||
#endif
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
puts ("Done.\n");
|
||||
}
|
||||
else {
|
||||
puts ("Fail.\n");
|
||||
}
|
||||
#endif
|
||||
(*fn->post) (cookie);
|
||||
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int CYC2_ps_dump (Altera_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
/* Readback is only available through the Slave Parallel and */
|
||||
/* boundary-scan interfaces. */
|
||||
printf ("%s: Passive Serial Dumping is unavailable\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
static int CYC2_ps_reloc (Altera_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Altera_CYC2_Passive_Serial_fns *fn_r, *fn =
|
||||
(Altera_CYC2_Passive_Serial_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
ulong addr;
|
||||
|
||||
/* Get the relocated table address */
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Altera_CYC2_Passive_Serial_fns *) addr;
|
||||
|
||||
if (!fn_r->relocated) {
|
||||
|
||||
if (memcmp (fn_r, fn,
|
||||
sizeof (Altera_CYC2_Passive_Serial_fns))
|
||||
== 0) {
|
||||
/* good copy of the table, fix the descriptor pointer */
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
|
||||
desc);
|
||||
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Altera_pre_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->config) + reloc_offset;
|
||||
fn_r->config = (Altera_config_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->status) + reloc_offset;
|
||||
fn_r->status = (Altera_status_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Altera_done_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->write) + reloc_offset;
|
||||
fn_r->write = (Altera_write_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->abort) + reloc_offset;
|
||||
fn_r->abort = (Altera_abort_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Altera_post_fn) addr;
|
||||
|
||||
fn_r->relocated = TRUE;
|
||||
|
||||
} else {
|
||||
/* this table has already been moved */
|
||||
/* XXX - should check to see if the descriptor is correct */
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
335
drivers/fpga/fpga.c
Normal file
335
drivers/fpga/fpga.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic FPGA support
|
||||
*/
|
||||
#include <common.h> /* core U-Boot definitions */
|
||||
#include <xilinx.h> /* xilinx specific definitions */
|
||||
#include <altera.h> /* altera specific definitions */
|
||||
|
||||
#if 0
|
||||
#define FPGA_DEBUG /* define FPGA_DEBUG to get debug messages */
|
||||
#endif
|
||||
|
||||
/* Local definitions */
|
||||
#ifndef CONFIG_MAX_FPGA_DEVICES
|
||||
#define CONFIG_MAX_FPGA_DEVICES 5
|
||||
#endif
|
||||
|
||||
/* Enable/Disable debug console messages */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/* Local static data */
|
||||
static ulong relocation_offset = 0;
|
||||
static int next_desc = FPGA_INVALID_DEVICE;
|
||||
static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
|
||||
|
||||
/* Local static functions */
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum );
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate( int devnum, void *buf,
|
||||
size_t bsize, char *fn );
|
||||
static int fpga_dev_info( int devnum );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* fpga_no_sup
|
||||
* 'no support' message function
|
||||
*/
|
||||
static void fpga_no_sup( char *fn, char *msg )
|
||||
{
|
||||
if ( fn && msg ) {
|
||||
printf( "%s: No support for %s.\n", fn, msg);
|
||||
} else if ( msg ) {
|
||||
printf( "No support for %s.\n", msg);
|
||||
} else {
|
||||
printf( "No FPGA suport!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* fpga_get_desc
|
||||
* map a device number to a descriptor
|
||||
*/
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum )
|
||||
{
|
||||
fpga_desc *desc = (fpga_desc * )NULL;
|
||||
|
||||
if (( devnum >= 0 ) && (devnum < next_desc )) {
|
||||
desc = &desc_table[devnum];
|
||||
PRINTF( "%s: found fpga descriptor #%d @ 0x%p\n",
|
||||
__FUNCTION__, devnum, desc );
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_validate
|
||||
* generic parameter checking code
|
||||
*/
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate( int devnum, void *buf,
|
||||
size_t bsize, char *fn )
|
||||
{
|
||||
fpga_desc * desc = fpga_get_desc( devnum );
|
||||
|
||||
if ( !desc ) {
|
||||
printf( "%s: Invalid device number %d\n", fn, devnum );
|
||||
}
|
||||
|
||||
if ( !buf ) {
|
||||
printf( "%s: Null buffer.\n", fn );
|
||||
return (fpga_desc * const)NULL;
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_dev_info
|
||||
* generic multiplexing code
|
||||
*/
|
||||
static int fpga_dev_info( int devnum )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
const fpga_desc * const desc = fpga_get_desc( devnum );
|
||||
|
||||
if ( desc ) {
|
||||
PRINTF( "%s: Device Descriptor @ 0x%p\n",
|
||||
__FUNCTION__, desc->devdesc );
|
||||
|
||||
switch ( desc->devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if defined(CONFIG_FPGA_XILINX)
|
||||
printf( "Xilinx Device\nDescriptor @ 0x%p\n", desc );
|
||||
ret_val = xilinx_info( desc->devdesc );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if defined(CONFIG_FPGA_ALTERA)
|
||||
printf( "Altera Device\nDescriptor @ 0x%p\n", desc );
|
||||
ret_val = altera_info( desc->devdesc );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, desc->devtype );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: Invalid device number %d\n",
|
||||
__FUNCTION__, devnum );
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_reloc
|
||||
* generic multiplexing code
|
||||
*/
|
||||
int fpga_reloc( fpga_type devtype, void *desc, ulong reloc_off )
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
PRINTF( "%s: Relocating Device of type %d @ 0x%p with offset %lx\n",
|
||||
__FUNCTION__, devtype, desc, reloc_off );
|
||||
|
||||
switch ( devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if defined(CONFIG_FPGA_XILINX)
|
||||
ret_val = xilinx_reloc( desc, reloc_off );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if defined(CONFIG_FPGA_ALTERA)
|
||||
ret_val = altera_reloc( desc, reloc_off );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, devtype );
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* fgpa_init is usually called from misc_init_r() and MUST be called
|
||||
* before any of the other fpga functions are used.
|
||||
*/
|
||||
void fpga_init( ulong reloc_off )
|
||||
{
|
||||
relocation_offset = reloc_off;
|
||||
next_desc = 0;
|
||||
memset( desc_table, 0, sizeof(desc_table));
|
||||
|
||||
PRINTF( "%s: CONFIG_FPGA = 0x%x\n", __FUNCTION__, CONFIG_FPGA );
|
||||
}
|
||||
|
||||
/* fpga_count
|
||||
* Basic interface function to get the current number of devices available.
|
||||
*/
|
||||
int fpga_count( void )
|
||||
{
|
||||
return next_desc;
|
||||
}
|
||||
|
||||
/* fpga_add
|
||||
* Attempts to relocate the device/board specific interface code
|
||||
* to the proper RAM locations and adds the device descriptor to
|
||||
* the device table.
|
||||
*/
|
||||
int fpga_add( fpga_type devtype, void *desc )
|
||||
{
|
||||
int devnum = FPGA_INVALID_DEVICE;
|
||||
|
||||
if ( next_desc < 0 ) {
|
||||
printf( "%s: FPGA support not initialized!\n", __FUNCTION__ );
|
||||
} else if (( devtype > fpga_min_type ) && ( devtype < fpga_undefined )) {
|
||||
if ( desc ) {
|
||||
if ( next_desc < CONFIG_MAX_FPGA_DEVICES ) {
|
||||
if ( fpga_reloc( devtype, desc, relocation_offset )
|
||||
== FPGA_SUCCESS ) {
|
||||
devnum = next_desc;
|
||||
desc_table[next_desc].devtype = devtype;
|
||||
desc_table[next_desc++].devdesc = desc;
|
||||
} else {
|
||||
printf( "%s: Unable to relocate device interface table!\n",
|
||||
__FUNCTION__ );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: Exceeded Max FPGA device count\n", __FUNCTION__ );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: NULL device descriptor\n", __FUNCTION__ );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: Unsupported FPGA type %d\n", __FUNCTION__, devtype );
|
||||
}
|
||||
|
||||
return devnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic multiplexing code
|
||||
*/
|
||||
int fpga_load( int devnum, void *buf, size_t bsize )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ );
|
||||
|
||||
if ( desc ) {
|
||||
switch ( desc->devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if defined(CONFIG_FPGA_XILINX)
|
||||
ret_val = xilinx_load( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if defined(CONFIG_FPGA_ALTERA)
|
||||
ret_val = altera_load( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, desc->devtype );
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* fpga_dump
|
||||
* generic multiplexing code
|
||||
*/
|
||||
int fpga_dump( int devnum, void *buf, size_t bsize )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ );
|
||||
|
||||
if ( desc ) {
|
||||
switch ( desc->devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if defined(CONFIG_FPGA_XILINX)
|
||||
ret_val = xilinx_dump( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if defined(CONFIG_FPGA_ALTERA)
|
||||
ret_val = altera_dump( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, desc->devtype );
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_info
|
||||
* front end to fpga_dev_info. If devnum is invalid, report on all
|
||||
* available devices.
|
||||
*/
|
||||
int fpga_info( int devnum )
|
||||
{
|
||||
if ( devnum == FPGA_INVALID_DEVICE ) {
|
||||
if ( next_desc > 0 ) {
|
||||
int dev;
|
||||
|
||||
for ( dev = 0; dev < next_desc; dev++ ) {
|
||||
fpga_dev_info( dev );
|
||||
}
|
||||
return FPGA_SUCCESS;
|
||||
} else {
|
||||
printf( "%s: No FPGA devices available.\n", __FUNCTION__ );
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
else return fpga_dev_info( devnum );
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
663
drivers/fpga/spartan2.c
Normal file
663
drivers/fpga/spartan2.c
Normal file
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.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 <spartan2.h> /* Spartan-II device family */
|
||||
|
||||
/* Define FPGA_DEBUG to get debug printf's */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
#undef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
#undef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
|
||||
/* Note: The assumption is that we cannot possibly run fast enough to
|
||||
* overrun the device (the Slave Parallel mode can free run at 50MHz).
|
||||
* If there is a need to operate slower, define CONFIG_FPGA_DELAY in
|
||||
* the board config file to slow things down.
|
||||
*/
|
||||
#ifndef CONFIG_FPGA_DELAY
|
||||
#define CONFIG_FPGA_DELAY()
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT
|
||||
#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
|
||||
#endif
|
||||
|
||||
static int Spartan2_sp_load( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
static int Spartan2_sp_dump( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
/* static int Spartan2_sp_info( Xilinx_desc *desc ); */
|
||||
static int Spartan2_sp_reloc( Xilinx_desc *desc, ulong reloc_offset );
|
||||
|
||||
static int Spartan2_ss_load( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
static int Spartan2_ss_dump( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
/* static int Spartan2_ss_info( Xilinx_desc *desc ); */
|
||||
static int Spartan2_ss_reloc( Xilinx_desc *desc, ulong reloc_offset );
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Generic Implementation */
|
||||
int Spartan2_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
|
||||
ret_val = Spartan2_ss_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
|
||||
ret_val = Spartan2_sp_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int Spartan2_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
|
||||
ret_val = Spartan2_ss_dump (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
|
||||
ret_val = Spartan2_sp_dump (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int Spartan2_info( Xilinx_desc *desc )
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int Spartan2_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (desc->family != Xilinx_Spartan2) {
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
return FPGA_FAIL;
|
||||
} else
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
ret_val = Spartan2_ss_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
ret_val = Spartan2_sp_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Slave Parallel Generic Implementation */
|
||||
|
||||
static int Spartan2_sp_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
|
||||
|
||||
PRINTF ("%s: start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, fn);
|
||||
|
||||
if (fn) {
|
||||
size_t bytecount = 0;
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
unsigned long ts; /* timestamp */
|
||||
|
||||
PRINTF ("%s: Function Table:\n"
|
||||
"ptr:\t0x%p\n"
|
||||
"struct: 0x%p\n"
|
||||
"pre: 0x%p\n"
|
||||
"pgm:\t0x%p\n"
|
||||
"init:\t0x%p\n"
|
||||
"err:\t0x%p\n"
|
||||
"clk:\t0x%p\n"
|
||||
"cs:\t0x%p\n"
|
||||
"wr:\t0x%p\n"
|
||||
"read data:\t0x%p\n"
|
||||
"write data:\t0x%p\n"
|
||||
"busy:\t0x%p\n"
|
||||
"abort:\t0x%p\n",
|
||||
"post:\t0x%p\n\n",
|
||||
__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
|
||||
fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
|
||||
fn->abort, fn->post);
|
||||
|
||||
/*
|
||||
* This code is designed to emulate the "Express Style"
|
||||
* Continuous Data Loading in Slave Parallel Mode for
|
||||
* the Spartan-II Family.
|
||||
*/
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Loading FPGA Device %d...\n", cookie);
|
||||
#endif
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/* Establish the initial state */
|
||||
(*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
|
||||
|
||||
/* Get ready for the burn */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
|
||||
|
||||
ts = get_timer (0); /* get current time */
|
||||
/* Now wait for INIT and BUSY to go high */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for INIT to clear.\n");
|
||||
(*fn->abort) (cookie); /* abort the burn */
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
|
||||
|
||||
(*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */
|
||||
(*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
/* Load the data */
|
||||
while (bytecount < bsize) {
|
||||
/* XXX - do we check for an Ctrl-C press in here ??? */
|
||||
/* XXX - Check the error bit? */
|
||||
|
||||
(*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
ts = get_timer (0); /* get current time */
|
||||
while ((*fn->busy) (cookie)) {
|
||||
/* XXX - we should have a check in here somewhere to
|
||||
* make sure we aren't busy forever... */
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for BUSY to clear.\n");
|
||||
(*fn->abort) (cookie); /* abort the burn */
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */
|
||||
(*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
#endif
|
||||
|
||||
/* now check for done signal */
|
||||
ts = get_timer (0); /* get current time */
|
||||
ret_val = FPGA_SUCCESS;
|
||||
while ((*fn->done) (cookie) == FPGA_FAIL) {
|
||||
/* XXX - we should have a check in here somewhere to
|
||||
* make sure we aren't busy forever... */
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for DONE to clear.\n");
|
||||
(*fn->abort) (cookie); /* abort the burn */
|
||||
ret_val = FPGA_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
puts ("Done.\n");
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Run the post configuration function if there is one.
|
||||
*/
|
||||
if (*fn->post) {
|
||||
(*fn->post) (cookie);
|
||||
}
|
||||
|
||||
else {
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
puts ("Fail.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int Spartan2_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
|
||||
|
||||
if (fn) {
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
size_t bytecount = 0;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
|
||||
printf ("Starting Dump of FPGA Device %d...\n", cookie);
|
||||
|
||||
(*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
/* dump the data */
|
||||
while (bytecount < bsize) {
|
||||
/* XXX - do we check for an Ctrl-C press in here ??? */
|
||||
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
(*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
(*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
#endif
|
||||
puts ("Done.\n");
|
||||
|
||||
/* XXX - checksum the data? */
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static int Spartan2_sp_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan2_Slave_Parallel_fns *fn_r, *fn =
|
||||
(Xilinx_Spartan2_Slave_Parallel_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
ulong addr;
|
||||
|
||||
/* Get the relocated table address */
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Xilinx_Spartan2_Slave_Parallel_fns *) addr;
|
||||
|
||||
if (!fn_r->relocated) {
|
||||
|
||||
if (memcmp (fn_r, fn,
|
||||
sizeof (Xilinx_Spartan2_Slave_Parallel_fns))
|
||||
== 0) {
|
||||
/* good copy of the table, fix the descriptor pointer */
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
|
||||
desc);
|
||||
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Xilinx_pre_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->pgm) + reloc_offset;
|
||||
fn_r->pgm = (Xilinx_pgm_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->init) + reloc_offset;
|
||||
fn_r->init = (Xilinx_init_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Xilinx_done_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->clk) + reloc_offset;
|
||||
fn_r->clk = (Xilinx_clk_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->err) + reloc_offset;
|
||||
fn_r->err = (Xilinx_err_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->cs) + reloc_offset;
|
||||
fn_r->cs = (Xilinx_cs_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->wr) + reloc_offset;
|
||||
fn_r->wr = (Xilinx_wr_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->rdata) + reloc_offset;
|
||||
fn_r->rdata = (Xilinx_rdata_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->wdata) + reloc_offset;
|
||||
fn_r->wdata = (Xilinx_wdata_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->busy) + reloc_offset;
|
||||
fn_r->busy = (Xilinx_busy_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->abort) + reloc_offset;
|
||||
fn_r->abort = (Xilinx_abort_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Xilinx_post_fn) addr;
|
||||
|
||||
fn_r->relocated = TRUE;
|
||||
|
||||
} else {
|
||||
/* this table has already been moved */
|
||||
/* XXX - should check to see if the descriptor is correct */
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int Spartan2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
|
||||
int i;
|
||||
unsigned char val;
|
||||
|
||||
PRINTF ("%s: start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, fn);
|
||||
|
||||
if (fn) {
|
||||
size_t bytecount = 0;
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
unsigned long ts; /* timestamp */
|
||||
|
||||
PRINTF ("%s: Function Table:\n"
|
||||
"ptr:\t0x%p\n"
|
||||
"struct: 0x%p\n"
|
||||
"pgm:\t0x%p\n"
|
||||
"init:\t0x%p\n"
|
||||
"clk:\t0x%p\n"
|
||||
"wr:\t0x%p\n"
|
||||
"done:\t0x%p\n\n",
|
||||
__FUNCTION__, &fn, fn, fn->pgm, fn->init,
|
||||
fn->clk, fn->wr, fn->done);
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Loading FPGA Device %d...\n", cookie);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/* Establish the initial state */
|
||||
(*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
|
||||
|
||||
/* Wait for INIT state (init low) */
|
||||
ts = get_timer (0); /* get current time */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for INIT to start.\n");
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while (!(*fn->init) (cookie));
|
||||
|
||||
/* Get ready for the burn */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
|
||||
|
||||
ts = get_timer (0); /* get current time */
|
||||
/* Now wait for INIT to go high */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for INIT to clear.\n");
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while ((*fn->init) (cookie));
|
||||
|
||||
/* Load the data */
|
||||
while (bytecount < bsize) {
|
||||
|
||||
/* Xilinx detects an error if INIT goes low (active)
|
||||
while DONE is low (inactive) */
|
||||
if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
|
||||
puts ("** CRC error during FPGA load.\n");
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
val = data [bytecount ++];
|
||||
i = 8;
|
||||
do {
|
||||
/* Deassert the clock */
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Write data */
|
||||
(*fn->wr) ((val & 0x80), TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Assert the clock */
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
val <<= 1;
|
||||
i --;
|
||||
} while (i > 0);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
#endif
|
||||
|
||||
/* now check for done signal */
|
||||
ts = get_timer (0); /* get current time */
|
||||
ret_val = FPGA_SUCCESS;
|
||||
(*fn->wr) (TRUE, TRUE, cookie);
|
||||
|
||||
while (! (*fn->done) (cookie)) {
|
||||
/* XXX - we should have a check in here somewhere to
|
||||
* make sure we aren't busy forever... */
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
putc ('*');
|
||||
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for DONE to clear.\n");
|
||||
ret_val = FPGA_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
|
||||
/*
|
||||
* Run the post configuration function if there is one.
|
||||
*/
|
||||
if (*fn->post) {
|
||||
(*fn->post) (cookie);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
puts ("Done.\n");
|
||||
}
|
||||
else {
|
||||
puts ("Fail.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
/* Readback is only available through the Slave Parallel and */
|
||||
/* boundary-scan interfaces. */
|
||||
printf ("%s: Slave Serial Dumping is unavailable\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
static int Spartan2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan2_Slave_Serial_fns *fn_r, *fn =
|
||||
(Xilinx_Spartan2_Slave_Serial_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
ulong addr;
|
||||
|
||||
/* Get the relocated table address */
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Xilinx_Spartan2_Slave_Serial_fns *) addr;
|
||||
|
||||
if (!fn_r->relocated) {
|
||||
|
||||
if (memcmp (fn_r, fn,
|
||||
sizeof (Xilinx_Spartan2_Slave_Serial_fns))
|
||||
== 0) {
|
||||
/* good copy of the table, fix the descriptor pointer */
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
|
||||
desc);
|
||||
|
||||
if (fn->pre) {
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Xilinx_pre_fn) addr;
|
||||
}
|
||||
|
||||
addr = (ulong) (fn->pgm) + reloc_offset;
|
||||
fn_r->pgm = (Xilinx_pgm_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->init) + reloc_offset;
|
||||
fn_r->init = (Xilinx_init_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Xilinx_done_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->clk) + reloc_offset;
|
||||
fn_r->clk = (Xilinx_clk_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->wr) + reloc_offset;
|
||||
fn_r->wr = (Xilinx_wr_fn) addr;
|
||||
|
||||
if (fn->post) {
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Xilinx_post_fn) addr;
|
||||
}
|
||||
|
||||
fn_r->relocated = TRUE;
|
||||
|
||||
} else {
|
||||
/* this table has already been moved */
|
||||
/* XXX - should check to see if the descriptor is correct */
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
||||
}
|
668
drivers/fpga/spartan3.c
Normal file
668
drivers/fpga/spartan3.c
Normal file
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configuration support for Xilinx Spartan3 devices. Based
|
||||
* on spartan2.c (Rich Ireland, rireland@enterasys.com).
|
||||
*/
|
||||
|
||||
#include <common.h> /* core U-Boot definitions */
|
||||
#include <spartan3.h> /* Spartan-II device family */
|
||||
|
||||
/* Define FPGA_DEBUG to get debug printf's */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
#undef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
#undef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
|
||||
/* Note: The assumption is that we cannot possibly run fast enough to
|
||||
* overrun the device (the Slave Parallel mode can free run at 50MHz).
|
||||
* If there is a need to operate slower, define CONFIG_FPGA_DELAY in
|
||||
* the board config file to slow things down.
|
||||
*/
|
||||
#ifndef CONFIG_FPGA_DELAY
|
||||
#define CONFIG_FPGA_DELAY()
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT
|
||||
#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
|
||||
#endif
|
||||
|
||||
static int Spartan3_sp_load( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
static int Spartan3_sp_dump( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
/* static int Spartan3_sp_info( Xilinx_desc *desc ); */
|
||||
static int Spartan3_sp_reloc( Xilinx_desc *desc, ulong reloc_offset );
|
||||
|
||||
static int Spartan3_ss_load( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
static int Spartan3_ss_dump( Xilinx_desc *desc, void *buf, size_t bsize );
|
||||
/* static int Spartan3_ss_info( Xilinx_desc *desc ); */
|
||||
static int Spartan3_ss_reloc( Xilinx_desc *desc, ulong reloc_offset );
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Generic Implementation */
|
||||
int Spartan3_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
|
||||
ret_val = Spartan3_ss_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
|
||||
ret_val = Spartan3_sp_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int Spartan3_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
|
||||
ret_val = Spartan3_ss_dump (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
|
||||
ret_val = Spartan3_sp_dump (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int Spartan3_info( Xilinx_desc *desc )
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int Spartan3_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (desc->family != Xilinx_Spartan3) {
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
return FPGA_FAIL;
|
||||
} else
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
ret_val = Spartan3_ss_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
ret_val = Spartan3_sp_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Slave Parallel Generic Implementation */
|
||||
|
||||
static int Spartan3_sp_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns;
|
||||
|
||||
PRINTF ("%s: start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, fn);
|
||||
|
||||
if (fn) {
|
||||
size_t bytecount = 0;
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
unsigned long ts; /* timestamp */
|
||||
|
||||
PRINTF ("%s: Function Table:\n"
|
||||
"ptr:\t0x%p\n"
|
||||
"struct: 0x%p\n"
|
||||
"pre: 0x%p\n"
|
||||
"pgm:\t0x%p\n"
|
||||
"init:\t0x%p\n"
|
||||
"err:\t0x%p\n"
|
||||
"clk:\t0x%p\n"
|
||||
"cs:\t0x%p\n"
|
||||
"wr:\t0x%p\n"
|
||||
"read data:\t0x%p\n"
|
||||
"write data:\t0x%p\n"
|
||||
"busy:\t0x%p\n"
|
||||
"abort:\t0x%p\n",
|
||||
"post:\t0x%p\n\n",
|
||||
__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
|
||||
fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
|
||||
fn->abort, fn->post);
|
||||
|
||||
/*
|
||||
* This code is designed to emulate the "Express Style"
|
||||
* Continuous Data Loading in Slave Parallel Mode for
|
||||
* the Spartan-II Family.
|
||||
*/
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Loading FPGA Device %d...\n", cookie);
|
||||
#endif
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/* Establish the initial state */
|
||||
(*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
|
||||
|
||||
/* Get ready for the burn */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
|
||||
|
||||
ts = get_timer (0); /* get current time */
|
||||
/* Now wait for INIT and BUSY to go high */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for INIT to clear.\n");
|
||||
(*fn->abort) (cookie); /* abort the burn */
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
|
||||
|
||||
(*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */
|
||||
(*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
/* Load the data */
|
||||
while (bytecount < bsize) {
|
||||
/* XXX - do we check for an Ctrl-C press in here ??? */
|
||||
/* XXX - Check the error bit? */
|
||||
|
||||
(*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
ts = get_timer (0); /* get current time */
|
||||
while ((*fn->busy) (cookie)) {
|
||||
/* XXX - we should have a check in here somewhere to
|
||||
* make sure we aren't busy forever... */
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for BUSY to clear.\n");
|
||||
(*fn->abort) (cookie); /* abort the burn */
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */
|
||||
(*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
#endif
|
||||
|
||||
/* now check for done signal */
|
||||
ts = get_timer (0); /* get current time */
|
||||
ret_val = FPGA_SUCCESS;
|
||||
while ((*fn->done) (cookie) == FPGA_FAIL) {
|
||||
/* XXX - we should have a check in here somewhere to
|
||||
* make sure we aren't busy forever... */
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for DONE to clear.\n");
|
||||
(*fn->abort) (cookie); /* abort the burn */
|
||||
ret_val = FPGA_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
puts ("Done.\n");
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Run the post configuration function if there is one.
|
||||
*/
|
||||
if (*fn->post) {
|
||||
(*fn->post) (cookie);
|
||||
}
|
||||
|
||||
else {
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
puts ("Fail.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int Spartan3_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns;
|
||||
|
||||
if (fn) {
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
size_t bytecount = 0;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
|
||||
printf ("Starting Dump of FPGA Device %d...\n", cookie);
|
||||
|
||||
(*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
/* dump the data */
|
||||
while (bytecount < bsize) {
|
||||
/* XXX - do we check for an Ctrl-C press in here ??? */
|
||||
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
(*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
(*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
#endif
|
||||
puts ("Done.\n");
|
||||
|
||||
/* XXX - checksum the data? */
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
static int Spartan3_sp_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan3_Slave_Parallel_fns *fn_r, *fn =
|
||||
(Xilinx_Spartan3_Slave_Parallel_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
ulong addr;
|
||||
|
||||
/* Get the relocated table address */
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Xilinx_Spartan3_Slave_Parallel_fns *) addr;
|
||||
|
||||
if (!fn_r->relocated) {
|
||||
|
||||
if (memcmp (fn_r, fn,
|
||||
sizeof (Xilinx_Spartan3_Slave_Parallel_fns))
|
||||
== 0) {
|
||||
/* good copy of the table, fix the descriptor pointer */
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
|
||||
desc);
|
||||
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Xilinx_pre_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->pgm) + reloc_offset;
|
||||
fn_r->pgm = (Xilinx_pgm_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->init) + reloc_offset;
|
||||
fn_r->init = (Xilinx_init_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Xilinx_done_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->clk) + reloc_offset;
|
||||
fn_r->clk = (Xilinx_clk_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->err) + reloc_offset;
|
||||
fn_r->err = (Xilinx_err_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->cs) + reloc_offset;
|
||||
fn_r->cs = (Xilinx_cs_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->wr) + reloc_offset;
|
||||
fn_r->wr = (Xilinx_wr_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->rdata) + reloc_offset;
|
||||
fn_r->rdata = (Xilinx_rdata_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->wdata) + reloc_offset;
|
||||
fn_r->wdata = (Xilinx_wdata_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->busy) + reloc_offset;
|
||||
fn_r->busy = (Xilinx_busy_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->abort) + reloc_offset;
|
||||
fn_r->abort = (Xilinx_abort_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Xilinx_post_fn) addr;
|
||||
|
||||
fn_r->relocated = TRUE;
|
||||
|
||||
} else {
|
||||
/* this table has already been moved */
|
||||
/* XXX - should check to see if the descriptor is correct */
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int Spartan3_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan3_Slave_Serial_fns *fn = desc->iface_fns;
|
||||
int i;
|
||||
unsigned char val;
|
||||
|
||||
PRINTF ("%s: start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, fn);
|
||||
|
||||
if (fn) {
|
||||
size_t bytecount = 0;
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
int cookie = desc->cookie; /* make a local copy */
|
||||
unsigned long ts; /* timestamp */
|
||||
|
||||
PRINTF ("%s: Function Table:\n"
|
||||
"ptr:\t0x%p\n"
|
||||
"struct: 0x%p\n"
|
||||
"pgm:\t0x%p\n"
|
||||
"init:\t0x%p\n"
|
||||
"clk:\t0x%p\n"
|
||||
"wr:\t0x%p\n"
|
||||
"done:\t0x%p\n\n",
|
||||
__FUNCTION__, &fn, fn, fn->pgm, fn->init,
|
||||
fn->clk, fn->wr, fn->done);
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Loading FPGA Device %d...\n", cookie);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/* Establish the initial state */
|
||||
(*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
|
||||
|
||||
/* Wait for INIT state (init low) */
|
||||
ts = get_timer (0); /* get current time */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for INIT to start.\n");
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while (!(*fn->init) (cookie));
|
||||
|
||||
/* Get ready for the burn */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
|
||||
|
||||
ts = get_timer (0); /* get current time */
|
||||
/* Now wait for INIT to go high */
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for INIT to clear.\n");
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while ((*fn->init) (cookie));
|
||||
|
||||
/* Load the data */
|
||||
while (bytecount < bsize) {
|
||||
|
||||
/* Xilinx detects an error if INIT goes low (active)
|
||||
while DONE is low (inactive) */
|
||||
if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
|
||||
puts ("** CRC error during FPGA load.\n");
|
||||
return (FPGA_FAIL);
|
||||
}
|
||||
val = data [bytecount ++];
|
||||
i = 8;
|
||||
do {
|
||||
/* Deassert the clock */
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Write data */
|
||||
(*fn->wr) ((val & 0x80), TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
/* Assert the clock */
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
val <<= 1;
|
||||
i --;
|
||||
} while (i > 0);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.'); /* let them know we are alive */
|
||||
#endif
|
||||
}
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
#endif
|
||||
|
||||
/* now check for done signal */
|
||||
ts = get_timer (0); /* get current time */
|
||||
ret_val = FPGA_SUCCESS;
|
||||
(*fn->wr) (TRUE, TRUE, cookie);
|
||||
|
||||
while (! (*fn->done) (cookie)) {
|
||||
/* XXX - we should have a check in here somewhere to
|
||||
* make sure we aren't busy forever... */
|
||||
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
|
||||
|
||||
putc ('*');
|
||||
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
|
||||
puts ("** Timeout waiting for DONE to clear.\n");
|
||||
ret_val = FPGA_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
putc ('\n'); /* terminate the dotted line */
|
||||
|
||||
/*
|
||||
* Run the post configuration function if there is one.
|
||||
*/
|
||||
if (*fn->post) {
|
||||
(*fn->post) (cookie);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
puts ("Done.\n");
|
||||
}
|
||||
else {
|
||||
puts ("Fail.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int Spartan3_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
/* Readback is only available through the Slave Parallel and */
|
||||
/* boundary-scan interfaces. */
|
||||
printf ("%s: Slave Serial Dumping is unavailable\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
static int Spartan3_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume the worst */
|
||||
Xilinx_Spartan3_Slave_Serial_fns *fn_r, *fn =
|
||||
(Xilinx_Spartan3_Slave_Serial_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
ulong addr;
|
||||
|
||||
/* Get the relocated table address */
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Xilinx_Spartan3_Slave_Serial_fns *) addr;
|
||||
|
||||
if (!fn_r->relocated) {
|
||||
|
||||
if (memcmp (fn_r, fn,
|
||||
sizeof (Xilinx_Spartan3_Slave_Serial_fns))
|
||||
== 0) {
|
||||
/* good copy of the table, fix the descriptor pointer */
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
|
||||
desc);
|
||||
|
||||
if (fn->pre) {
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Xilinx_pre_fn) addr;
|
||||
}
|
||||
|
||||
addr = (ulong) (fn->pgm) + reloc_offset;
|
||||
fn_r->pgm = (Xilinx_pgm_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->init) + reloc_offset;
|
||||
fn_r->init = (Xilinx_init_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Xilinx_done_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->clk) + reloc_offset;
|
||||
fn_r->clk = (Xilinx_clk_fn) addr;
|
||||
|
||||
addr = (ulong) (fn->wr) + reloc_offset;
|
||||
fn_r->wr = (Xilinx_wr_fn) addr;
|
||||
|
||||
if (fn->post) {
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Xilinx_post_fn) addr;
|
||||
}
|
||||
|
||||
fn_r->relocated = TRUE;
|
||||
|
||||
} else {
|
||||
/* this table has already been moved */
|
||||
/* XXX - should check to see if the descriptor is correct */
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
||||
}
|
231
drivers/fpga/stratixII.c
Normal file
231
drivers/fpga/stratixII.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* (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>
|
||||
|
||||
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;
|
||||
}
|
554
drivers/fpga/virtex2.c
Normal file
554
drivers/fpga/virtex2.c
Normal file
@@ -0,0 +1,554 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
* Keith Outwater, keith_outwater@mvis.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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configuration support for Xilinx Virtex2 devices. Based
|
||||
* on spartan2.c (Rich Ireland, rireland@enterasys.com).
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <virtex2.h>
|
||||
|
||||
#if 0
|
||||
#define FPGA_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the SelectMap interface can be overrun by the processor, define
|
||||
* CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
|
||||
* file and add board-specific support for checking BUSY status. By default,
|
||||
* assume that the SelectMap interface cannot be overrun.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
#undef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_FPGA_DELAY
|
||||
#define CONFIG_FPGA_DELAY()
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
#define CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't allow config cycle to be interrupted
|
||||
*/
|
||||
#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
|
||||
#undef CONFIG_SYS_FPGA_CHECK_CTRLC
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for errors during configuration by default
|
||||
*/
|
||||
#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
|
||||
#define CONFIG_SYS_FPGA_CHECK_ERROR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default timeout in mS for INIT_B to deassert after PROG_B has
|
||||
* been deasserted. Per the latest Virtex II Handbook (page 347), the
|
||||
* max time from PORG_B deassertion to INIT_B deassertion is 4uS per
|
||||
* data frame for the XC2V8000. The XC2V8000 has 2860 data frames
|
||||
* which yields 11.44 mS. So let's make it bigger in order to handle
|
||||
* an XC2V1000, if anyone can ever get ahold of one.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT_INIT
|
||||
#define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ/2 /* 500 ms */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default timeout for waiting for BUSY to deassert during configuration.
|
||||
* This is normally not necessary since for most reasonable configuration
|
||||
* clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
|
||||
#define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ/200 /* 5 ms*/
|
||||
#endif
|
||||
|
||||
/* Default timeout for waiting for FPGA to enter operational mode after
|
||||
* configuration data has been written.
|
||||
*/
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT_CONFIG
|
||||
#define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ/5 /* 200 ms */
|
||||
#endif
|
||||
|
||||
static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize);
|
||||
static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize);
|
||||
static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset);
|
||||
|
||||
static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize);
|
||||
static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize);
|
||||
static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset);
|
||||
|
||||
int Virtex2_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
|
||||
ret_val = Virtex2_ss_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
case slave_selectmap:
|
||||
PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
|
||||
ret_val = Virtex2_ssm_load (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int Virtex2_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
|
||||
ret_val = Virtex2_ss_dump (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
case slave_parallel:
|
||||
PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
|
||||
ret_val = Virtex2_ssm_dump (desc, buf, bsize);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int Virtex2_info (Xilinx_desc * desc)
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
int Virtex2_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
if (desc->family != Xilinx_Virtex2) {
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
return FPGA_FAIL;
|
||||
} else
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
ret_val = Virtex2_ss_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
case slave_selectmap:
|
||||
ret_val = Virtex2_ssm_reloc (desc, reloc_offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported interface type, %d\n",
|
||||
__FUNCTION__, desc->iface);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Virtex-II Slave SelectMap configuration loader. Configuration via
|
||||
* SelectMap is as follows:
|
||||
* 1. Set the FPGA's PROG_B line low.
|
||||
* 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
|
||||
* 3. Write data to the SelectMap port. If INIT_B goes low at any time
|
||||
* this process, a configuration error (most likely CRC failure) has
|
||||
* ocurred. At this point a status word may be read from the
|
||||
* SelectMap interface to determine the source of the problem (You
|
||||
* could, for instance, put this in your 'abort' function handler).
|
||||
* 4. After all data has been written, test the state of the FPGA
|
||||
* INIT_B and DONE lines. If both are high, configuration has
|
||||
* succeeded. Congratulations!
|
||||
*/
|
||||
static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
|
||||
|
||||
PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
|
||||
__FUNCTION__, __LINE__, fn);
|
||||
|
||||
if (fn) {
|
||||
size_t bytecount = 0;
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
int cookie = desc->cookie;
|
||||
unsigned long ts;
|
||||
|
||||
/* Gotta split this one up (so the stack won't blow??) */
|
||||
PRINTF ("%s:%d: Function Table:\n"
|
||||
" base 0x%p\n"
|
||||
" struct 0x%p\n"
|
||||
" pre 0x%p\n"
|
||||
" prog 0x%p\n"
|
||||
" init 0x%p\n"
|
||||
" error 0x%p\n",
|
||||
__FUNCTION__, __LINE__,
|
||||
&fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
|
||||
PRINTF (" clock 0x%p\n"
|
||||
" cs 0x%p\n"
|
||||
" write 0x%p\n"
|
||||
" rdata 0x%p\n"
|
||||
" wdata 0x%p\n"
|
||||
" busy 0x%p\n"
|
||||
" abort 0x%p\n"
|
||||
" post 0x%p\n\n",
|
||||
fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
|
||||
fn->busy, fn->abort, fn->post);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Initializing FPGA Device %d...\n", cookie);
|
||||
#endif
|
||||
/*
|
||||
* Run the pre configuration function if there is one.
|
||||
*/
|
||||
if (*fn->pre) {
|
||||
(*fn->pre) (cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assert the program line. The minimum pulse width for
|
||||
* Virtex II devices is 300 nS (Tprogram parameter in datasheet).
|
||||
* There is no maximum value for the pulse width. Check to make
|
||||
* sure that INIT_B goes low after assertion of PROG_B
|
||||
*/
|
||||
(*fn->pgm) (TRUE, TRUE, cookie);
|
||||
udelay (10);
|
||||
ts = get_timer (0);
|
||||
do {
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
|
||||
printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
|
||||
" to assert.\n", __FUNCTION__, __LINE__,
|
||||
CONFIG_SYS_FPGA_WAIT_INIT);
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while (!(*fn->init) (cookie));
|
||||
|
||||
(*fn->pgm) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
|
||||
/*
|
||||
* Start a timer and wait for INIT_B to go high
|
||||
*/
|
||||
ts = get_timer (0);
|
||||
do {
|
||||
CONFIG_FPGA_DELAY ();
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
|
||||
printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
|
||||
" to deassert.\n", __FUNCTION__, __LINE__,
|
||||
CONFIG_SYS_FPGA_WAIT_INIT);
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
|
||||
|
||||
(*fn->wr) (TRUE, TRUE, cookie);
|
||||
(*fn->cs) (TRUE, TRUE, cookie);
|
||||
|
||||
udelay (10000);
|
||||
|
||||
/*
|
||||
* Load the data byte by byte
|
||||
*/
|
||||
while (bytecount < bsize) {
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
|
||||
if (ctrlc ()) {
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((*fn->done) (cookie) == FPGA_SUCCESS) {
|
||||
PRINTF ("%s:%d:done went active early, bytecount = %d\n",
|
||||
__FUNCTION__, __LINE__, bytecount);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
|
||||
if ((*fn->init) (cookie)) {
|
||||
printf ("\n%s:%d: ** Error: INIT asserted during"
|
||||
" configuration\n", __FUNCTION__, __LINE__);
|
||||
printf ("%d = buffer offset, %d = buffer size\n",
|
||||
bytecount, bsize);
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
(*fn->wdata) (data[bytecount++], TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
|
||||
/*
|
||||
* Cycle the clock pin
|
||||
*/
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
|
||||
ts = get_timer (0);
|
||||
while ((*fn->busy) (cookie)) {
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
|
||||
printf ("%s:%d: ** Timeout after %d ticks waiting for"
|
||||
" BUSY to deassert\n",
|
||||
__FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY);
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
|
||||
*/
|
||||
CONFIG_FPGA_DELAY ();
|
||||
(*fn->cs) (FALSE, TRUE, cookie);
|
||||
(*fn->wr) (FALSE, TRUE, cookie);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n');
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for successful configuration. FPGA INIT_B and DONE should
|
||||
* both be high upon successful configuration.
|
||||
*/
|
||||
ts = get_timer (0);
|
||||
ret_val = FPGA_SUCCESS;
|
||||
while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
|
||||
if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
|
||||
printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to"
|
||||
"assert and INIT to deassert\n",
|
||||
__FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
|
||||
(*fn->abort) (cookie);
|
||||
ret_val = FPGA_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret_val == FPGA_SUCCESS) {
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("Initialization of FPGA device %d complete\n", cookie);
|
||||
#endif
|
||||
/*
|
||||
* Run the post configuration function if there is one.
|
||||
*/
|
||||
if (*fn->post) {
|
||||
(*fn->post) (cookie);
|
||||
}
|
||||
} else {
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
printf ("** Initialization of FPGA device %d FAILED\n",
|
||||
cookie);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
printf ("%s:%d: NULL Interface function table!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the FPGA configuration data
|
||||
*/
|
||||
static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
|
||||
|
||||
if (fn) {
|
||||
unsigned char *data = (unsigned char *) buf;
|
||||
size_t bytecount = 0;
|
||||
int cookie = desc->cookie;
|
||||
|
||||
printf ("Starting Dump of FPGA Device %d...\n", cookie);
|
||||
|
||||
(*fn->cs) (TRUE, TRUE, cookie);
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
|
||||
while (bytecount < bsize) {
|
||||
#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
|
||||
if (ctrlc ()) {
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Cycle the clock and read the data
|
||||
*/
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
(*fn->rdata) (&(data[bytecount++]), cookie);
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
if (bytecount % (bsize / 40) == 0)
|
||||
putc ('.');
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Deassert CS_B and cycle the clock to deselect the device.
|
||||
*/
|
||||
(*fn->cs) (FALSE, FALSE, cookie);
|
||||
(*fn->clk) (FALSE, TRUE, cookie);
|
||||
(*fn->clk) (TRUE, TRUE, cookie);
|
||||
|
||||
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
|
||||
putc ('\n');
|
||||
#endif
|
||||
puts ("Done.\n");
|
||||
} else {
|
||||
printf ("%s:%d: NULL Interface function table!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Relocate the addresses in the function table from FLASH (or ROM,
|
||||
* or whatever) to RAM.
|
||||
*/
|
||||
static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
ulong addr;
|
||||
int ret_val = FPGA_FAIL;
|
||||
Xilinx_Virtex2_Slave_SelectMap_fns *fn_r, *fn =
|
||||
(Xilinx_Virtex2_Slave_SelectMap_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
/*
|
||||
* Get the relocated table address
|
||||
*/
|
||||
addr = (ulong) fn + reloc_offset;
|
||||
fn_r = (Xilinx_Virtex2_Slave_SelectMap_fns *) addr;
|
||||
|
||||
/*
|
||||
* Check to see if the table has already been relocated. If not, do
|
||||
* a sanity check to make sure there is a faithful copy of the
|
||||
* FLASH based function table in RAM, then adjust the table.
|
||||
*/
|
||||
if (!fn_r->relocated) {
|
||||
if (memcmp
|
||||
(fn_r, fn, sizeof (Xilinx_Virtex2_Slave_SelectMap_fns))
|
||||
== 0) {
|
||||
desc->iface_fns = fn_r;
|
||||
} else {
|
||||
PRINTF ("%s:%d: Invalid function table at 0x%p\n",
|
||||
__FUNCTION__, __LINE__, fn_r);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
PRINTF ("%s:%d: Relocating descriptor at 0x%p\n",
|
||||
__FUNCTION__, __LINE__, desc);
|
||||
|
||||
addr = (ulong) (fn->pre) + reloc_offset;
|
||||
fn_r->pre = (Xilinx_pre_fn) addr;
|
||||
addr = (ulong) (fn->pgm) + reloc_offset;
|
||||
fn_r->pgm = (Xilinx_pgm_fn) addr;
|
||||
addr = (ulong) (fn->init) + reloc_offset;
|
||||
fn_r->init = (Xilinx_init_fn) addr;
|
||||
addr = (ulong) (fn->done) + reloc_offset;
|
||||
fn_r->done = (Xilinx_done_fn) addr;
|
||||
addr = (ulong) (fn->err) + reloc_offset;
|
||||
fn_r->err = (Xilinx_err_fn) addr;
|
||||
addr = (ulong) (fn->clk) + reloc_offset;
|
||||
fn_r->clk = (Xilinx_clk_fn) addr;
|
||||
addr = (ulong) (fn->cs) + reloc_offset;
|
||||
fn_r->cs = (Xilinx_cs_fn) addr;
|
||||
addr = (ulong) (fn->wr) + reloc_offset;
|
||||
fn_r->wr = (Xilinx_wr_fn) addr;
|
||||
addr = (ulong) (fn->rdata) + reloc_offset;
|
||||
fn_r->rdata = (Xilinx_rdata_fn) addr;
|
||||
addr = (ulong) (fn->wdata) + reloc_offset;
|
||||
fn_r->wdata = (Xilinx_wdata_fn) addr;
|
||||
addr = (ulong) (fn->busy) + reloc_offset;
|
||||
fn_r->busy = (Xilinx_busy_fn) addr;
|
||||
addr = (ulong) (fn->abort) + reloc_offset;
|
||||
fn_r->abort = (Xilinx_abort_fn) addr;
|
||||
addr = (ulong) (fn->post) + reloc_offset;
|
||||
fn_r->post = (Xilinx_post_fn) addr;
|
||||
fn_r->relocated = TRUE;
|
||||
} else {
|
||||
printf ("%s:%d: Function table @0x%p has already been relocated\n", __FUNCTION__, __LINE__, fn_r);
|
||||
desc->iface_fns = fn_r;
|
||||
}
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: NULL Interface function table!\n", __FUNCTION__);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
Xilinx_Virtex2_Slave_Serial_fns *fn =
|
||||
(Xilinx_Virtex2_Slave_Serial_fns *) (desc->iface_fns);
|
||||
|
||||
if (fn) {
|
||||
printf ("%s:%d: Slave Serial Loading is unsupported\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
} else {
|
||||
printf ("%s:%d: NULL Interface function table!\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 tw=78: */
|
307
drivers/fpga/xilinx.c
Normal file
307
drivers/fpga/xilinx.c
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
* Keith Outwater, keith_outwater@mvis.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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Xilinx FPGA support
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <virtex2.h>
|
||||
#include <spartan2.h>
|
||||
#include <spartan3.h>
|
||||
|
||||
#if 0
|
||||
#define FPGA_DEBUG
|
||||
#endif
|
||||
|
||||
/* Define FPGA_DEBUG to get debug printf's */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/* Local Static Functions */
|
||||
static int xilinx_validate (Xilinx_desc * desc, char *fn);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int xilinx_load (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
} else
|
||||
switch (desc->family) {
|
||||
case Xilinx_Spartan2:
|
||||
#if defined(CONFIG_FPGA_SPARTAN2)
|
||||
PRINTF ("%s: Launching the Spartan-II Loader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = Spartan2_load (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for Spartan-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Spartan3:
|
||||
#if defined(CONFIG_FPGA_SPARTAN3)
|
||||
PRINTF ("%s: Launching the Spartan-III Loader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = Spartan3_load (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for Spartan-III devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Virtex2:
|
||||
#if defined(CONFIG_FPGA_VIRTEX2)
|
||||
PRINTF ("%s: Launching the Virtex-II Loader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = Virtex2_load (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for Virtex-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int xilinx_dump (Xilinx_desc * desc, void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
} else
|
||||
switch (desc->family) {
|
||||
case Xilinx_Spartan2:
|
||||
#if defined(CONFIG_FPGA_SPARTAN2)
|
||||
PRINTF ("%s: Launching the Spartan-II Reader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = Spartan2_dump (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for Spartan-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Spartan3:
|
||||
#if defined(CONFIG_FPGA_SPARTAN3)
|
||||
PRINTF ("%s: Launching the Spartan-III Reader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = Spartan3_dump (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for Spartan-III devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Virtex2:
|
||||
#if defined( CONFIG_FPGA_VIRTEX2)
|
||||
PRINTF ("%s: Launching the Virtex-II Reader...\n",
|
||||
__FUNCTION__);
|
||||
ret_val = Virtex2_dump (desc, buf, bsize);
|
||||
#else
|
||||
printf ("%s: No support for Virtex-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int xilinx_info (Xilinx_desc * desc)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
if (xilinx_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("Family: \t");
|
||||
switch (desc->family) {
|
||||
case Xilinx_Spartan2:
|
||||
printf ("Spartan-II\n");
|
||||
break;
|
||||
case Xilinx_Spartan3:
|
||||
printf ("Spartan-III\n");
|
||||
break;
|
||||
case Xilinx_Virtex2:
|
||||
printf ("Virtex-II\n");
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
printf ("Unknown family type, %d\n", desc->family);
|
||||
}
|
||||
|
||||
printf ("Interface type:\t");
|
||||
switch (desc->iface) {
|
||||
case slave_serial:
|
||||
printf ("Slave Serial\n");
|
||||
break;
|
||||
case master_serial: /* Not used */
|
||||
printf ("Master Serial\n");
|
||||
break;
|
||||
case slave_parallel:
|
||||
printf ("Slave Parallel\n");
|
||||
break;
|
||||
case jtag_mode: /* Not used */
|
||||
printf ("JTAG Mode\n");
|
||||
break;
|
||||
case slave_selectmap:
|
||||
printf ("Slave SelectMap Mode\n");
|
||||
break;
|
||||
case master_selectmap:
|
||||
printf ("Master SelectMap Mode\n");
|
||||
break;
|
||||
/* Add new interface types here */
|
||||
default:
|
||||
printf ("Unsupported interface type, %d\n", desc->iface);
|
||||
}
|
||||
|
||||
printf ("Device Size: \t%d bytes\n"
|
||||
"Cookie: \t0x%x (%d)\n",
|
||||
desc->size, desc->cookie, desc->cookie);
|
||||
|
||||
if (desc->iface_fns) {
|
||||
printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
|
||||
switch (desc->family) {
|
||||
case Xilinx_Spartan2:
|
||||
#if defined(CONFIG_FPGA_SPARTAN2)
|
||||
Spartan2_info (desc);
|
||||
#else
|
||||
/* just in case */
|
||||
printf ("%s: No support for Spartan-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Spartan3:
|
||||
#if defined(CONFIG_FPGA_SPARTAN3)
|
||||
Spartan3_info (desc);
|
||||
#else
|
||||
/* just in case */
|
||||
printf ("%s: No support for Spartan-III devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Virtex2:
|
||||
#if defined(CONFIG_FPGA_VIRTEX2)
|
||||
Virtex2_info (desc);
|
||||
#else
|
||||
/* just in case */
|
||||
printf ("%s: No support for Virtex-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
/* we don't need a message here - we give one up above */
|
||||
;
|
||||
}
|
||||
} else
|
||||
printf ("No Device Function Table.\n");
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int xilinx_reloc (Xilinx_desc * desc, ulong reloc_offset)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume a failure */
|
||||
|
||||
if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
} else
|
||||
switch (desc->family) {
|
||||
case Xilinx_Spartan2:
|
||||
#if defined(CONFIG_FPGA_SPARTAN2)
|
||||
ret_val = Spartan2_reloc (desc, reloc_offset);
|
||||
#else
|
||||
printf ("%s: No support for Spartan-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Spartan3:
|
||||
#if defined(CONFIG_FPGA_SPARTAN3)
|
||||
ret_val = Spartan3_reloc (desc, reloc_offset);
|
||||
#else
|
||||
printf ("%s: No support for Spartan-III devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
case Xilinx_Virtex2:
|
||||
#if defined(CONFIG_FPGA_VIRTEX2)
|
||||
ret_val = Virtex2_reloc (desc, reloc_offset);
|
||||
#else
|
||||
printf ("%s: No support for Virtex-II devices.\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
printf ("%s: Unsupported family type, %d\n",
|
||||
__FUNCTION__, desc->family);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int xilinx_validate (Xilinx_desc * desc, char *fn)
|
||||
{
|
||||
int ret_val = FALSE;
|
||||
|
||||
if (desc) {
|
||||
if ((desc->family > min_xilinx_type) &&
|
||||
(desc->family < max_xilinx_type)) {
|
||||
if ((desc->iface > min_xilinx_iface_type) &&
|
||||
(desc->iface < max_xilinx_iface_type)) {
|
||||
if (desc->size) {
|
||||
ret_val = TRUE;
|
||||
} else
|
||||
printf ("%s: NULL part size\n", fn);
|
||||
} else
|
||||
printf ("%s: Invalid Interface type, %d\n",
|
||||
fn, desc->iface);
|
||||
} else
|
||||
printf ("%s: Invalid family type, %d\n", fn, desc->family);
|
||||
} else
|
||||
printf ("%s: NULL descriptor!\n", fn);
|
||||
|
||||
return ret_val;
|
||||
}
|
Reference in New Issue
Block a user