
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@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@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@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