[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