public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [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,
+					&reg16);
+	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