avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
250
u-boot/drivers/fpga/ACEX1K.c
Normal file
250
u-boot/drivers/fpga/ACEX1K.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h> /* core U-Boot definitions */
|
||||
#include <console.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 ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize);
|
||||
static int ACEX1K_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
|
||||
/* static int ACEX1K_ps_info(Altera_desc *desc); */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ACEX1K Generic Implementation */
|
||||
int ACEX1K_load(Altera_desc *desc, const 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, const 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;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ACEX1K Passive Serial Generic Implementation */
|
||||
|
||||
static int ACEX1K_ps_load(Altera_desc *desc, const 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, const 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;
|
||||
}
|
||||
22
u-boot/drivers/fpga/Makefile
Normal file
22
u-boot/drivers/fpga/Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# (C) Copyright 2008
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += fpga.o
|
||||
obj-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
|
||||
obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
|
||||
obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
|
||||
obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
|
||||
obj-$(CONFIG_FPGA_XILINX) += xilinx.o
|
||||
obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o
|
||||
ifdef CONFIG_FPGA_ALTERA
|
||||
obj-y += altera.o
|
||||
obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
|
||||
obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
|
||||
obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
|
||||
obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
|
||||
obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
|
||||
endif
|
||||
176
u-boot/drivers/fpga/altera.c
Normal file
176
u-boot/drivers/fpga/altera.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Altera FPGA support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <ACEX1K.h>
|
||||
#include <stratixII.h>
|
||||
|
||||
/* Define FPGA_DEBUG to 1 to get debug printf's */
|
||||
#define FPGA_DEBUG 0
|
||||
|
||||
static const struct altera_fpga {
|
||||
enum altera_family family;
|
||||
const char *name;
|
||||
int (*load)(Altera_desc *, const void *, size_t);
|
||||
int (*dump)(Altera_desc *, const void *, size_t);
|
||||
int (*info)(Altera_desc *);
|
||||
} altera_fpga[] = {
|
||||
#if defined(CONFIG_FPGA_ACEX1K)
|
||||
{ Altera_ACEX1K, "ACEX1K", ACEX1K_load, ACEX1K_dump, ACEX1K_info },
|
||||
{ Altera_CYC2, "ACEX1K", ACEX1K_load, ACEX1K_dump, ACEX1K_info },
|
||||
#elif defined(CONFIG_FPGA_CYCLON2)
|
||||
{ Altera_ACEX1K, "CycloneII", CYC2_load, CYC2_dump, CYC2_info },
|
||||
{ Altera_CYC2, "CycloneII", CYC2_load, CYC2_dump, CYC2_info },
|
||||
#endif
|
||||
#if defined(CONFIG_FPGA_STRATIX_II)
|
||||
{ Altera_StratixII, "StratixII", StratixII_load,
|
||||
StratixII_dump, StratixII_info },
|
||||
#endif
|
||||
#if defined(CONFIG_FPGA_STRATIX_V)
|
||||
{ Altera_StratixV, "StratixV", stratixv_load, NULL, NULL },
|
||||
#endif
|
||||
#if defined(CONFIG_FPGA_SOCFPGA)
|
||||
{ Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int altera_validate(Altera_desc *desc, const char *fn)
|
||||
{
|
||||
if (!desc) {
|
||||
printf("%s: NULL descriptor!\n", fn);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((desc->family < min_altera_type) ||
|
||||
(desc->family > max_altera_type)) {
|
||||
printf("%s: Invalid family type, %d\n", fn, desc->family);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((desc->iface < min_altera_iface_type) ||
|
||||
(desc->iface > max_altera_iface_type)) {
|
||||
printf("%s: Invalid Interface type, %d\n", fn, desc->iface);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!desc->size) {
|
||||
printf("%s: NULL part size\n", fn);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct altera_fpga *
|
||||
altera_desc_to_fpga(Altera_desc *desc, const char *fn)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (altera_validate(desc, fn)) {
|
||||
printf("%s: Invalid device descriptor\n", fn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(altera_fpga); i++) {
|
||||
if (desc->family == altera_fpga[i].family)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(altera_fpga)) {
|
||||
printf("%s: Unsupported family type, %d\n", fn, desc->family);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &altera_fpga[i];
|
||||
}
|
||||
|
||||
int altera_load(Altera_desc *desc, const void *buf, size_t bsize)
|
||||
{
|
||||
const struct altera_fpga *fpga = altera_desc_to_fpga(desc, __func__);
|
||||
|
||||
if (!fpga)
|
||||
return FPGA_FAIL;
|
||||
|
||||
debug_cond(FPGA_DEBUG, "%s: Launching the %s Loader...\n",
|
||||
__func__, fpga->name);
|
||||
if (fpga->load)
|
||||
return fpga->load(desc, buf, bsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int altera_dump(Altera_desc *desc, const void *buf, size_t bsize)
|
||||
{
|
||||
const struct altera_fpga *fpga = altera_desc_to_fpga(desc, __func__);
|
||||
|
||||
if (!fpga)
|
||||
return FPGA_FAIL;
|
||||
|
||||
debug_cond(FPGA_DEBUG, "%s: Launching the %s Reader...\n",
|
||||
__func__, fpga->name);
|
||||
if (fpga->dump)
|
||||
return fpga->dump(desc, buf, bsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int altera_info(Altera_desc *desc)
|
||||
{
|
||||
const struct altera_fpga *fpga = altera_desc_to_fpga(desc, __func__);
|
||||
|
||||
if (!fpga)
|
||||
return FPGA_FAIL;
|
||||
|
||||
printf("Family: \t%s\n", fpga->name);
|
||||
|
||||
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%zd 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);
|
||||
if (fpga->info)
|
||||
fpga->info(desc);
|
||||
} else {
|
||||
printf("No Device Function Table.\n");
|
||||
}
|
||||
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
205
u-boot/drivers/fpga/cyclon2.c
Normal file
205
u-boot/drivers/fpga/cyclon2.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* (C) Copyright 2006
|
||||
* Heiko Schocher, hs@denx.de
|
||||
* Based on ACE1XK.c
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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, const void *buf, size_t bsize);
|
||||
static int CYC2_ps_dump(Altera_desc *desc, const void *buf, size_t bsize);
|
||||
/* static int CYC2_ps_info( Altera_desc *desc ); */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* CYCLON2 Generic Implementation */
|
||||
int CYC2_load(Altera_desc *desc, const 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;
|
||||
|
||||
case fast_passive_parallel:
|
||||
/* Fast Passive Parallel (FPP) and PS only differ in what is
|
||||
* done in the write() callback. Use the existing PS load
|
||||
* function for FPP, too.
|
||||
*/
|
||||
PRINTF ("%s: Launching Fast Passive Parallel 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, const 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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* CYCLON2 Passive Serial Generic Implementation */
|
||||
static int CYC2_ps_load(Altera_desc *desc, const 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) (false, true, cookie); /* De-assert nCONFIG */
|
||||
udelay(100);
|
||||
(*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, const 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;
|
||||
}
|
||||
317
u-boot/drivers/fpga/fpga.c
Normal file
317
u-boot/drivers/fpga/fpga.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* Generic FPGA support */
|
||||
#include <common.h> /* core U-Boot definitions */
|
||||
#include <xilinx.h> /* xilinx specific definitions */
|
||||
#include <altera.h> /* altera specific definitions */
|
||||
#include <lattice.h>
|
||||
|
||||
/* Local definitions */
|
||||
#ifndef CONFIG_MAX_FPGA_DEVICES
|
||||
#define CONFIG_MAX_FPGA_DEVICES 5
|
||||
#endif
|
||||
|
||||
/* Local static data */
|
||||
static int next_desc = FPGA_INVALID_DEVICE;
|
||||
static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
const fpga_desc *const fpga_get_desc(int devnum)
|
||||
{
|
||||
fpga_desc *desc = (fpga_desc *)NULL;
|
||||
|
||||
if ((devnum >= 0) && (devnum < next_desc)) {
|
||||
desc = &desc_table[devnum];
|
||||
debug("%s: found fpga descriptor #%d @ 0x%p\n",
|
||||
__func__, devnum, desc);
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
/*
|
||||
* fpga_validate
|
||||
* generic parameter checking code
|
||||
*/
|
||||
const fpga_desc *const fpga_validate(int devnum, const void *buf,
|
||||
size_t bsize, char *fn)
|
||||
{
|
||||
const 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) {
|
||||
debug("%s: Device Descriptor @ 0x%p\n",
|
||||
__func__, 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 *)__func__, "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 *)__func__, "Altera devices");
|
||||
#endif
|
||||
break;
|
||||
case fpga_lattice:
|
||||
#if defined(CONFIG_FPGA_LATTICE)
|
||||
printf("Lattice Device\nDescriptor @ 0x%p\n", desc);
|
||||
ret_val = lattice_info(desc->devdesc);
|
||||
#else
|
||||
fpga_no_sup((char *)__func__, "Lattice devices");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf("%s: Invalid or unsupported device type %d\n",
|
||||
__func__, desc->devtype);
|
||||
}
|
||||
} else {
|
||||
printf("%s: Invalid device number %d\n", __func__, devnum);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* fpga_init is usually called from misc_init_r() and MUST be called
|
||||
* before any of the other fpga functions are used.
|
||||
*/
|
||||
void fpga_init(void)
|
||||
{
|
||||
next_desc = 0;
|
||||
memset(desc_table, 0, sizeof(desc_table));
|
||||
|
||||
debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpga_count
|
||||
* Basic interface function to get the current number of devices available.
|
||||
*/
|
||||
int fpga_count(void)
|
||||
{
|
||||
return next_desc;
|
||||
}
|
||||
|
||||
/*
|
||||
* fpga_add
|
||||
* Add 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", __func__);
|
||||
} else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) {
|
||||
if (desc) {
|
||||
if (next_desc < CONFIG_MAX_FPGA_DEVICES) {
|
||||
devnum = next_desc;
|
||||
desc_table[next_desc].devtype = devtype;
|
||||
desc_table[next_desc++].devdesc = desc;
|
||||
} else {
|
||||
printf("%s: Exceeded Max FPGA device count\n",
|
||||
__func__);
|
||||
}
|
||||
} else {
|
||||
printf("%s: NULL device descriptor\n", __func__);
|
||||
}
|
||||
} else {
|
||||
printf("%s: Unsupported FPGA type %d\n", __func__, devtype);
|
||||
}
|
||||
|
||||
return devnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert bitstream data and load into the fpga
|
||||
*/
|
||||
int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
printf("Bitstream support not implemented for this FPGA device\n");
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CMD_FPGA_LOADFS)
|
||||
int fpga_fsload(int devnum, const void *buf, size_t size,
|
||||
fpga_fs_info *fpga_fsinfo)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
const fpga_desc *desc = fpga_validate(devnum, buf, size,
|
||||
(char *)__func__);
|
||||
|
||||
if (desc) {
|
||||
switch (desc->devtype) {
|
||||
case fpga_xilinx:
|
||||
#if defined(CONFIG_FPGA_XILINX)
|
||||
ret_val = xilinx_loadfs(desc->devdesc, buf, size,
|
||||
fpga_fsinfo);
|
||||
#else
|
||||
fpga_no_sup((char *)__func__, "Xilinx devices");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf("%s: Invalid or unsupported device type %d\n",
|
||||
__func__, desc->devtype);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generic multiplexing code
|
||||
*/
|
||||
int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
|
||||
(char *)__func__);
|
||||
|
||||
if (desc) {
|
||||
switch (desc->devtype) {
|
||||
case fpga_xilinx:
|
||||
#if defined(CONFIG_FPGA_XILINX)
|
||||
ret_val = xilinx_load(desc->devdesc, buf, bsize,
|
||||
bstype);
|
||||
#else
|
||||
fpga_no_sup((char *)__func__, "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 *)__func__, "Altera devices");
|
||||
#endif
|
||||
break;
|
||||
case fpga_lattice:
|
||||
#if defined(CONFIG_FPGA_LATTICE)
|
||||
ret_val = lattice_load(desc->devdesc, buf, bsize);
|
||||
#else
|
||||
fpga_no_sup((char *)__func__, "Lattice devices");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf("%s: Invalid or unsupported device type %d\n",
|
||||
__func__, desc->devtype);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* fpga_dump
|
||||
* generic multiplexing code
|
||||
*/
|
||||
int fpga_dump(int devnum, const void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
|
||||
(char *)__func__);
|
||||
|
||||
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 *)__func__, "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 *)__func__, "Altera devices");
|
||||
#endif
|
||||
break;
|
||||
case fpga_lattice:
|
||||
#if defined(CONFIG_FPGA_LATTICE)
|
||||
ret_val = lattice_dump(desc->devdesc, buf, bsize);
|
||||
#else
|
||||
fpga_no_sup((char *)__func__, "Lattice devices");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf("%s: Invalid or unsupported device type %d\n",
|
||||
__func__, 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", __func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return fpga_dev_info(devnum);
|
||||
}
|
||||
3149
u-boot/drivers/fpga/ivm_core.c
Normal file
3149
u-boot/drivers/fpga/ivm_core.c
Normal file
File diff suppressed because it is too large
Load Diff
380
u-boot/drivers/fpga/lattice.c
Normal file
380
u-boot/drivers/fpga/lattice.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* (C) Copyright 2010
|
||||
* Stefano Babic, DENX Software Engineering, sbabic@denx.de.
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* ispVM functions adapted from Lattice's ispmVMEmbedded code:
|
||||
* Copyright 2009 Lattice Semiconductor Corp.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <fpga.h>
|
||||
#include <lattice.h>
|
||||
|
||||
static lattice_board_specific_func *pfns;
|
||||
static const char *fpga_image;
|
||||
static unsigned long read_bytes;
|
||||
static unsigned long bufsize;
|
||||
static unsigned short expectedCRC;
|
||||
|
||||
/*
|
||||
* External variables and functions declared in ivm_core.c module.
|
||||
*/
|
||||
extern unsigned short g_usCalculatedCRC;
|
||||
extern unsigned short g_usDataType;
|
||||
extern unsigned char *g_pucIntelBuffer;
|
||||
extern unsigned char *g_pucHeapMemory;
|
||||
extern unsigned short g_iHeapCounter;
|
||||
extern unsigned short g_iHEAPSize;
|
||||
extern unsigned short g_usIntelDataIndex;
|
||||
extern unsigned short g_usIntelBufferSize;
|
||||
extern char *const g_szSupportedVersions[];
|
||||
|
||||
|
||||
/*
|
||||
* ispVMDelay
|
||||
*
|
||||
* Users must implement a delay to observe a_usTimeDelay, where
|
||||
* bit 15 of the a_usTimeDelay defines the unit.
|
||||
* 1 = milliseconds
|
||||
* 0 = microseconds
|
||||
* Example:
|
||||
* a_usTimeDelay = 0x0001 = 1 microsecond delay.
|
||||
* a_usTimeDelay = 0x8001 = 1 millisecond delay.
|
||||
*
|
||||
* This subroutine is called upon to provide a delay from 1 millisecond to a few
|
||||
* hundreds milliseconds each time.
|
||||
* It is understood that due to a_usTimeDelay is defined as unsigned short, a 16
|
||||
* bits integer, this function is restricted to produce a delay to 64000
|
||||
* micro-seconds or 32000 milli-second maximum. The VME file will never pass on
|
||||
* to this function a delay time > those maximum number. If it needs more than
|
||||
* those maximum, the VME file will launch the delay function several times to
|
||||
* realize a larger delay time cummulatively.
|
||||
* It is perfectly alright to provide a longer delay than required. It is not
|
||||
* acceptable if the delay is shorter.
|
||||
*/
|
||||
void ispVMDelay(unsigned short delay)
|
||||
{
|
||||
if (delay & 0x8000)
|
||||
delay = (delay & ~0x8000) * 1000;
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
void writePort(unsigned char a_ucPins, unsigned char a_ucValue)
|
||||
{
|
||||
a_ucValue = a_ucValue ? 1 : 0;
|
||||
|
||||
switch (a_ucPins) {
|
||||
case g_ucPinTDI:
|
||||
pfns->jtag_set_tdi(a_ucValue);
|
||||
break;
|
||||
case g_ucPinTCK:
|
||||
pfns->jtag_set_tck(a_ucValue);
|
||||
break;
|
||||
case g_ucPinTMS:
|
||||
pfns->jtag_set_tms(a_ucValue);
|
||||
break;
|
||||
default:
|
||||
printf("%s: requested unknown pin\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char readPort(void)
|
||||
{
|
||||
return pfns->jtag_get_tdo();
|
||||
}
|
||||
|
||||
void sclock(void)
|
||||
{
|
||||
writePort(g_ucPinTCK, 0x01);
|
||||
writePort(g_ucPinTCK, 0x00);
|
||||
}
|
||||
|
||||
void calibration(void)
|
||||
{
|
||||
/* Apply 2 pulses to TCK. */
|
||||
writePort(g_ucPinTCK, 0x00);
|
||||
writePort(g_ucPinTCK, 0x01);
|
||||
writePort(g_ucPinTCK, 0x00);
|
||||
writePort(g_ucPinTCK, 0x01);
|
||||
writePort(g_ucPinTCK, 0x00);
|
||||
|
||||
ispVMDelay(0x8001);
|
||||
|
||||
/* Apply 2 pulses to TCK. */
|
||||
writePort(g_ucPinTCK, 0x01);
|
||||
writePort(g_ucPinTCK, 0x00);
|
||||
writePort(g_ucPinTCK, 0x01);
|
||||
writePort(g_ucPinTCK, 0x00);
|
||||
}
|
||||
|
||||
/*
|
||||
* GetByte
|
||||
*
|
||||
* Returns a byte to the caller. The returned byte depends on the
|
||||
* g_usDataType register. If the HEAP_IN bit is set, then the byte
|
||||
* is returned from the HEAP. If the LHEAP_IN bit is set, then
|
||||
* the byte is returned from the intelligent buffer. Otherwise,
|
||||
* the byte is returned directly from the VME file.
|
||||
*/
|
||||
unsigned char GetByte(void)
|
||||
{
|
||||
unsigned char ucData;
|
||||
unsigned int block_size = 4 * 1024;
|
||||
|
||||
if (g_usDataType & HEAP_IN) {
|
||||
|
||||
/*
|
||||
* Get data from repeat buffer.
|
||||
*/
|
||||
|
||||
if (g_iHeapCounter > g_iHEAPSize) {
|
||||
|
||||
/*
|
||||
* Data over-run.
|
||||
*/
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
ucData = g_pucHeapMemory[g_iHeapCounter++];
|
||||
} else if (g_usDataType & LHEAP_IN) {
|
||||
|
||||
/*
|
||||
* Get data from intel buffer.
|
||||
*/
|
||||
|
||||
if (g_usIntelDataIndex >= g_usIntelBufferSize) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
ucData = g_pucIntelBuffer[g_usIntelDataIndex++];
|
||||
} else {
|
||||
if (read_bytes == bufsize) {
|
||||
return 0xFF;
|
||||
}
|
||||
ucData = *fpga_image++;
|
||||
read_bytes++;
|
||||
|
||||
if (!(read_bytes % block_size)) {
|
||||
printf("Downloading FPGA %ld/%ld completed\r",
|
||||
read_bytes,
|
||||
bufsize);
|
||||
}
|
||||
|
||||
if (expectedCRC != 0) {
|
||||
ispVMCalculateCRC32(ucData);
|
||||
}
|
||||
}
|
||||
|
||||
return ucData;
|
||||
}
|
||||
|
||||
signed char ispVM(void)
|
||||
{
|
||||
char szFileVersion[9] = { 0 };
|
||||
signed char cRetCode = 0;
|
||||
signed char cIndex = 0;
|
||||
signed char cVersionIndex = 0;
|
||||
unsigned char ucReadByte = 0;
|
||||
unsigned short crc;
|
||||
|
||||
g_pucHeapMemory = NULL;
|
||||
g_iHeapCounter = 0;
|
||||
g_iHEAPSize = 0;
|
||||
g_usIntelDataIndex = 0;
|
||||
g_usIntelBufferSize = 0;
|
||||
g_usCalculatedCRC = 0;
|
||||
expectedCRC = 0;
|
||||
ucReadByte = GetByte();
|
||||
switch (ucReadByte) {
|
||||
case FILE_CRC:
|
||||
crc = (unsigned char)GetByte();
|
||||
crc <<= 8;
|
||||
crc |= GetByte();
|
||||
expectedCRC = crc;
|
||||
|
||||
for (cIndex = 0; cIndex < 8; cIndex++)
|
||||
szFileVersion[cIndex] = GetByte();
|
||||
|
||||
break;
|
||||
default:
|
||||
szFileVersion[0] = (signed char) ucReadByte;
|
||||
for (cIndex = 1; cIndex < 8; cIndex++)
|
||||
szFileVersion[cIndex] = GetByte();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Compare the VME file version against the supported version.
|
||||
*
|
||||
*/
|
||||
|
||||
for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0;
|
||||
cVersionIndex++) {
|
||||
for (cIndex = 0; cIndex < 8; cIndex++) {
|
||||
if (szFileVersion[cIndex] !=
|
||||
g_szSupportedVersions[cVersionIndex][cIndex]) {
|
||||
cRetCode = VME_VERSION_FAILURE;
|
||||
break;
|
||||
}
|
||||
cRetCode = 0;
|
||||
}
|
||||
|
||||
if (cRetCode == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cRetCode < 0) {
|
||||
return VME_VERSION_FAILURE;
|
||||
}
|
||||
|
||||
printf("VME file checked: starting downloading to FPGA\n");
|
||||
|
||||
ispVMStart();
|
||||
|
||||
cRetCode = ispVMCode();
|
||||
|
||||
ispVMEnd();
|
||||
ispVMFreeMem();
|
||||
puts("\n");
|
||||
|
||||
if (cRetCode == 0 && expectedCRC != 0 &&
|
||||
(expectedCRC != g_usCalculatedCRC)) {
|
||||
printf("Expected CRC: 0x%.4X\n", expectedCRC);
|
||||
printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC);
|
||||
return VME_CRC_FAILURE;
|
||||
}
|
||||
return cRetCode;
|
||||
}
|
||||
|
||||
static int lattice_validate(Lattice_desc *desc, const char *fn)
|
||||
{
|
||||
int ret_val = false;
|
||||
|
||||
if (desc) {
|
||||
if ((desc->family > min_lattice_type) &&
|
||||
(desc->family < max_lattice_type)) {
|
||||
if ((desc->iface > min_lattice_iface_type) &&
|
||||
(desc->iface < max_lattice_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;
|
||||
}
|
||||
|
||||
int lattice_load(Lattice_desc *desc, const void *buf, size_t bsize)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
if (!lattice_validate(desc, (char *)__func__)) {
|
||||
printf("%s: Invalid device descriptor\n", __func__);
|
||||
} else {
|
||||
pfns = desc->iface_fns;
|
||||
|
||||
switch (desc->family) {
|
||||
case Lattice_XP2:
|
||||
fpga_image = buf;
|
||||
read_bytes = 0;
|
||||
bufsize = bsize;
|
||||
debug("%s: Launching the Lattice ISPVME Loader:"
|
||||
" addr %p size 0x%lx...\n",
|
||||
__func__, fpga_image, bufsize);
|
||||
ret_val = ispVM();
|
||||
if (ret_val)
|
||||
printf("%s: error %d downloading FPGA image\n",
|
||||
__func__, ret_val);
|
||||
else
|
||||
puts("FPGA downloaded successfully\n");
|
||||
break;
|
||||
default:
|
||||
printf("%s: Unsupported family type, %d\n",
|
||||
__func__, desc->family);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int lattice_dump(Lattice_desc *desc, const void *buf, size_t bsize)
|
||||
{
|
||||
puts("Dump not supported for Lattice FPGA\n");
|
||||
|
||||
return FPGA_FAIL;
|
||||
|
||||
}
|
||||
|
||||
int lattice_info(Lattice_desc *desc)
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
if (lattice_validate(desc, (char *)__func__)) {
|
||||
printf("Family: \t");
|
||||
switch (desc->family) {
|
||||
case Lattice_XP2:
|
||||
puts("XP2\n");
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
printf("Unknown family type, %d\n", desc->family);
|
||||
}
|
||||
|
||||
puts("Interface type:\t");
|
||||
switch (desc->iface) {
|
||||
case lattice_jtag_mode:
|
||||
puts("JTAG Mode\n");
|
||||
break;
|
||||
/* Add new interface types here */
|
||||
default:
|
||||
printf("Unsupported interface type, %d\n", desc->iface);
|
||||
}
|
||||
|
||||
printf("Device Size: \t%d bytes\n",
|
||||
desc->size);
|
||||
|
||||
if (desc->iface_fns) {
|
||||
printf("Device Function Table @ 0x%p\n",
|
||||
desc->iface_fns);
|
||||
switch (desc->family) {
|
||||
case Lattice_XP2:
|
||||
break;
|
||||
/* Add new family types here */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
puts("No Device Function Table.\n");
|
||||
}
|
||||
|
||||
if (desc->desc)
|
||||
printf("Model: \t%s\n", desc->desc);
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf("%s: Invalid device descriptor\n", __func__);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
304
u-boot/drivers/fpga/socfpga.c
Normal file
304
u-boot/drivers/fpga/socfpga.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Altera Corporation <www.altera.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/arch/fpga_manager.h>
|
||||
#include <asm/arch/reset_manager.h>
|
||||
#include <asm/arch/system_manager.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Timeout count */
|
||||
#define FPGA_TIMEOUT_CNT 0x1000000
|
||||
|
||||
static struct socfpga_fpga_manager *fpgamgr_regs =
|
||||
(struct socfpga_fpga_manager *)SOCFPGA_FPGAMGRREGS_ADDRESS;
|
||||
static struct socfpga_system_manager *sysmgr_regs =
|
||||
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
|
||||
|
||||
/* Set CD ratio */
|
||||
static void fpgamgr_set_cd_ratio(unsigned long ratio)
|
||||
{
|
||||
clrsetbits_le32(&fpgamgr_regs->ctrl,
|
||||
0x3 << FPGAMGRREGS_CTRL_CDRATIO_LSB,
|
||||
(ratio & 0x3) << FPGAMGRREGS_CTRL_CDRATIO_LSB);
|
||||
}
|
||||
|
||||
static int fpgamgr_dclkcnt_set(unsigned long cnt)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
/* Clear any existing done status */
|
||||
if (readl(&fpgamgr_regs->dclkstat))
|
||||
writel(0x1, &fpgamgr_regs->dclkstat);
|
||||
|
||||
/* Write the dclkcnt */
|
||||
writel(cnt, &fpgamgr_regs->dclkcnt);
|
||||
|
||||
/* Wait till the dclkcnt done */
|
||||
for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
|
||||
if (!readl(&fpgamgr_regs->dclkstat))
|
||||
continue;
|
||||
|
||||
writel(0x1, &fpgamgr_regs->dclkstat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Start the FPGA programming by initialize the FPGA Manager */
|
||||
static int fpgamgr_program_init(void)
|
||||
{
|
||||
unsigned long msel, i;
|
||||
|
||||
/* Get the MSEL value */
|
||||
msel = readl(&fpgamgr_regs->stat);
|
||||
msel &= FPGAMGRREGS_STAT_MSEL_MASK;
|
||||
msel >>= FPGAMGRREGS_STAT_MSEL_LSB;
|
||||
|
||||
/*
|
||||
* Set the cfg width
|
||||
* If MSEL[3] = 1, cfg width = 32 bit
|
||||
*/
|
||||
if (msel & 0x8) {
|
||||
setbits_le32(&fpgamgr_regs->ctrl,
|
||||
FPGAMGRREGS_CTRL_CFGWDTH_MASK);
|
||||
|
||||
/* To determine the CD ratio */
|
||||
/* MSEL[1:0] = 0, CD Ratio = 1 */
|
||||
if ((msel & 0x3) == 0x0)
|
||||
fpgamgr_set_cd_ratio(CDRATIO_x1);
|
||||
/* MSEL[1:0] = 1, CD Ratio = 4 */
|
||||
else if ((msel & 0x3) == 0x1)
|
||||
fpgamgr_set_cd_ratio(CDRATIO_x4);
|
||||
/* MSEL[1:0] = 2, CD Ratio = 8 */
|
||||
else if ((msel & 0x3) == 0x2)
|
||||
fpgamgr_set_cd_ratio(CDRATIO_x8);
|
||||
|
||||
} else { /* MSEL[3] = 0 */
|
||||
clrbits_le32(&fpgamgr_regs->ctrl,
|
||||
FPGAMGRREGS_CTRL_CFGWDTH_MASK);
|
||||
|
||||
/* To determine the CD ratio */
|
||||
/* MSEL[1:0] = 0, CD Ratio = 1 */
|
||||
if ((msel & 0x3) == 0x0)
|
||||
fpgamgr_set_cd_ratio(CDRATIO_x1);
|
||||
/* MSEL[1:0] = 1, CD Ratio = 2 */
|
||||
else if ((msel & 0x3) == 0x1)
|
||||
fpgamgr_set_cd_ratio(CDRATIO_x2);
|
||||
/* MSEL[1:0] = 2, CD Ratio = 4 */
|
||||
else if ((msel & 0x3) == 0x2)
|
||||
fpgamgr_set_cd_ratio(CDRATIO_x4);
|
||||
}
|
||||
|
||||
/* To enable FPGA Manager configuration */
|
||||
clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCE_MASK);
|
||||
|
||||
/* To enable FPGA Manager drive over configuration line */
|
||||
setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
|
||||
|
||||
/* Put FPGA into reset phase */
|
||||
setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
|
||||
|
||||
/* (1) wait until FPGA enter reset phase */
|
||||
for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
|
||||
if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_RESETPHASE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not in reset state, return error */
|
||||
if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_RESETPHASE) {
|
||||
puts("FPGA: Could not reset\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Release FPGA from reset phase */
|
||||
clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
|
||||
|
||||
/* (2) wait until FPGA enter configuration phase */
|
||||
for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
|
||||
if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_CFGPHASE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not in configuration state, return error */
|
||||
if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_CFGPHASE) {
|
||||
puts("FPGA: Could not configure\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Clear all interrupts in CB Monitor */
|
||||
writel(0xFFF, &fpgamgr_regs->gpio_porta_eoi);
|
||||
|
||||
/* Enable AXI configuration */
|
||||
setbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write the RBF data to FPGA Manager */
|
||||
static void fpgamgr_program_write(const void *rbf_data, unsigned long rbf_size)
|
||||
{
|
||||
uint32_t src = (uint32_t)rbf_data;
|
||||
uint32_t dst = SOCFPGA_FPGAMGRDATA_ADDRESS;
|
||||
|
||||
/* Number of loops for 32-byte long copying. */
|
||||
uint32_t loops32 = rbf_size / 32;
|
||||
/* Number of loops for 4-byte long copying + trailing bytes */
|
||||
uint32_t loops4 = DIV_ROUND_UP(rbf_size % 32, 4);
|
||||
|
||||
asm volatile(
|
||||
"1: ldmia %0!, {r0-r7}\n"
|
||||
" stmia %1!, {r0-r7}\n"
|
||||
" sub %1, #32\n"
|
||||
" subs %2, #1\n"
|
||||
" bne 1b\n"
|
||||
" cmp %3, #0\n"
|
||||
" beq 3f\n"
|
||||
"2: ldr %2, [%0], #4\n"
|
||||
" str %2, [%1]\n"
|
||||
" subs %3, #1\n"
|
||||
" bne 2b\n"
|
||||
"3: nop\n"
|
||||
: "+r"(src), "+r"(dst), "+r"(loops32), "+r"(loops4) :
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "cc");
|
||||
}
|
||||
|
||||
/* Ensure the FPGA entering config done */
|
||||
static int fpgamgr_program_poll_cd(void)
|
||||
{
|
||||
const uint32_t mask = FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK |
|
||||
FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK;
|
||||
unsigned long reg, i;
|
||||
|
||||
/* (3) wait until full config done */
|
||||
for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
|
||||
reg = readl(&fpgamgr_regs->gpio_ext_porta);
|
||||
|
||||
/* Config error */
|
||||
if (!(reg & mask)) {
|
||||
printf("FPGA: Configuration error.\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Config done without error */
|
||||
if (reg & mask)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Timeout happened, return error */
|
||||
if (i == FPGA_TIMEOUT_CNT) {
|
||||
printf("FPGA: Timeout waiting for program.\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* Disable AXI configuration */
|
||||
clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ensure the FPGA entering init phase */
|
||||
static int fpgamgr_program_poll_initphase(void)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
/* Additional clocks for the CB to enter initialization phase */
|
||||
if (fpgamgr_dclkcnt_set(0x4))
|
||||
return -5;
|
||||
|
||||
/* (4) wait until FPGA enter init phase or user mode */
|
||||
for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
|
||||
if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_INITPHASE)
|
||||
break;
|
||||
if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not in configuration state, return error */
|
||||
if (i == FPGA_TIMEOUT_CNT)
|
||||
return -6;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ensure the FPGA entering user mode */
|
||||
static int fpgamgr_program_poll_usermode(void)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
/* Additional clocks for the CB to exit initialization phase */
|
||||
if (fpgamgr_dclkcnt_set(0x5000))
|
||||
return -7;
|
||||
|
||||
/* (5) wait until FPGA enter user mode */
|
||||
for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
|
||||
if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
|
||||
break;
|
||||
}
|
||||
/* If not in configuration state, return error */
|
||||
if (i == FPGA_TIMEOUT_CNT)
|
||||
return -8;
|
||||
|
||||
/* To release FPGA Manager drive over configuration line */
|
||||
clrbits_le32(&fpgamgr_regs->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FPGA Manager to program the FPGA. This is the interface used by FPGA driver.
|
||||
* Return 0 for sucess, non-zero for error.
|
||||
*/
|
||||
int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
|
||||
{
|
||||
unsigned long status;
|
||||
|
||||
if ((uint32_t)rbf_data & 0x3) {
|
||||
puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Prior programming the FPGA, all bridges need to be shut off */
|
||||
|
||||
/* Disable all signals from hps peripheral controller to fpga */
|
||||
writel(0, &sysmgr_regs->fpgaintfgrp_module);
|
||||
|
||||
/* Disable all signals from FPGA to HPS SDRAM */
|
||||
#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080
|
||||
writel(0, SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS);
|
||||
|
||||
/* Disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
|
||||
socfpga_bridges_reset(1);
|
||||
|
||||
/* Unmap the bridges from NIC-301 */
|
||||
writel(0x1, SOCFPGA_L3REGS_ADDRESS);
|
||||
|
||||
/* Initialize the FPGA Manager */
|
||||
status = fpgamgr_program_init();
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Write the RBF data to FPGA Manager */
|
||||
fpgamgr_program_write(rbf_data, rbf_size);
|
||||
|
||||
/* Ensure the FPGA entering config done */
|
||||
status = fpgamgr_program_poll_cd();
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Ensure the FPGA entering init phase */
|
||||
status = fpgamgr_program_poll_initphase();
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Ensure the FPGA entering user mode */
|
||||
return fpgamgr_program_poll_usermode();
|
||||
}
|
||||
456
u-boot/drivers/fpga/spartan2.c
Normal file
456
u-boot/drivers/fpga/spartan2.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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, const void *buf, size_t bsize);
|
||||
static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
/* static int spartan2_sp_info(xilinx_desc *desc ); */
|
||||
|
||||
static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
/* static int spartan2_ss_info(xilinx_desc *desc ); */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Generic Implementation */
|
||||
static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int spartan2_dump(xilinx_desc *desc, const 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;
|
||||
}
|
||||
|
||||
static int spartan2_info(xilinx_desc *desc)
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Slave Parallel Generic Implementation */
|
||||
|
||||
static int spartan2_sp_load(xilinx_desc *desc, const 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) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_sp_dump(xilinx_desc *desc, const 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_ss_load(xilinx_desc *desc, const 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)) {
|
||||
|
||||
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, const 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;
|
||||
}
|
||||
|
||||
struct xilinx_fpga_op spartan2_op = {
|
||||
.load = spartan2_load,
|
||||
.dump = spartan2_dump,
|
||||
.info = spartan2_info,
|
||||
};
|
||||
474
u-boot/drivers/fpga/spartan3.c
Normal file
474
u-boot/drivers/fpga/spartan3.c
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* 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, const void *buf, size_t bsize);
|
||||
static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
/* static int spartan3_sp_info(xilinx_desc *desc ); */
|
||||
|
||||
static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
/* static int spartan3_ss_info(xilinx_desc *desc); */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Generic Implementation */
|
||||
static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int spartan3_dump(xilinx_desc *desc, const 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;
|
||||
}
|
||||
|
||||
static int spartan3_info(xilinx_desc *desc)
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Spartan-II Slave Parallel Generic Implementation */
|
||||
|
||||
static int spartan3_sp_load(xilinx_desc *desc, const 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_sp_dump(xilinx_desc *desc, const 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_ss_load(xilinx_desc *desc, const 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");
|
||||
if (*fn->abort)
|
||||
(*fn->abort) (cookie);
|
||||
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");
|
||||
if (*fn->abort)
|
||||
(*fn->abort) (cookie);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while ((*fn->init) (cookie));
|
||||
|
||||
/* Load the data */
|
||||
if(*fn->bwr)
|
||||
(*fn->bwr) (data, bsize, true, cookie);
|
||||
else {
|
||||
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");
|
||||
if (*fn->abort)
|
||||
(*fn->abort) (cookie);
|
||||
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, const 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;
|
||||
}
|
||||
|
||||
struct xilinx_fpga_op spartan3_op = {
|
||||
.load = spartan3_load,
|
||||
.dump = spartan3_dump,
|
||||
.info = spartan3_info,
|
||||
};
|
||||
190
u-boot/drivers/fpga/stratixII.c
Normal file
190
u-boot/drivers/fpga/stratixII.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* (C) Copyright 2007
|
||||
* Eran Liberty, Extricom , eran.liberty@gmail.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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_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 transferred 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;
|
||||
}
|
||||
103
u-boot/drivers/fpga/stratixv.c
Normal file
103
u-boot/drivers/fpga/stratixv.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <altera.h>
|
||||
#include <spi.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
/* Write the RBF data to FPGA via SPI */
|
||||
static int program_write(int spi_bus, int spi_dev, const void *rbf_data,
|
||||
unsigned long rbf_size)
|
||||
{
|
||||
struct spi_slave *slave;
|
||||
int ret;
|
||||
|
||||
debug("%s (%d): data=%p size=%ld\n",
|
||||
__func__, __LINE__, rbf_data, rbf_size);
|
||||
|
||||
/* FIXME: How to get the max. SPI clock and SPI mode? */
|
||||
slave = spi_setup_slave(spi_bus, spi_dev, 27777777, SPI_MODE_3);
|
||||
if (!slave)
|
||||
return -1;
|
||||
|
||||
if (spi_claim_bus(slave))
|
||||
return -1;
|
||||
|
||||
ret = spi_xfer(slave, rbf_size * 8, rbf_data, (void *)rbf_data,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
|
||||
spi_release_bus(slave);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the interface used by FPGA driver.
|
||||
* Return 0 for sucess, non-zero for error.
|
||||
*/
|
||||
int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
|
||||
{
|
||||
altera_board_specific_func *pfns = desc->iface_fns;
|
||||
int cookie = desc->cookie;
|
||||
int spi_bus;
|
||||
int spi_dev;
|
||||
int ret = 0;
|
||||
|
||||
if ((u32)rbf_data & 0x3) {
|
||||
puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Run the pre configuration function if there is one */
|
||||
if (pfns->pre)
|
||||
(pfns->pre)(cookie);
|
||||
|
||||
/* Establish the initial state */
|
||||
if (pfns->config) {
|
||||
/* De-assert nCONFIG */
|
||||
(pfns->config)(false, true, cookie);
|
||||
|
||||
/* nConfig minimum low pulse width is 2us */
|
||||
udelay(200);
|
||||
|
||||
/* Assert nCONFIG */
|
||||
(pfns->config)(true, true, cookie);
|
||||
|
||||
/* nCONFIG high to first rising clock on DCLK min 1506 us */
|
||||
udelay(1600);
|
||||
}
|
||||
|
||||
/* Write the RBF data to FPGA */
|
||||
if (pfns->write) {
|
||||
/*
|
||||
* Use board specific data function to write bitstream
|
||||
* into the FPGA
|
||||
*/
|
||||
ret = (pfns->write)(rbf_data, rbf_size, true, cookie);
|
||||
} else {
|
||||
/*
|
||||
* Use common SPI functions to write bitstream into the
|
||||
* FPGA
|
||||
*/
|
||||
spi_bus = COOKIE2SPI_BUS(cookie);
|
||||
spi_dev = COOKIE2SPI_DEV(cookie);
|
||||
ret = program_write(spi_bus, spi_dev, rbf_data, rbf_size);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check done pin */
|
||||
if (pfns->done) {
|
||||
ret = (pfns->done)(cookie);
|
||||
|
||||
if (ret)
|
||||
printf("Error: DONE not set (ret=%d)!\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
427
u-boot/drivers/fpga/virtex2.c
Normal file
427
u-boot/drivers/fpga/virtex2.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
* Keith Outwater, keith_outwater@mvis.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configuration support for Xilinx Virtex2 devices. Based
|
||||
* on spartan2.c (Rich Ireland, rireland@enterasys.com).
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <console.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, const void *buf, size_t bsize);
|
||||
static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
|
||||
static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
|
||||
|
||||
static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int virtex2_dump(xilinx_desc *desc, const 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;
|
||||
}
|
||||
|
||||
static int virtex2_info(xilinx_desc *desc)
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, const 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, const 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;
|
||||
}
|
||||
|
||||
static int virtex2_ss_load(xilinx_desc *desc, const 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, const void *buf, size_t bsize)
|
||||
{
|
||||
printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 tw=78: */
|
||||
|
||||
struct xilinx_fpga_op virtex2_op = {
|
||||
.load = virtex2_load,
|
||||
.dump = virtex2_dump,
|
||||
.info = virtex2_info,
|
||||
};
|
||||
281
u-boot/drivers/fpga/xilinx.c
Normal file
281
u-boot/drivers/fpga/xilinx.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* (C) Copyright 2012-2013, Xilinx, Michal Simek
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
* Keith Outwater, keith_outwater@mvis.com
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Xilinx FPGA support
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <fpga.h>
|
||||
#include <virtex2.h>
|
||||
#include <spartan2.h>
|
||||
#include <spartan3.h>
|
||||
#include <zynqpl.h>
|
||||
|
||||
/* Local Static Functions */
|
||||
static int xilinx_validate(xilinx_desc *desc, char *fn);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
unsigned int length;
|
||||
unsigned int swapsize;
|
||||
char buffer[80];
|
||||
unsigned char *dataptr;
|
||||
unsigned int i;
|
||||
const fpga_desc *desc;
|
||||
xilinx_desc *xdesc;
|
||||
|
||||
dataptr = (unsigned char *)fpgadata;
|
||||
/* Find out fpga_description */
|
||||
desc = fpga_validate(devnum, dataptr, 0, (char *)__func__);
|
||||
/* Assign xilinx device description */
|
||||
xdesc = desc->devdesc;
|
||||
|
||||
/* skip the first bytes of the bitsteam, their meaning is unknown */
|
||||
length = (*dataptr << 8) + *(dataptr + 1);
|
||||
dataptr += 2;
|
||||
dataptr += length;
|
||||
|
||||
/* get design name (identifier, length, string) */
|
||||
length = (*dataptr << 8) + *(dataptr + 1);
|
||||
dataptr += 2;
|
||||
if (*dataptr++ != 0x61) {
|
||||
debug("%s: Design name id not recognized in bitstream\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr + 1);
|
||||
dataptr += 2;
|
||||
for (i = 0; i < length; i++)
|
||||
buffer[i] = *dataptr++;
|
||||
|
||||
printf(" design filename = \"%s\"\n", buffer);
|
||||
|
||||
/* get part number (identifier, length, string) */
|
||||
if (*dataptr++ != 0x62) {
|
||||
printf("%s: Part number id not recognized in bitstream\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr + 1);
|
||||
dataptr += 2;
|
||||
for (i = 0; i < length; i++)
|
||||
buffer[i] = *dataptr++;
|
||||
|
||||
if (xdesc->name) {
|
||||
i = (ulong)strstr(buffer, xdesc->name);
|
||||
if (!i) {
|
||||
printf("%s: Wrong bitstream ID for this device\n",
|
||||
__func__);
|
||||
printf("%s: Bitstream ID %s, current device ID %d/%s\n",
|
||||
__func__, buffer, devnum, xdesc->name);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} else {
|
||||
printf("%s: Please fill correct device ID to xilinx_desc\n",
|
||||
__func__);
|
||||
}
|
||||
printf(" part number = \"%s\"\n", buffer);
|
||||
|
||||
/* get date (identifier, length, string) */
|
||||
if (*dataptr++ != 0x63) {
|
||||
printf("%s: Date identifier not recognized in bitstream\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr += 2;
|
||||
for (i = 0; i < length; i++)
|
||||
buffer[i] = *dataptr++;
|
||||
printf(" date = \"%s\"\n", buffer);
|
||||
|
||||
/* get time (identifier, length, string) */
|
||||
if (*dataptr++ != 0x64) {
|
||||
printf("%s: Time identifier not recognized in bitstream\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr += 2;
|
||||
for (i = 0; i < length; i++)
|
||||
buffer[i] = *dataptr++;
|
||||
printf(" time = \"%s\"\n", buffer);
|
||||
|
||||
/* get fpga data length (identifier, length) */
|
||||
if (*dataptr++ != 0x65) {
|
||||
printf("%s: Data length id not recognized in bitstream\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
swapsize = ((unsigned int) *dataptr << 24) +
|
||||
((unsigned int) *(dataptr + 1) << 16) +
|
||||
((unsigned int) *(dataptr + 2) << 8) +
|
||||
((unsigned int) *(dataptr + 3));
|
||||
dataptr += 4;
|
||||
printf(" bytes in bitstream = %d\n", swapsize);
|
||||
|
||||
return fpga_load(devnum, dataptr, swapsize, bstype);
|
||||
}
|
||||
|
||||
int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
if (!desc->operations || !desc->operations->load) {
|
||||
printf("%s: Missing load operation\n", __func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
return desc->operations->load(desc, buf, bsize, bstype);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CMD_FPGA_LOADFS)
|
||||
int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
fpga_fs_info *fpga_fsinfo)
|
||||
{
|
||||
if (!xilinx_validate(desc, (char *)__func__)) {
|
||||
printf("%s: Invalid device descriptor\n", __func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
if (!desc->operations || !desc->operations->loadfs) {
|
||||
printf("%s: Missing loadfs operation\n", __func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
return desc->operations->loadfs(desc, buf, bsize, fpga_fsinfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize)
|
||||
{
|
||||
if (!xilinx_validate (desc, (char *)__FUNCTION__)) {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
if (!desc->operations || !desc->operations->dump) {
|
||||
printf("%s: Missing dump operation\n", __func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
return desc->operations->dump(desc, buf, bsize);
|
||||
}
|
||||
|
||||
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;
|
||||
case xilinx_zynq:
|
||||
printf("Zynq PL\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;
|
||||
case devcfg:
|
||||
printf("Device configuration interface (Zynq)\n");
|
||||
break;
|
||||
/* Add new interface types here */
|
||||
default:
|
||||
printf ("Unsupported interface type, %d\n", desc->iface);
|
||||
}
|
||||
|
||||
printf("Device Size: \t%zd bytes\n"
|
||||
"Cookie: \t0x%x (%d)\n",
|
||||
desc->size, desc->cookie, desc->cookie);
|
||||
if (desc->name)
|
||||
printf("Device name: \t%s\n", desc->name);
|
||||
|
||||
if (desc->iface_fns)
|
||||
printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
|
||||
else
|
||||
printf ("No Device Function Table.\n");
|
||||
|
||||
if (desc->operations && desc->operations->info)
|
||||
desc->operations->info(desc);
|
||||
|
||||
ret_val = FPGA_SUCCESS;
|
||||
} else {
|
||||
printf ("%s: Invalid device descriptor\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
496
u-boot/drivers/fpga/zynqpl.c
Normal file
496
u-boot/drivers/fpga/zynqpl.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
* (C) Copyright 2012-2013, Xilinx, Michal Simek
|
||||
*
|
||||
* (C) Copyright 2012
|
||||
* Joe Hershberger <joe.hershberger@ni.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <console.h>
|
||||
#include <asm/io.h>
|
||||
#include <fs.h>
|
||||
#include <zynqpl.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
#define DEVCFG_CTRL_PCFG_PROG_B 0x40000000
|
||||
#define DEVCFG_ISR_FATAL_ERROR_MASK 0x00740040
|
||||
#define DEVCFG_ISR_ERROR_FLAGS_MASK 0x00340840
|
||||
#define DEVCFG_ISR_RX_FIFO_OV 0x00040000
|
||||
#define DEVCFG_ISR_DMA_DONE 0x00002000
|
||||
#define DEVCFG_ISR_PCFG_DONE 0x00000004
|
||||
#define DEVCFG_STATUS_DMA_CMD_Q_F 0x80000000
|
||||
#define DEVCFG_STATUS_DMA_CMD_Q_E 0x40000000
|
||||
#define DEVCFG_STATUS_DMA_DONE_CNT_MASK 0x30000000
|
||||
#define DEVCFG_STATUS_PCFG_INIT 0x00000010
|
||||
#define DEVCFG_MCTRL_PCAP_LPBK 0x00000010
|
||||
#define DEVCFG_MCTRL_RFIFO_FLUSH 0x00000002
|
||||
#define DEVCFG_MCTRL_WFIFO_FLUSH 0x00000001
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_WAIT
|
||||
#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SYS_FPGA_PROG_TIME
|
||||
#define CONFIG_SYS_FPGA_PROG_TIME (CONFIG_SYS_HZ * 4) /* 4 s */
|
||||
#endif
|
||||
|
||||
static int zynq_info(xilinx_desc *desc)
|
||||
{
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
#define DUMMY_WORD 0xffffffff
|
||||
|
||||
/* Xilinx binary format header */
|
||||
static const u32 bin_format[] = {
|
||||
DUMMY_WORD, /* Dummy words */
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
0x000000bb, /* Sync word */
|
||||
0x11220044, /* Sync word */
|
||||
DUMMY_WORD,
|
||||
DUMMY_WORD,
|
||||
0xaa995566, /* Sync word */
|
||||
};
|
||||
|
||||
#define SWAP_NO 1
|
||||
#define SWAP_DONE 2
|
||||
|
||||
/*
|
||||
* Load the whole word from unaligned buffer
|
||||
* Keep in your mind that it is byte loading on little-endian system
|
||||
*/
|
||||
static u32 load_word(const void *buf, u32 swap)
|
||||
{
|
||||
u32 word = 0;
|
||||
u8 *bitc = (u8 *)buf;
|
||||
int p;
|
||||
|
||||
if (swap == SWAP_NO) {
|
||||
for (p = 0; p < 4; p++) {
|
||||
word <<= 8;
|
||||
word |= bitc[p];
|
||||
}
|
||||
} else {
|
||||
for (p = 3; p >= 0; p--) {
|
||||
word <<= 8;
|
||||
word |= bitc[p];
|
||||
}
|
||||
}
|
||||
|
||||
return word;
|
||||
}
|
||||
|
||||
static u32 check_header(const void *buf)
|
||||
{
|
||||
u32 i, pattern;
|
||||
int swap = SWAP_NO;
|
||||
u32 *test = (u32 *)buf;
|
||||
|
||||
debug("%s: Let's check bitstream header\n", __func__);
|
||||
|
||||
/* Checking that passing bin is not a bitstream */
|
||||
for (i = 0; i < ARRAY_SIZE(bin_format); i++) {
|
||||
pattern = load_word(&test[i], swap);
|
||||
|
||||
/*
|
||||
* Bitstreams in binary format are swapped
|
||||
* compare to regular bistream.
|
||||
* Do not swap dummy word but if swap is done assume
|
||||
* that parsing buffer is binary format
|
||||
*/
|
||||
if ((__swab32(pattern) != DUMMY_WORD) &&
|
||||
(__swab32(pattern) == bin_format[i])) {
|
||||
pattern = __swab32(pattern);
|
||||
swap = SWAP_DONE;
|
||||
debug("%s: data swapped - let's swap\n", __func__);
|
||||
}
|
||||
|
||||
debug("%s: %d/%x: pattern %x/%x bin_format\n", __func__, i,
|
||||
(u32)&test[i], pattern, bin_format[i]);
|
||||
if (pattern != bin_format[i]) {
|
||||
debug("%s: Bitstream is not recognized\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
debug("%s: Found bitstream header at %x %s swapinng\n", __func__,
|
||||
(u32)buf, swap == SWAP_NO ? "without" : "with");
|
||||
|
||||
return swap;
|
||||
}
|
||||
|
||||
static void *check_data(u8 *buf, size_t bsize, u32 *swap)
|
||||
{
|
||||
u32 word, p = 0; /* possition */
|
||||
|
||||
/* Because buf doesn't need to be aligned let's read it by chars */
|
||||
for (p = 0; p < bsize; p++) {
|
||||
word = load_word(&buf[p], SWAP_NO);
|
||||
debug("%s: word %x %x/%x\n", __func__, word, p, (u32)&buf[p]);
|
||||
|
||||
/* Find the first bitstream dummy word */
|
||||
if (word == DUMMY_WORD) {
|
||||
debug("%s: Found dummy word at position %x/%x\n",
|
||||
__func__, p, (u32)&buf[p]);
|
||||
*swap = check_header(&buf[p]);
|
||||
if (*swap) {
|
||||
/* FIXME add full bitstream checking here */
|
||||
return &buf[p];
|
||||
}
|
||||
}
|
||||
/* Loop can be huge - support CTRL + C */
|
||||
if (ctrlc())
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int zynq_dma_transfer(u32 srcbuf, u32 srclen, u32 dstbuf, u32 dstlen)
|
||||
{
|
||||
unsigned long ts;
|
||||
u32 isr_status;
|
||||
|
||||
/* Set up the transfer */
|
||||
writel((u32)srcbuf, &devcfg_base->dma_src_addr);
|
||||
writel(dstbuf, &devcfg_base->dma_dst_addr);
|
||||
writel(srclen, &devcfg_base->dma_src_len);
|
||||
writel(dstlen, &devcfg_base->dma_dst_len);
|
||||
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
|
||||
/* Polling the PCAP_INIT status for Set */
|
||||
ts = get_timer(0);
|
||||
while (!(isr_status & DEVCFG_ISR_DMA_DONE)) {
|
||||
if (isr_status & DEVCFG_ISR_ERROR_FLAGS_MASK) {
|
||||
debug("%s: Error: isr = 0x%08X\n", __func__,
|
||||
isr_status);
|
||||
debug("%s: Write count = 0x%08X\n", __func__,
|
||||
readl(&devcfg_base->write_count));
|
||||
debug("%s: Read count = 0x%08X\n", __func__,
|
||||
readl(&devcfg_base->read_count));
|
||||
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) {
|
||||
printf("%s: Timeout wait for DMA to complete\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
}
|
||||
|
||||
debug("%s: DMA transfer is done\n", __func__);
|
||||
|
||||
/* Clear out the DMA status */
|
||||
writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
|
||||
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
static int zynq_dma_xfer_init(bitstream_type bstype)
|
||||
{
|
||||
u32 status, control, isr_status;
|
||||
unsigned long ts;
|
||||
|
||||
/* Clear loopback bit */
|
||||
clrbits_le32(&devcfg_base->mctrl, DEVCFG_MCTRL_PCAP_LPBK);
|
||||
|
||||
if (bstype != BIT_PARTIAL) {
|
||||
zynq_slcr_devcfg_disable();
|
||||
|
||||
/* Setting PCFG_PROG_B signal to high */
|
||||
control = readl(&devcfg_base->ctrl);
|
||||
writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
|
||||
/* Setting PCFG_PROG_B signal to low */
|
||||
writel(control & ~DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
|
||||
|
||||
/* Polling the PCAP_INIT status for Reset */
|
||||
ts = get_timer(0);
|
||||
while (readl(&devcfg_base->status) & DEVCFG_STATUS_PCFG_INIT) {
|
||||
if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
|
||||
printf("%s: Timeout wait for INIT to clear\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting PCFG_PROG_B signal to high */
|
||||
writel(control | DEVCFG_CTRL_PCFG_PROG_B, &devcfg_base->ctrl);
|
||||
|
||||
/* Polling the PCAP_INIT status for Set */
|
||||
ts = get_timer(0);
|
||||
while (!(readl(&devcfg_base->status) &
|
||||
DEVCFG_STATUS_PCFG_INIT)) {
|
||||
if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
|
||||
printf("%s: Timeout wait for INIT to set\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
|
||||
/* Clear it all, so if Boot ROM comes back, it can proceed */
|
||||
writel(0xFFFFFFFF, &devcfg_base->int_sts);
|
||||
|
||||
if (isr_status & DEVCFG_ISR_FATAL_ERROR_MASK) {
|
||||
debug("%s: Fatal errors in PCAP 0x%X\n", __func__, isr_status);
|
||||
|
||||
/* If RX FIFO overflow, need to flush RX FIFO first */
|
||||
if (isr_status & DEVCFG_ISR_RX_FIFO_OV) {
|
||||
writel(DEVCFG_MCTRL_RFIFO_FLUSH, &devcfg_base->mctrl);
|
||||
writel(0xFFFFFFFF, &devcfg_base->int_sts);
|
||||
}
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
status = readl(&devcfg_base->status);
|
||||
|
||||
debug("%s: Status = 0x%08X\n", __func__, status);
|
||||
|
||||
if (status & DEVCFG_STATUS_DMA_CMD_Q_F) {
|
||||
debug("%s: Error: device busy\n", __func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
debug("%s: Device ready\n", __func__);
|
||||
|
||||
if (!(status & DEVCFG_STATUS_DMA_CMD_Q_E)) {
|
||||
if (!(readl(&devcfg_base->int_sts) & DEVCFG_ISR_DMA_DONE)) {
|
||||
/* Error state, transfer cannot occur */
|
||||
debug("%s: ISR indicates error\n", __func__);
|
||||
return FPGA_FAIL;
|
||||
} else {
|
||||
/* Clear out the status */
|
||||
writel(DEVCFG_ISR_DMA_DONE, &devcfg_base->int_sts);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & DEVCFG_STATUS_DMA_DONE_CNT_MASK) {
|
||||
/* Clear the count of completed DMA transfers */
|
||||
writel(DEVCFG_STATUS_DMA_DONE_CNT_MASK, &devcfg_base->status);
|
||||
}
|
||||
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
static u32 *zynq_align_dma_buffer(u32 *buf, u32 len, u32 swap)
|
||||
{
|
||||
u32 *new_buf;
|
||||
u32 i;
|
||||
|
||||
if ((u32)buf != ALIGN((u32)buf, ARCH_DMA_MINALIGN)) {
|
||||
new_buf = (u32 *)ALIGN((u32)buf, ARCH_DMA_MINALIGN);
|
||||
|
||||
/*
|
||||
* This might be dangerous but permits to flash if
|
||||
* ARCH_DMA_MINALIGN is greater than header size
|
||||
*/
|
||||
if (new_buf > buf) {
|
||||
debug("%s: Aligned buffer is after buffer start\n",
|
||||
__func__);
|
||||
new_buf -= ARCH_DMA_MINALIGN;
|
||||
}
|
||||
printf("%s: Align buffer at %x to %x(swap %d)\n", __func__,
|
||||
(u32)buf, (u32)new_buf, swap);
|
||||
|
||||
for (i = 0; i < (len/4); i++)
|
||||
new_buf[i] = load_word(&buf[i], swap);
|
||||
|
||||
buf = new_buf;
|
||||
} else if (swap != SWAP_DONE) {
|
||||
/* For bitstream which are aligned */
|
||||
u32 *new_buf = (u32 *)buf;
|
||||
|
||||
printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
|
||||
swap);
|
||||
|
||||
for (i = 0; i < (len/4); i++)
|
||||
new_buf[i] = load_word(&buf[i], swap);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int zynq_validate_bitstream(xilinx_desc *desc, const void *buf,
|
||||
size_t bsize, u32 blocksize, u32 *swap,
|
||||
bitstream_type *bstype)
|
||||
{
|
||||
u32 *buf_start;
|
||||
u32 diff;
|
||||
|
||||
buf_start = check_data((u8 *)buf, blocksize, swap);
|
||||
|
||||
if (!buf_start)
|
||||
return FPGA_FAIL;
|
||||
|
||||
/* Check if data is postpone from start */
|
||||
diff = (u32)buf_start - (u32)buf;
|
||||
if (diff) {
|
||||
printf("%s: Bitstream is not validated yet (diff %x)\n",
|
||||
__func__, diff);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
if ((u32)buf < SZ_1M) {
|
||||
printf("%s: Bitstream has to be placed up to 1MB (%x)\n",
|
||||
__func__, (u32)buf);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
if (zynq_dma_xfer_init(*bstype))
|
||||
return FPGA_FAIL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
bitstream_type bstype)
|
||||
{
|
||||
unsigned long ts; /* Timestamp */
|
||||
u32 isr_status, swap;
|
||||
|
||||
/*
|
||||
* send bsize inplace of blocksize as it was not a bitstream
|
||||
* in chunks
|
||||
*/
|
||||
if (zynq_validate_bitstream(desc, buf, bsize, bsize, &swap,
|
||||
&bstype))
|
||||
return FPGA_FAIL;
|
||||
|
||||
buf = zynq_align_dma_buffer((u32 *)buf, bsize, swap);
|
||||
|
||||
debug("%s: Source = 0x%08X\n", __func__, (u32)buf);
|
||||
debug("%s: Size = %zu\n", __func__, bsize);
|
||||
|
||||
/* flush(clean & invalidate) d-cache range buf */
|
||||
flush_dcache_range((u32)buf, (u32)buf +
|
||||
roundup(bsize, ARCH_DMA_MINALIGN));
|
||||
|
||||
if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
|
||||
return FPGA_FAIL;
|
||||
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
/* Check FPGA configuration completion */
|
||||
ts = get_timer(0);
|
||||
while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
|
||||
if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
|
||||
printf("%s: Timeout wait for FPGA to config\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
}
|
||||
|
||||
debug("%s: FPGA config done\n", __func__);
|
||||
|
||||
if (bstype != BIT_PARTIAL)
|
||||
zynq_slcr_devcfg_enable();
|
||||
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CMD_FPGA_LOADFS)
|
||||
static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize,
|
||||
fpga_fs_info *fsinfo)
|
||||
{
|
||||
unsigned long ts; /* Timestamp */
|
||||
u32 isr_status, swap;
|
||||
u32 partialbit = 0;
|
||||
loff_t blocksize, actread;
|
||||
loff_t pos = 0;
|
||||
int fstype;
|
||||
char *interface, *dev_part, *filename;
|
||||
|
||||
blocksize = fsinfo->blocksize;
|
||||
interface = fsinfo->interface;
|
||||
dev_part = fsinfo->dev_part;
|
||||
filename = fsinfo->filename;
|
||||
fstype = fsinfo->fstype;
|
||||
|
||||
if (fs_set_blk_dev(interface, dev_part, fstype))
|
||||
return FPGA_FAIL;
|
||||
|
||||
if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
|
||||
return FPGA_FAIL;
|
||||
|
||||
if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap,
|
||||
&partialbit))
|
||||
return FPGA_FAIL;
|
||||
|
||||
dcache_disable();
|
||||
|
||||
do {
|
||||
buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
|
||||
|
||||
if (zynq_dma_transfer((u32)buf | 1, blocksize >> 2,
|
||||
0xffffffff, 0))
|
||||
return FPGA_FAIL;
|
||||
|
||||
bsize -= blocksize;
|
||||
pos += blocksize;
|
||||
|
||||
if (fs_set_blk_dev(interface, dev_part, fstype))
|
||||
return FPGA_FAIL;
|
||||
|
||||
if (bsize > blocksize) {
|
||||
if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0)
|
||||
return FPGA_FAIL;
|
||||
} else {
|
||||
if (fs_read(filename, (u32) buf, pos, bsize, &actread) < 0)
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
} while (bsize > blocksize);
|
||||
|
||||
buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap);
|
||||
|
||||
if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0))
|
||||
return FPGA_FAIL;
|
||||
|
||||
dcache_enable();
|
||||
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
|
||||
/* Check FPGA configuration completion */
|
||||
ts = get_timer(0);
|
||||
while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) {
|
||||
if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) {
|
||||
printf("%s: Timeout wait for FPGA to config\n",
|
||||
__func__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
isr_status = readl(&devcfg_base->int_sts);
|
||||
}
|
||||
|
||||
debug("%s: FPGA config done\n", __func__);
|
||||
|
||||
if (!partialbit)
|
||||
zynq_slcr_devcfg_enable();
|
||||
|
||||
return FPGA_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int zynq_dump(xilinx_desc *desc, const void *buf, size_t bsize)
|
||||
{
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
struct xilinx_fpga_op zynq_op = {
|
||||
.load = zynq_load,
|
||||
#if defined(CONFIG_CMD_FPGA_LOADFS)
|
||||
.loadfs = zynq_loadfs,
|
||||
#endif
|
||||
.dump = zynq_dump,
|
||||
.info = zynq_info,
|
||||
};
|
||||
Reference in New Issue
Block a user