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:
2026-03-03 21:46:32 +02:00
parent fe3ba02c96
commit 68d74d3181
11967 changed files with 2221897 additions and 0 deletions

View 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;
}

View 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

View 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;
}

View 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
View 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);
}

File diff suppressed because it is too large Load Diff

View 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;
}

View 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();
}

View 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,
};

View 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,
};

View 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;
}

View 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;
}

View 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,
};

View 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;
}

View 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,
};