* [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too.
@ 2006-12-02 22:15 Pantelis Antoniou
2006-12-02 22:15 ` [U-Boot-Users] [PATCH 2/8] Support LATTICE FPGA parts using JTAG programming. Interface to FPGA API Pantelis Antoniou
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:15 UTC (permalink / raw)
To: u-boot
Auto complete did not work when the HUSH parser was selected.
Fix this obvious problem.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
README | 4 ----
common/main.c | 25 +++++++++++++++++++++++--
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/README b/README
index ecfd1f8..e28f935 100644
--- a/README
+++ b/README
@@ -1511,10 +1511,6 @@ The following options need to be configured:
Enable auto completion of commands using TAB.
- Note that this feature has NOT been implemented yet
- for the "hush" shell.
-
-
CFG_HUSH_PARSER
Define this variable to enable the "hush" shell (from
diff --git a/common/main.c b/common/main.c
index cc4b50f..a8ae07c 100644
--- a/common/main.c
+++ b/common/main.c
@@ -718,10 +718,11 @@ static void cread_add_str(char *str, int strsize, int insert, unsigned long *num
}
}
-static int cread_line(char *buf, unsigned int *len)
+static int cread_line(const char *const prompt, char *buf, unsigned int *len)
{
unsigned long num = 0;
unsigned long eol_num = 0;
+ int num2, col;
unsigned long rlen;
unsigned long wlen;
char ichar;
@@ -840,6 +841,7 @@ static int cread_line(char *buf, unsigned int *len)
insert = !insert;
break;
case CTL_CH('x'):
+ case CTL_CH('u'): /* like that too */
BEGINNING_OF_LINE();
ERASE_TO_EOL();
break;
@@ -889,6 +891,25 @@ static int cread_line(char *buf, unsigned int *len)
REFRESH_TO_EOL();
continue;
}
+#ifdef CONFIG_AUTO_COMPLETE
+ case '\t':
+
+ /* do not autocomplete when in the middle */
+ if (num < eol_num) {
+ getcmd_cbeep();
+ break;
+ }
+
+ buf[num] = '\0';
+ col = strlen(prompt) + eol_num;
+ num2 = num;
+ if (cmd_auto_complete(prompt, buf, &num2, &col)) {
+ col = num2 - num;
+ num += col;
+ eol_num += col;
+ }
+ break;
+#endif
default:
cread_add_char(ichar, insert, &num, &eol_num, buf, *len);
break;
@@ -931,7 +952,7 @@ int readline (const char *const prompt)
puts (prompt);
- rc = cread_line(p, &len);
+ rc = cread_line(prompt, p, &len);
return rc < 0 ? rc : len;
#else
char *p = console_buffer;
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 2/8] Support LATTICE FPGA parts using JTAG programming. Interface to FPGA API.
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
@ 2006-12-02 22:15 ` Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 3/8] Support LATTICE FPGA parts using JTAG programming. JTAG core Pantelis Antoniou
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:15 UTC (permalink / raw)
To: u-boot
Add support for Lattice FPGA parts programmed using JTAG.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
common/Makefile | 4
common/fpga.c | 30 +++
common/lattice.c | 218 ++++++++++++++++++++++++
common/lattice_ec.c | 461 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/fpga.h | 3
include/lattice.h | 85 +++++++++
include/lattice_ec.h | 85 +++++++++
7 files changed, 884 insertions(+), 2 deletions(-)
diff --git a/common/Makefile b/common/Makefile
index 0106088..79d11a5 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -47,7 +47,9 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o \
env_nvram.o env_nowhere.o \
exports.o \
flash.o fpga.o ft_build.o \
- hush.o kgdb.o lcd.o lists.o lynxkdi.o \
+ hush.o kgdb.o \
+ lattice.o lattice_ec.o lattice_ivm_core.o lattice_ivm_supp.o \
+ lcd.o lists.o lynxkdi.o \
memsize.o miiphybb.o miiphyutil.o \
s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \
usb.o usb_kbd.o usb_storage.o \
diff --git a/common/fpga.c b/common/fpga.c
index 2eff239..8374814 100644
--- a/common/fpga.c
+++ b/common/fpga.c
@@ -28,6 +28,7 @@
#include <common.h> /* core U-Boot definitions */
#include <xilinx.h> /* xilinx specific definitions */
#include <altera.h> /* altera specific definitions */
+#include <lattice.h> /* lattice specific definitions */
#if defined(CONFIG_FPGA)
@@ -150,6 +151,14 @@ static int fpga_dev_info( int devnum )
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
#endif
break;
+ case fpga_lattice:
+#if CONFIG_FPGA & CFG_FPGA_LATTICE
+ printf( "Lattice Device\nDescriptor @ 0x%p\n", desc );
+ ret_val = lattice_info( desc->devdesc );
+#else
+ fpga_no_sup( __FUNCTION__, "Lattice devices" );
+#endif
+ break;
default:
printf( "%s: Invalid or unsupported device type %d\n",
__FUNCTION__, desc->devtype );
@@ -188,6 +197,13 @@ int fpga_reloc( fpga_type devtype, void *desc, ulong reloc_off )
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
#endif
break;
+ case fpga_lattice:
+#if CONFIG_FPGA & CFG_FPGA_LATTICE
+ ret_val = lattice_reloc( desc, reloc_off );
+#else
+ fpga_no_sup( __FUNCTION__, "Lattice devices" );
+#endif
+ break;
default:
printf( "%s: Invalid or unsupported device type %d\n",
__FUNCTION__, devtype );
@@ -281,6 +297,13 @@ int fpga_load( int devnum, void *buf, size_t bsize )
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
#endif
break;
+ case fpga_lattice:
+#if CONFIG_FPGA & CFG_FPGA_LATTICE
+ ret_val = lattice_load( desc->devdesc, buf, bsize );
+#else
+ fpga_no_sup( __FUNCTION__, "Lattice devices" );
+#endif
+ break;
default:
printf( "%s: Invalid or unsupported device type %d\n",
__FUNCTION__, desc->devtype );
@@ -314,6 +337,13 @@ int fpga_dump( int devnum, void *buf, size_t bsize )
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
#endif
break;
+ case fpga_lattice:
+#if CONFIG_FPGA & CFG_FPGA_LATTICE
+ ret_val = lattice_dump( desc->devdesc, buf, bsize );
+#else
+ fpga_no_sup( __FUNCTION__, "Lattice devices" );
+#endif
+ break;
default:
printf( "%s: Invalid or unsupported device type %d\n",
__FUNCTION__, desc->devtype );
diff --git a/common/lattice.c b/common/lattice.c
new file mode 100644
index 0000000..26e1aa2
--- /dev/null
+++ b/common/lattice.c
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on common/lattice.c (C) Copyright 2002
+ * by Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ * by Keith Outwater, keith_outwater at mvis.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Lattice FPGA support
+ */
+
+#include <common.h>
+#include <lattice_ec.h>
+
+#include <lattice_vmopcode.h>
+
+#if (CONFIG_FPGA & CFG_FPGA_LATTICE)
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef FPGA_DEBUG
+#define PRINTF(fmt,args...) printf(fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Local Static Functions */
+static int lattice_validate(Lattice_desc *desc, char *fn);
+
+int lattice_load(Lattice_desc *desc, void *buf, size_t bsize)
+{
+ int ret_val = FPGA_FAIL; /* assume a failure */
+
+ if (!lattice_validate(desc, (char *)__FUNCTION__)) {
+ printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ switch (desc->family) {
+ case Lattice_EC:
+#if (CONFIG_FPGA & CFG_EC)
+ PRINTF("%s: Launching the EC Loader...\n",
+ __FUNCTION__);
+ ret_val = EC_load(desc, buf, bsize);
+#else
+ printf("%s: No support for EC devices.\n",
+ __FUNCTION__);
+#endif
+ break;
+ default:
+ printf("%s: Unsupported family type, %d\n",
+ __FUNCTION__, desc->family);
+ }
+
+ return ret_val;
+}
+
+int lattice_dump(Lattice_desc *desc, void *buf, size_t bsize)
+{
+ int ret_val = FPGA_FAIL; /* assume a failure */
+
+ if (!lattice_validate(desc, (char *)__FUNCTION__)) {
+ printf("%s: Invalid device descriptor\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ switch (desc->family) {
+ case Lattice_EC:
+#if (CONFIG_FPGA & CFG_EC)
+ PRINTF("%s: Launching the EC Reader...\n",
+ __FUNCTION__);
+ ret_val = EC_dump(desc, buf, bsize);
+#else
+ printf("%s: No support for EC devices.\n",
+ __FUNCTION__);
+#endif
+ break;
+
+ default:
+ printf("%s: Unsupported family type, %d\n",
+ __FUNCTION__, desc->family);
+ }
+
+ return ret_val;
+}
+
+int lattice_info(Lattice_desc *desc)
+{
+ if (!lattice_validate(desc, (char *)__FUNCTION__)) {
+ printf("%s: Invalid device descriptor\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ if (!desc->iface_fns) {
+ printf("No Device Function Table.\n");
+ return FPGA_FAIL;
+ }
+
+ printf ("Family: \t");
+ switch (desc->family) {
+ case Lattice_EC:
+ printf ("EC\n");
+ break;
+ /* Add new family types here */
+ default:
+ printf("Unknown family type, %d\n", desc->family);
+ }
+
+ printf ("Interface type:\t");
+ switch (desc->iface) {
+ case lattice_jtag_mode:
+ printf("JTAG Mode\n");
+ break;
+ default:
+ printf("Unsupported interface type, %d\n", desc->iface);
+ }
+
+ printf("Device Size: \t%d bytes\n"
+ "Cookie: \t0x%x (%d)\n",
+ desc->size, desc->cookie, desc->cookie);
+
+ printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
+ switch (desc->family) {
+ case Lattice_EC:
+#if (CONFIG_FPGA & CFG_EC)
+ EC_info(desc);
+#else
+ /* just in case */
+ printf("%s: No support for EC devices.\n",
+ __FUNCTION__);
+#endif
+ break;
+ /* Add new family types here */
+ default:
+ /* we don't need a message here - we give one up above */
+ ;
+ }
+
+ return FPGA_SUCCESS;
+}
+
+int lattice_reloc(Lattice_desc *desc, ulong reloc_offset)
+{
+ int ret_val = FPGA_FAIL; /* assume a failure */
+
+ if (!lattice_validate (desc, (char *)__FUNCTION__)) {
+ printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ switch (desc->family) {
+ case Lattice_EC:
+#if (CONFIG_FPGA & CFG_EC)
+ ret_val = EC_reloc(desc, reloc_offset);
+#else
+ printf("%s: No support for EC devices.\n",
+ __FUNCTION__);
+#endif
+ break;
+ /* Add new family types here */
+ default:
+ printf("%s: Unsupported family type, %d\n",
+ __FUNCTION__, desc->family);
+ }
+
+ return ret_val;
+}
+
+static int lattice_validate(Lattice_desc *desc, char *fn)
+{
+ if (!desc) {
+ printf ("%s: NULL descriptor!\n", fn);
+ return 0;
+ }
+
+ if (desc->family <= min_lattice_type &&
+ desc->family >= max_lattice_type) {
+ printf ("%s: Invalid family type, %d\n", fn, desc->family);
+ return 0;
+ }
+ if (desc->iface <= min_lattice_iface_type &&
+ desc->iface >= max_lattice_iface_type) {
+ printf ("%s: Invalid Interface type, %d\n", fn, desc->iface);
+ return 0;
+ }
+ if (!desc->size) {
+ printf ("%s: NULL part size\n", fn);
+ return 0;
+ }
+
+ return 1;
+}
+
+#endif
diff --git a/common/lattice_ec.c b/common/lattice_ec.c
new file mode 100644
index 0000000..1b8b485
--- /dev/null
+++ b/common/lattice_ec.c
@@ -0,0 +1,461 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on common/spartan2.c
+ * (C) Copyright 2002
+ * by Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h> /* core U-Boot definitions */
+#include <asm/types.h>
+
+#include <lattice_ec.h> /* Lattice EC device family */
+
+#include <lattice_vmopcode.h>
+#include <lattice_ivm_core.h>
+
+#if (CONFIG_FPGA & (CFG_LATTICE | CFG_EC))
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef FPGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* 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 CFG_FPGA_WAIT
+#define CFG_FPGA_WAIT CFG_HZ/100 /* 10 ms */
+#endif
+
+static int EC_jtag_load( Lattice_desc *desc, void *buf, size_t bsize);
+static int EC_jtag_dump( Lattice_desc *desc, void *buf, size_t bsize);
+/* static int EC_jtag_info( Lattice_desc *desc ); */
+static int EC_jtag_reloc( Lattice_desc *desc, ulong reloc_offset);
+
+/* Lattice EC Generic Implementation */
+int EC_load (Lattice_desc * desc, void *buf, size_t bsize)
+{
+ int ret_val = FPGA_FAIL;
+
+ switch (desc->iface) {
+ case lattice_jtag_mode:
+ PRINTF ("%s: Launching JTAG Load\n", __FUNCTION__);
+ ret_val = EC_jtag_load (desc, buf, bsize);
+ break;
+
+ default:
+ printf ("%s: Unsupported interface type, %d\n",
+ __FUNCTION__, desc->iface);
+ }
+
+ return ret_val;
+}
+
+int EC_dump (Lattice_desc * desc, void *buf, size_t bsize)
+{
+ int ret_val = FPGA_FAIL;
+
+ switch (desc->iface) {
+ case lattice_jtag_mode:
+ PRINTF ("%s: Launching JTAG Dump\n", __FUNCTION__);
+ ret_val = EC_jtag_dump (desc, buf, bsize);
+ break;
+
+ default:
+ printf ("%s: Unsupported interface type, %d\n",
+ __FUNCTION__, desc->iface);
+ }
+
+ return ret_val;
+}
+
+int EC_info( Lattice_desc *desc )
+{
+ return FPGA_SUCCESS;
+}
+
+
+int EC_reloc (Lattice_desc * desc, ulong reloc_offset)
+{
+ int ret_val = FPGA_FAIL; /* assume a failure */
+
+ if (desc->family != Lattice_EC) {
+ printf ("%s: Unsupported family type, %d\n",
+ __FUNCTION__, desc->family);
+ return FPGA_FAIL;
+ } else
+ switch (desc->iface) {
+ case lattice_jtag_mode:
+ ret_val = EC_jtag_reloc (desc, reloc_offset);
+ break;
+
+ default:
+ printf ("%s: Unsupported interface type, %d\n",
+ __FUNCTION__, desc->iface);
+ }
+
+ return ret_val;
+}
+
+/*********************************************************************/
+
+static void rewind_buffer(void *cookie);
+
+static int lattice_ec_verbose = 0;
+
+static int EC_jtag_load (Lattice_desc * desc, void *buf, size_t bsize)
+{
+ static struct Lattice_EC_private priv;
+ Lattice_EC_JTAG_fns *fn = desc->iface_fns;
+ char version[9];
+ int j, ret;
+ u16 ecrc = 0;
+ u16 ccrc = 0;
+ int val;
+
+ /* play it safe */
+ version[0] = '\0';
+
+ PRINTF ("%s: start with interface functions @ 0x%p\n",
+ __FUNCTION__, fn);
+
+ if (!fn) {
+ printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ PRINTF ("%s: Function Table:\n"
+ "ptr:\t0x%p\n"
+ "struct: 0x%p\n"
+ "pre:\t0x%p\n"
+ "post:\t0x%p\n"
+ "jtag_write_port:\t0x%p\n"
+ "jtag_read_port:\t0x%p\n\n",
+ __FUNCTION__, &fn, fn, fn->pre, fn->post,
+ fn->jtag_write_port, fn->jtag_read_port);
+
+ priv.fpga_prog_base = buf;
+ priv.fpga_prog_end = buf + bsize;
+ priv.fpga_prog_next = buf;
+ priv.fpga_steps_reset = (bsize * 2 / 50); /* one step */
+ priv.fpga_steps = 0;
+ priv.fpga_spin = 0;
+ desc->priv = &priv;
+
+ ispvm_reset(&priv.d, desc); /* Reset state of programming code */
+ rewind_buffer(desc);
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+ printf("FPGA: "); /* Two spaces (at least)! */
+#endif
+
+ lattice_ec_verbose = 0;
+
+ ccrc = 0;
+ val = lattice_ec_next_byte(desc);
+ if (val == -1) {
+ PRINTF("Invalid file\n");
+ return VME_INVALID_FILE;
+ }
+ switch(val) {
+ case FILE_CRC:
+ val = lattice_ec_next_byte(desc);
+ if (val == -1) {
+ PRINTF("Invalid file\n");
+ return VME_INVALID_FILE;
+ }
+ ecrc = (val & 0xff) << 8;
+ val = lattice_ec_next_byte(desc);
+ if (val == -1) {
+ PRINTF("Invalid file\n");
+ return VME_INVALID_FILE;
+ }
+ ecrc |= val & 0xff;
+
+ while ((val = lattice_ec_next_byte(desc)) != -1)
+ ccrc = ispvm_crc(&priv.d, (u8)val, ccrc);
+
+ if (ecrc && ecrc != ccrc) {
+ PRINTF("Expected CRC: 0x%.4X\n", ecrc);
+ PRINTF("Calculated CRC: 0x%.4X\n", ccrc);
+ return VME_CRC_FAILURE;
+ }
+
+ rewind_buffer(desc);
+#ifdef FPGA_DEBUG
+ lattice_ec_verbose = 1;
+#endif
+ (void)lattice_ec_next_byte(desc);
+ (void)lattice_ec_next_byte(desc);
+ (void)lattice_ec_next_byte(desc);
+
+ for (j = 0; j < 8; j++) {
+ val = lattice_ec_next_byte(desc);
+ if (val == -1)
+ break;
+ version[j] = val & 0xff;
+ }
+
+ break;
+
+ default:
+ version[0] = (signed char) val;
+ for (j = 1; j < 8; j++) {
+ val = lattice_ec_next_byte(desc);
+ if (val == -1)
+ break;
+ version[j] = val & 0xff;
+ }
+ break;
+ }
+
+ ret = ispvm_validate_version(&priv.d, version);
+ if (ret < 0)
+ return VME_VERSION_FAILURE;
+
+ PRINTF("FPGA pre-program\n");
+ if (fn->pre)
+ fn->pre(0);
+
+ /* Reset FPGA */
+ PRINTF("FPGA reset\n");
+ fn->jtag_write_port(0, LATTICE_JTAG_RST, 1);
+ udelay(1000);
+ fn->jtag_write_port(0, LATTICE_JTAG_RST, 0);
+
+ /* lattice_ec_verbose = 0; */
+
+ ispvm_start(&priv.d);
+ ret = ispvm_code(&priv.d);
+ ispvm_end(&priv.d);
+
+ if (ret != 0) {
+ if (fn->post)
+ (*fn->post)(0, 0);
+
+ PRINTF(" FAILED! (code = %d)\n", cRetCode);
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+ printf(" FAIL!\n");
+#endif
+ return FPGA_FAIL;
+ }
+
+ PRINTF(" OK\n");
+
+ PRINTF("FPGA post-program\n");
+ if (fn->post)
+ (*fn->post)(0, 1);
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+ printf("\b\b done.\n");
+#endif
+
+ return FPGA_SUCCESS;
+}
+
+static int EC_jtag_dump (Lattice_desc * desc, void *buf, size_t bsize)
+{
+ /* Readback is only available through the Slave Parallel and */
+ /* boundary-scan interfaces. */
+ printf ("%s: JTAG Dumping is unavailable\n",
+ __FUNCTION__);
+ return FPGA_FAIL;
+}
+
+static int EC_jtag_reloc (Lattice_desc * desc, ulong reloc_offset)
+{
+ ulong addr;
+ Lattice_EC_JTAG_fns *fn_r, *fn = desc->iface_fns;
+
+ if (!fn) {
+ printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+ return FPGA_FAIL;
+ }
+
+ /* Get the relocated table address */
+ addr = (ulong) fn + reloc_offset;
+ fn_r = (Lattice_EC_JTAG_fns *) addr;
+
+ if (fn_r->relocated) {
+ /* this table has already been moved */
+ /* XXX - should check to see if the descriptor is correct */
+ desc->iface_fns = fn_r;
+ return FPGA_SUCCESS;
+ }
+
+ if (memcmp(fn_r, fn, sizeof(Lattice_EC_JTAG_fns)) != 0) {
+ PRINTF ("%s: Invalid function table at 0x%p\n",
+ __FUNCTION__, fn_r);
+ return FPGA_FAIL;
+ }
+
+ /* good copy of the table,
+ * fix the descriptor pointer
+ */
+ desc->iface_fns = fn_r;
+ PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
+ desc);
+
+ addr = (ulong) (fn->pre) + reloc_offset;
+ fn_r->pre = (Lattice_pre_fn) addr;
+
+ addr = (ulong) (fn->post) + reloc_offset;
+ fn_r->post = (Lattice_post_fn) addr;
+
+ addr = (ulong) (fn->jtag_write_port) + reloc_offset;
+ fn_r->jtag_write_port = (Lattice_jtag_write_port_fn) addr;
+
+ addr = (ulong) (fn->jtag_read_port) + reloc_offset;
+ fn_r->jtag_read_port = (Lattice_jtag_read_port_fn) addr;
+
+ fn_r->relocated = TRUE;
+
+ return FPGA_SUCCESS;
+}
+
+/****************************************************************************/
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+
+static const char spin_txt[] = "|/-\\";
+
+static inline void fpga_progress(Lattice_desc *desc)
+{
+ struct Lattice_EC_private *priv = desc->priv;
+
+ if (--priv->fpga_steps >= 0)
+ return;
+
+ priv->fpga_steps = priv->fpga_steps_reset;
+ printf("\b%c", spin_txt[priv->fpga_spin]);
+ if (++priv->fpga_spin >= 4)
+ priv->fpga_spin = 0;
+}
+
+#else
+
+#define fpga_progress(desc) do { } while(0)
+
+#endif
+
+static void rewind_buffer(void *cookie)
+{
+ Lattice_desc * desc = cookie;
+ struct Lattice_EC_private *priv = desc->priv;
+
+ priv->fpga_prog_next = priv->fpga_prog_base;
+
+ if (lattice_ec_verbose)
+ printf("\nRewind:\n");
+}
+
+int lattice_ec_next_byte(void *cookie)
+{
+ Lattice_desc * desc = cookie;
+ struct Lattice_EC_private *priv = desc->priv;
+ unsigned char val;
+ int pos;
+
+ if (priv == NULL || priv->fpga_prog_next == NULL ||
+ priv->fpga_prog_next >= priv->fpga_prog_end)
+ return -1;
+
+ val = *priv->fpga_prog_next & 0xff;
+
+ if (lattice_ec_verbose) {
+ pos = priv->fpga_prog_next - priv->fpga_prog_base;
+ if ((pos % 16) == 0)
+ PRINTF("[%04x]", pos & 0xffff);
+
+ PRINTF(" %02x", val);
+ }
+
+ priv->fpga_prog_next++;
+
+ if (lattice_ec_verbose) {
+ pos = priv->fpga_prog_next - priv->fpga_prog_base;
+ if ((pos % 16) == 0)
+ PRINTF("\n");
+ }
+
+ fpga_progress(desc);
+
+ return val;
+}
+
+#ifdef FPGA_DEBUG
+static const char *pin_txt[] = {
+ [LATTICE_JTAG_TDI] = "TDI",
+ [LATTICE_JTAG_TCK] = "TCK",
+ [LATTICE_JTAG_TMS] = "TMS",
+ [LATTICE_JTAG_TDO] = "TDO",
+ [LATTICE_JTAG_CE] = "CE",
+ [LATTICE_JTAG_RST] = "RST",
+};
+#endif
+
+int lattice_ec_read_port(void *cookie)
+{
+ Lattice_desc * desc = cookie;
+ Lattice_EC_JTAG_fns *fn = desc->iface_fns;
+ struct Lattice_EC_private *priv = desc->priv;
+ int val;
+
+ (void)priv;
+ val = fn->jtag_read_port(0);
+
+ if (lattice_ec_verbose)
+ PRINTF("R-TDO=%d\n", val);
+
+ return val;
+}
+
+void lattice_ec_write_port(void *cookie, int pin, int value)
+{
+ Lattice_desc * desc = cookie;
+ Lattice_EC_JTAG_fns *fn = desc->iface_fns;
+ struct Lattice_EC_private *priv = desc->priv;
+
+ (void)priv;
+
+ if (lattice_ec_verbose)
+ PRINTF("W-%s=%d\n", pin_txt[pin], value & 1);
+
+ fn->jtag_write_port(0, pin, value);
+}
+
+#endif
diff --git a/include/fpga.h b/include/fpga.h
index a038aa1..f04b64a 100644
--- a/include/fpga.h
+++ b/include/fpga.h
@@ -47,7 +47,7 @@
/* FPGA Manufacturer bits in CONFIG_FPGA */
#define CFG_FPGA_XILINX CFG_FPGA_MAN( 0x1 )
#define CFG_FPGA_ALTERA CFG_FPGA_MAN( 0x2 )
-
+#define CFG_FPGA_LATTICE CFG_FPGA_MAN( 0x4 )
/* fpga_xxxx function return value definitions */
#define FPGA_SUCCESS 0
@@ -61,6 +61,7 @@ typedef enum { /* typedef fpga_type */
fpga_min_type, /* range check value */
fpga_xilinx, /* Xilinx Family) */
fpga_altera, /* unimplemented */
+ fpga_lattice, /* lattice */
fpga_undefined /* invalid range check value */
} fpga_type; /* end, typedef fpga_type */
diff --git a/include/lattice.h b/include/lattice.h
new file mode 100644
index 0000000..edd3e74
--- /dev/null
+++ b/include/lattice.h
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on include/xilinx.h
+ * (C) Copyright 2002
+ * by Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <fpga.h>
+
+#ifndef _LATTICE_H_
+#define _LATTICE_H_
+
+/* Lattice Model definitions */
+#define CFG_EC CFG_FPGA_DEV( 0x1 )
+#define CFG_LATTICE_EC (CFG_FPGA_LATTICE | CFG_EC)
+
+/* Lattice Interface definitions */
+#define CFG_LATTICE_IF_JTAG CFG_FPGA_IF( 0x1 ) /* jtag */
+
+/* Lattice types */
+typedef enum { /* typedef Lattice_iface */
+ min_lattice_iface_type, /* low range check value */
+ lattice_jtag_mode, /* jtag/tap serial */
+ max_lattice_iface_type /* insert all new types before this */
+} Lattice_iface; /* end, typedef Lattice_iface */
+
+typedef enum { /* typedef Lattice_Family */
+ min_lattice_type, /* low range check value */
+ Lattice_EC, /* EC Family */
+ max_lattice_type /* insert all new types before this */
+} Lattice_Family; /* end, typedef Lattice_Family */
+
+typedef struct { /* typedef Lattice_desc */
+ Lattice_Family family; /* part type */
+ Lattice_iface iface; /* interface type */
+ size_t size; /* bytes of data part can accept */
+ void * iface_fns; /* interface function table */
+ int cookie; /* implementation specific cookie */
+ void * priv; /* private info */
+} Lattice_desc; /* end, typedef Lattice_desc */
+
+/* Generic Lattice Functions */
+extern int lattice_load( Lattice_desc *desc, void *image, size_t size );
+extern int lattice_dump( Lattice_desc *desc, void *buf, size_t bsize );
+extern int lattice_info( Lattice_desc *desc );
+extern int lattice_reloc( Lattice_desc *desc, ulong reloc_offset );
+
+/* Board specific implementation specific function types */
+
+#define LATTICE_JTAG_TDI 0
+#define LATTICE_JTAG_TCK 1
+#define LATTICE_JTAG_TMS 2
+#define LATTICE_JTAG_TDO 3
+#define LATTICE_JTAG_CE 4
+#define LATTICE_JTAG_RST 5
+
+typedef int (*Lattice_pre_fn)( int cookie );
+typedef int (*Lattice_post_fn)( int cookie, int success);
+
+typedef void (*Lattice_jtag_write_port_fn)(int cookie, unsigned int pin,
+ unsigned int value);
+typedef int (*Lattice_jtag_read_port_fn)(int cookie);
+
+#endif /* _LATTICE_H_ */
diff --git a/include/lattice_ec.h b/include/lattice_ec.h
new file mode 100644
index 0000000..f92a87c
--- /dev/null
+++ b/include/lattice_ec.h
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on include/spartan2.h
+ * (C) Copyright 2002
+ * by Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _EC_H_
+#define _EC_H_
+
+#include <lattice.h>
+#include <lattice_ivm_core.h>
+
+struct Lattice_EC_private {
+ unsigned char *fpga_prog_base;
+ unsigned char *fpga_prog_end;
+ unsigned char *fpga_prog_next;
+ int fpga_steps_reset;
+ int fpga_steps;
+ int fpga_spin;
+ struct ispvm_desc d;
+};
+
+extern int EC_load(Lattice_desc *desc, void *image, size_t size);
+extern int EC_dump(Lattice_desc *desc, void *buf, size_t bsize);
+extern int EC_info(Lattice_desc *desc);
+extern int EC_reloc(Lattice_desc *desc, ulong reloc_off);
+
+/* JTAG Implementation function table */
+typedef struct {
+ Lattice_pre_fn pre;
+ Lattice_post_fn post;
+ Lattice_jtag_write_port_fn jtag_write_port;
+ Lattice_jtag_read_port_fn jtag_read_port;
+ int relocated;
+} Lattice_EC_JTAG_fns;
+
+/* Device Image Sizes
+ *********************************************************************/
+/* Lattice EC (1.8V) */
+#define LATTICE_LFEC1_SIZE 6144/8
+#define LATTICE_LFEC3_SIZE 12288/8
+#define LATTICE_LFEC6_SIZE 25600/8
+
+/* Descriptor Macros
+ *********************************************************************/
+/* CE devices */
+#define LATTICE_LFEC1_DESC(iface, fn_table, cookie) \
+{ Lattice_CE, iface, LATTICE_LFEC1_SIZE, fn_table, cookie }
+
+#define LATTICE_LFEC3_DESC(iface, fn_table, cookie) \
+{ Lattice_CE, iface, LATTICE_LFEC3_SIZE, fn_table, cookie }
+
+#define LATTICE_LFEC6_DESC(iface, fn_table, cookie) \
+{ Lattice_CE, iface, LATTICE_LFEC6_SIZE, fn_table, cookie }
+
+/* API to the IVM */
+/*********************************************************************/
+
+extern int lattice_ec_next_byte(void *cookie);
+extern int lattice_ec_read_port(void *cookie);
+extern void lattice_ec_write_port(void *cookie, int pin, int value);
+
+#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 3/8] Support LATTICE FPGA parts using JTAG programming. JTAG core.
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
2006-12-02 22:15 ` [U-Boot-Users] [PATCH 2/8] Support LATTICE FPGA parts using JTAG programming. Interface to FPGA API Pantelis Antoniou
@ 2006-12-02 22:16 ` Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 4/8] Support LATTICE FPGA parts using JTAG programming. Support functions Pantelis Antoniou
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:16 UTC (permalink / raw)
To: u-boot
Add support for Lattice FPGA parts programmed using JTAG.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
common/lattice_ivm_core.c | 750 ++++++++++++++++++++++++++++++++++++++++++++
include/lattice_ivm_core.h | 214 +++++++++++++
include/lattice_vmopcode.h | 286 +++++++++++++++++
3 files changed, 1250 insertions(+), 0 deletions(-)
diff --git a/common/lattice_ivm_core.c b/common/lattice_ivm_core.c
new file mode 100644
index 0000000..419b269
--- /dev/null
+++ b/common/lattice_ivm_core.c
@@ -0,0 +1,750 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on redboot's lattice_ivm_core.c
+ *
+ * This file was based on ASP8347DB's redboot sources
+ * with the same name. The file was not carrying any copyright
+ * markings while RedBoot is clearly GPL licensed.
+
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <lattice.h>
+#include <lattice_ec.h>
+
+#include <lattice_ivm_core.h>
+#include <lattice_vmopcode.h>
+
+#if (CONFIG_FPGA & CFG_FPGA_LATTICE)
+
+/* Enable/Disable debug console messages */
+#ifdef FPGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * Reset all global variables to a known state, as this code may be
+ * reused (but not reloaded)
+ */
+void ispvm_reset(struct ispvm_desc *d, void *input_cookie)
+{
+ d->cookie = input_cookie;
+
+ d->flow_control = 0x0000;
+ d->data_type = 0x0000;
+ d->end_DR = DRPAUSE;
+ d->end_IR = IRPAUSE;
+ d->head_DR = 0;
+ d->head_IR = 0;
+ d->tail_DR = 0;
+ d->tail_IR = 0;
+ d->data_size = 0;
+ d->frequency = 1000;
+ d->max_size = 0;
+ d->shift_value = 0;
+ d->repeat_loops = 0;
+ d->vendor = LATTICE;
+ d->current_jtag_state = 0;
+ d->heap_memory = NULL;
+ d->heap_counter = 0;
+ d->intel_data_idx = 0;
+ d->intel_buffer_size = 0;
+ d->TDO_size = 0;
+ d->MASK_size = 0;
+ d->TDI_size = 0;
+ d->DMASK_size = 0;
+ d->LCOUNT_size = 0;
+ d->HDR_size = 0;
+ d->TDR_size = 0;
+ d->HIR_size = 0;
+ d->TIR_size = 0;
+ d->HEAP_size = 0;
+
+ if (d->out_MASK_data)
+ free(d->out_MASK_data);
+ if (d->in_TDI_data)
+ free(d->in_TDI_data);
+ if (d->out_TDO_data)
+ free(d->out_TDO_data);
+ if (d->HIR_data)
+ free(d->HIR_data);
+ if (d->TIR_data)
+ free(d->TIR_data);
+ if (d->HDR_data)
+ free(d->HDR_data);
+ if (d->TDR_data)
+ free(d->TDR_data);
+ if (d->intel_buffer)
+ free(d->intel_buffer);
+ if (d->out_DMASK_data)
+ free(d->out_DMASK_data);
+ if (d->LVDS_list)
+ free(d->LVDS_list);
+
+ d->out_MASK_data = NULL;
+ d->in_TDI_data = NULL;
+ d->out_TDO_data = NULL;
+ d->HIR_data = NULL;
+ d->TIR_data = NULL;
+ d->HDR_data = NULL;
+ d->TDR_data = NULL;
+ d->intel_buffer = NULL;
+ d->out_DMASK_data = NULL;
+ d->LVDS_list = NULL;
+
+ d->out_MASK_data_size = 0;
+ d->in_TDI_data_size = 0;
+ d->out_TDO_data_size = 0;
+ d->HIR_data_size = 0;
+ d->TIR_data_size = 0;
+ d->HDR_data_size = 0;
+ d->TDR_data_size = 0;
+ d->intel_buffer_alloc_size = 0;
+ d->out_DMASK_data_size = 0;
+ d->LVDS_list_size = 0;
+
+ d->LVDS_pair_count = 0;
+}
+
+/* Enable the port to the device and set the state to RESET (TLR). */
+void ispvm_start(struct ispvm_desc *d)
+{
+ /* turn the Lattice Cable on */
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_CE, 1);
+ /* step devices to RESET state */
+ ispvm_state_machine(d, RESET);
+}
+
+/*
+ * Set the state of devices to RESET to enable the devices and disable
+ * the port.
+ */
+void ispvm_end(struct ispvm_desc *d)
+{
+ /* step devices to RESET state */
+ ispvm_state_machine(d, RESET);
+ /* wake up devices */
+ udelay(1000);
+ /* disable the Lattice Cable */
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_CE, 0);
+}
+
+/* Calculate the 32-bit CRC. */
+u16 ispvm_crc(struct ispvm_desc *d, u8 data, u16 ccrc)
+{
+ int i;
+ u8 fdata = 0;
+ u16 crce;
+ static const u16 crc_table[16] = {
+ 0x0000, 0xCC01, 0xD801, 0x1400,
+ 0xF001, 0x3C00, 0x2800, 0xE401,
+ 0xA001, 0x6C00, 0x7800, 0xB401,
+ 0x5000, 0x9C01, 0x8801, 0x4400
+ };
+
+ for (i = 0; i < 8; i++) {
+ fdata <<= 1;
+ if (data & 0x01)
+ fdata |= 0x01;
+ data >>= 1;
+ }
+
+ crce = crc_table[ccrc & 0xF];
+ ccrc = (ccrc >> 4) & 0x0FFF;
+ ccrc = ccrc ^ crce ^ crc_table[fdata & 0xF];
+ crce = crc_table[ccrc & 0xF];
+ ccrc = (ccrc >> 4) & 0x0FFF;
+ ccrc = ccrc ^ crce ^ crc_table[(fdata >> 4) & 0xF];
+
+ return ccrc;
+}
+
+int ispvm_validate_version(struct ispvm_desc *d, const char *version)
+{
+ static const char *vertab[] = {
+ "__VME2.0",
+ "__VME3.0",
+ "____12.0",
+ NULL
+ };
+ int i, j, ret;
+
+ ret = 0;
+ for (i = 0; vertab[i] != NULL; i++) {
+ for (j = 0; j < 8; j++) {
+ if (version[j] != vertab[i][j]) {
+ ret = VME_VERSION_FAILURE;
+ break;
+ }
+ ret = 0;
+ }
+
+ if (ret == 0)
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Returns a byte to the caller. The returned byte depends on the
+ * d->data_type 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.
+ */
+int ispvm_get(struct ispvm_desc *d)
+{
+ if (d->data_type & HEAP_IN) {
+ if (d->heap_counter > d->heap_repeat_size)
+ return -1;
+ return d->heap_memory[d->heap_counter++];
+ }
+
+ if (d->data_type & LHEAP_IN) {
+ if (d->intel_data_idx > d->intel_buffer_size)
+ return -1;
+ return d->intel_buffer[d->intel_buffer_size++];
+ }
+
+ /* get next byte from buffer */
+ return lattice_ec_next_byte(d->cookie);
+}
+
+/*
+ * Allocate memory based on target. The memory size is specified
+ * by size.
+ */
+int ispvm_alloc(struct ispvm_desc *d, int target, int size)
+{
+ switch (target) {
+ case XTDI:
+ case TDI:
+ if (d->in_TDI_data != NULL && d->in_TDI_data_size <= size)
+ break;
+
+ if (d->in_TDI_data != NULL) {
+ free(d->in_TDI_data);
+ d->in_TDI_data = NULL;
+ d->in_TDI_data_size = 0;
+ }
+ d->in_TDI_data = malloc(size / 8 + 2);
+ if (d->in_TDI_data != NULL)
+ d->in_TDI_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case XTDO:
+ case TDO:
+ if (d->out_TDO_data != NULL && d->out_TDO_data_size <= size)
+ break;
+
+ if (d->out_TDO_data != NULL) {
+ free(d->out_TDO_data);
+ d->out_TDO_data = NULL;
+ d->out_TDO_data_size = 0;
+ }
+ d->out_TDO_data = malloc(size / 8 + 2);
+ if (d->out_TDO_data != NULL)
+ d->out_TDO_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case MASK:
+ if (d->out_MASK_data != NULL && d->out_MASK_data_size <= size)
+ break;
+
+ if (d->out_MASK_data != NULL) {
+ free(d->out_MASK_data);
+ d->out_MASK_data = NULL;
+ d->out_MASK_data_size = 0;
+ }
+ d->out_MASK_data = malloc(size / 8 + 2);
+ if (d->out_MASK_data != NULL)
+ d->out_MASK_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case HIR:
+ if (d->HIR_data != NULL && d->HIR_data_size <= size)
+ break;
+
+ if (d->HIR_data != NULL) {
+ free(d->HIR_data);
+ d->HIR_data = NULL;
+ d->HIR_data_size = 0;
+ }
+ d->HIR_data = malloc(size / 8 + 2);
+ if (d->HIR_data != NULL)
+ d->HIR_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case TIR:
+ if (d->TIR_data != NULL && d->TIR_data_size <= size)
+ break;
+
+ if (d->TIR_data != NULL) {
+ free(d->TIR_data);
+ d->TIR_data = NULL;
+ d->TIR_data_size = 0;
+ }
+ d->TIR_data = malloc(size / 8 + 2);
+ if (d->TIR_data != NULL)
+ d->TIR_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case HDR:
+ if (d->HDR_data != NULL && d->HDR_data_size <= size)
+ break;
+
+ if (d->HDR_data != NULL) {
+ free(d->HDR_data);
+ d->HDR_data = NULL;
+ d->HDR_data_size = 0;
+ }
+ d->HDR_data = malloc(size / 8 + 2);
+ if (d->HDR_data != NULL)
+ d->HDR_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case TDR:
+ if (d->TDR_data != NULL && d->TDR_data_size <= size)
+ break;
+
+ if (d->TDR_data != NULL) {
+ free(d->TDR_data);
+ d->TDR_data = NULL;
+ d->TDR_data_size = 0;
+ }
+ d->TDR_data = malloc(size / 8 + 2);
+ if (d->TDR_data != NULL)
+ d->TDR_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case HEAP:
+ if (d->heap_memory != NULL && d->heap_memory_size <= size)
+ break;
+
+ if (d->heap_memory != NULL) {
+ free(d->heap_memory);
+ d->heap_memory = NULL;
+ d->heap_memory_size = 0;
+ }
+ d->heap_memory = malloc(size + 2);
+ if (d->heap_memory != NULL)
+ d->heap_memory_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case DMASK:
+ if (d->out_DMASK_data != NULL && d->out_DMASK_data_size <= size)
+ break;
+
+ if (d->out_DMASK_data != NULL) {
+ free(d->out_DMASK_data);
+ d->out_DMASK_data = NULL;
+ d->out_DMASK_data_size = 0;
+ }
+ d->out_DMASK_data = malloc(size / 8 + 2);
+ if (d->out_DMASK_data != NULL)
+ d->out_DMASK_data_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case LHEAP:
+ if (d->intel_buffer != NULL && d->intel_buffer_alloc_size <= size)
+ break;
+
+ if (d->intel_buffer != NULL) {
+ free(d->intel_buffer);
+ d->intel_buffer = NULL;
+ d->intel_buffer_alloc_size = 0;
+ }
+ d->intel_buffer = malloc(size + 2);
+ if (d->intel_buffer != NULL)
+ d->intel_buffer_alloc_size = size;
+ else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ case LVDS:
+ if (d->LVDS_list != NULL && d->LVDS_list_size <= size)
+ break;
+
+ if (d->LVDS_list != NULL) {
+ free(d->LVDS_list);
+ d->LVDS_list = NULL;
+ d->LVDS_list_size = 0;
+ }
+ d->LVDS_list = malloc(size * sizeof(LVDSPair));
+ if (d->LVDS_list != NULL) {
+ memset(d->LVDS_list, 0, size * sizeof(LVDSPair));
+ d->LVDS_list_size = size;
+ } else
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * This is the heart of the embedded engine. All the high-level opcodes
+ * are extracted here. Once they have been identified, then it
+ * will call other functions to handle the processing.
+ */
+int ispvm_code(struct ispvm_desc *d)
+{
+ int i, j, state, opcode;
+ int ret = 0;
+
+ /*
+ * Check the compression flag only if this is the first time
+ * this function is entered. Do not check the compression flag if
+ * it is being called recursively from other functions within
+ * the embedded engine.
+ */
+ if (!(d->data_type & LHEAP_IN) && !(d->data_type & HEAP_IN)) {
+ ret = ispvm_get(d);
+ if (ret == -1)
+ return VME_INVALID_FILE;
+ if (ret == 0xf1)
+ d->data_type |= COMPRESS;
+ else if (ret == 0xf2)
+ d->data_type &= ~COMPRESS;
+ else
+ return VME_INVALID_FILE;
+ }
+
+ /* Begin looping through all the VME opcodes. */
+ while ((opcode = ispvm_get(d)) >= 0) {
+
+ switch (opcode) {
+
+ /* Step the JTAG state machine. */
+ case STATE:
+ PRINTF("STATE:\n");
+ state = ispvm_get(d);
+ if (state == -1)
+ return VME_INVALID_FILE;
+ ispvm_state_machine(d, state);
+ break;
+
+ /* Shift in data into the device. */
+ case SIR:
+ PRINTF("SIR:\n");
+
+ ret = ispvm_shift(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ case SDR:
+ PRINTF("SDR:\n");
+ ret = ispvm_shift(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ case XSDR:
+ PRINTF("XSDR:\n");
+ ret = ispvm_shift(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ /* perform delay */
+ case WAIT:
+ PRINTF("WAIT:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ if (j & 0x8000) {
+ i = j & ~0x8000;
+ while (i-- > 0)
+ udelay(1000);
+ } else
+ udelay(j);
+ break;
+
+ /* Issue clock toggles. */
+ case TCK:
+ PRINTF("TCK:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ for (i = 0; i < j; i++)
+ ispvm_clock(d);
+ break;
+
+ /* Set the ENDDR. */
+ case ENDDR:
+ PRINTF("ENDDR:\n");
+ d->end_DR = ispvm_get(d);
+ break;
+
+ /* Set the ENDIR. */
+ case ENDIR:
+ PRINTF("ENDIR:\n");
+ d->end_IR = ispvm_get(d);
+ break;
+
+ /*
+ * Set the header/trailer of the device in order to
+ * bypass successfully.
+ */
+ case HIR:
+ PRINTF("HIR:\n");
+ ret = ispvm_amble(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ case TIR:
+ PRINTF("TIR:\n");
+ ret = ispvm_amble(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ case HDR:
+ PRINTF("HDR:\n");
+ ret = ispvm_amble(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ case TDR:
+ PRINTF("TDR:\n");
+ ret = ispvm_amble(d, opcode);
+ if (ret != 0)
+ return ret;
+ break;
+
+ /*
+ * The maximum RAM required to support processing
+ * one row of the VME file.
+ */
+ case MEM:
+ PRINTF("MEM:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->max_size = j;
+ break;
+
+ /* Set the VENDOR type. */
+ case VENDOR:
+ PRINTF("VENDOR:\n");
+ opcode = ispvm_get(d);
+ switch (opcode) {
+ case LATTICE:
+ d->vendor = LATTICE;
+ break;
+ case ALTERA:
+ d->vendor = ALTERA;
+ break;
+ case XILINX:
+ d->vendor = XILINX;
+ break;
+ default:
+ return VME_INVALID_FILE;
+ }
+ break;
+
+ /*
+ * Set the flow control. Flow control determines the
+ * personality of the embedded engine.
+ */
+ case SETFLOW:
+ PRINTF("SETFLOW:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->flow_control |= j & 0xffff;
+ break;
+
+ /* Unset the flow control. */
+ case RESETFLOW:
+ PRINTF("RESETFLOW:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->flow_control &= ~j & 0xffff;
+ break;
+
+ /* Allocate heap size to store loops. */
+ case HEAP:
+ PRINTF("HEAP:\n");
+ ret = ispvm_get(d);
+ if (ret != SECUREHEAP)
+ return VME_INVALID_FILE;
+
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->heap_repeat_size = j;
+
+ /*
+ * Store the maximum size of the HEAP buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->heap_repeat_size > d->HEAP_size)
+ d->HEAP_size = d->heap_repeat_size;
+
+ j = ispvm_alloc(d, HEAP, d->heap_repeat_size);
+ if (j != 0)
+ return VME_OUT_OF_MEMORY;
+ break;
+
+ /* Execute loops. */
+ case REPEAT:
+ PRINTF("REPEAT:\n");
+ d->repeat_loops = 0;
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ ret = ispvm_loop(d, j);
+ if (ret != 0)
+ return ret;
+ break;
+
+ /* Exit point from processing loops. */
+ case ENDLOOP:
+ PRINTF("ENDLOOP:\n");
+ return ret;
+
+ /*
+ * The only valid exit point that indicates end
+ * of programming.
+ */
+ case ENDVME:
+ PRINTF("ENDVME:\n");
+ return ret;
+
+ /* Right-shift address. */
+ case SHR:
+ PRINTF("SHR:\n");
+ d->flow_control |= SHIFTRIGHT;
+ d->shift_value = d->repeat_loops * ispvm_get(d);
+ break;
+
+ /* Left-shift address. */
+ case SHL:
+ PRINTF("SHL:\n");
+ d->flow_control |= SHIFTLEFT;
+ d->shift_value = d->repeat_loops * ispvm_get(d);
+ break;
+
+ /* Set the d->frequency. */
+ case FREQUENCY:
+ PRINTF("FREQUENCY:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->frequency = j / 1000;
+ break;
+
+ /* Process LCOUNT command. */
+ case LCOUNT:
+ PRINTF("LCOUNT:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ ret = ispvm_lcount(d, j);
+ if (ret != 0)
+ return ret;
+ break;
+
+ /* Set the flow control to verify USERCODE. */
+ case VUES:
+ PRINTF("VUES:\n");
+ d->flow_control |= VERIFYUES;
+ break;
+
+ /* Display comment. */
+ case COMMENT:
+ PRINTF("COMMENT:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ j = ispvm_comment(d, j);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ break;
+
+ /* Process LVDS command. */
+ case LVDS:
+ PRINTF("LVDS:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ j = ispvm_process_lvds(d, j);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ break;
+
+ /* Discard header. */
+ case HEADER:
+ PRINTF("HEADER:\n");
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ j = ispvm_header(d, j);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ break;
+
+ /* Invalid opcode encountered. */
+ default:
+ return VME_INVALID_FILE;
+ }
+ }
+
+ /*
+ * Invalid exit point. Processing the token 'ENDVME' is the only
+ * valid way to exit the embedded engine.
+ */
+ return VME_INVALID_FILE;
+}
+
+#endif
diff --git a/include/lattice_ivm_core.h b/include/lattice_ivm_core.h
new file mode 100644
index 0000000..1c939c7
--- /dev/null
+++ b/include/lattice_ivm_core.h
@@ -0,0 +1,214 @@
+/*
+ * (C) Copyright 2006
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * This file was based on ASP8347DB's redboot sources
+ * with the same name. The file was not carrying any copyright
+ * markings while RedBoot is clearly GPL licensed.
+
+ * lattice_ivm_core definitions
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef LATTICE_IVM_CORE_H
+#define LATTICE_IVM_CORE_H
+
+#include <asm/types.h>
+
+/* Type definitions */
+
+/* Support LVDS */
+typedef struct {
+ u16 positive_idx;
+ u16 negative_idx;
+ int update;
+} LVDSPair;
+
+/* the state of the program engine */
+struct ispvm_desc {
+
+ /* upper layer cookie */
+ void *cookie;
+
+ /*
+ * Flow control register.
+ * Each bit in the register can potentially change the
+ * personality of the embedded engine.
+ */
+ u16 flow_control;
+
+ /* holds the data type of the current row */
+ u16 data_type;
+
+ /* the state that the device goes to after SDR */
+ u8 end_DR;
+
+ /* the state that the device goes to after SIR */
+ u8 end_IR;
+
+ /* number of lead devices in bypass */
+ u16 head_DR;
+
+ /* sum of IR length of lead devices */
+ u16 head_IR;
+
+ /* number of tail devices in bypass */
+ u16 tail_DR;
+
+ /* sum of IR length of tail devices */
+ u16 tail_IR;
+
+ /* Number of bits of data or instruction
+ * to be shifted into or out from the device
+ */
+ u16 data_size;
+
+ /* Stores the frequency. Default to 1 MHz. */
+ int frequency;
+
+ /*
+ * Stores the maximum amount of ram needed to hold a
+ * row of data.
+ */
+ u16 max_size;
+
+ /* Stores the LSH or RSH value. */
+ u16 shift_value;
+
+ /* Stores the current repeat loop value. */
+ u16 repeat_loops;
+
+ /* Stores the current vendor. */
+ int vendor;
+
+ /* Stores the current state of the JTAG state machine. */
+ int current_jtag_state;
+
+ /* holds the entire repeat loop */
+ u8 *heap_memory;
+
+ /* holds the entire repeat loop allocated size */
+ int heap_memory_size;
+
+ /* points to the current byte in the repeat loop */
+ u16 heap_counter;
+
+ /* current size of the repeat in bytes */
+ u16 heap_repeat_size;
+
+ /* points to the current byte of the intelligent buffer */
+ u16 intel_data_idx;
+
+ /* holds the size of the intelligent buffer */
+ u16 intel_buffer_size;
+
+ /*
+ *
+ * Holds the maximum size of each respective buffer.
+ * These variables are used to write the HEX files when
+ * converting VME to HEX.
+ */
+ u16 TDO_size;
+ u16 MASK_size;
+ u16 TDI_size;
+ u16 DMASK_size;
+ u16 LCOUNT_size;
+ u16 HDR_size;
+ u16 TDR_size;
+ u16 HIR_size;
+ u16 TIR_size;
+ u16 HEAP_size;
+
+ /* one row of MASK data */
+ u8 *out_MASK_data;
+ unsigned int out_MASK_data_size;
+
+ /* one row of TDI data */
+ u8 *in_TDI_data;
+ unsigned int in_TDI_data_size;
+
+ /* one row of TDO data */
+ u8 *out_TDO_data;
+ unsigned int out_TDO_data_size;
+
+ /* current SIR header */
+ u8 *HIR_data;
+ unsigned int HIR_data_size;
+
+ /* current SIR trailer */
+ u8 *TIR_data;
+ unsigned int TIR_data_size;
+
+ /* current SDR header */
+ u8 *HDR_data;
+ unsigned int HDR_data_size;
+
+ /* current SDR trailer */
+ u8 *TDR_data;
+ unsigned int TDR_data_size;
+
+ /* current intelligent buffer */
+ u8 *intel_buffer;
+ unsigned int intel_buffer_alloc_size;
+
+ /* one row of DMASK data */
+ u8 *out_DMASK_data;
+ unsigned int out_DMASK_data_size;
+
+ /* List to hold all LVDS pairs. */
+ LVDSPair *LVDS_list;
+ unsigned int LVDS_list_size;
+ u16 LVDS_pair_count;
+};
+
+/* interface function prototypes */
+void ispvm_reset(struct ispvm_desc *d, void *cookie);
+void ispvm_start(struct ispvm_desc *d);
+void ispvm_end(struct ispvm_desc *d);
+u16 ispvm_crc(struct ispvm_desc *d, u8 data, u16 ccrc);
+int ispvm_validate_version(struct ispvm_desc *d, const char *version);
+int ispvm_code(struct ispvm_desc *d);
+
+/* internal function prototypes. */
+int ispvm_data_code(struct ispvm_desc *d);
+int ispvm_data_size(struct ispvm_desc *d);
+int ispvm_data(struct ispvm_desc *d, u8 *data);
+int ispvm_shift(struct ispvm_desc *d, int code);
+int ispvm_amble(struct ispvm_desc *d, int code);
+int ispvm_loop(struct ispvm_desc *d, int repeats);
+int ispvm_bit_shift(struct ispvm_desc *d, int mode, u16 bits);
+int ispvm_comment(struct ispvm_desc *d, int size);
+int ispvm_header(struct ispvm_desc *d, int size);
+int ispvm_lcount(struct ispvm_desc *d, int size);
+void ispvm_clock(struct ispvm_desc *d);
+void ispvm_bypass(struct ispvm_desc *d, int scan_type, u16 bits);
+void ispvm_state_machine(struct ispvm_desc *d, int next_state);
+int ispvm_send(struct ispvm_desc *d, u16 size);
+int ispvm_read(struct ispvm_desc *d, u16 size);
+int ispvm_read_and_save(struct ispvm_desc *d, u16 size);
+int ispvm_process_lvds(struct ispvm_desc *d, int count);
+
+/* lattice functions */
+int ispvm_get(struct ispvm_desc *d);
+int ispvm_alloc(struct ispvm_desc *d, int types, int size);
+
+
+#endif
diff --git a/include/lattice_vmopcode.h b/include/lattice_vmopcode.h
new file mode 100644
index 0000000..b9c8646
--- /dev/null
+++ b/include/lattice_vmopcode.h
@@ -0,0 +1,286 @@
+/*
+ * (C) Copyright 2006
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * lattice_ivm_core definitions
+ *
+ * This file was based on ASP8347DB's redboot sources
+ * with the same name. The file was not carrying any copyright
+ * markings while RedBoot is clearly GPL licensed.
+
+ * This is the include file for Lattice Semiconductor's ispVM
+ * Embedded software application.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef LATTICE_VMOPCODE_H
+#define LATTICE_VMOPCODE_H
+
+/* VME version. */
+#define VME_VERSION_NUMBER "12.0"
+
+#define VMEHEXMAX 60000L /* The hex file is split 60K per file . */
+#define SCANMAX 64000L /* The maximum SDR/SIR burst . */
+
+/* Supported JTAG state transitions. */
+
+#define RESET 0x00
+#define IDLE 0x01
+#define IRPAUSE 0x02
+#define DRPAUSE 0x03
+#define SHIFTIR 0x04
+#define SHIFTDR 0x05
+/* 11/15/05 Nguyen changed to support DRCAPTURE*/
+#define DRCAPTURE 0x06
+
+/*
+ * Flow control register bit definitions. A set bit indicates
+ * that the register currently exhibits the corresponding mode.
+ */
+
+#define INTEL_PRGM 0x0001 /* Intelligent programming is in effect */
+#define CASCADE 0x0002 /* Currently splitting large SDR */
+#define REPEATLOOP 0x0008 /* Currently executing a repeat loop */
+#define SHIFTRIGHT 0x0080 /* The next data stream needs a right shift */
+#define SHIFTLEFT 0x0100 /* The next data stream needs a left shift */
+#define VERIFYUES 0x0200 /* Continue if fail is in effect */
+
+/*
+ * DataType register bit definitions. A set bit indicates
+ * that the register currently holds the corresponding type of data.
+ */
+
+#define EXPRESS 0x0001 /* Simultaneous program and verify */
+#define SIR_DATA 0x0002 /* SIR is the active SVF command */
+#define SDR_DATA 0x0004 /* SDR is the active SVF command */
+#define COMPRESS 0x0008 /* Data is compressed */
+#define TDI_DATA 0x0010 /* TDI data is present */
+#define TDO_DATA 0x0020 /* TDO data is present */
+#define MASK_DATA 0x0040 /* MASK data is present */
+#define HEAP_IN 0x0080 /* Data is from the heap */
+#define LHEAP_IN 0x0200 /* Data is from intel data buffer */
+#define VARIABLE 0x0400 /* Data is from a declared variable */
+#define CRC_DATA 0x0800 /* CRC data is pressent */
+#define CMASK_DATA 0x1000 /* CMASK data is pressent */
+#define RMASK_DATA 0x2000 /* RMASK data is pressent */
+#define READ_DATA 0x4000 /* READ data is pressent */
+#define DMASK_DATA 0x8000 /* DMASK data is pressent */
+
+/* Pin opcodes */
+#define signalENABLE 0x1C /* ispENABLE */
+#define signalTMS 0x1D /* TMS */
+#define signalTCK 0x1E /* TCK */
+#define signalTDI 0x1F /* TDI */
+#define signalTRST 0x2 /* TRST */
+
+/* Supported vendors. */
+#define VENDOR 0x56
+#define LATTICE 0x01
+#define ALTERA 0x02
+#define XILINX 0x03
+
+/* Opcode definitions */
+
+/* The end of the current SDR data stream. */
+#define ENDDATA 0x00
+
+/* The duration to stay at the stable state. */
+#define RUNTEST 0x01
+
+/* The stable state after SDR. */
+#define ENDDR 0x02
+
+/* The stable state after SIR. */
+#define ENDIR 0x03
+
+/* The stable state after RUNTEST. */
+#define ENDSTATE 0x04
+
+/* Assert the TRST pin. */
+#define TRST 0x05
+
+/* The sum of the IR bits of the leading devices. */
+#define HIR 0x06
+
+/* The sum of the IR bits of the trailing devices. */
+#define TIR 0x07
+
+/* The number of leading devices. */
+#define HDR 0x08
+
+/* The number of trailing devices. */
+#define TDR 0x09
+
+/* Assert the ispEN pin. */
+#define ispEN 0x0A
+
+/* The maximum clock rate to run the JTAG state machine. */
+#define FREQUENCY 0x0B
+
+/* Move to the next stable state. */
+#define STATE 0x10
+
+/* The instruction stream follows. */
+#define SIR 0x11
+
+/* The data stream follows. */
+#define SDR 0x12
+
+/* The following data stream feeds into the device. */
+#define TDI 0x13
+
+/* The following data stream is compared against the device. */
+#define TDO 0x14
+
+/* The following data stream is used as mask. */
+#define MASK 0x15
+
+/* The following data stream is for simultaneous program and verify. */
+#define XSDR 0x16
+
+/*
+ * The following data stream is for shift in only.
+ * It must be stored for the next XSDR.
+ */
+#define XTDI 0x17
+
+/*
+ * is not data stream.
+ * The data stream was stored from the previous XTDI.
+ */
+#define XTDO 0x18
+
+/* The maximum memory needed to allocate in order hold one row of data */
+#define MEM 0x19
+
+/* The duration of delay to observe. */
+#define WAIT 0x1A
+
+/* The number of TCK pulses. */
+#define TCK 0x1B
+
+/* Set the flow control register for right shift. */
+#define SHR 0x23
+
+/* Set the flow control register for left shift. */
+#define SHL 0x24
+
+/* The memory size needed to hold one loop. */
+#define HEAP 0x32
+
+/* The beginning of the loop. */
+#define REPEAT 0x33
+
+/* The beginning of data following the loop. */
+#define LEFTPAREN 0x35
+
+/* Plac holder for loop data. */
+#define VAR 0x55
+
+/* The delay time in seconds that must be observed. */
+#define SEC 0x1C
+
+/* The mask for TDI data. */
+#define SMASK 0x1D
+
+/* The absolute maximum wait time. */
+#define MAX 0x1E
+
+/* Assert the targeted pin. */
+#define ON 0x1F
+
+/* Dis-assert the targeted pin. */
+#define OFF 0x20
+
+/* Change the flow control register. */
+#define SETFLOW 0x30
+
+/* Clear the flow control register. */
+#define RESETFLOW 0x31
+
+/* The following data stream is used for CRC calculation. */
+#define CRC 0x47
+
+/* The following data stream is used as mask for CRC calculation. */
+#define CMASK 0x48
+
+/* The following data stream is used as mask for read and save. */
+#define RMASK 0x49
+
+/* The following data stream is used for read and save. */
+#define READ 0x50
+
+/* The end of the repeat loop. */
+#define ENDLOOP 0x59
+
+/* Used to secure the HEAP opcode. */
+#define SECUREHEAP 0x60
+
+/* Support continue if fail. */
+#define VUES 0x61
+
+/* The following data stream is used for dynamic I/O. */
+#define DMASK 0x62
+
+/* Support SVF comments in the VME file. */
+#define COMMENT 0x63
+
+/* Support header in VME file. */
+#define HEADER 0x64
+
+/* Support crc-protected VME file. */
+#define FILE_CRC 0x65
+
+/* Support intelligent programming. */
+#define LCOUNT 0x66
+
+/* Support intelligent programming. */
+#define LDELAY 0x67
+
+/* Support intelligent programming. */
+#define LSDR 0x68
+
+/* Memory needed to hold intelligent data buffer */
+#define LHEAP 0x69
+
+/* Allow continuation. */
+#define CONTINUE 0x70
+
+/* Support LVDS. */
+#define LVDS 0x71
+
+/* End of the VME file. */
+#define ENDVME 0x7F
+
+/* End of file. */
+#define ENDFILE 0xFF
+
+/* ispVM Embedded Return Codes */
+#define VME_OK 0
+#define VME_VERIFICATION_FAILURE -1
+#define VME_FILE_READ_FAILURE -2
+#define VME_VERSION_FAILURE -3
+#define VME_INVALID_FILE -4
+#define VME_ARGUMENT_FAILURE -5
+#define VME_CRC_FAILURE -6
+#define VME_OUT_OF_MEMORY -7
+
+#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 4/8] Support LATTICE FPGA parts using JTAG programming. Support functions.
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
2006-12-02 22:15 ` [U-Boot-Users] [PATCH 2/8] Support LATTICE FPGA parts using JTAG programming. Interface to FPGA API Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 3/8] Support LATTICE FPGA parts using JTAG programming. JTAG core Pantelis Antoniou
@ 2006-12-02 22:16 ` Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 5/8] Adds support for RedBoot Pantelis Antoniou
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:16 UTC (permalink / raw)
To: u-boot
Add support for Lattice FPGA parts programmed using JTAG.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
common/lattice_ivm_supp.c | 1426 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1426 insertions(+), 0 deletions(-)
diff --git a/common/lattice_ivm_supp.c b/common/lattice_ivm_supp.c
new file mode 100644
index 0000000..797dff1
--- /dev/null
+++ b/common/lattice_ivm_supp.c
@@ -0,0 +1,1426 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on redboot's lattice_ivm_core.c
+ *
+ * This file was based on ASP8347DB's redboot sources
+ * with the same name. The file was not carrying any copyright
+ * markings while RedBoot is clearly GPL licensed.
+
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <lattice.h>
+#include <lattice_ec.h>
+
+#include <lattice_ivm_core.h>
+#include <lattice_vmopcode.h>
+
+#if (CONFIG_FPGA & CFG_FPGA_LATTICE)
+
+/* Enable/Disable debug console messages */
+#ifdef FPGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * Returns a VME-encoded number, usually used to indicate the
+ * bit length of an SIR/SDR command.
+ */
+int ispvm_data_size(struct ispvm_desc *d)
+{
+ int i, j, val;
+
+ i = j = 0;
+ while ((val = ispvm_get(d)) != -1 && (val & 0x80)) {
+ j |= (val & 0x7F) << i;
+ i += 7;
+ }
+ if (val == -1)
+ return -1;
+ j |= (val & 0x7F) << i;
+ return j;
+}
+
+/* Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command. */
+int ispvm_data_code(struct ispvm_desc *d)
+{
+ int ret, data;
+ int data_source = 0; /* source file by default */
+
+ if (d->data_type & HEAP_IN)
+ data_source = 1; /* source from memory */
+
+ /* Clear the data type register. */
+ d->data_type &= ~(MASK_DATA + TDI_DATA + TDO_DATA + DMASK_DATA);
+
+ /*
+ * Iterate through SIR/SDR command and look
+ * for TDI, TDO, MASK, etc.
+ */
+ while ((data = ispvm_get(d)) >= 0) {
+
+ ret = ispvm_alloc(d, data, d->max_size);
+ if (ret != 0)
+ return VME_OUT_OF_MEMORY;
+
+ switch (data) {
+
+ case TDI:
+ /*
+ * Store the maximum size of the TDI buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->TDI_size)
+ d->TDI_size = d->data_size;
+
+ /*
+ * Updated data type register to indicate that TDI data
+ * is currently being used. Process the data in the VME
+ * file into the TDI buffer.
+ */
+ d->data_type |= TDI_DATA;
+ ret = ispvm_data(d, d->in_TDI_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ break;
+
+ case XTDO:
+ /*
+ * Store the maximum size of the TDO buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->TDO_size)
+ d->TDO_size = d->data_size;
+
+ /*
+ * Updated data type register to indicate that TDO data
+ * is currently being used.
+ */
+ d->data_type |= TDO_DATA;
+ break;
+
+ case TDO:
+ /*
+ * Store the maximum size of the TDO buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->TDO_size)
+ d->TDO_size = d->data_size;
+
+ /*
+ * Updated data type register to indicate that TDO data
+ * is currently being used. Process the data in the VME
+ * file into the TDO buffer.
+ */
+ d->data_type |= TDO_DATA;
+ ret = ispvm_data(d, d->out_TDO_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ break;
+
+ case MASK:
+ /*
+ * Store the maximum size of the MASK buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->MASK_size)
+ d->MASK_size = d->data_size;
+
+ /*
+ * Updated data type register to indicate that MASK data
+ * is currently being used. Process the data in the VME
+ * file into the TDO buffer.
+ */
+ d->data_type |= MASK_DATA;
+ ret = ispvm_data(d, d->out_MASK_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ break;
+
+ case DMASK:
+ /*
+ * Store the maximum size of the DMASK buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->DMASK_size)
+ d->DMASK_size = d->data_size;
+
+ /*
+ * Updated data type register to indicate that DMASK
+ * data is currently being used. Process the data in
+ * the VME file into the TDO buffer.
+ */
+
+ d->data_type |= DMASK_DATA;
+ ret = ispvm_data(d, d->out_DMASK_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ break;
+
+ case CONTINUE:
+ return 0;
+
+ /* Encountered invalid opcode. */
+ default:
+ return VME_INVALID_FILE;
+ }
+
+ if (data == TDI) {
+ /*
+ * Left bit shift. Used when performing
+ * algorithm looping.
+ */
+ if (d->flow_control & SHIFTLEFT) {
+ ispvm_bit_shift(d, SHL, d->shift_value);
+ d->flow_control &= ~SHIFTLEFT;
+ }
+
+ /*
+ * Right bit shift. Used when performing
+ * algorithm looping.
+ */
+ if (d->flow_control & SHIFTRIGHT) {
+ ispvm_bit_shift(d, SHR, d->shift_value);
+ d->flow_control &= ~SHIFTRIGHT;
+ }
+ }
+
+ if (data_source)
+ d->data_type |= HEAP_IN; /* restore data from memory */
+ }
+
+ if (data_source) /* fetch data from heap memory upon return */
+ d->data_type |= HEAP_IN;
+
+ if (data < 0)
+ return VME_INVALID_FILE; /* invalid opcode */
+
+ return 0;
+}
+
+/*
+ * Extract one row of data operand from the current data type opcode. Perform
+ * the decompression if necessary. Extra RAM is not required for the
+ * decompression process. The decompression scheme employed in this module
+ * is on row by row basis. The format of the data stream:
+ * [compression code][compressed data stream]
+ * 0x00 --No compression
+ * 0x01 --Compress by 0x00.
+ * Example:
+ * Original stream: 0x000000000000000000000001
+ * Compressed stream: 0x01000901
+ * Detail: 0x01 is the code, 0x00 is the key,
+ * 0x09 is the count of 0x00 bytes,
+ * 0x01 is the uncompressed byte.
+ * 0x02 --Compress by 0xFF.
+ * Example:
+ * Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01
+ * Compressed stream: 0x02FF0901
+ * Detail: 0x02 is the code, 0xFF is the key,
+ * 0x09 is the count of 0xFF bytes,
+ * 0x01 is the uncompressed byte.
+ * 0x03
+ * : :
+ * 0xFE -- Compress by nibble blocks.
+ * Example:
+ * Original stream: 0x84210842108421084210
+ * Compressed stream: 0x0584210
+ * Detail: 0x05 is the code, means 5 nibbles block.
+ * 0x84210 is the 5 nibble blocks.
+ * The whole row is 80 bits given by d->data_size
+ * The number of times the block repeat itself
+ * is found by d->data_size/(4*0x05) which is 4.
+ * 0xFF -- Compress by the most frequently happen byte.
+ * Example:
+ * Original stream: 0x04020401030904040404
+ * Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0)
+ * or: 0xFF044090181C240
+ * Detail: 0xFF is the code, 0x04 is the key.
+ * a bit of 0 represent the key shall be put into
+ * the current bit position and a bit of 1
+ * represent copying the next of 8 bits of data
+ * in.
+ */
+
+int ispvm_data(struct ispvm_desc *d, u8 *ptr)
+{
+ int i, j, k, l, size, gotdata, FFcount, compress, data;
+ u8 compr_char, val;
+ int compression = 0;
+
+ gotdata = 0;
+ FFcount = 0;
+ compress = 0;
+ data = 0;
+ compr_char = 0xff;
+
+ /*convert number in bits to bytes */
+ if (d->data_size % 8 > 0)
+ size = d->data_size / 8 + 1;
+ else
+ size = d->data_size / 8;
+
+ /*
+ * If there is compression, then check if compress by
+ * key of 0x00 or 0xFF
+ * or by other keys or by nibble blocks
+ */
+ if (d->data_type & COMPRESS) {
+ compression = 1;
+
+ compress = ispvm_get(d);
+ if (compress == -1)
+ return VME_INVALID_FILE;
+
+ if (compress == VAR && (d->data_type & HEAP_IN)) {
+ gotdata = 1;
+ d->data_type &= ~HEAP_IN;
+ compress = ispvm_get(d);
+ if (compress == -1)
+ return VME_INVALID_FILE;
+ }
+
+ switch (compress) {
+
+ /* No compression */
+ case 0x00:
+ compression = 0;
+ break;
+
+ /* Compress by byte 0x00 */
+ case 0x01:
+ compr_char = 0x00;
+ break;
+
+ /* Compress by byte 0xFF */
+ case 0x02:
+ compr_char = 0xFF;
+ break;
+
+ /* Huffman encoding */
+ case 0xFF:
+ j = ispvm_get(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+
+ compr_char = j;
+
+ i = 8;
+ for (l = 0; l < size; l++) {
+ ptr[l] = 0x00;
+ if (i > 7) {
+ data = ispvm_get(d);
+ if (data == -1)
+ return VME_INVALID_FILE;
+ i = 0;
+ }
+ if ((data << i++) & 0x80) {
+ k = 8;
+ } else {
+ ptr[l] = compr_char;
+ k = 0;
+ }
+
+ for (j = 0; j < k; j++) {
+ if (i > 7) {
+ data = ispvm_get(d);
+ if (data == -1)
+ return VME_INVALID_FILE;
+ i = 0;
+ }
+ ptr[l] |= ((data << i++) & 0x80) >> j;
+ }
+ }
+ size = 0;
+ break;
+
+ default:
+ for (l = 0; l < size; l++)
+ ptr[l] = 0x00;
+
+ for (l = 0; l < compress; l++) {
+ if ((l % 2) == 0) {
+ data = ispvm_get(d);
+ if (data == -1)
+ return VME_INVALID_FILE;
+ }
+ for (i = 0; i < size * 2 / compress; i++) {
+ j = l + i * compress;
+ /* clear the nibble to zero first */
+ if (j % 2) {
+ if (l % 2)
+ val = data & 0x0F;
+ else
+ val = data >> 4;
+ } else {
+ if (l % 2)
+ val = data << 4;
+ else
+ val = data & 0xF0;
+ }
+
+ ptr[j / 2] |= val;
+ }
+ }
+ size = 0;
+ break;
+ }
+ }
+
+ FFcount = 0;
+
+ /* Decompress by byte 0x00 or 0xFF */
+ for (l = 0; l < size; l++) {
+ if (FFcount <= 0) {
+ data = ispvm_get(d);
+ if (data == -1)
+ return VME_INVALID_FILE;
+
+ if (data == VAR && (d->data_type & HEAP_IN) &&
+ !gotdata && !(d->data_type & COMPRESS)) {
+ gotdata = 1;
+ d->data_type &= ~HEAP_IN;
+ data = ispvm_get(d);
+ if (data == -1)
+ return VME_INVALID_FILE;
+ }
+ ptr[l] = data & 0xff;
+
+ /* decompression is on? set num. of 0xff/0x00 bytes */
+ if (compression && data == compr_char) {
+ FFcount = ispvm_data_size(d);
+ if (FFcount == -1)
+ return VME_INVALID_FILE;
+ }
+ } else {
+ FFcount--; /* Use up the 0xFF chain first */
+ ptr[l] = compr_char & 0xff;
+ }
+ }
+
+ if (gotdata) {
+ d->data_type |= HEAP_IN;
+ gotdata = 0;
+ }
+
+ return 0;
+}
+
+/* Processes the SDR/XSDR/SIR commands. */
+int ispvm_shift(struct ispvm_desc *d, int code)
+{
+ int i, j;
+ int ret;
+
+ ret = 0;
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+
+ d->data_size = j;
+
+ /* clear the flags first */
+ d->data_type &= ~(SIR_DATA + EXPRESS + SDR_DATA);
+
+ switch (code) {
+
+ case SIR:
+ d->data_type |= SIR_DATA;
+ /*
+ * 1/15/04 If performing cascading, then go
+ * directly to SHIFTIR.
+ * Else, go to IRPAUSE before going to SHIFTIR
+ */
+ if (d->flow_control & CASCADE) {
+ ispvm_state_machine(d, SHIFTIR);
+ break;
+ }
+ ispvm_state_machine(d, IRPAUSE);
+ ispvm_state_machine(d, SHIFTIR);
+ if (d->head_IR > 0) {
+ ispvm_bypass(d, HIR, d->head_IR);
+ ispvm_clock(d);
+ }
+ break;
+
+ case XSDR:
+ /* mark simultaneous in and out */
+ d->data_type |= EXPRESS;
+ /* fall-through */
+
+ case SDR:
+ d->data_type |= SDR_DATA;
+
+ /*
+ * 1/15/04 If already in SHIFTDR, then do not move
+ * state or shift in header. This would imply that the
+ * previously shifted frame was a cascaded frame.
+ */
+ if (d->current_jtag_state == SHIFTDR)
+ break;
+
+ /*
+ * 1/15/04 If performing cascading, then go directly
+ * to SHIFTDR. Else, go to DRPAUSE before going to SHIFTDR
+ */
+ if (d->flow_control & CASCADE) {
+ if (d->current_jtag_state == DRPAUSE) {
+ ispvm_state_machine(d, SHIFTDR);
+ /*
+ * 1/15/04 If cascade flag has been set and
+ * the current state is DRPAUSE, this implies
+ * that the first cascaded frame is about to be
+ * shifted in. The header must be shifted prior
+ * to shifting the first cascaded frame.
+ */
+ if (d->head_DR > 0) {
+ ispvm_bypass(d, HDR, d->head_DR);
+ ispvm_clock(d);
+ }
+ } else
+ ispvm_state_machine(d, SHIFTDR);
+ } else {
+ ispvm_state_machine(d, DRPAUSE);
+ ispvm_state_machine(d, SHIFTDR);
+ if (d->head_DR > 0) {
+ ispvm_bypass(d, HDR, d->head_DR);
+ ispvm_clock(d);
+ }
+ }
+ break;
+
+ default:
+ return VME_INVALID_FILE;
+ }
+
+ ret = ispvm_data_code(d);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+
+ if (d->data_type & DMASK_DATA) {
+ ret = ispvm_read_and_save(d, d->data_size);
+ if (!ret) {
+ if (d->tail_DR > 0) {
+ ispvm_clock(d);
+ ispvm_bypass(d, TDR, d->tail_DR);
+ }
+ ispvm_state_machine(d, DRPAUSE);
+ ispvm_state_machine(d, SHIFTDR);
+ if (d->head_DR > 0) {
+ ispvm_bypass(d, HDR, d->head_DR);
+ ispvm_clock(d);
+ }
+ for (i = 0; i < d->data_size / 8 + 1; i++)
+ d->in_TDI_data[i] = d->out_TDO_data[i];
+ d->data_type &= ~(TDO_DATA + DMASK_DATA);
+ ret = ispvm_send(d, d->data_size);
+ }
+ } else if (d->data_type & TDO_DATA) {
+ ret = ispvm_read(d, d->data_size);
+ if (ret == -1 && d->vendor == XILINX) {
+ for (j = 0; j < 30; j++) {
+ ret = ispvm_read(d, d->data_size);
+ if (!ret)
+ break;
+
+ /* Always DRPAUSE */
+ ispvm_state_machine(d, DRPAUSE);
+
+ /* Bypass other devices when appropriate */
+ ispvm_bypass(d, TDR, d->tail_DR);
+ ispvm_state_machine(d, d->end_DR);
+ ispvm_state_machine(d, IDLE);
+ udelay(1000);
+ }
+ }
+ } else
+ ret = ispvm_send(d, d->data_size); /*TDI only */
+
+ /*transfer the input data to the output buffer for the next verify */
+ if ((d->data_type & EXPRESS) ||
+ (code == SDR && d->out_TDO_data != NULL))
+ for (i = 0; i < d->data_size / 8 + 1; i++)
+ d->out_TDO_data[i] = d->in_TDI_data[i];
+
+ switch (code) {
+
+ case SIR:
+ /* 1/15/04 If not performing cascading, then shift ENDIR */
+ if ((d->flow_control & CASCADE))
+ break;
+
+ if (d->tail_IR > 0) {
+ ispvm_clock(d);
+ ispvm_bypass(d, TIR, d->tail_IR);
+ }
+ ispvm_state_machine(d, d->end_IR);
+ break;
+
+ case XSDR:
+ case SDR:
+ /* 1/15/04 If not performing cascading, then shift ENDDR */
+ if ((d->flow_control & CASCADE))
+ break;
+
+ if (d->tail_DR > 0) {
+ ispvm_clock(d);
+ ispvm_bypass(d, TDR, d->tail_DR);
+ }
+ ispvm_state_machine(d, d->end_DR);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/* This routine is to extract Header and Trailer parameter for SIR and
+ * SDR operations.
+ *
+ * The Header and Trailer parameter are the pre-amble and post-amble bit
+ * stream need to be shifted into TDI or out of TDO of the devices. Mostly
+ * is for the purpose of bypassing the leading or trailing devices. ispVM
+ * supports only shifting data into TDI to bypass the devices.
+ *
+ * For a single device, the header and trailer parameters are all set to 0
+ * as default by ispVM. If it is for multiple devices, the header and trailer
+ * value will change as specified by the VME file.
+ */
+
+int ispvm_amble(struct ispvm_desc *d, int code)
+{
+ int j, ret;
+ int compress = 0;
+
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+
+ d->data_size = j;
+
+ if (d->data_size) {
+ /*
+ * Discard the TDI byte and set the compression bit in the
+ * data type register to false if compression is set
+ * because TDI data after HIR/HDR/TIR/TDR is not compressed.
+ */
+ j = ispvm_get(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+
+ if (d->data_type & COMPRESS) {
+ d->data_type &= ~(COMPRESS);
+ compress = 1;
+ }
+ }
+
+ switch (code) {
+ case HIR:
+ /*
+ * Store the maximum size of the HIR buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->HIR_size)
+ d->HIR_size = d->data_size;
+
+ /* Assign the HIR value and allocate memory. */
+ d->head_IR = d->data_size;
+ if (d->head_IR) {
+ ret = ispvm_alloc(d, HIR, d->head_IR);
+ if (ret != 0)
+ return VME_OUT_OF_MEMORY;
+ ret = ispvm_data(d, d->HIR_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+
+ }
+ break;
+
+ case TIR:
+ /*
+ * Store the maximum size of the TIR buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->TIR_size)
+ d->TIR_size = d->data_size;
+
+ /* Assign the TIR value and allocate memory. */
+ d->tail_IR = d->data_size;
+ if (d->tail_IR) {
+ ret = ispvm_alloc(d, TIR, d->tail_IR);
+ if (ret != 0)
+ return VME_OUT_OF_MEMORY;
+ ret = ispvm_data(d, d->TIR_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ }
+ break;
+
+ case HDR:
+ /*
+ * Store the maximum size of the HDR buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->HDR_size)
+ d->HDR_size = d->data_size;
+
+ /* Assign the HDR value and allocate memory. */
+ d->head_DR = d->data_size;
+ if (d->head_DR) {
+ ret = ispvm_alloc(d, HDR, d->head_DR);
+ if (ret != 0)
+ return VME_OUT_OF_MEMORY;
+ ret = ispvm_data(d, d->HDR_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ }
+ break;
+
+ case TDR:
+
+ /*
+ * Store the maximum size of the TDR buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->data_size > d->TDR_size)
+ d->TDR_size = d->data_size;
+
+ /* Assign the TDR value and allocate memory. */
+ d->tail_DR = d->data_size;
+ if (d->tail_DR) {
+ ret = ispvm_alloc(d, TDR, d->tail_DR);
+ if (ret != 0)
+ return VME_OUT_OF_MEMORY;
+ ret = ispvm_data(d, d->TDR_data);
+ if (ret != 0)
+ return VME_INVALID_FILE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Re-enable compression if it was previously set. */
+ if (compress)
+ d->data_type |= COMPRESS;
+
+ if (d->data_size > 0 && ispvm_get(d) != CONTINUE)
+ return VME_INVALID_FILE; /* invalid opcode */
+
+ return 0;
+}
+
+/*
+ * Perform the function call upon by the REPEAT opcode.
+ * Memory is to be allocated to store the entire loop from REPEAT to ENDLOOP.
+ * After the loop is stored then execution begin. The REPEATLOOP flag is set
+ * on the d->flow_control register to indicate the repeat loop is in session
+ * and therefore fetch opcode from the memory instead of from the file.
+ */
+int ispvm_loop(struct ispvm_desc *d, int repeats)
+{
+ int i, j;
+ int ret = 0;
+
+ d->shift_value = 0;
+ for (i = 0; i < d->heap_repeat_size; i++) {
+ j = ispvm_get(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->heap_memory[i] = j;
+ }
+
+ if (d->heap_memory[i - 1] != ENDLOOP)
+ return VME_INVALID_FILE;
+
+ d->flow_control |= REPEATLOOP;
+ d->data_type |= HEAP_IN;
+
+ for (i = 0; i < repeats; i++) {
+ d->heap_counter = 0;
+ ret = ispvm_code(d);
+ d->repeat_loops++;
+ if (ret < 0)
+ break;
+ }
+
+ d->data_type &= ~HEAP_IN;
+ d->flow_control &= ~REPEATLOOP;
+ return ret;
+}
+
+/*
+ * Shift the TDI stream left or right by the number of bits. The data in
+ * d->in_TDI_data is of the VME format, so the actual shifting is the reverse of
+ * IEEE 1532 or SVF format.
+ */
+int ispvm_bit_shift(struct ispvm_desc *d, int mode, u16 bits)
+{
+ u16 i, size, j;
+
+ if (d->data_size % 8 > 0)
+ size = d->data_size / 8 + 1;
+ else
+ size = d->data_size / 8;
+
+ switch (mode) {
+
+ case SHR:
+ for (i = 0; i < size; i++) {
+ if (d->in_TDI_data[i] == 0)
+ continue;
+ j = bits;
+ while (j > 0) {
+ d->in_TDI_data[i] <<= 1;
+ if (d->in_TDI_data[i] == 0) {
+ i--;
+ d->in_TDI_data[i] = 1;
+ }
+ j--;
+ }
+ }
+ break;
+
+ case SHL:
+ for (i = 0; i < size; i++) {
+ if (d->in_TDI_data[i] == 0)
+ continue;
+ j = bits;
+ while (j > 0) {
+ d->in_TDI_data[i] >>= 1;
+ if (d->in_TDI_data[i] == 0) {
+ i--;
+ d->in_TDI_data[i] = 8;
+ }
+ j--;
+ }
+ }
+ break;
+
+ default:
+ return VME_INVALID_FILE;
+ }
+
+ return 0;
+}
+
+/* Displays the SVF comments. */
+int ispvm_comment(struct ispvm_desc *d, int size)
+{
+ int i, j;
+
+ /* Print character to the terminal. */
+ printf("VM-Comment: ");
+ for (i = 0; i < size; i++) {
+ j = ispvm_get(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ printf("%c", j);
+ }
+ printf("\n");
+
+ return 0;
+}
+
+/* Iterate the length of the header and discard it. */
+int ispvm_header(struct ispvm_desc *d, int size)
+{
+ int i, j;
+
+ for (i = 0; i < size; i++) {
+ j = ispvm_get(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ }
+ return 0;
+}
+
+/* Process the intelligent programming loops. */
+int ispvm_lcount(struct ispvm_desc *d, int size)
+{
+ int i, j, k;
+ int ret = 0;
+ int repheap = 0;
+
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+
+ d->intel_buffer_size = j;
+
+ /* Allocate memory for intel buffer. */
+ ret = ispvm_alloc(d, LHEAP, d->intel_buffer_size);
+ if (ret != 0)
+ return VME_OUT_OF_MEMORY;
+
+ /*
+ * Store the maximum size of the intelligent buffer.
+ * Used to convert VME to HEX.
+ */
+ if (d->intel_buffer_size > d->LCOUNT_size)
+ d->LCOUNT_size = d->intel_buffer_size;
+
+ /* Copy intel data to the buffer */
+ for (i = 0; i < d->intel_buffer_size; i++) {
+ k = ispvm_get(d);
+ if (k == -1)
+ return VME_INVALID_FILE;
+ d->intel_buffer[i] = k;
+ }
+
+ /*
+ * Set the data type register to get data from the
+ * intelligent data buffer.
+ */
+ d->data_type |= LHEAP_IN;
+
+ /*
+ * If the HEAP_IN flag is set, temporarily unset the flag
+ * so data will be retrieved from the status buffer.
+ */
+ if (d->data_type & HEAP_IN) {
+ d->data_type &= ~HEAP_IN;
+ repheap = 1;
+ }
+
+ /* Iterate through the intelligent programming command. */
+ for (i = 0; i < size; i++) {
+ d->intel_data_idx = 0;
+
+ /*
+ * Make recursive call to process the intelligent
+ * programming commands.
+ */
+ ret = ispvm_code(d);
+ if (ret >= 0)
+ break; /* success? */
+ }
+
+ /*
+ * If HEAP_IN flag was temporarily disabled,
+ * re-enable it before exiting.
+ */
+ if (repheap)
+ d->data_type |= HEAP_IN;
+
+ /*
+ * Set the data type register to not get data from
+ * the intelligent data buffer.
+ */
+ d->data_type &= ~LHEAP_IN;
+ return ret;
+}
+
+/* Applies a single pulse to TCK. */
+void ispvm_clock(struct ispvm_desc *d)
+{
+ int idle;
+
+ idle = 1000 / d->frequency + !!(1000 % d->frequency);
+
+ /* NOTE: we assume that at least one usec will pass
+ * until getting the port toggled
+ */
+ idle--;
+
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TCK, 0x01);
+ if (idle > 0)
+ udelay(idle);
+
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TCK, 0x00);
+ if (idle > 0)
+ udelay(idle);
+}
+
+/*
+ * This procedure takes care of the HIR, HDR, TIR, TDR for the
+ * purpose of putting the other devices into Bypass mode. The
+ * current state is checked to find out if it is at DRPAUSE or
+ * IRPAUSE. If it is at DRPAUSE, perform bypass register scan.
+ * If it is at IRPAUSE, scan into instruction registers the bypass
+ * instruction.
+ */
+void ispvm_bypass(struct ispvm_desc *d, int scan_type, u16 bits)
+{
+ int i, j, bit;
+ u8 val = 0;
+ u8 *pcSource = 0;
+
+ if (bits <= 0)
+ return;
+
+ switch (scan_type) {
+ case HIR:
+ pcSource = d->HIR_data;
+ break;
+ case TIR:
+ pcSource = d->TIR_data;
+ break;
+ case HDR:
+ pcSource = d->HDR_data;
+ break;
+ case TDR:
+ pcSource = d->TDR_data;
+ break;
+ default:
+ break;
+ }
+
+ j = 0;
+ for (i = 0; i < bits - 1; i++) {
+ /* Scan instruction or bypass register */
+ if (i % 8 == 0)
+ val = pcSource[j++];
+ bit = !!((val << (i % 8)) & 0x80);
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI, bit);
+ ispvm_clock(d);
+ }
+
+ if ((i % 8) == 0)
+ val = pcSource[j++];
+
+ bit = !!((val << (i % 8)) & 0x80);
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI, bit);
+}
+
+/*
+ * This procedure steps all devices in the daisy chain from a given
+ * JTAG state to the next desirable state. If the next state is TLR,
+ * the JTAG state machine is brute forced into TLR by driving TMS
+ * high and pulse TCK 6 times.
+ */
+void ispvm_state_machine(struct ispvm_desc *d, int next)
+{
+ /*
+ * JTAG state machine transition trajectory table
+ */
+ static const struct {
+ u8 cur_state; /* From this state */
+ u8 next_state; /* Step to this state */
+ u8 pattern; /* Tragectory of TMS */
+ u8 pulses; /* Number of steps */
+ } jtag_transitions[24] = {
+ /* Transitions from RESET */
+ { RESET, RESET, 0xFC, 6 },
+ { RESET, IDLE, 0x00, 1 },
+ { RESET, DRPAUSE, 0x50, 5 },
+ { RESET, IRPAUSE, 0x68, 6 },
+
+ /* Transitions from IDLE */
+ { IDLE, RESET, 0xE0, 3 },
+ { IDLE, DRPAUSE, 0xA0, 4 },
+ { IDLE, IRPAUSE, 0xD0, 5 },
+
+ /* Transitions from DRPAUSE */
+ { DRPAUSE, RESET, 0xF8, 5 },
+ { DRPAUSE, IDLE, 0xC0, 3 },
+ { DRPAUSE, IRPAUSE, 0xF4, 7 },
+
+ /* Transitions from IRPAUSE */
+ { IRPAUSE, RESET, 0xF8, 5 },
+ { IRPAUSE, IDLE, 0xC0, 3 },
+ { IRPAUSE, DRPAUSE, 0xE8, 6 },
+
+ /* Extra transitions using SHIFTDR */
+ { DRPAUSE, SHIFTDR, 0x80, 2 },
+ { IRPAUSE, SHIFTDR, 0xE0, 5 },
+ { SHIFTDR, DRPAUSE, 0x80, 2 },
+ { SHIFTDR, IDLE, 0xC0, 3 },
+
+ /* Extra transitions using SHIFTIR */
+ { IRPAUSE, SHIFTIR, 0x80, 2 },
+ { SHIFTIR, IRPAUSE, 0x80, 2 },
+ { SHIFTIR, IDLE, 0xC0, 3 },
+
+ /* 11/15/05 Nguyen changed to support DRCAPTURE */
+ { DRPAUSE, DRCAPTURE, 0xE0, 4 },
+ { DRCAPTURE, DRPAUSE, 0x80, 2 },
+ { IDLE, DRCAPTURE, 0x80, 2 },
+ { IRPAUSE, DRCAPTURE, 0xE0, 4}
+ };
+
+ int i, j, maxstate;
+
+ /* already there? */
+ if (d->current_jtag_state == next && next != RESET)
+ return;
+
+ maxstate = sizeof(jtag_transitions) / sizeof(jtag_transitions[0]);
+ for (j = 0; j < maxstate; j++)
+ if (d->current_jtag_state == jtag_transitions[j].cur_state &&
+ next == jtag_transitions[j].next_state)
+ break;
+
+ d->current_jtag_state = next;
+ for (i = 0; i < jtag_transitions[j].pulses; i++) {
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TMS,
+ (jtag_transitions[j].pattern << i) & 0x80);
+ ispvm_clock(d);
+ }
+
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI, 0);
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TMS, 0);
+}
+
+/*
+ * Send the TDI data stream to devices. The data stream can be
+ * instructions or data.
+ */
+int ispvm_send(struct ispvm_desc *d, u16 size)
+{
+ int i, j, bit;
+ u8 val = 0;
+
+ for (i = 0, j = 0; i < size - 1; i++) {
+ if ((i % 8) == 0)
+ val = d->in_TDI_data[j++];
+ bit = !!((val << (i % 8)) & 0x80);
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI, bit);
+ ispvm_clock(d);
+ }
+
+ /* Take care of the last bit */
+ if ((i % 8) == 0)
+ val = d->in_TDI_data[j];
+
+ bit = !!((val << (i % 8)) & 0x80);
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI, bit);
+
+ /* 1/15/04 Clock in last bit for the first n-1 cascaded frames */
+ if (d->flow_control & CASCADE)
+ ispvm_clock(d);
+
+ return 0;
+}
+
+/* Read the data stream from devices and verify. */
+int ispvm_read(struct ispvm_desc *d, u16 size)
+{
+ int i, j, k, bit, lasti, errors, dflg;
+ u8 data, mask, indata, display;
+
+ errors = 0;
+ lasti = size - 1;
+ j = 0;
+ k = 0;
+ dflg = 1;
+ data = 0;
+ mask = 0;
+ indata = 0;
+ display = 0;
+
+ /*
+ * If mask is not all zeros, then set the display flag to 0x00,
+ * otherwise it shall be set to 0x01 to indicate that data read from
+ * the device shall be displayed. If VME_DEBUG is defined, always
+ * display data.
+ */
+ for (i = 0; i < (size + 7) / 8; i++) {
+ if (d->data_type & MASK_DATA) {
+ if (d->out_MASK_data[i] != 0x00) {
+ dflg = 0;
+ break;
+ }
+ } else {
+ dflg = 0x00;
+ break;
+ }
+ }
+
+ /* Begin shifting data in and out of the device. */
+ for (i = 0; i < size; i++) {
+ if (k == 0) {
+ /* Grab byte from TDO buffer. */
+ if (d->data_type & TDO_DATA)
+ data = d->out_TDO_data[j];
+
+ /* Grab byte from MASK buffer. */
+ if (d->data_type & MASK_DATA)
+ mask = d->out_MASK_data[j];
+ else
+ mask = 0xFF;
+
+ /* Grab byte from TDI buffer. */
+ if (d->data_type & TDI_DATA)
+ indata = d->in_TDI_data[j];
+
+ j++;
+ }
+
+ bit = lattice_ec_read_port(d->cookie);
+
+ if (dflg) {
+ display <<= 1;
+ display |= bit;
+ }
+
+ /* Check if data read from port matches with expected TDO. */
+ if (d->data_type & TDO_DATA) {
+ if ((mask << k) & 0x80) {
+ if (bit != !!((data << k) & 0x80)) {
+ errors++;
+ dflg = 1;
+ }
+ }
+ }
+
+ /* Write TDI data to the port. */
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI,
+ (((indata << k) & 0x80) ? 0x01 : 0x00));
+
+ /* Clock data out from the data shift register. */
+ if (i < lasti || (d->flow_control & CASCADE))
+ ispvm_clock(d);
+
+ k++;
+ if (k >= 8) {
+
+ if (dflg) {
+ /*
+ * Store displayed data in the TDO buffer.
+ * By reusing the TDO buffer to store displayed
+ * data, there is no need to allocate a buffer
+ * simply to hold display data. This will not
+ * cause any false verification errors because
+ * the true TDO byte has already been consumed.
+ */
+ d->out_TDO_data[j - 1] = display;
+ display = 0;
+ }
+ k = 0;
+ }
+ }
+
+ if (dflg) {
+ /* Display data read from the device. */
+ printf("\nDisplay Data: 0x");
+
+ for (i = ((size + 7) / 8); i > 0; i--) {
+ mask = d->out_TDO_data[i - 1];
+ data = 0;
+
+ /* Flip mask and store it in data. */
+ for (j = 0; j < 8; j++) {
+ data <<= 1;
+ if (mask & 0x01)
+ data |= 0x01;
+ mask >>= 1;
+ }
+
+ printf(" %02X", ((unsigned int)data) & 0xff);
+ }
+ printf("\n\n");
+ }
+
+ if (errors > 0) {
+ if (d->flow_control & VERIFYUES) {
+ printf("USERCODE verification failed."
+ " Continue programming......\n\n");
+ d->flow_control &= ~VERIFYUES;
+ return 0;
+ }
+
+ return VME_VERIFICATION_FAILURE;
+
+ }
+
+ if (d->flow_control & VERIFYUES) {
+ printf("USERCODE verification passed."
+ " Programming aborted. \n\n");
+ d->flow_control &= ~VERIFYUES;
+ return 1;
+ }
+ return 0;
+}
+
+/* Support dynamic I/O. */
+int ispvm_read_and_save(struct ispvm_desc *d, u16 size)
+{
+ int i, j, k, l, m, lasti, bit, outbit;
+ u8 data, dmask, indata, outdata;
+
+ lasti = size - 1;
+ j = 0;
+ k = 0;
+ l = 0;
+ m = 0;
+ data = 0;
+ dmask = 0;
+ indata = 0;
+
+ /* Iterate through the data bits. */
+ for (i = 0; i < size; i++) {
+ if (k == 0) {
+ /* Grab byte from DMASK buffer. */
+ if (d->data_type & DMASK_DATA)
+ dmask = d->out_DMASK_data[j];
+ else
+ dmask = 0x00;
+
+ /* Grab byte from TDI buffer. */
+ if (d->data_type & TDI_DATA)
+ indata = d->in_TDI_data[j];
+
+ j++;
+ }
+
+ bit = lattice_ec_read_port(d->cookie);
+ data = !!((indata << k) & 0x80);
+
+ /* Initialize the byte to be zero. */
+ if (l % 8 == 0)
+ d->out_TDO_data[l / 8] = 0x00;
+
+ /*
+ * Use TDI, DMASK, and device TDO to create new TDI (actually
+ * stored in d->out_TDO_data).
+ */
+ if ((dmask << k) & 0x80) {
+
+ if (d->LVDS_list) {
+ for (m = 0; m < d->LVDS_pair_count; m++) {
+ if (d->LVDS_list[m].negative_idx
+ == i) {
+ d->LVDS_list[m].update = 0x01;
+ break;
+ }
+ }
+ }
+
+ /* DMASK bit is 1, use TDI. */
+ outbit = data & 1;
+ } else
+ outbit = bit;
+
+ /* DMASK bit is 0, use device TDO. */
+ outdata = outbit << (7 - l % 8);
+ d->out_TDO_data[l / 8] |= outdata;
+
+ /* Shift in TDI in order to get TDO out. */
+ l++;
+ lattice_ec_write_port(d->cookie, LATTICE_JTAG_TDI, data);
+ if (i < lasti)
+ ispvm_clock(d);
+
+ k++;
+ if (k >= 8)
+ k = 0;
+ }
+
+ /*
+ * If d->LVDS_list exists and pairs need updating, then update
+ * the negative-pair to receive the flipped positive-pair value.
+ */
+ if (!d->LVDS_list)
+ return 0;
+
+ for (m = 0; m < d->LVDS_pair_count; m++)
+ if (d->LVDS_list[m].update)
+ break;
+
+ /* update not found? */
+ if (m >= d->LVDS_pair_count)
+ return 0;
+
+ /* Read the positive value and flip it. */
+ outdata = d->out_TDO_data[d->LVDS_list[m].positive_idx / 8];
+ data = !((outdata << (d->LVDS_list[m].positive_idx % 8)) & 0x80);
+
+ /* Get the byte that needs modification. */
+ indata = d->out_TDO_data[d->LVDS_list[m].negative_idx / 8];
+
+ if (data) {
+ /* Copy over the current byte and set the negative bit to 1 */
+ data = 0x00;
+ for (i = 7; i >= 0; i--) {
+ data <<= 1;
+ if (7 - (d->LVDS_list[m].negative_idx % 8) == i)
+ /* Set negative bit to 1. */
+ data |= 0x01;
+ else if (indata & 0x80)
+ data |= 0x01;
+
+ indata <<= 1;
+ }
+
+
+ } else {
+ /* Copy over the current byte and set the negative bit to 0. */
+ data = 0x00;
+ for (i = 7; i >= 0; i--) {
+ data <<= 1;
+ if (7 - (d->LVDS_list[m].negative_idx % 8) == i)
+ /* Set negative bit to 0. */
+ data |= 0x00;
+ else if (indata & 0x80)
+ data |= 0x01;
+
+ indata <<= 1;
+ }
+ }
+
+ /* Store the modified byte. */
+ d->out_TDO_data[d->LVDS_list[m].negative_idx / 8] = data;
+
+ return 0;
+}
+
+int ispvm_process_lvds(struct ispvm_desc *d, int count)
+{
+ int i, j;
+ /* LVDSPair * pLVDSPair = NULL; */
+
+ /* Allocate memory to hold LVDS pairs. */
+ j = ispvm_alloc(d, LVDS, count);
+ if (j != 0)
+ return VME_OUT_OF_MEMORY;
+ d->LVDS_pair_count = count;
+
+ /* Iterate through each given LVDS pair. */
+ for (i = 0; i < count; i++) {
+ /*
+ * Assign the positive and negative indices
+ * of the LVDS pair.
+ */
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+
+ d->LVDS_list[i].positive_idx = j;
+
+ j = ispvm_data_size(d);
+ if (j == -1)
+ return VME_INVALID_FILE;
+ d->LVDS_list[i].negative_idx = j;
+ }
+
+ return 0;
+}
+
+#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 5/8] Adds support for RedBoot
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
` (2 preceding siblings ...)
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 4/8] Support LATTICE FPGA parts using JTAG programming. Support functions Pantelis Antoniou
@ 2006-12-02 22:16 ` Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 6/8] Support Analogue Micro's ASP8347DB board. CONFIG file Pantelis Antoniou
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:16 UTC (permalink / raw)
To: u-boot
Provide support for RedBoot's FIS & config variables.
For PPC provide also a way to boot a redboot compiled Linux kernel.
The bd_t is different in that case.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
README | 70 ++++
common/Makefile | 1
common/cmd_bootm.c | 20 +
common/redboot.c | 978 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/redboot.h | 98 +++++
5 files changed, 1166 insertions(+), 1 deletions(-)
diff --git a/README b/README
index e28f935..c3055c0 100644
--- a/README
+++ b/README
@@ -2324,6 +2324,76 @@ Low Level (hardware related) configuration options:
some other boot loader or by a debugger which
performs these intializations itself.
+- CONFIG_REDBOOT
+ Add support for read-only parsing of the FIS & config areas.
+ For PPC also add an option to boot a kernel compiled for RedBoot.
+
+ The redboot command is also enabled conditional on CFG_CMD_FLASH.
+
+ - Select a different FIS
+ > redboot fis select ([bank] [sector] | reset)
+
+ - Display FIS
+ > redboot fis list
+
+ - Set an environment variable from a member variable of a FIS entry
+
+ > redboot fis setenv var type name
+
+ Where type: flash_base, mem_base, size, entry_point, data_length.
+
+ An example given a FIS entry of
+
+ Name FLASH addr Mem addr Datalen Length Entry point
+ Linux 0xF0470000 0x00100000 0x000FA000 0x00100000 0x00100000
+
+ > redboot fis setenv linux_base flash_base Linux
+
+ Would set the environment variable linux_base to 0xf0470000
+
+ - Print either all the RedBoot config variables or a specific one
+
+ > redboot config printenv [config-var] [member]
+
+ member is one of value, type, enable-sense, enable-key with value
+ being the default one.
+
+ - Set an environment variable from a RedBoot config variable
+
+ > redboot config setenv var config-var [member]
+
+ For example when given a config variable of
+
+ tsec1_esa=00:08:e5:11:32:33
+ type=esa enable-sense=true
+
+ > redboot config setenv ethaddr tsec1_esa
+
+ would set the ethaddr environment variable to 00:08:e5:11:32:33
+
+ - Boot a RedBoot kernel [PPC specific]
+
+ > redboot exec address
+
+ The PPC bd_t differs for kernels compiled for redboot; this command
+ lets you boot such a kernel.
+
+ RedBoot config defaults (can be overriden on board config):
+
+ - Sector containing the FIS area (negative values for counting from the end)
+ CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK -1
+
+ - FIS directory entry size
+ CONFIG_REDBOOT_DIRECTORY_ENTRY_SIZE 0x100
+
+ - Size of the config area
+ CONFIG_REDBOOT_FLASH_CONFIG_SIZE 4096
+
+ - Size of the script config variables
+ CONFIG_REDBOOT_FLASH_SCRIPT_SIZE 256
+
+ - Size of the string config variables
+ CONFIG_REDBOOT_FLASH_STRING_SIZE 128
Building the Software:
======================
diff --git a/common/Makefile b/common/Makefile
index 79d11a5..13dc6ae 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -51,6 +51,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o \
lattice.o lattice_ec.o lattice_ivm_core.o lattice_ivm_supp.o \
lcd.o lists.o lynxkdi.o \
memsize.o miiphybb.o miiphyutil.o \
+ redboot.o \
s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \
usb.o usb_kbd.o usb_storage.o \
virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 7aae8a6..578d05b 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -146,6 +146,12 @@ extern void lynxkdi_boot( image_header_t * );
#define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */
#endif
+#ifdef CONFIG_REDBOOT_BD_T_SIZE
+extern void board_redboot_bd_t_adapt(void *kbd,
+ ulong cmd_start, ulong cmd_end,
+ ulong initrd_start, ulong initrd_end);
+#endif
+
image_header_t header;
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
@@ -533,6 +539,11 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
char *of_flat_tree = NULL;
ulong of_data = 0;
#endif
+#ifdef CONFIG_REDBOOT_BD_T_SIZE
+#define BD_T_SIZE max(sizeof(bd_t), CONFIG_REDBOOT_BD_T_SIZE)
+#else
+#define BD_T_SIZE sizeof(bd_t)
+#endif
if ((s = getenv ("initrd_high")) != NULL) {
/* a value of "no" or a similar string will act like 0,
@@ -575,7 +586,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
debug ("=> set upper limit to 0x%08lX\n", sp);
cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
- kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
+ kbd = (bd_t *)(((ulong)cmdline - BD_T_SIZE) & ~0xF);
if ((s = getenv("bootargs")) == NULL)
s = "";
@@ -904,6 +915,13 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,
initrd_end = 0;
}
+ /* redboot bd_t modify */
+#ifdef CONFIG_REDBOOT_BD_T_SIZE
+ if ((s = getenv ("redboot_bd_t")) != NULL)
+ board_redboot_bd_t_adapt(kbd, cmd_start, cmd_end,
+ initrd_start, initrd_end);
+#endif
+
debug ("## Transferring control to Linux (at address %08lx) ...\n",
(ulong)kernel);
diff --git a/common/redboot.c b/common/redboot.c
new file mode 100644
index 0000000..22c4373
--- /dev/null
+++ b/common/redboot.c
@@ -0,0 +1,978 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on Linux & RedBoot code fragments
+ * by David Woodhouse, dwmw2 at infradead.org
+ * by Mark Sattler, msalter at redhat.com
+ * by Gary Thomas, gthomas at redhat.com
+ *
+ * RedBoot flash images/configuration & kernel startup
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <flash.h>
+#include <command.h>
+
+#include <redboot.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#ifdef CFG_INIT_RAM_LOCK
+#include <asm/cache.h>
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_FLASH) && defined(CONFIG_REDBOOT)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void board_redboot_bd_t_adapt(void *kbd,
+ ulong cmd_start, ulong cmd_end,
+ ulong initrd_start, ulong initrd_end);
+
+extern flash_info_t flash_info[]; /* info for FLASH chips */
+
+static inline int redboot_checksum(struct fis_image_desc *img)
+{
+ /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */
+ return 1;
+}
+
+static int get_sector_size(flash_info_t *info, int sector)
+{
+ ulong s, e;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return 0;
+
+ if ((unsigned int)sector >= info->sector_count)
+ return 0;
+
+ s = info->start[sector];
+ if (sector < info->sector_count - 1)
+ e = info->start[sector + 1];
+ else
+ e = info->start[0] + info->size;
+
+ return e - s;
+}
+
+/* get the sector which corresponds to this address */
+static int get_sector(flash_info_t *info, void *ptr)
+{
+ int i;
+ ulong s, e;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return -1;
+
+ if (info->start[0] > (ulong)ptr ||
+ info->start[info->sector_count - 1] < (ulong)ptr)
+ return -1;
+
+ for (i = 0; i < info->sector_count; i++) {
+ s = info->start[i];
+ if (i < info->sector_count - 1)
+ e = info->start[i + 1];
+ else
+ e = info->start[0] + info->size;
+
+ if (s <= (ulong)ptr && e > (ulong)ptr)
+ return i;
+ }
+
+ /* should not happen */
+ return -1;
+}
+
+static void *get_fis(flash_info_t *info, void *fis)
+{
+ int dir_block, sector;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ return NULL;
+
+ /* already given a fis address (verify it) */
+ if (fis != NULL) {
+ if (info->start[0] > (ulong)fis ||
+ info->start[info->sector_count - 1] < (ulong)fis)
+ return NULL;
+ return fis;
+ }
+
+ /* go with defaults */
+ dir_block = CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK;
+ if (dir_block < 0)
+ sector = info->sector_count + dir_block;
+ else
+ sector = dir_block;
+
+ if ((unsigned int)sector >= info->sector_count)
+ return NULL;
+
+ return (void *)info->start[sector];
+}
+
+static int get_fis_slots(flash_info_t *info, void *fis, int *swapped)
+{
+ int i, sector, sector_size, slots;
+ struct fis_image_desc *ptr;
+
+ *swapped = -1;
+
+ fis = get_fis(info, fis);
+ if (fis == NULL)
+ return -1;
+
+ sector = get_sector(info, fis);
+ sector_size = get_sector_size(info, sector);
+
+ slots = sector_size / sizeof(struct fis_image_desc);
+
+ /* first pass; detect swap status */
+ for (i = 0, ptr = fis; i < slots; i++, ptr++) {
+ if (ptr->name[0] == 0xFF)
+ break;
+
+ if (!memcmp(ptr->name, "FIS directory", 14))
+ *swapped = swab32(ptr->size) == sector_size;
+ }
+
+ if (*swapped == -1)
+ return -1;
+
+ return i;
+}
+
+void *redboot_fis_get(int bank, int dir_block, flash_info_t **infop)
+{
+ flash_info_t *info;
+ int block;
+
+ if (bank < 1 || bank > CFG_MAX_FLASH_BANKS) {
+ printf("Only FLASH Banks # 1 ... # %d supported\n",
+ CFG_MAX_FLASH_BANKS);
+ return NULL;
+ }
+ info = &flash_info[bank-1];
+ if (info->flash_id == FLASH_UNKNOWN) {
+ printf("FLASH Bank #%d, not present\n", bank);
+ return NULL;
+ }
+
+ if (dir_block < 0)
+ block = info->sector_count + dir_block;
+ else
+ block = dir_block;
+
+ if ((unsigned int)block >= info->sector_count) {
+ printf("FLASH dir_block %d out of range in Bank #%d\n",
+ dir_block, bank);
+ return NULL;
+ }
+
+ if (infop)
+ *infop = info;
+ return (void *)info->start[block];
+}
+
+
+int redboot_fis_entry_lookup(flash_info_t *info, void *fis,
+ struct fis_image_desc *fis_buf, const char *name)
+{
+ int i, slots, swapped, name_len;
+ struct fis_image_desc *ptr;
+
+ fis = get_fis(info, fis);
+ if (fis == NULL)
+ return -1;
+
+ slots = get_fis_slots(info, fis, &swapped);
+ if (slots == -1) {
+ printf("fis list: FIS not found\n");
+ return -1;
+ }
+
+ name_len = strlen(name);
+
+ /* now do the proper read (with swapping if needed */
+ for (i = 0, ptr = fis; i < slots; i++, ptr++) {
+
+ if (ptr->name[0] == 0xFF)
+ break;
+
+ /* copy to buffer */
+ memcpy(fis_buf, ptr, sizeof(struct fis_image_desc));
+ if (swapped) {
+ /* The unsigned long fields were written with the
+ * wrong byte sex, name and pad have no byte sex.
+ */
+ swab32s(&fis_buf->flash_base);
+ swab32s(&fis_buf->mem_base);
+ swab32s(&fis_buf->size);
+ swab32s(&fis_buf->entry_point);
+ swab32s(&fis_buf->data_length);
+ swab32s(&fis_buf->desc_cksum);
+ swab32s(&fis_buf->file_cksum);
+ }
+
+ /* found */
+ if (strcmp(name, fis_buf->name) == 0)
+ return 0;
+ }
+
+ return -1;
+}
+
+int redboot_fis_list(flash_info_t *info, void *fis)
+{
+ int i, slots, swapped, found;
+ static struct fis_image_desc fis_buf; /* static; save stack space */
+ struct fis_image_desc *ptr;
+ u32 last, lowest, flash_base;
+
+ fis = get_fis(info, fis);
+ if (fis == NULL) {
+ printf("fis list: could not get FIS\n");
+ return -1;
+ }
+
+ slots = get_fis_slots(info, fis, &swapped);
+ if (slots == -1) {
+ printf("fis list: FIS not found\n");
+ return -1;
+ }
+
+ printf("%-16s %-10s %-10s %-10s %-10s %-s\n",
+ "Name", "FLASH addr", "Mem addr",
+ "Datalen", "Length", "Entry point" );
+
+ last = 0;
+ do {
+ found = -1;
+ lowest = 0xFFFFFFFF;
+
+ /* now do the proper read (with swapping if needed */
+ for (i = 0, ptr = fis; i < slots; i++, ptr++) {
+
+ if (ptr->name[0] == 0xFF)
+ break;
+
+ if (swapped)
+ flash_base = swab32(ptr->flash_base);
+ else
+ flash_base = ptr->flash_base;
+
+ if (flash_base > last && flash_base < lowest) {
+ lowest = flash_base;
+ found = i;
+ }
+ }
+
+ if (found >= 0) {
+ ptr = fis;
+ memcpy(&fis_buf, &ptr[found],
+ sizeof(struct fis_image_desc));
+ if (swapped) {
+ /* The unsigned long fields were written
+ * with the wrong byte sex, name and pad
+ * have no byte sex.
+ */
+ swab32s(&fis_buf.flash_base);
+ swab32s(&fis_buf.mem_base);
+ swab32s(&fis_buf.size);
+ swab32s(&fis_buf.entry_point);
+ swab32s(&fis_buf.data_length);
+ swab32s(&fis_buf.desc_cksum);
+ swab32s(&fis_buf.file_cksum);
+ }
+
+ printf("%-16s 0x%08lX 0x%08lX 0x%08lX "
+ "0x%08lX 0x%08lX\n",
+ fis_buf.name,
+ (unsigned long)fis_buf.flash_base,
+ fis_buf.mem_base,
+ fis_buf.data_length, fis_buf.size,
+ (unsigned long)fis_buf.entry_point);
+ }
+ last = lowest;
+ } while (found >= 0);
+
+ return 0;
+}
+
+int redboot_fis_setenv(flash_info_t *info, void *fis, const char *name,
+ const char *what, char *var)
+{
+ static struct fis_image_desc fis_buf; /* static; save stack space */
+ static char varbuf[12];
+ int i;
+
+ i = redboot_fis_entry_lookup(info, fis, &fis_buf, name);
+ if (i != 0)
+ return -1;
+
+ if (strcmp(what, "flash_base") == 0)
+ sprintf(varbuf, "0x%x", fis_buf.flash_base);
+ else if (strcmp(what, "mem_base") == 0)
+ sprintf(varbuf, "0x%x", fis_buf.mem_base);
+ else if (strcmp(what, "size") == 0)
+ sprintf(varbuf, "0x%x", fis_buf.size);
+ else if (strcmp(what, "entry_point") == 0)
+ sprintf(varbuf, "0x%x", fis_buf.entry_point);
+ else if (strcmp(what, "data_length") == 0)
+ sprintf(varbuf, "0x%x", fis_buf.data_length);
+ else
+ return -1;
+
+ setenv(var, varbuf);
+
+ return 0;
+}
+
+/*************************************************************************/
+
+#define CONFIG_KEY1 0x0badface
+#define CONFIG_KEY2 0xdeaddead
+
+/*
+ * Layout of config data
+ * Each data item is variable length, with the name, type and dependencies
+ * encoded into the object.
+ * offset contents
+ * 0 data type
+ * 1 length of name (N)
+ * 2 enable sense
+ * 3 length of enable key (M)
+ * 4 key name
+ * N+4 enable key
+ * M+N+4 data value
+ */
+
+#define TYPE(dp) ((dp)[0])
+#define KEYLEN(dp) ((dp)[1])
+#define ENABLE_SENSE(dp) ((dp)[2])
+#define ENABLE_KEYLEN(dp) ((dp)[3])
+#define KEY(dp) ((dp)+4)
+#define ENABLE_KEY(dp) ((dp)+4+KEYLEN(dp))
+#define VALUE(dp) ((dp)+4+KEYLEN(dp)+ENABLE_KEYLEN(dp))
+
+void *get_config(flash_info_t *info, void *fis, int *sizep, int *swappedp)
+{
+ static struct fis_image_desc fis_buf; /* static; save stack space */
+ int i;
+ ulong base, size;
+ void *config;
+ u32 *ps, *pe;
+
+ /* lookup the RedBoot config */
+ i = redboot_fis_entry_lookup(info, fis, &fis_buf, "RedBoot config");
+ if (i != 0)
+ return NULL;
+
+ base = fis_buf.flash_base;
+ size = fis_buf.data_length;
+
+ config = (void *)base;
+
+ /* verify */
+ ps = (u32 *)base;
+ if (ps[1] != CONFIG_KEY1 && ps[1] != swab32(CONFIG_KEY1))
+ return NULL;
+
+ if (ps[1] == CONFIG_KEY1) {
+ *swappedp = 0;
+ if (ps[0] != size)
+ return NULL;
+ pe = (u32 *)(base + ps[0]);
+ if (pe[-2] != CONFIG_KEY2)
+ return NULL;
+ } else {
+ *swappedp = 1;
+ if (swab32(ps[0]) != size)
+ return NULL;
+ pe = (u32 *)(base + swab32(ps[0]));
+ if (pe[-2] != swab32(CONFIG_KEY2))
+ return NULL;
+ }
+
+ *sizep = size;
+ return config;
+}
+
+#define CONFIG_EMPTY 0
+#define CONFIG_BOOL 1
+#define CONFIG_INT 2
+#define CONFIG_STRING 3
+#define CONFIG_SCRIPT 4
+#define CONFIG_IP 5
+#define CONFIG_ESA 6
+#define CONFIG_NETPORT 7
+
+static const int config_len_tab[] = {
+ [CONFIG_EMPTY] = 0,
+ [CONFIG_BOOL] = 4,
+ [CONFIG_INT] = 4,
+ [CONFIG_STRING] = CONFIG_REDBOOT_FLASH_STRING_SIZE,
+ [CONFIG_SCRIPT] = CONFIG_REDBOOT_FLASH_SCRIPT_SIZE,
+ [CONFIG_IP] = 4,
+ [CONFIG_ESA] = 8,
+ [CONFIG_NETPORT]= CONFIG_REDBOOT_FLASH_STRING_SIZE,
+};
+
+static const char *config_txt_tab[] = {
+ [CONFIG_EMPTY] = "",
+ [CONFIG_BOOL] = "bool",
+ [CONFIG_INT] = "int",
+ [CONFIG_STRING] = "string",
+ [CONFIG_SCRIPT] = "script",
+ [CONFIG_IP] = "ip",
+ [CONFIG_ESA] = "esa",
+ [CONFIG_NETPORT]= "netport",
+};
+
+static inline int config_length(int type)
+{
+ if ((unsigned int)type >=
+ sizeof(config_len_tab)/sizeof(config_len_tab[0]))
+ return -1;
+ return config_len_tab[type];
+}
+
+static const char *config_format_value(int type, const char *value,
+ char *small_buf, int swapped)
+{
+ int val;
+ unsigned int uval;
+ const char *fmt;
+
+ switch (type) {
+ case CONFIG_BOOL:
+ val = *(int *)value;
+ if (swapped)
+ val = swab32(val);
+ fmt = val ? "true" : "false";
+ break;
+ case CONFIG_INT:
+ val = *(int *)value;
+ if (swapped)
+ val = swab32(val);
+ sprintf(small_buf, "%d", val);
+ fmt = small_buf;
+ break;
+ case CONFIG_STRING:
+ fmt = value;
+ break;
+ case CONFIG_SCRIPT:
+ fmt = value;
+ break;
+ case CONFIG_IP:
+ uval = *(unsigned int *)value;
+ if (swapped)
+ uval = swab32(uval);
+ sprintf(small_buf, "%u.%u.%u.%u",
+ (uval >> 24) & 0xff, (uval >> 16) & 0xff,
+ (uval >> 8) & 0xff, uval & 0xff);
+ fmt = small_buf;
+ break;
+ case CONFIG_ESA:
+ sprintf(small_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ value[0] & 0xff, value[1] & 0xff,
+ value[2] & 0xff, value[3] & 0xff,
+ value[4] & 0xff, value[5] & 0xff);
+ fmt = small_buf;
+ break;
+ case CONFIG_NETPORT:
+ fmt = value;
+ break;
+
+ default:
+ fmt = ""; /* empty */
+ break;
+ }
+
+ return fmt;
+}
+
+int redboot_config_printenv(flash_info_t *info, void *fis,
+ char *small_buf, const char *what)
+{
+ int size, cfglen, len, printit, swapped;
+ void *config;
+ char *dp, *dpe;
+
+ if (small_buf == NULL)
+ return -1;
+
+ config = get_config(info, fis, &size, &swapped);
+ if (config == NULL)
+ return -1;
+
+ /* point to the config data */
+ dp = config + 8;
+ dpe = config + size - 8;
+
+ for (; dp < dpe; dp += len) {
+
+ cfglen = config_length(TYPE(dp));
+ if (cfglen < 0) /* illegal type */
+ return -1;
+
+ len = 4 + KEYLEN(dp) + ENABLE_KEYLEN(dp) + cfglen;
+
+ /* don't bother with the empty */
+ if (TYPE(dp) == CONFIG_EMPTY)
+ continue;
+
+ /* printf("%p: %02x %02x %02x %02x\n",
+ dp, (int)dp[0] & 0xff, (int)dp[1] & 0xff,
+ (int)dp[2] & 0xff, (int)dp[3] & 0xff); */
+
+ printit = what == NULL ||
+ (what != NULL && strcmp(what, KEY(dp)) == 0);
+
+ if (printit) {
+ printf("%s=%s\n", KEY(dp),
+ config_format_value(TYPE(dp),
+ VALUE(dp), small_buf, swapped));
+ printf("\ttype=%s", config_txt_tab[(int)TYPE(dp)]);
+ printf(" enable-sense=%s",
+ ENABLE_SENSE(dp) ? "true" : "false");
+ if (ENABLE_KEYLEN(dp) > 0)
+ printf(" enable-key=%s", ENABLE_KEY(dp));
+ printf("\n");
+
+ if (what)
+ break;
+ }
+ }
+
+ return 0;
+}
+
+const char *redboot_config_getenv(flash_info_t *info, void *fis,
+ char *small_buf, const char *what, const char *special)
+{
+ int size, cfglen, len, swapped;
+ void *config;
+ char *dp, *dpe;
+
+ /* this time we need that */
+ if (what == NULL || small_buf == NULL)
+ return NULL;
+
+ config = get_config(info, fis, &size, &swapped);
+ if (config == NULL)
+ return NULL;
+
+ /* point to the config data */
+ dp = config + 8;
+ dpe = config + size - 8;
+
+ for (; dp < dpe; dp += len) {
+
+ cfglen = config_length(TYPE(dp));
+ if (cfglen < 0) /* illegal type */
+ return NULL;
+
+ len = 4 + KEYLEN(dp) + ENABLE_KEYLEN(dp) + cfglen;
+
+ /* don't bother with the empty */
+ if (TYPE(dp) == CONFIG_EMPTY)
+ continue;
+
+ if (strcmp(what, KEY(dp)) == 0) {
+
+ /* return value */
+ if (special == NULL || strcmp(special, "value") == 0)
+ return config_format_value(TYPE(dp), VALUE(dp),
+ small_buf, swapped);
+
+ if (strcmp(special, "type") == 0)
+ return config_txt_tab[(int)TYPE(dp)];
+
+ if (strcmp(special, "enable-sense") == 0)
+ return ENABLE_SENSE(dp) ? "true" : "false";
+
+ if (strcmp(special, "enable-key") == 0)
+ return ENABLE_KEY(dp);
+ }
+ }
+
+ return NULL;
+}
+
+int redboot_config_setenv(flash_info_t *info, void *fis,
+ const char *var, const char *what, const char *special)
+{
+ static char small_buf[18];
+ const char *value;
+
+ value = redboot_config_getenv(info, fis, small_buf, what, special);
+ if (!value)
+ return -1;
+
+ setenv((char *)var, (char *)value);
+
+ return 0;
+}
+
+/*************************************************************/
+
+#ifdef CONFIG_PPC
+
+/* Note: Only tested on a PPC board - other arches
+ * should be made to work with not much trouble
+ *
+ * The way this works is: we do pretty much what
+ * we do for a bootm case of a uImage (even creating
+ * the u-boot's idea of bd_t). And then we call
+ * board specific code to fix the mess.
+ */
+
+static void __attribute__((noinline))
+redboot_linux_exec(ulong addr, ulong ramdisk_address, ulong ramdisk_length)
+{
+ ulong sp;
+ ulong initrd_start, initrd_end;
+ ulong cmd_start, cmd_end;
+ char *cmdline;
+ char *s;
+ bd_t *kbd;
+
+ initrd_start = ramdisk_address;
+ initrd_end = ramdisk_address + ramdisk_length;
+
+ /*
+ * Booting a (Linux) kernel image
+ *
+ * Allocate space for command line and board info - the
+ * address should be as high as possible within the reach of
+ * the kernel (see CFG_BOOTMAPSZ settings), but in unused
+ * memory, which means far enough below the current stack
+ * pointer.
+ */
+
+ /* point stack@the end of memory */
+ /* redboot is different that u-boot in that regard */
+ sp = (gd->bd->bi_memstart + gd->bd->bi_memsize) - 16;
+ sp &= ~0x0f;
+
+ debug ("## Current stack ends at 0x%08lX ", sp);
+
+ sp -= 2048; /* just to be sure */
+
+ debug ("=> set upper limit to 0x%08lX\n", sp);
+
+ cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
+ kbd = (bd_t *)(((ulong)cmdline - CONFIG_REDBOOT_BD_T_SIZE) & ~0xF);
+
+ if ((s = getenv("bootargs")) != NULL) {
+
+ strcpy (cmdline, s);
+
+ cmd_start = (ulong)&cmdline[0];
+ cmd_end = cmd_start + strlen(cmdline);
+ } else {
+ cmd_start = 0;
+ cmd_end = 0;
+ }
+
+ *kbd = *(gd->bd);
+
+ if ((s = getenv("clocks_in_mhz")) != NULL) {
+ /* convert all clock information to MHz */
+ kbd->bi_intfreq /= 1000000L;
+ kbd->bi_busfreq /= 1000000L;
+#if defined(CONFIG_MPC8220)
+ kbd->bi_inpfreq /= 1000000L;
+ kbd->bi_pcifreq /= 1000000L;
+ kbd->bi_pevfreq /= 1000000L;
+ kbd->bi_flbfreq /= 1000000L;
+ kbd->bi_vcofreq /= 1000000L;
+#endif
+#if defined(CONFIG_CPM2)
+ kbd->bi_cpmfreq /= 1000000L;
+ kbd->bi_brgfreq /= 1000000L;
+ kbd->bi_sccfreq /= 1000000L;
+ kbd->bi_vco /= 1000000L;
+#endif
+#if defined(CONFIG_MPC5xxx)
+ kbd->bi_ipbfreq /= 1000000L;
+ kbd->bi_pcifreq /= 1000000L;
+#endif /* CONFIG_MPC5xxx */
+ }
+
+ /* convert u-boot bd_t to redboot_bd_t in place */
+ board_redboot_bd_t_adapt(kbd, cmd_start, cmd_end,
+ initrd_start, initrd_end);
+
+ debug ("## Transferring control to Linux (at address %08lx) ...\n",
+ (ulong)kernel);
+
+ SHOW_BOOT_PROGRESS (15);
+
+#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
+ unlock_ram_in_cache();
+#endif
+ dcache_disable();
+ icache_disable();
+ disable_interrupts();
+
+ /* Call into Linux */
+ __asm__ volatile (
+ /* Start by disabling MMU - the mappings are */
+ /* 1-1 so this should not cause any problems */
+ "mfmsr 3\n"
+ "li 4,0xFFFFFFCF\n"
+ "and 3,3,4\n"
+ "sync\n"
+ "mtmsr 3\n"
+ "sync\n"
+
+ /* Now set up parameters to jump into linux */
+
+ "mtlr %0\n" /* set entry address in LR */
+ "mr 1,%1\n" /* set stack pointer */
+ "mr 3,%2\n" /* set board info in R3 */
+ "mr 4,%3\n" /* set command line in R4 */
+ "blr \n" /* jump into linux */
+ :
+ : "r"(addr), "r"(sp), "r"(kbd), "r"(cmd_start)
+ : "r3", "r4");
+
+ /* never reached */
+}
+#endif /* CONFIG_PPC */
+
+extern flash_info_t flash_info[]; /* info for FLASH chips */
+
+int do_redboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int i, j;
+ char *name, *var;
+ static int bank = 1;
+ static int dir_block = -1; /* defaults */
+ void *fis;
+ static char small_buf[18];
+ const char *value;
+
+ if (argc < 2)
+ goto usage;
+
+ if (strcmp(argv[1], "fis") == 0) {
+
+ if (argc < 3)
+ goto usage;
+
+ if (strcmp(argv[2], "select") == 0) {
+
+ i = bank;
+ j = dir_block;
+
+ if (argc == 3 || strcmp(argv[3], "show") == 0) {
+ ; /* nothing */
+ } else if (argc >= 4 && strcmp(argv[3], "reset") == 0) {
+ i = 1;
+ j = -1;
+ } else {
+ if (argc >= 4)
+ i = simple_strtoul(argv[3], NULL, 16);
+ if (argc >= 5)
+ j = simple_strtol(argv[4], NULL, 16);
+ }
+
+ fis = redboot_fis_get(i, j, NULL);
+ if (fis == NULL) {
+ printf("Illegal selection:"
+ " bank %ld, dir_block # %ld\n",
+ i, j);
+ return 1;
+ }
+
+ printf("bank #%ld, dir-block #%ld:"
+ " RedBoot FIS @%p\n",
+ bank, dir_block, fis);
+ bank = i;
+ dir_block = j;
+ return 0;
+ }
+
+ if (strcmp(argv[2], "list") == 0) {
+
+ fis = redboot_fis_get(bank, dir_block, NULL);
+ if (fis == NULL) {
+ printf("Illegal selection:"
+ " bank %ld, dir_block # %ld\n",
+ bank, dir_block);
+ return 1;
+ }
+
+ printf("\nbank #%ld, dir-block #%ld:"
+ " RedBoot FIS @%p\n", bank, dir_block,
+ fis);
+
+ redboot_fis_list(&flash_info[bank-1], fis);
+
+ return 0;
+ }
+
+ if (strcmp(argv[2], "setenv") == 0) {
+
+ if (argc < 6)
+ goto usage;
+
+ var = argv[3];
+ name = argv[5];
+
+ fis = redboot_fis_get(bank, dir_block, NULL);
+ if (fis == NULL) {
+ printf("Illegal selection:"
+ " bank %ld, dir_block # %ld\n",
+ bank, dir_block);
+ return 1;
+ }
+
+ i = redboot_fis_setenv(&flash_info[bank-1], fis, name,
+ argv[4], var);
+ if (i != 0) {
+ printf("Unable to set var '%s' from '%s'\n",
+ argv[4], name);
+ return 1;
+ }
+
+ return 0;
+ }
+ }
+
+ if (strcmp(argv[1], "config") == 0) {
+
+ if (argc < 3)
+ goto usage;
+
+ fis = redboot_fis_get(bank, dir_block, NULL);
+ if (fis == NULL) {
+ printf("Illegal selection:"
+ " bank %ld, dir_block # %ld\n",
+ bank, dir_block);
+ return 1;
+ }
+
+ if (strcmp(argv[2], "printenv") == 0) {
+
+ if (argc >= 5) {
+ value = redboot_config_getenv(
+ &flash_info[bank-1],
+ fis, small_buf,
+ argv[3], argv[4]);
+ if (value)
+ printf("%s=%s\n", argv[3], value);
+ } else
+ redboot_config_printenv(
+ &flash_info[bank-1],
+ fis, small_buf,
+ argc >= 4 ? argv[3] : NULL);
+
+ return 0;
+ }
+
+ if (strcmp(argv[2], "setenv") == 0) {
+
+ if (argc < 5)
+ goto usage;
+
+ i = redboot_config_setenv(&flash_info[bank-1], fis,
+ argv[3], argv[4], argc >= 6 ? argv[5] : NULL);
+ if (i != 0) {
+ printf("Failed to set variable\n");
+ return 1;
+ }
+
+ return 0;
+ }
+ }
+
+#ifdef CONFIG_PPC
+ if (strcmp(argv[1], "exec") == 0) {
+ ulong addr, ramdisk_start, ramdisk_length;
+
+ addr = 0;
+ ramdisk_start = 0;
+ ramdisk_length = 0;
+
+ if (argc >= 3)
+ addr = simple_strtoul(argv[2], NULL, 16);
+ else if ((value = getenv("loadaddr")) != NULL)
+ addr = simple_strtoul(value, NULL, 16);
+ else if ((value = getenv("redboot_kernel_address")) != NULL)
+ addr = simple_strtoul(value, NULL, 16);
+ else {
+ printf("Kernel address not found\n");
+ goto usage;
+ }
+
+ if ((value = getenv("redboot_ramdisk_address")) != NULL)
+ ramdisk_start = simple_strtoul(value, NULL, 16);
+
+ if ((value = getenv("redboot_ramdisk_length")) != NULL)
+ ramdisk_length = simple_strtoul(value, NULL, 16);
+
+ redboot_linux_exec(addr, ramdisk_start, ramdisk_length);
+ }
+
+#endif
+
+usage:
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+}
+
+
+U_BOOT_CMD(
+ redboot, 6, 1, do_redboot,
+ "redboot - redboot support commands\n",
+ "select ([bank] [sector] | reset)\n"
+ " - Select FIS\n"
+ "redboot fis list\n"
+ " - List FIS\n"
+ "redboot fis setenv var type name\n"
+ " - Set variable var to the type variable of the image\n"
+ " type: flash_base, mem_base, size, entry_point, data_length\n"
+ "redboot config printenv [cfgvar] [member]\n"
+ " - Print Redboot config key(s) of [member] of [cfgvar]\n"
+ "redboot config setenv var cfgvar [member]\n"
+ " - Print Redboot config key(s) of [member] of cfgvar\n"
+#ifdef CONFIG_PPC
+ "redboot exec [address]\n"
+ " - Boot a Linux kernel compiled for redboot\n"
+#endif
+ "" /* last empty string */
+);
+
+#endif
+
diff --git a/include/redboot.h b/include/redboot.h
new file mode 100644
index 0000000..620fe86
--- /dev/null
+++ b/include/redboot.h
@@ -0,0 +1,98 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on Linux & RedBoot code fragments
+ * by David Woodhouse, dwmw2 at infradead.org
+ * by Mark Sattler, msalter at redhat.com
+ * by Gary Thomas, gthomas at redhat.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef REDBOOT_H
+#define REDBOOT_H
+
+#include <common.h>
+#include <flash.h>
+
+struct fis_image_desc {
+ u8 name[16]; /* Null terminated name */
+ u32 flash_base; /* Address within FLASH of image */
+ u32 mem_base; /* Address in memory where it executes */
+ u32 size; /* Length of image */
+ u32 entry_point; /* Execution entry point */
+ u32 data_length; /* Length of actual data */
+ u8 _pad[256-(16+7*sizeof(u32))];
+ u32 desc_cksum; /* Checksum over image descriptor */
+ u32 file_cksum; /* Checksum over image data */
+};
+
+/*
+ * redboot config is stored like this
+ * note that we don't define it, since we can work
+ * without having a fixed size config
+ *
+ * struct redboot_config {
+ * u32 len;
+ * u32 key1;
+ * char config_data[MAX_CONFIG_DATA-(4*4)];
+ * u32 key2;
+ * u32 long cksum;
+ * };
+ *
+ */
+
+/* defaults */
+#ifndef CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK
+#define CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK -1 /* last block */
+#endif
+
+#ifndef CONFIG_REDBOOT_DIRECTORY_ENTRY_SIZE
+#define CONFIG_REDBOOT_DIRECTORY_ENTRY_SIZE 0x100 /* default */
+#endif
+
+#ifndef CONFIG_REDBOOT_FLASH_SCRIPT_SIZE
+#define CONFIG_REDBOOT_FLASH_SCRIPT_SIZE 256
+#endif
+
+#ifndef CONFIG_REDBOOT_FLASH_STRING_SIZE
+#define CONFIG_REDBOOT_FLASH_STRING_SIZE 128
+#endif
+
+#ifndef CONFIG_REDBOOT_FLASH_CONFIG_SIZE
+#define CONFIG_REDBOOT_FLASH_CONFIG_SIZE 4096
+#endif
+
+void *redboot_fis_get(int bank, int dir_block, flash_info_t **infop);
+int redboot_fis_list(flash_info_t *info, void *fis);
+int redboot_fis_entry_lookup(flash_info_t *info, void *fis,
+ struct fis_image_desc *fis_buf, const char *name);
+int redboot_fis_setenv(flash_info_t *info, void *fis,
+ const char *name, const char *what, char *var);
+
+int redboot_config_printenv(flash_info_t *info, void *fis,
+ char *small_buf, const char *what);
+const char *redboot_config_getenv(flash_info_t *info, void *fis,
+ char *small_buf, const char *what, const char *special);
+int redboot_config_setenv(flash_info_t *info, void *fis,
+ const char *var, const char *what, const char *special);
+
+#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 6/8] Support Analogue Micro's ASP8347DB board. CONFIG file.
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
` (3 preceding siblings ...)
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 5/8] Adds support for RedBoot Pantelis Antoniou
@ 2006-12-02 22:16 ` Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 7/8] Support Analogue Micro's ASP8347DB board. Implementation Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 8/8] Pantelis Antoniou MAINTAINER update Pantelis Antoniou
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:16 UTC (permalink / raw)
To: u-boot
Add support for Analogue Micro's ASP8347DB board.
The board is originally shipped with RedBoot.
All appropriate settings are migrated to u-boot & the
old kernel booted; a drop in bootloader replacement.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
include/configs/ASP8347DB.h | 690 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 690 insertions(+), 0 deletions(-)
diff --git a/include/configs/ASP8347DB.h b/include/configs/ASP8347DB.h
new file mode 100644
index 0000000..83ffb7b
--- /dev/null
+++ b/include/configs/ASP8347DB.h
@@ -0,0 +1,690 @@
+/*
+ * (C) Copyright 2006
+ * Pantelis Antoniou, Embedded Alley pantelis at embeddedalley.com
+ *
+ * Based on TQM834x by
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * ASP8347DB board configuration file
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define DEBUG
+#undef DEBUG
+
+/*
+ * High Level Configuration Options
+ */
+#define CONFIG_E300 1 /* E300 Family */
+#define CONFIG_MPC83XX 1 /* MPC83XX family */
+#define CONFIG_MPC834X 1 /* MPC834X specific */
+#define CONFIG_MPC8349 1 /* MPC8349 specific */
+#define CONFIG_ASP8347DB 1 /* ASP8347DB board specific */
+
+/* IMMR Base Addres Register, use Freescale default: 0xff400000 */
+#define CFG_IMMR 0xff000000
+
+/* System clock. Primary input clock when in PCI host mode */
+#define CONFIG_83XX_CLKIN 66666000 /* 66,666 MHz */
+
+/*
+ * Local Bus LCRR
+ * LCRR: DLL bypass, Clock divider is 8
+ *
+ * for CSB = 266 MHz it gives LCB clock frequency = 33 MHz
+ *
+ * External Local Bus rate is
+ * CLKIN * HRCWL_CSB_TO_CLKIN / HRCWL_LCL_BUS_TO_SCB_CLK / LCRR_CLKDIV
+ */
+#define CFG_LCRR (LCRR_DBYP | LCRR_CLKDIV_8)
+
+/* board pre init: do not call, nothing to do */
+#undef CONFIG_BOARD_EARLY_INIT_F
+
+/* detect the number of flash banks */
+#define CONFIG_BOARD_EARLY_INIT_R
+
+/* auto complete please */
+#define CONFIG_AUTO_COMPLETE
+
+/*
+ * DDR Setup
+ */
+#define CFG_DDR_BASE 0x00000000 /* DDR is system memory */
+#define CFG_SDRAM_BASE CFG_DDR_BASE
+#define CFG_SDRAM_SIZE 128
+#define CFG_DDR_SDRAM_BASE CFG_DDR_BASE
+#define DDR_CASLAT_25 /* CASLAT set to 2.5 */
+#undef CONFIG_DDR_ECC /* only for ECC DDR module */
+#undef CONFIG_SPD_EEPROM /* do not use SPD EEPROM for DDR setup */
+
+#define CFG_MEMTEST_START 0x00100000 /* memtest region */
+#define CFG_MEMTEST_END 0x00200000
+
+/*
+ * FLASH on the Local Bus
+ */
+#define CFG_FLASH_CFI /* use the Common Flash Interface */
+#define CFG_FLASH_CFI_DRIVER /* use the CFI driver */
+#undef CFG_FLASH_CHECKSUM
+#define CFG_FLASH_BASE 0xf0000000 /* start of FLASH */
+#define CFG_FLASH_SIZE 64 /* FLASH size in MB */
+
+/* buffered writes in the AMD chip set is not supported yet */
+#undef CFG_FLASH_USE_BUFFER_WRITE
+
+/*
+ * FLASH bank number detection
+ */
+
+#define CFG_MAX_FLASH_BANKS 1
+#define CFG_MAX_FLASH_SECT 512 /* max sectors per device */
+
+/* 32 bit device at 0x80000000 via GPCM (0x8000_1801) */
+#define CFG_BR0_PRELIM ((CFG_FLASH_BASE & BR_BA) | \
+ BR_MS_GPCM | BR_PS_16 | BR_V)
+
+/* FLASH timing */
+#define CFG_OR_TIMING_FLASH (OR_GPCM_CSNT | OR_GPCM_BCTLD | \
+ OR_GPCM_CSNT | OR_GPCM_ACS_0b11 | \
+ OR_GPCM_SCY_7 | OR_GPCM_TRLX | \
+ OR_GPCM_EHTR)
+
+#define CFG_PRELIM_OR_AM 0xfc000000 /* OR addr mask: 64MB */
+
+#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH)
+
+#define CFG_LBLAWAR0_PRELIM 0x8000001c /* 32 MB size (2^(size + 1)) */
+#define CFG_LBLAWBAR0_PRELIM CFG_FLASH_BASE /* Window base at flash base */
+
+#define ASP8347DB_FPGA_BASE 0xf8000000
+
+/* FPGA : 32bit */
+#define CFG_BR1_PRELIM ((ASP8347DB_FPGA_BASE & BR_BA) | \
+ BR_MS_GPCM | BR_PS_32 | BR_V)
+#define CFG_OR1_PRELIM (0xffff0000 | OR_GPCM_ACS_0b11 | \
+ OR_GPCM_SCY_15 | OR_GPCM_TRLX | \
+ OR_GPCM_EHTR)
+#define CFG_LBLAWBAR1_PRELIM ASP8347DB_FPGA_BASE
+#define CFG_LBLAWAR1_PRELIM 0x80000016
+
+/* disable remaining mappings */
+#define CFG_BR2_PRELIM 0x00000000
+#define CFG_OR2_PRELIM 0x00000000
+#define CFG_LBLAWBAR2_PRELIM 0x00000000
+#define CFG_LBLAWAR2_PRELIM 0x00000000
+
+#define CFG_BR3_PRELIM 0x00000000
+#define CFG_OR3_PRELIM 0x00000000
+#define CFG_LBLAWBAR3_PRELIM 0x00000000
+#define CFG_LBLAWAR3_PRELIM 0x00000000
+
+#define CFG_BR4_PRELIM 0x00000000
+#define CFG_OR4_PRELIM 0x00000000
+#define CFG_LBLAWBAR4_PRELIM 0x00000000
+#define CFG_LBLAWAR4_PRELIM 0x00000000
+
+#define CFG_BR5_PRELIM 0x00000000
+#define CFG_OR5_PRELIM 0x00000000
+#define CFG_LBLAWBAR5_PRELIM 0x00000000
+#define CFG_LBLAWAR5_PRELIM 0x00000000
+
+#define CFG_BR6_PRELIM 0x00000000
+#define CFG_OR6_PRELIM 0x00000000
+#define CFG_LBLAWBAR6_PRELIM 0x00000000
+#define CFG_LBLAWAR6_PRELIM 0x00000000
+
+#define CFG_BR7_PRELIM 0x00000000
+#define CFG_OR7_PRELIM 0x00000000
+#define CFG_LBLAWBAR7_PRELIM 0x00000000
+#define CFG_LBLAWAR7_PRELIM 0x00000000
+
+/*
+ * Monitor config
+ */
+#define CFG_MONITOR_BASE TEXT_BASE
+
+#if (CFG_MONITOR_BASE < CFG_FLASH_BASE)
+#define CFG_RAMBOOT
+#else
+#undef CFG_RAMBOOT
+#endif
+
+#define CONFIG_L1_INIT_RAM
+#define CFG_INIT_RAM_LOCK 1
+#define CFG_INIT_RAM_ADDR 0xFD000000 /* Initial RAM address */
+#define CFG_INIT_RAM_END 0x1000 /* End of used area in RAM */
+
+#define CFG_GBL_DATA_SIZE 0x100 /* num bytes initial data */
+#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+
+#define CFG_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Mon */
+#define CFG_MALLOC_LEN (128 * 1024) /* Reserved for malloc */
+
+/*
+ * Serial Port
+ */
+#define CONFIG_CONS_INDEX 1
+#undef CONFIG_SERIAL_SOFTWARE_FIFO
+#define CFG_NS16550
+#define CFG_NS16550_SERIAL
+#define CFG_NS16550_REG_SIZE 1
+#define CFG_NS16550_CLK get_bus_freq(0)
+
+#define CFG_BAUDRATE_TABLE \
+ {300, 600, 1200, 2400, 4800, 9600, 19200, 38400,115200}
+
+#define CFG_NS16550_COM1 (CFG_IMMR + 0x4500)
+#define CFG_NS16550_COM2 (CFG_IMMR + 0x4600)
+
+/*
+ * I2C
+ */
+#undef CONFIG_HARD_I2C /* I2C with hardware support */
+#undef CONFIG_SOFT_I2C /* I2C bit-banged */
+#define CFG_I2C_SPEED 400000 /* I2C speed: 400KHz */
+#define CFG_I2C_SLAVE 0x7F /* slave address */
+#define CFG_I2C_OFFSET 0x3000
+
+/*
+ * TSEC
+ */
+#define CONFIG_TSEC_ENET /* tsec ethernet support */
+#define CONFIG_MII
+
+#define CFG_TSEC1_OFFSET 0x24000
+#define CFG_TSEC1 (CFG_IMMR + CFG_TSEC1_OFFSET)
+#define CFG_TSEC2_OFFSET 0x25000
+#define CFG_TSEC2 (CFG_IMMR + CFG_TSEC2_OFFSET)
+
+#if defined(CONFIG_TSEC_ENET)
+
+#ifndef CONFIG_NET_MULTI
+#define CONFIG_NET_MULTI
+#endif
+
+#define CONFIG_MPC83XX_TSEC1 1
+#define CONFIG_MPC83XX_TSEC1_NAME "TSEC0"
+#define CONFIG_MPC83XX_TSEC2 1
+#define CONFIG_MPC83XX_TSEC2_NAME "TSEC1"
+#define TSEC1_PHY_ADDR 1
+#define TSEC2_PHY_ADDR 2
+#define TSEC1_PHYIDX 0
+#define TSEC2_PHYIDX 0
+
+/* Options are: TSEC[0-1] */
+#define CONFIG_ETHPRIME "TSEC0"
+
+#endif /* CONFIG_TSEC_ENET */
+
+/*
+ * General PCI
+ * Addresses are mapped 1-1.
+ */
+#define CONFIG_PCI
+
+#if defined(CONFIG_PCI)
+
+#define CONFIG_PCI_PNP /* do pci plug-and-play */
+#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */
+
+/* PCI1 host bridge */
+#define CFG_PCI1_MEM_BASE 0xc0000000
+#define CFG_PCI1_MEM_PHYS CFG_PCI1_MEM_BASE
+#define CFG_PCI1_MEM_SIZE 0x20000000 /* 512M */
+#define CFG_PCI1_IO_BASE 0xe2000000
+#define CFG_PCI1_IO_PHYS CFG_PCI1_IO_BASE
+#define CFG_PCI1_IO_SIZE 0x1000000 /* 16M */
+
+
+#undef CONFIG_EEPRO100
+#define CONFIG_EEPRO100
+#undef CONFIG_TULIP
+
+#if !defined(CONFIG_PCI_PNP)
+ #define PCI_ENET0_IOADDR CFG_PCI1_IO_BASE
+ #define PCI_ENET0_MEMADDR CFG_PCI1_MEM_BASE
+ #define PCI_IDSEL_NUMBER 0x1c /* slot0 (IDSEL) = 28 */
+#endif
+
+#define CFG_PCI_SUBSYS_VENDORID 0x1957 /* Freescale */
+
+#endif /* CONFIG_PCI */
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#ifndef CFG_RAMBOOT
+#define CFG_ENV_IS_IN_FLASH 1
+#define CFG_ENV_ADDR (CFG_MONITOR_BASE + 0x40000)
+#define CFG_ENV_SECT_SIZE 0x10000 /* 64K(one sector) for env */
+#define CFG_ENV_SIZE 0x2000
+#else
+#define CFG_NO_FLASH 1 /* Flash is not usable now */
+#define CFG_ENV_IS_NOWHERE 1 /* Store ENV in memory only */
+#define CFG_ENV_ADDR (CFG_MONITOR_BASE - 0x1000)
+#define CFG_ENV_SIZE 0x2000
+#endif
+
+#define CONFIG_LOADS_ECHO 1 /* echo on serial download */
+#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */
+
+/* Common commands */
+#define CFG_CMD_ASP8347DB_COMMON CFG_CMD_PING \
+ | CFG_CMD_MII | CFG_CMD_JFFS2
+
+#if defined(CFG_RAMBOOT)
+
+#if defined(CONFIG_PCI)
+#define CONFIG_COMMANDS ((CONFIG_CMD_DFL | CFG_CMD_PCI \
+ | CFG_CMD_ASP8347DB_COMMON) \
+ & \
+ ~(CFG_CMD_ENV | CFG_CMD_LOADS))
+#else
+#define CONFIG_COMMANDS ((CONFIG_CMD_DFL \
+ | CFG_CMD_ASP8347DB_COMMON) \
+ & \
+ ~(CFG_CMD_ENV | CFG_CMD_LOADS))
+#endif
+
+#else /* CFG_RAMBOOT */
+
+#if defined(CONFIG_PCI)
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_PCI \
+ | CFG_CMD_ASP8347DB_COMMON)
+#else
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL \
+ | CFG_CMD_ASP8347DB_COMMON)
+#endif
+
+#endif /* CFG_RAMBOOT */
+
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_LOAD_ADDR 0x2000000 /* default load address */
+#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+
+#define CONFIG_CMDLINE_EDITING 1 /* add command line history */
+#define CFG_HUSH_PARSER 1 /* Use the HUSH parser */
+#ifdef CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2 "> "
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* print buffer size */
+#define CFG_MAXARGS 16 /* max num of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* boot arg buffer size */
+#define CFG_HZ 1000 /* decrementer freq: 1ms */
+
+#undef CONFIG_WATCHDOG /* watchdog disabled */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
+
+/*
+ * Cache Configuration
+ */
+#define CFG_DCACHE_SIZE 32768
+#define CFG_CACHELINE_SIZE 32
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT 5 /*log base 2 of the above value*/
+#endif
+
+#define CFG_HRCW_LOW ( \
+ HRCWL_LCL_BUS_TO_SCB_CLK_1X1 | \
+ HRCWL_DDR_TO_SCB_CLK_1X1 | \
+ HRCWL_CSB_TO_CLKIN_4X1 | \
+ HRCWL_VCO_BYPASS | \
+ HRCWL_CORE_TO_CSB_1_5X1)
+
+#define CFG_HRCW_HIGH ( \
+ HRCWH_PCI_HOST | \
+ HRCWH_32_BIT_PCI | \
+ HRCWH_PCI1_ARBITER_ENABLE | \
+ HRCWH_PCI2_ARBITER_DISABLE | \
+ HRCWH_CORE_ENABLE | \
+ HRCWH_FROM_0X00000100 | \
+ HRCWH_BOOTSEQ_DISABLE | \
+ HRCWH_SW_WATCHDOG_DISABLE | \
+ HRCWH_ROM_LOC_LOCAL_16BIT | \
+ HRCWH_TSEC1M_IN_GMII | \
+ HRCWH_TSEC2M_IN_GMII)
+
+/* System IO Config */
+#if 0
+#define CFG_SICRH SICRH_TSOBI1
+#define CFG_SICRL SICRL_LDP_A
+#else
+#define CFG_SICRH 0x000000a0
+#define CFG_SICRL 0x80000000
+#endif
+
+/* i-cache and d-cache disabled */
+#define CFG_HID0_INIT 0x000000000
+#define CFG_HID0_FINAL CFG_HID0_INIT
+#define CFG_HID2 HID2_HBE
+
+/* DDR 0 - 128 */
+#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | \
+ BATL_MEMCOHERENCE)
+#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | \
+ BATU_VS | BATU_VP)
+
+/* DCACHE */
+#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | \
+ BATL_MEMCOHERENCE)
+#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | \
+ BATU_VS | BATU_VP)
+
+#define CFG_IBAT2L 0
+#define CFG_IBAT2U 0
+
+/* PCI */
+#ifdef CONFIG_PCI
+#define CFG_IBAT3L (CFG_PCI1_MEM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
+#define CFG_IBAT3U (CFG_PCI1_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+#define CFG_IBAT4L (CFG_PCI1_MEM_BASE + 0x10000000 | BATL_PP_10 | \
+ BATL_MEMCOHERENCE)
+#define CFG_IBAT4U (CFG_PCI1_MEM_BASE + 0x10000000 | BATU_BL_256M | \
+ BATU_VS | BATU_VP)
+#define CFG_IBAT5L (CFG_PCI1_IO_BASE | BATL_PP_10 | BATL_CACHEINHIBIT | \
+ BATL_GUARDEDSTORAGE)
+#define CFG_IBAT5U (CFG_PCI1_IO_BASE + 0x10000000 | BATU_BL_16M | \
+ BATU_VS | BATU_VP)
+#else
+#define CFG_IBAT3L (0)
+#define CFG_IBAT3U (0)
+#define CFG_IBAT4L (0)
+#define CFG_IBAT4U (0)
+#define CFG_IBAT5L (0)
+#define CFG_IBAT5U (0)
+#endif
+
+/* IMMR */
+#define CFG_IBAT6L (CFG_IMMR | BATL_PP_10 | BATL_CACHEINHIBIT | \
+ BATL_GUARDEDSTORAGE)
+#define CFG_IBAT6U (CFG_IMMR | BATU_BL_1M | BATU_VS | BATU_VP)
+
+/* FLASH */
+#define CFG_IBAT7L (CFG_FLASH_BASE | BATL_PP_10 | BATL_CACHEINHIBIT | \
+ BATL_GUARDEDSTORAGE)
+#define CFG_IBAT7U (CFG_FLASH_BASE | BATU_BL_256M | BATU_VS | BATU_VP)
+
+#define CFG_DBAT0L CFG_IBAT0L
+#define CFG_DBAT0U CFG_IBAT0U
+#define CFG_DBAT1L CFG_IBAT1L
+#define CFG_DBAT1U CFG_IBAT1U
+#define CFG_DBAT2L CFG_IBAT2L
+#define CFG_DBAT2U CFG_IBAT2U
+#define CFG_DBAT3L CFG_IBAT3L
+#define CFG_DBAT3U CFG_IBAT3U
+#define CFG_DBAT4L CFG_IBAT4L
+#define CFG_DBAT4U CFG_IBAT4U
+#define CFG_DBAT5L CFG_IBAT5L
+#define CFG_DBAT5U CFG_IBAT5U
+#define CFG_DBAT6L CFG_IBAT6L
+#define CFG_DBAT6U CFG_IBAT6U
+#define CFG_DBAT7L CFG_IBAT7L
+#define CFG_DBAT7U CFG_IBAT7U
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM 0x02 /* Software reboot */
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE 230400 /* speed of kgdb serial port */
+#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */
+#endif
+
+/*
+ * Environment Configuration
+ */
+
+#if defined(CONFIG_TSEC_ENET)
+#define CONFIG_ETHADDR D2:DA:5E:44:BC:29
+#define CONFIG_HAS_ETH1
+#define CONFIG_ETH1ADDR 1E:F3:40:21:92:53
+#endif
+
+#define CONFIG_IPADDR 192.168.1.249
+
+#define CONFIG_HOSTNAME asp8347db
+#define CONFIG_ROOTPATH /exports/asp8347db-root
+#define CONFIG_BOOTFILE uImage-rattler
+
+#define CONFIG_SERVERIP 192.168.1.10
+#define CONFIG_GATEWAYIP 192.168.1.1
+#define CONFIG_NETMASK 255.255.255.0
+
+#define CONFIG_LOADADDR 200000 /* default for tftp and bootm */
+
+#define CONFIG_BOOTDELAY 6 /* -1 disables auto-boot */
+#undef CONFIG_BOOTARGS /* the boot command will set bootargs */
+
+#define CONFIG_BAUDRATE 38400
+
+#define CONFIG_PREBOOT "echo;" \
+ "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \
+ "echo"
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "hostname=asp8347db\0" \
+ "nfsargs=setenv bootargs root=/dev/nfs rw " \
+ "nfsroot=${serverip}:${rootpath}\0" \
+ "ramargs=setenv bootargs root=/dev/ram rw\0" \
+ "addip=setenv bootargs ${bootargs} " \
+ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
+ ":${hostname}:${netdev}:off panic=1\0" \
+ "addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\
+ "flash_nfs=run nfsargs addip addtty;" \
+ "bootm ${kernel_addr}\0" \
+ "flash_self=run ramargs addip addtty;" \
+ "bootm ${kernel_addr} ${ramdisk_addr}\0" \
+ "net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;" \
+ "bootm\0" \
+ "rootpath=/exports/asp8347db-root\0" \
+ "bootfile=uImage-rattler\0" \
+ "kernel_addr=80060000\0" \
+ "ramdisk_addr=80160000\0" \
+ "load=tftp 100000 /tftpboot/asp8347db/u-boot.bin\0" \
+ "update=protect off 80000000 8003ffff; " \
+ "era 80000000 8003ffff; cp.b 100000 80000000 40000\0" \
+ "upd=run load;run update\0" \
+ ""
+
+#define CONFIG_BOOTCOMMAND "run flash_self"
+
+/*
+ * JFFS2 partitions
+ */
+/* mtdparts command line support */
+#define CONFIG_JFFS2_CMDLINE
+#define MTDIDS_DEFAULT "nor0=ASP8347DB"
+
+/* default mtd partition table */
+#define MTDPARTS_DEFAULT "mtdparts=ASP8347DB:" \
+ "256k(u-boot),64k(env),64k(env2)," \
+ "64k(ASP8347DB.FPGA)," \
+ "4m(jffs2),1m(Linux)," \
+ "27136k(spare)," \
+ "64k(RedBoot);"\
+/*
+ * Lattice FPGA configuration support
+ */
+#define CONFIG_FPGA_COUNT 1
+#define CONFIG_FPGA CFG_LATTICE_EC
+#define CFG_FPGA_PROG_FEEDBACK
+
+/*
+ * Enable the call to misc_init_r() for miscellaneous platform
+ * dependent initialization.
+ */
+#define CONFIG_MISC_INIT_R
+
+/*
+ * Enable call to last_stage_init()
+ */
+#define CONFIG_LAST_STAGE_INIT
+
+/*
+ * RedBoot support (this is conditional to CFG_CMD_FLASH)
+ */
+#define CONFIG_REDBOOT 1
+#define CONFIG_REDBOOT_FLASH_SCRIPT_SIZE 512
+#define CONFIG_REDBOOT_FLASH_CONFIG_SIZE 65536
+
+#ifndef __ASSEMBLY__
+
+/* Damn RedBoot has a totally different bd_t */
+typedef struct redboot_bd_info {
+ unsigned int bi_tag; /* Should be 0x42444944 "BDID" */
+ unsigned int bi_size; /* Size of this structure */
+ unsigned int bi_revision; /* revision of this structure */
+ unsigned int bi_bdate; /* bootstrap date, i.e. 0x19971106 */
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in Hz */
+ unsigned int bi_cpmfreq; /* CPM Freq, in Hz */
+ unsigned int bi_brgfreq; /* BRG Freq, in Hz */
+ unsigned int bi_vco; /* VCO Out from PLL */
+ unsigned int bi_pci_freq; /* PCI Freq, in Hz */
+ unsigned int bi_baudrate; /* Default console baud rate */
+ unsigned int bi_immr; /* IMMR when called from boot rom */
+ unsigned char bi_enetaddr[6];
+ unsigned int bi_flashbase; /* Physical address of FLASH memory */
+ unsigned int bi_flashsize; /* Length of FLASH memory */
+ int bi_flashwidth; /* Width (8,16,32,64) */
+ unsigned char *bi_cmdline; /* Pointer to command line */
+ unsigned char bi_esa[3][6]; /* Ethernet station addresses */
+ unsigned int bi_ramdisk_begin;
+ unsigned int bi_ramdisk_end;
+ struct { /* info about [main] video screen */
+ short x_res; /* Horizontal resolution in pixels */
+ short y_res; /* Vertical resolution in pixels */
+ short bpp; /* Bits/pixel */
+ short mode; /* Type of pixels (packed, indexed) */
+ unsigned long fb; /* frame buffer (pixel) memory */
+ } bi_video;
+ void (*bi_cputc)(char); /* Write a character */
+ char (*bi_cgetc)(void); /* Read a character */
+ int (*bi_ctstc)(void); /* Test for input */
+} redboot_bd_t;
+
+#endif
+
+#define CONFIG_REDBOOT_BD_T_SIZE sizeof(redboot_bd_t)
+
+/*
+ * Status LEDs
+ */
+#define CONFIG_STATUS_LED 1 /* Status LED enabled */
+#define CONFIG_BOARD_SPECIFIC_LED /* board has board specific leds */
+
+#define STATUS_LED_BIT LED1
+
+#define STATUS_LED_PERIOD (CFG_HZ / 2)
+#define STATUS_LED_STATE STATUS_LED_BLINKING
+
+#define STATUS_LED_ACTIVE 1 /* LED on for bit == 0 */
+#define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
+
+#ifndef __ASSEMBLY__
+
+/* LEDs */
+
+/* led_id_t is unsigned int mask */
+typedef unsigned int led_id_t;
+
+#define __led_toggle(_msk) \
+ do { \
+ ((volatile immap_t *)CFG_IMMR)->pgio[0].dat ^= (_msk); \
+ } while(0)
+
+#define __led_set(_msk, _st) \
+ do { \
+ if ((_st)) \
+ ((volatile immap_t *)CFG_IMMR)->pgio[0].dat |= \
+ (_msk); \
+ else \
+ ((volatile immap_t *)CFG_IMMR)->pgio[0].dat &= \
+ ~(_msk); \
+ } while(0)
+
+#define __led_init(msk, st) __led_set(msk, st)
+
+#endif
+
+/*
+ * GPIOS
+ */
+
+/* easy powerpc bit defines */
+#define _B(x) (1 << (31 - (x)))
+
+/* GPIO1 */
+#define ECP_TMS _B(2) /* FPGA programming */
+#define ECP_TCK _B(3)
+#define ECP_TDI _B(4)
+#define ECP_TDO _B(5)
+#define FPGA_RST _B(6) /* FPGA reset */
+#define USB0_RST _B(7) /* USB0 reset */
+#define USB1_RST _B(8) /* USB1 reset */
+#define LED1 _B(9)
+#define LED2 _B(10)
+#define LED3 _B(11)
+#define LED4 _B(12)
+#define LED_ALL (LED1 | LED2 | LED3 /* | LED4 */ )
+
+/* GPIO2 */
+#define PHY1_RST _B(13) /* PHY1 reset */
+#define PHY2_RST _B(14) /* PHY2 reset */
+#define ETH_RST _B(19) /* Ethernet global reset */
+#define ETH_EN _B(18) /* Ethernet global enable */
+
+#endif /* __CONFIG_H */
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 7/8] Support Analogue Micro's ASP8347DB board. Implementation.
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
` (4 preceding siblings ...)
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 6/8] Support Analogue Micro's ASP8347DB board. CONFIG file Pantelis Antoniou
@ 2006-12-02 22:16 ` Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 8/8] Pantelis Antoniou MAINTAINER update Pantelis Antoniou
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:16 UTC (permalink / raw)
To: u-boot
Add support for Analogue Micro's ASP8347DB board.
The board is originally shipped with RedBoot.
All appropriate settings are migrated to u-boot & the
old kernel booted; a drop in bootloader replacement.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
MAKEALL | 3
Makefile | 3
board/asp8347db/Makefile | 52 ++++++
board/asp8347db/asp8347db.c | 371 +++++++++++++++++++++++++++++++++++++++++++
board/asp8347db/config.mk | 23 +++
board/asp8347db/fpga.c | 240 ++++++++++++++++++++++++++++
board/asp8347db/pci.c | 222 ++++++++++++++++++++++++++
board/asp8347db/u-boot.lds | 122 ++++++++++++++
include/status_led.h | 2
9 files changed, 1037 insertions(+), 1 deletions(-)
diff --git a/MAKEALL b/MAKEALL
index 74bf383..82ade78 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -130,7 +130,8 @@ LIST_8260=" \
#########################################################################
LIST_83xx=" \
- TQM834x MPC8349EMDS MPC8349ITX MPC8360EMDS \
+ ASP8347DB TQM834x MPC8349EMDS MPC8349ITX \
+ MPC8360EMDS \
"
diff --git a/Makefile b/Makefile
index d2534ab..4e5a78d 100644
--- a/Makefile
+++ b/Makefile
@@ -1588,6 +1588,9 @@ r5200_config : unconfig
## MPC83xx Systems
#########################################################################
+ASP8347DB_config: unconfig
+ @$(MKCONFIG) $(@:_config=) ppc mpc83xx asp8347db
+
TQM834x_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc mpc83xx tqm834x
diff --git a/board/asp8347db/Makefile b/board/asp8347db/Makefile
new file mode 100644
index 0000000..a865a9b
--- /dev/null
+++ b/board/asp8347db/Makefile
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS = $(BOARD).o fpga.o pci.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/asp8347db/asp8347db.c b/board/asp8347db/asp8347db.c
new file mode 100644
index 0000000..10551d3
--- /dev/null
+++ b/board/asp8347db/asp8347db.c
@@ -0,0 +1,371 @@
+/*
+ * (C) Copyright 2006
+ * Pantelis Antoniou, Embedded Alley, pantelis at embeddedalley.com
+ *
+ * Based on tqm384x.c by
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#define DEBUG
+
+#include <common.h>
+#include <ioports.h>
+#include <mpc83xx.h>
+#include <asm/mpc8349_pci.h>
+#include <i2c.h>
+#include <spd.h>
+#include <miiphy.h>
+#include <asm-ppc/mmu.h>
+#include <pci.h>
+
+#ifdef CONFIG_REDBOOT
+#include <redboot.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define IOSYNC asm("eieio")
+#define ISYNC asm("isync")
+#define SYNC asm("sync")
+#define FPW FLASH_PORT_WIDTH
+#define FPWV FLASH_PORT_WIDTHV
+
+#define DDR_MAX_SIZE_PER_CS 0x20000000
+
+#define TIMING_CASLAT TIMING_CFG1_CASLAT_25
+#define MODE_CASLAT DDR_MODE_CASLAT_25
+
+#define INITIAL_CS_CONFIG (CSCONFIG_EN | CSCONFIG_ROW_BIT_12 | \
+ CSCONFIG_COL_BIT_9)
+
+/* External definitions */
+ulong flash_get_size (ulong base, int banknum);
+extern flash_info_t flash_info[];
+
+/* Local variable */
+static volatile immap_t *im = (immap_t *)CFG_IMMR;
+
+/**************************************************************************
+ * Board initialzation after relocation to RAM. Used to detect the number
+ * of Flash banks on TQM834x.
+ */
+int board_early_init_r (void)
+{
+ /* sanity check, IMMARBAR should be mirrored at offset zero of IMMR */
+ if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im)
+ return 0;
+
+ /* setup GPIO ports */
+ im->pgio[0].dat = 0xc5f00000;
+ im->pgio[0].odr = 0;
+ im->pgio[0].dir = 0x3a700000;
+ im->pgio[0].imr = 0;
+ im->pgio[0].icr = 0;
+
+ im->pgio[1].dat = 0x00001000;
+ im->pgio[1].odr = 0;
+ im->pgio[1].dir = 0x00003000;
+ im->pgio[1].imr = 0;
+ im->pgio[1].icr = 0;
+
+ /* turn on all LEDS */
+ im->pgio[0].dat |= LED_ALL;
+ im->pgio[0].odr &= ~LED_ALL;
+ im->pgio[0].dir |= LED_ALL;
+
+ /* reset & enable ethernet */
+ udelay(100);
+ im->pgio[1].dat = (im->pgio[1].dat & ~ETH_RST) | ETH_EN;
+ udelay(100);
+ im->pgio[1].dat |= ETH_RST;
+ udelay(100);
+ im->pgio[1].dat &= ~ETH_EN;
+ udelay(100);
+
+ /* reset PHYs */
+ im->pgio[1].dat |= PHY1_RST | PHY2_RST;
+ udelay(250);
+ im->pgio[1].dat &= ~(PHY1_RST | PHY2_RST);
+ udelay(250);
+
+ /* turn off all leds */
+ im->pgio[0].dat &= ~LED_ALL;
+
+ return 0;
+}
+
+/**************************************************************************
+ * DRAM initalization and size detection
+ */
+long int initdram (int board_type)
+{
+ long size, known_size;
+
+ /* 128MB */
+ known_size = 128 << 20;
+
+ im->sysconf.ddrlaw[0].bar = 0;
+ im->sysconf.ddrlaw[0].ar = 0;
+
+ /* 128M */
+ im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE;
+ im->sysconf.ddrlaw[0].ar = LAWAR_EN | LAWAR_SIZE_128M;
+ im->sysconf.ddrlaw[1].bar = 0;
+ im->sysconf.ddrlaw[1].ar = 0;
+
+ /* set CS bounds to 128M */
+ im->ddr.sdram_cfg = 0x02000000;
+ im->ddr.csbnds[0].csbnds = 0x00000007;
+ im->ddr.csbnds[1].csbnds = 0;
+ im->ddr.csbnds[2].csbnds = 0;
+ im->ddr.csbnds[3].csbnds = 0;
+ im->ddr.cs_config[0] = 0x80800101;
+ im->ddr.cs_config[1] = 0;
+ im->ddr.cs_config[2] = 0;
+ im->ddr.cs_config[3] = 0;
+ im->ddr.timing_cfg_1 = 0x36332321;
+ im->ddr.timing_cfg_2 = 0x02000400;
+ im->ddr.sdram_cfg = 0x02000000;
+ im->ddr.sdram_mode = 0x00000062;
+ SYNC;
+
+ im->ddr.sdram_interval = 0x03e80000;
+ im->ddr.sdram_clk_cntl = 0x81000000;
+ SYNC;
+
+ /* the errata workaround from TQM does not work */
+ /* I don't really know why, */
+
+ udelay(200);
+
+ im->ddr.sdram_cfg = 0xc2000000;
+ SYNC;
+
+ udelay(1000);
+
+ /* size detection */
+ debug("\n");
+ size = get_ram_size(CFG_DDR_BASE, known_size);
+ if (size != known_size)
+ debug("Detected other size than what expected!\n");
+
+ return size;
+}
+
+/**************************************************************************
+ * checkboard()
+ */
+int checkboard (void)
+{
+ puts("Board: ASP8347DB\n");
+
+#ifdef CONFIG_PCI
+ volatile immap_t * immr;
+ u32 w, f;
+
+ immr = (immap_t *)CFG_IMMR;
+ if (!(immr->reset.rcwh & RCWH_PCIHOST)) {
+ printf("PCI: NOT in host mode..?!\n");
+ return 0;
+ }
+
+ /* get bus width */
+ w = 32;
+ if (immr->reset.rcwh & RCWH_PCI64)
+ w = 64;
+
+ /* get clock */
+ f = gd->pci_clk;
+
+ printf("PCI1: %d bit, %d MHz\n", w, f / 1000000);
+#else
+ printf("PCI: disabled\n");
+#endif
+ return 0;
+}
+
+/* in fpga.c */
+extern int asp8347db_init_fpga(void);
+extern int asp8347db_autoload_fpga(void);
+
+/*
+ * Miscellaneous intialization
+ */
+int misc_init_r (void)
+{
+#ifdef CONFIG_FPGA
+ asp8347db_init_fpga();
+#endif
+ return 0;
+}
+
+/*
+ * Final init hook before entering command loop.
+ */
+int last_stage_init (void)
+{
+#ifdef CONFIG_REDBOOT
+ const char *s;
+ void *fis;
+ flash_info_t *info;
+ int migrated;
+ static const char *image_name = "ASP8347DB.FPGA";
+ ulong fpga_image_base = 0, fpga_image_size = 0;
+ ulong redboot_linux_base = 0, redboot_linux_size = 0;
+
+ /* we now migrate settings from redboot */
+ /* only we locate the FIS */
+ if ((s = getenv("redboot_migrated")) == NULL && *s != 'n' &&
+ (fis = redboot_fis_get(1, -1, &info)) != NULL) {
+
+ migrated = 0;
+
+ printf("REDB.:");
+
+ /* first snarf the FPGA image location from the FIS */
+ if (redboot_fis_setenv(info, fis, image_name, "flash_base",
+ "fpga_image_base") == 0 &&
+ (s = getenv("fpga_image_base")) != NULL)
+ fpga_image_base = simple_strtoul(s, NULL, 16);
+
+ if (redboot_fis_setenv(info, fis, image_name, "data_length",
+ "fpga_image_size") == 0 &&
+ (s = getenv("fpga_image_size")) != NULL)
+ fpga_image_size = simple_strtoul(s, NULL, 16);
+
+ if (fpga_image_base == 0 || fpga_image_size == 0) {
+ setenv("fpga_image_base", NULL);
+ setenv("fpga_image_size", NULL);
+ } else {
+ printf(" FPGA");
+ migrated += 2;
+ }
+
+ /* now get the ethernet addresses */
+ if (redboot_config_setenv(info, fis, "ethaddr",
+ "tsec1_esa", NULL) == 0 &&
+ getenv("ethaddr")) {
+ printf(" TSEC1");
+ migrated++;
+ }
+
+ if (redboot_config_setenv(info, fis, "eth1addr",
+ "tsec2_esa", NULL) == 0 &&
+ getenv("eth1addr")) {
+ printf(" TSEC2");
+ migrated++;
+ }
+
+ /* now get the linux image */
+ if (redboot_fis_setenv(info, fis, "Linux", "flash_base",
+ "redboot_linux_base") == 0 &&
+ (s = getenv("redboot_linux_base")) != NULL)
+ redboot_linux_base = simple_strtoul(s, NULL, 16);
+
+ if (redboot_fis_setenv(info, fis, "Linux", "data_length",
+ "redboot_linux_size") == 0 &&
+ (s = getenv("redboot_linux_size")) != NULL)
+ redboot_linux_size = simple_strtoul(s, NULL, 16);
+
+ if (redboot_linux_base == 0 || redboot_linux_size == 0) {
+ setenv("redboot_linux_base", NULL);
+ setenv("redboot_linux_size", NULL);
+ } else {
+ setenv("bootcmd", "redboot exec ${redboot_linux_base}");
+
+ printf(" Linux");
+ migrated += 2;
+ }
+
+ if (migrated > 0) {
+ printf(".\n");
+ setenv("redboot_migrated", "y");
+ } else {
+ printf("No variables migrated!\n");
+ }
+
+ }
+#endif
+
+#ifdef CONFIG_FPGA
+ asp8347db_autoload_fpga();
+#endif
+ return 0;
+}
+
+/* immediate return - no printing from redboot */
+volatile void __attribute__((noinline)) redboot_nothing(void) { }
+
+void board_redboot_bd_t_adapt(void *kbd,
+ ulong cmd_start, ulong cmd_end,
+ ulong initrd_start, ulong initrd_end)
+{
+ static bd_t ubd;
+ redboot_bd_t *rbd;
+
+ /* keep u-boot's idea of a bd_t */
+ ubd = *(bd_t *)kbd;
+
+ /* point redboot bd at the old uboot space
+ * we make sure that the area is large enough to hold both
+ */
+ rbd = kbd;
+ memset(rbd, 0, sizeof(*rbd));
+
+ /* now fill in redboot bd_t with the proper values */
+ rbd->bi_tag = 0x42444944;
+ rbd->bi_size = sizeof(*rbd);
+ rbd->bi_revision = 0x0102;
+ rbd->bi_bdate = 0x04012005;
+ rbd->bi_memstart = ubd.bi_memstart;
+ rbd->bi_memsize = ubd.bi_memsize;
+ rbd->bi_baudrate = ubd.bi_baudrate;
+ rbd->bi_cmdline = (unsigned char *)cmd_start;
+ memcpy(rbd->bi_enetaddr, ubd.bi_enetaddr, 6);
+ memcpy(rbd->bi_esa[0], ubd.bi_enetaddr, 6);
+#ifdef CONFIG_HAS_ETH1
+ memcpy(rbd->bi_esa[1], ubd.bi_enet1addr, 6);
+#endif
+#ifdef CONFIG_HAS_ETH2
+ memcpy(rbd->bi_esa[2], ubd.bi_enet2addr, 6);
+#endif
+#ifdef CONFIG_HAS_ETH3
+ memcpy(rbd->bi_esa[3], ubd.bi_enet3addr, 6);
+#endif
+ rbd->bi_ramdisk_begin = initrd_start;
+ rbd->bi_ramdisk_end = initrd_end;
+ rbd->bi_intfreq = ubd.bi_intfreq;
+ rbd->bi_busfreq = ubd.bi_busfreq;
+ rbd->bi_immr = ubd.bi_immrbar;
+ rbd->bi_flashbase = 0xf0000000;
+ rbd->bi_flashsize = 0x04000000;
+ rbd->bi_flashwidth = 16;
+
+ /* I/O functions */
+ /* we assume we don't overwrite them */
+ /* we are running pretty low & the stack is */
+ /* placed at the end of memory */
+ rbd->bi_cputc = (void *)redboot_nothing;
+ rbd->bi_cgetc = (void *)redboot_nothing;
+ rbd->bi_ctstc = (void *)redboot_nothing;
+}
+
diff --git a/board/asp8347db/config.mk b/board/asp8347db/config.mk
new file mode 100644
index 0000000..c3c8574
--- /dev/null
+++ b/board/asp8347db/config.mk
@@ -0,0 +1,23 @@
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+TEXT_BASE = 0xf0000000
diff --git a/board/asp8347db/fpga.c b/board/asp8347db/fpga.c
new file mode 100644
index 0000000..389ec56
--- /dev/null
+++ b/board/asp8347db/fpga.c
@@ -0,0 +1,240 @@
+/*
+ * (C) Copyright 2006 - Embedded Alley Solutions Inc.
+ * by Pantelis Antoniou, pantelis at embeddedalley.com
+ *
+ * Based on board/asp8347db/fpga.c
+ * (C) Copyright 2002
+ * by Rich Ireland, Enterasys Networks, rireland at enterasys.com.
+ * & Keith Outwater, keith_outwater at mvis.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/*
+ * EC FPGA configuration support for the ASP8437DB computer
+ */
+
+#include <common.h>
+#include <command.h>
+#include <watchdog.h>
+#include <flash.h>
+
+#include <lattice_ec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if (CONFIG_FPGA)
+
+#if 0
+#define ASP8437DB_FPGA_DEBUG
+#endif
+
+#ifdef ASP8437DB_FPGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+static void mdelay(int ms)
+{
+ ulong start = get_timer(0);
+ ulong delay;
+
+ delay = (ms * CFG_HZ) / 1000;
+ while (get_timer(start) < delay) {
+ udelay (1000);
+ WATCHDOG_RESET(); /* Trigger watchdog, if needed */
+ }
+}
+
+int rattler_fpga_loaded = 0;
+
+/****************************************************************/
+
+/* configure */
+static int rattler_pre_fn (int cookie)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+
+ PRINTF ("%s:%d:\n", __FUNCTION__, __LINE__);
+
+ im->pgio[0].dir &= ~(ECP_TMS | ECP_TCK | ECP_TDI | ECP_TDO | FPGA_RST);
+ im->pgio[0].dat |= ECP_TMS | ECP_TCK | ECP_TDI | FPGA_RST;
+ im->pgio[0].dir |= ECP_TMS | ECP_TCK | ECP_TDI | FPGA_RST;
+
+ /* and now reset */
+ im->pgio[0].dat |= FPGA_RST;
+ udelay(1000);
+ im->pgio[0].dat &= ~FPGA_RST;
+
+ rattler_fpga_loaded = 0;
+
+ return 0;
+}
+
+static int rattler_post_fn (int cookie, int success)
+{
+ PRINTF ("%s:%d:\n", __FUNCTION__, __LINE__);
+
+ if (!success)
+ return -1;
+
+ /* FLASH LEDs so we know FPGA is alive */
+ *(unsigned long *)(ASP8347DB_FPGA_BASE + 0xC) = 0x00; /* off */
+ mdelay(1000);
+ *(unsigned long *)(ASP8347DB_FPGA_BASE + 0xC) = 0x55; /* toggle */
+ mdelay(500);
+ *(unsigned long *)(ASP8347DB_FPGA_BASE + 0xC) = 0xAA; /* toggle */
+ mdelay(500);
+ *(unsigned long *)(ASP8347DB_FPGA_BASE + 0xC) = 0x00; /* off */
+
+ rattler_fpga_loaded = 1;
+
+ return 0;
+}
+
+static void rattler_jtag_write_port_fn(int cookie, unsigned int pin,
+ unsigned int val)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ u32 mask = 0;
+
+ switch (pin) {
+ case LATTICE_JTAG_TDI:
+ mask = ECP_TDI;
+ break;
+
+ case LATTICE_JTAG_TCK:
+ mask = ECP_TCK;
+ break;
+
+ case LATTICE_JTAG_TMS:
+ mask = ECP_TMS;
+ break;
+
+ case LATTICE_JTAG_RST:
+ mask = FPGA_RST;
+ break;
+
+ case LATTICE_JTAG_CE: /* not present */
+ break;
+
+ default:
+ PRINTF("Illegal pin %d\n", pin);
+ break;
+ }
+
+ /* not supported */
+ if (mask == 0)
+ return;
+
+ if (val)
+ im->pgio[0].dat |= mask;
+ else
+ im->pgio[0].dat &= ~mask;
+}
+
+static int rattler_jtag_read_port_fn(int cookie)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+
+ return !!(im->pgio[0].dat & ECP_TDO);
+}
+
+/* Note that these are pointers to code that is in Flash. They will be
+ * relocated at runtime.
+ */
+static Lattice_EC_JTAG_fns fpga_fns = {
+ .pre = rattler_pre_fn,
+ .post = rattler_post_fn,
+ .jtag_write_port = rattler_jtag_write_port_fn,
+ .jtag_read_port = rattler_jtag_read_port_fn,
+};
+
+Lattice_desc fpga[CONFIG_FPGA_COUNT] = {
+ {
+ Lattice_EC,
+ lattice_jtag_mode,
+ 65536, /* XXX */
+ &fpga_fns,
+ 0 }
+};
+
+/*
+ * Initialize the fpga. Return 1 on success, 0 on failure.
+ */
+int asp8347db_init_fpga(void)
+{
+ int i;
+
+ PRINTF ("%s:%d: Initialize FPGA interface"
+ " (relocation offset = 0x%.8lx)\n",
+ __FUNCTION__, __LINE__, gd->reloc_off);
+ fpga_init (gd->reloc_off);
+
+ for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
+ PRINTF ("%s:%d: Adding fpga %d\n", __FUNCTION__,
+ __LINE__, i);
+ fpga_add (fpga_lattice, &fpga[i]);
+ }
+ return 1;
+}
+
+extern int lattice_load (Lattice_desc * desc, void *buf, size_t bsize);
+
+/*
+ * Autoload the fpga. Return 1 on success, 0 on failure.
+ */
+int asp8347db_autoload_fpga(void)
+{
+ char *value;
+ ulong base = 0, size = 0;
+ int ret;
+
+ /* disable autoload set? */
+ value = getenv("fpga_autoload_disable");
+ if (value && *value == 'y') {
+ printf("FPGA: Autoload disabled; load manually...\n");
+ return 0;
+ }
+
+ if ((value = getenv("fpga_image_base")) != NULL)
+ base = simple_strtoul(value, NULL, 16);
+
+ if ((value = getenv("fpga_image_size")) != NULL)
+ size = simple_strtoul(value, NULL, 16);
+
+ if (base == 0 || size == 0) {
+ PRINTF("FPGA image variables not found\n");
+ return -1;
+ }
+
+ PRINTF("Autoloading FPGA\n");
+
+ ret = lattice_load(&fpga[0], (void *)base, (size_t)size);
+ if (ret != 0)
+ PRINTF("Autoloading FPGA failed with error %d\n", ret);
+
+ return ret;
+}
+
+#endif
+
+/* vim: set ts=8 tw=78 sw=8: */
diff --git a/board/asp8347db/pci.c b/board/asp8347db/pci.c
new file mode 100644
index 0000000..5ecf101
--- /dev/null
+++ b/board/asp8347db/pci.c
@@ -0,0 +1,222 @@
+/*
+ * (C) Copyright 2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <asm/mmu.h>
+#include <common.h>
+#include <pci.h>
+
+#ifdef CONFIG_PCI
+
+/* System RAM mapped to PCI space */
+#define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_SIZE (1024 * 1024 * 1024)
+
+#ifndef CONFIG_PCI_PNP
+static struct pci_config_table pci_tqm834x_config_table[] = {
+ {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_IDSEL_NUMBER, PCI_ANY_ID,
+ pci_cfgfunc_config_device, {PCI_ENET0_IOADDR,
+ PCI_ENET0_MEMADDR,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
+ }
+ },
+ {}
+};
+#endif
+
+static struct pci_controller pci1_hose = {
+#ifndef CONFIG_PCI_PNP
+ config_table:pci_tqm834x_config_table,
+#endif
+};
+
+
+/**************************************************************************
+ * pci_init_board()
+ *
+ * NOTICE: MPC8349 internally has two PCI controllers (PCI1 and PCI2) but since
+ * per ASP8347DB design physical connections to external devices (PCI sockets)
+ * are routed only to the PCI1 we do not account for the second one - this code
+ * supports PCI1 module only. Should support for the PCI2 be required in the
+ * future it needs a separate pci_controller structure (above) and handling -
+ * please refer to other boards' implementation for dual PCI host controllers,
+ * for example board/Marvell/db64360/pci.c, pci_init_board()
+ *
+ */
+void
+pci_init_board(void)
+{
+ volatile immap_t * immr;
+ volatile clk83xx_t * clk;
+ volatile law83xx_t * pci_law;
+ volatile pot83xx_t * pci_pot;
+ volatile pcictrl83xx_t * pci_ctrl;
+ volatile pciconf83xx_t * pci_conf;
+ u16 reg16;
+ u32 reg32;
+ struct pci_controller * hose;
+
+ immr = (immap_t *)CFG_IMMR;
+ clk = (clk83xx_t *)&immr->clk;
+ pci_law = immr->sysconf.pcilaw;
+ pci_pot = immr->ios.pot;
+ pci_ctrl = immr->pci_ctrl;
+ pci_conf = immr->pci_conf;
+
+ hose = &pci1_hose;
+
+ /*
+ * Configure PCI controller and PCI_CLK_OUTPUT
+ */
+
+ /*
+ * WARNING! only PCI_CLK_OUTPUT1 is enabled here as this is the one
+ * line actually used for clocking all external PCI devices in TQM83xx.
+ * Enabling other PCI_CLK_OUTPUT lines may lead to board's hang for
+ * unknown reasons - particularly PCI_CLK_OUTPUT6 and PCI_CLK_OUTPUT7
+ * are known to hang the board; this issue is under investigation
+ * (13 oct 05)
+ */
+ reg32 = OCCR_PCICOE1;
+#if 0
+ /* enabling all PCI_CLK_OUTPUT lines HANGS the board... */
+ reg32 = 0xff000000;
+#endif
+ if (clk->spmr & SPMR_CKID) {
+ /* PCI Clock is half CONFIG_83XX_CLKIN so need to set up OCCR
+ * fields accordingly */
+ reg32 |= (OCCR_PCI1CR | OCCR_PCI2CR);
+
+ reg32 |= (OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 \
+ | OCCR_PCICD3 | OCCR_PCICD4 | OCCR_PCICD5 \
+ | OCCR_PCICD6 | OCCR_PCICD7);
+ }
+
+ clk->occr = reg32;
+ udelay(2000);
+
+ /*
+ * Release PCI RST Output signal
+ */
+ pci_ctrl[0].gcr = 0;
+ udelay(2000);
+ pci_ctrl[0].gcr = 1;
+ udelay(2000);
+
+ /*
+ * Configure PCI Local Access Windows
+ */
+ pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR;
+ pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_512M;
+
+ pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR;
+ pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_16M;
+
+ /*
+ * Configure PCI Outbound Translation Windows
+ */
+
+ /* PCI1 mem space */
+ pci_pot[0].potar = (CFG_PCI1_MEM_BASE >> 12) & POTAR_TA_MASK;
+ pci_pot[0].pobar = (CFG_PCI1_MEM_PHYS >> 12) & POBAR_BA_MASK;
+ pci_pot[0].pocmr = POCMR_EN | (POCMR_CM_512M & POCMR_CM_MASK);
+
+ /* PCI1 IO space */
+ pci_pot[1].potar = (CFG_PCI1_IO_BASE >> 12) & POTAR_TA_MASK;
+ pci_pot[1].pobar = (CFG_PCI1_IO_PHYS >> 12) & POBAR_BA_MASK;
+ pci_pot[1].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_16M & POCMR_CM_MASK);
+
+ /*
+ * Configure PCI Inbound Translation Windows
+ */
+
+ /* we need RAM mapped to PCI space for the devices to
+ * access main memory */
+ pci_ctrl[0].pitar1 = 0x0;
+ pci_ctrl[0].pibar1 = 0x0;
+ pci_ctrl[0].piebar1 = 0x0;
+ pci_ctrl[0].piwar1 = PIWAR_EN | PIWAR_PF | \
+ PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | \
+ PIWAR_IWS_256M;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 0,
+ CFG_PCI1_MEM_BASE,
+ CFG_PCI1_MEM_PHYS,
+ CFG_PCI1_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 1,
+ CFG_PCI1_IO_BASE,
+ CFG_PCI1_IO_PHYS,
+ CFG_PCI1_IO_SIZE,
+ PCI_REGION_IO);
+
+ /* System memory space */
+ pci_set_region(hose->regions + 2,
+ CONFIG_PCI_SYS_MEM_BUS,
+ CONFIG_PCI_SYS_MEM_PHYS,
+ CONFIG_PCI_SYS_MEM_SIZE,
+ PCI_REGION_MEM | PCI_REGION_MEMORY);
+
+ hose->region_count = 3;
+
+ pci_setup_indirect(hose,
+ (CFG_IMMR+0x8300),
+ (CFG_IMMR+0x8304));
+
+ pci_register_hose(hose);
+
+ /*
+ * Write to Command register
+ */
+ reg16 = 0xff;
+ pci_hose_read_config_word (hose, PCI_BDF(0,0,0), PCI_COMMAND,
+ ®16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, PCI_BDF(0,0,0), PCI_COMMAND,
+ reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, PCI_BDF(0,0,0), PCI_STATUS,
+ 0xffff);
+ pci_hose_write_config_byte(hose, PCI_BDF(0,0,0), PCI_LATENCY_TIMER,
+ 0x80);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+ /*
+ * Hose scan.
+ */
+ hose->last_busno = pci_hose_scan(hose);
+}
+#endif /* CONFIG_PCI */
diff --git a/board/asp8347db/u-boot.lds b/board/asp8347db/u-boot.lds
new file mode 100644
index 0000000..020cfa6
--- /dev/null
+++ b/board/asp8347db/u-boot.lds
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc83xx/start.o (.text)
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
+ENTRY(_start)
diff --git a/include/status_led.h b/include/status_led.h
index db4c60f..52fb233 100644
--- a/include/status_led.h
+++ b/include/status_led.h
@@ -355,6 +355,8 @@ void status_led_set (int led, int state);
# define STATUS_LED_ACTIVE 0 /* LED on for bit == 0 */
# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */
+#elif defined(CONFIG_ASP8347DB)
+/* XXX empty just to avoid the error */
#else
# error Status LED configuration missing
#endif
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot-Users] [PATCH 8/8] Pantelis Antoniou MAINTAINER update.
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
` (5 preceding siblings ...)
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 7/8] Support Analogue Micro's ASP8347DB board. Implementation Pantelis Antoniou
@ 2006-12-02 22:16 ` Pantelis Antoniou
6 siblings, 0 replies; 8+ messages in thread
From: Pantelis Antoniou @ 2006-12-02 22:16 UTC (permalink / raw)
To: u-boot
Update with my new email address, add as a maintainer of ASP8347DB.
Also move NETVIA to unmaintained section.
---
Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com>
---
MAINTAINERS | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index ce20def..dfdf46c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21,9 +21,9 @@ Greg Allen <gallen@arlut.utexas.edu>
UTX8245 MPC8245
-Pantelis Antoniou <panto@intracom.gr>
+Pantelis Antoniou <pantelis@embeddedalley.com>
- NETVIA MPC8xx
+ ASP8347DB MPC834x
Reinhard Arlt <reinhard.arlt@esd-electronics.com>
@@ -368,6 +368,7 @@ Unknown / orphaned boards:
IAD210 MPC8xx
MBX MPC8xx
MBX860T MPC8xx
+ NETVIA MPC8xx
NX823 MPC8xx
RPXClassic MPC8xx
RPXlite MPC8xx
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-12-02 22:16 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-02 22:15 [U-Boot-Users] [PATCH 1/8] Make autocomplete work with HUSH parser too Pantelis Antoniou
2006-12-02 22:15 ` [U-Boot-Users] [PATCH 2/8] Support LATTICE FPGA parts using JTAG programming. Interface to FPGA API Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 3/8] Support LATTICE FPGA parts using JTAG programming. JTAG core Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 4/8] Support LATTICE FPGA parts using JTAG programming. Support functions Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 5/8] Adds support for RedBoot Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 6/8] Support Analogue Micro's ASP8347DB board. CONFIG file Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 7/8] Support Analogue Micro's ASP8347DB board. Implementation Pantelis Antoniou
2006-12-02 22:16 ` [U-Boot-Users] [PATCH 8/8] Pantelis Antoniou MAINTAINER update Pantelis Antoniou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox