[U-Boot-Users] [PATCH 3/8] Support LATTICE FPGA parts using JTAG programming. JTAG core.

Pantelis Antoniou pantelis at embeddedalley.com
Sat Dec 2 23:16:07 CET 2006


Add support for Lattice FPGA parts programmed using JTAG.

---
Signed-off-by: Pantelis Antoniou <pantelis at 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




More information about the U-Boot mailing list