meta-portwell/meta-pwneptune/recipes-neptune/plat-libs/files/cpld/lattice.c (1,326 lines of code) (raw):

#include <stdio.h> #include <sys/ioctl.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <getopt.h> #include <string.h> #include <termios.h> #include <sys/mman.h> #include "lattice.h" #include "ast-jtag.h" #define MAX_RETRY 1000 #define LATTICE_COL_SIZE 128 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) typedef struct { unsigned long int QF; unsigned int *CF; unsigned int CF_Line; unsigned int *UFM; unsigned int UFM_Line; unsigned int Version; unsigned int CheckSum; unsigned int FEARBits; unsigned int FeatureRow; } CPLDInfo; extern struct cpld_dev_info *cur_dev; extern xfer_mode mode; extern int debug; enum { CHECK_BUSY=0, CHECK_STATUS=1, }; enum { Only_CF=0, Both_CF_UFM=1, }; /*search the index of char in string*/ static int indexof(const char *str, const char *c) { char *ptr = strstr(str, c); int index = 0; if ( ptr ) { index = ptr - str; } else { index = -1; } return index; } /*identify the str start with a specific str or not*/ static int startWith(const char *str, const char *c) { int len = strlen(c); int i; for ( i=0; i<len; i++ ) { if ( str[i] != c[i] ) { return 0; } } return 1; } /*convert bit data to byte data*/ static unsigned int ShiftData(unsigned char *data, unsigned int *result, int len) { int i; int RetVal = 0; int result_index = 0, data_index = 0; int bit_count = 0; #ifdef CPLD_DEBUG printf("[%s][%s]\n", __func__, data); for ( i = 0; i < len; i++ ) { printf("%c", data[i]); if ( 0 == ((i+1) % 8) ) { printf("\n"); } } #endif for ( i = 0; i < len; i++ ) { data[i] = data[i] - 0x30; result[result_index] |= (data[i] << data_index); #ifdef CPLD_DEBUG printf("[%s]%x %d %x\n", __func__, data[i], data_index, result[result_index]); #endif data_index++; bit_count++; if ( 0 == ((i+1) % 32) ) { data_index = 0; #ifdef CPLD_DEBUG printf("[%s]%x\n", __func__, result[result_index]); #endif result_index++; } } if ( bit_count != len ) { printf("[%s] Expected Data Length is [%d] but not [%d] ", __func__, bit_count, len); RetVal = -1; } return RetVal; } static int LCMXO2Family_Check_Device_Status(int mode) { int RetVal = 0; int RETRY = MAX_RETRY; unsigned int buf[4]={0}; switch (mode) { case CHECK_BUSY: ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, LCMXO2_LSC_CHECK_BUSY); do { usleep(1000); buf[0] = 0; ast_jtag_tdo_xfer(0, 32, &buf[0]); buf[0] = (buf[0] >> 7) & 0x1; if ( 0 == buf[0] ) { break; } #ifdef CPLD_DEBUG else { printf("[%s][LCMXO2_LSC_CHECK_BUSY(0xF0)]%x\n",__func__ ,buf[0]); } #endif RETRY--; } while( RETRY ); if ( !RETRY ) { RetVal = -1; } break; case CHECK_STATUS: ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_LSC_READ_STATUS); do { usleep(1000); buf[0] = 0; ast_jtag_tdo_xfer(0, 32, &buf[0]); buf[0] = (buf[0] >> 12) & 0x3; if ( 0 == buf[0] ) { break; } #ifdef CPLD_DEBUG else { printf("[%s][LCMXO2_LSC_READ_STATUS(0x3C)]%x\n",__func__ ,buf[0]); } #endif RETRY--; } while ( RETRY ); if ( !RETRY ) { RetVal = -1; } break; default: break; } return RetVal; } /*write cf data*/ static int LCMXO2Family_SendCFdata(CPLDInfo *dev_info) { int RetVal = 0; int CurrentAddr = 0; int i; for ( i = 0; i < dev_info->CF_Line; i++ ) { printf("Writing Data: %d/%d (%.2f%%) \r",(i+1), dev_info->CF_Line, (((i+1)/(float)dev_info->CF_Line)*100)); CurrentAddr = (i * LATTICE_COL_SIZE) / 32; //RUNTEST IDLE 15 TCK 1.00E-003 SEC; ast_jtag_run_test_idle( 0, 0, 3); //set page to program page ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, LCMXO2_LSC_PROG_INCR_NV); //send data ast_jtag_tdi_xfer(0, LATTICE_COL_SIZE, &dev_info->CF[CurrentAddr]); //usleep(1000); RetVal = LCMXO2Family_Check_Device_Status(CHECK_BUSY); if ( RetVal < 0 ) { printf("[%s]Write CF Error\n", __func__); } } printf("\n"); return RetVal; } /*write ufm data if need*/ static int LCMXO2Family_SendUFMdata(CPLDInfo *dev_info) { int RetVal = 0; int CurrentAddr = 0; int i; for ( i = 0; i < dev_info->UFM_Line; i++ ) { CurrentAddr = (i * LATTICE_COL_SIZE) / 32; //RUNTEST IDLE 15 TCK 1.00E-003 SEC; ast_jtag_run_test_idle( 0, 0, 3); //set page to program page ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, LCMXO2_LSC_PROG_INCR_NV); //send data ast_jtag_tdi_xfer(0, LATTICE_COL_SIZE, &dev_info->UFM[CurrentAddr]); //usleep(1000); RetVal = LCMXO2Family_Check_Device_Status(CHECK_BUSY); if ( RetVal < 0 ) { printf("[%s]Write UFM Error\n", __func__); } } return RetVal; } /*check the size of cf and ufm*/ static int LCMXO2Family_Get_Update_Data_Size(FILE *jed_fd, int *cf_size, int *ufm_size) { const char TAG_CF_START[]="L000"; int ReadLineSize = LATTICE_COL_SIZE; unsigned char tmp_buf[ReadLineSize]; unsigned int CFStart = 0; unsigned int UFMStart = 0; const char TAG_UFM[]="NOTE TAG DATA"; int RetVal = 0; while( NULL != fgets(tmp_buf, ReadLineSize, jed_fd) ) { if ( startWith(tmp_buf, TAG_CF_START/*"L000"*/) ) { CFStart = 1; } else if ( startWith(tmp_buf, TAG_UFM/*"NOTE TAG DATA"*/) ) { UFMStart = 1; } if ( CFStart ) { if ( !startWith(tmp_buf, TAG_CF_START/*"L000"*/) && strlen(tmp_buf) != 1 ) { if ( startWith(tmp_buf,"0") || startWith(tmp_buf,"1") ) { (*cf_size)++; } else { CFStart = 0; } } } else if ( UFMStart ) { if ( !startWith(tmp_buf, TAG_UFM/*"NOTE TAG DATA"*/) && !startWith(tmp_buf, "L") && strlen(tmp_buf) != 1 ) { if ( startWith(tmp_buf,"0") || startWith(tmp_buf,"1") ) { (*ufm_size)++; } else { UFMStart = 0; } } } } //cf must greater than 0 if ( !(*cf_size) ) { RetVal = -1; } return RetVal; } static int LCMXO2Family_JED_File_Parser(FILE *jed_fd, CPLDInfo *dev_info, int cf_size, int ufm_size) { /**TAG Information**/ const char TAG_QF[]="QF"; const char TAG_CF_START[]="L000"; const char TAG_UFM[]="NOTE TAG DATA"; const char TAG_ROW[]="NOTE FEATURE"; const char TAG_CHECKSUM[]="C"; const char TAG_USERCODE[]="NOTE User Electronic"; /**TAG Information**/ int ReadLineSize = LATTICE_COL_SIZE + 2;//the len of 128 only contain data size, '\n' need to be considered, too. unsigned char tmp_buf[ReadLineSize]; unsigned char data_buf[LATTICE_COL_SIZE]; unsigned int CFStart = 0; unsigned int UFMStart = 0; unsigned int ROWStart = 0; unsigned int VersionStart = 0; unsigned int ChkSUMStart = 0; unsigned int JED_CheckSum = 0; int copy_size; int current_addr=0; int i; int RetVal = 0; int cf_size_used = (cf_size * LATTICE_COL_SIZE) / 8; // unit: bytes int ufm_size_used = (ufm_size * LATTICE_COL_SIZE) / 8; // unit: bytes dev_info->CF = (unsigned int*)malloc( cf_size_used ); memset(dev_info->CF, 0, cf_size_used); if ( ufm_size_used ) { dev_info->UFM = (unsigned int*)malloc( ufm_size_used ); memset(dev_info->UFM, 0, ufm_size_used); } dev_info->CF_Line=0; dev_info->UFM_Line=0; while( NULL != fgets(tmp_buf, ReadLineSize, jed_fd) ) { if ( startWith(tmp_buf, TAG_QF/*"QF"*/) ) { copy_size = indexof(tmp_buf, "*") - indexof(tmp_buf, "F") - 1; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, &tmp_buf[2], copy_size ); dev_info->QF = atol(data_buf); #ifdef CPLD_DEBUG printf("[QF]%ld\n",dev_info->QF); #endif } else if ( startWith(tmp_buf, TAG_CF_START/*"L000"*/) ) { #ifdef CPLD_DEBUG printf("[CFStart]\n"); #endif CFStart = 1; } else if ( startWith(tmp_buf, TAG_UFM/*"NOTE TAG DATA"*/) ) { #ifdef CPLD_DEBUG printf("[UFMStart]\n"); #endif UFMStart = 1; } else if ( startWith(tmp_buf, TAG_ROW/*"NOTE FEATURE"*/) ) { #ifdef CPLD_DEBUG printf("[ROWStart]\n"); #endif ROWStart = 1; } else if ( startWith(tmp_buf, TAG_USERCODE/*"NOTE User Electronic"*/) ) { #ifdef CPLD_DEBUG printf("[VersionStart]\n"); #endif VersionStart = 1; } else if ( startWith(tmp_buf, TAG_CHECKSUM/*"C"*/) ) { #ifdef CPLD_DEBUG printf("[ChkSUMStart]\n"); #endif ChkSUMStart = 1; } if ( CFStart ) { #ifdef CPLD_DEBUG printf("[%s][%d][%c]", __func__, strlen(tmp_buf), tmp_buf[0]); #endif if ( !startWith(tmp_buf, TAG_CF_START/*"L000"*/) && strlen(tmp_buf) != 1 ) { if ( startWith(tmp_buf,"0") || startWith(tmp_buf,"1") ) { current_addr = (dev_info->CF_Line * LATTICE_COL_SIZE) / 32; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, tmp_buf, LATTICE_COL_SIZE); /*convert string to byte data*/ ShiftData(data_buf, &dev_info->CF[current_addr], LATTICE_COL_SIZE); #ifdef CPLD_DEBUG printf("[%d]%x %x %x %x\n",dev_info->CF_Line, dev_info->CF[current_addr],dev_info->CF[current_addr+1],dev_info->CF[current_addr+2],dev_info->CF[current_addr+3]); #endif //each data has 128bits(4*unsigned int), so the for-loop need to be run 4 times for ( i = 0; i < sizeof(unsigned int); i++ ) { JED_CheckSum += (dev_info->CF[current_addr+i]>>24) & 0xff; JED_CheckSum += (dev_info->CF[current_addr+i]>>16) & 0xff; JED_CheckSum += (dev_info->CF[current_addr+i]>>8) & 0xff; JED_CheckSum += (dev_info->CF[current_addr+i]) & 0xff; } dev_info->CF_Line++; } else { #ifdef CPLD_DEBUG printf("[%s]CF Line: %d\n", __func__, dev_info->CF_Line); #endif CFStart = 0; } } } else if ( ChkSUMStart && strlen(tmp_buf) != 1 ) { ChkSUMStart = 0; copy_size = indexof(tmp_buf, "*") - indexof(tmp_buf, "C") - 1; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, &tmp_buf[1], copy_size ); dev_info->CheckSum = strtoul(data_buf, NULL, 16); printf("[ChkSUM]%x\n",dev_info->CheckSum); } else if ( ROWStart ) { if ( !startWith(tmp_buf, TAG_ROW/*"NOTE FEATURE"*/ ) && strlen(tmp_buf) != 1 ) { if ( startWith(tmp_buf, "E" ) ) { copy_size = strlen(tmp_buf) - indexof(tmp_buf, "E") - 2; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, &tmp_buf[1], copy_size ); dev_info->FeatureRow = strtoul(data_buf, NULL, 2); } else { copy_size = indexof(tmp_buf, "*") - 1; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, &tmp_buf[2], copy_size ); dev_info->FEARBits = strtoul(data_buf, NULL, 2); #ifdef CPLD_DEBUG printf("[FeatureROW]%x\n", dev_info->FeatureRow); printf("[FEARBits]%x\n", dev_info->FEARBits); #endif ROWStart = 0; } } } else if ( VersionStart ) { if ( !startWith(tmp_buf, TAG_USERCODE/*"NOTE User Electronic"*/) && strlen(tmp_buf) != 1 ) { VersionStart = 0; if ( startWith(tmp_buf, "UH") ) { copy_size = indexof(tmp_buf, "*") - indexof(tmp_buf, "H") - 1; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, &tmp_buf[2], copy_size ); dev_info->Version = strtoul(data_buf, NULL, 16); #ifdef CPLD_DEBUG printf("[UserCode]%x\n",dev_info->Version); #endif } } } else if ( UFMStart ) { if ( !startWith(tmp_buf, TAG_UFM/*"NOTE TAG DATA"*/) && !startWith(tmp_buf, "L") && strlen(tmp_buf) != 1 ) { if ( startWith(tmp_buf,"0") || startWith(tmp_buf,"1") ) { current_addr = (dev_info->UFM_Line * LATTICE_COL_SIZE) / 32; memset(data_buf, 0, sizeof(data_buf)); memcpy(data_buf, tmp_buf, LATTICE_COL_SIZE); ShiftData(data_buf, &dev_info->UFM[current_addr], LATTICE_COL_SIZE); #ifdef CPLD_DEBUG printf("%x %x %x %x\n",dev_info->UFM[current_addr],dev_info->UFM[current_addr+1],dev_info->UFM[current_addr+2],dev_info->UFM[current_addr+3]); #endif dev_info->UFM_Line++; } else { #ifdef CPLD_DEBUG printf("[%s]UFM Line: %d\n", __func__, dev_info->UFM_Line); #endif UFMStart = 0; } } } } JED_CheckSum = JED_CheckSum & 0xffff; if ( dev_info->CheckSum != JED_CheckSum || dev_info->CheckSum == 0) { printf("[%s] JED File CheckSum Error\n", __func__); RetVal = -1; } #ifdef CPLD_DEBUG else { printf("[%s] JED File CheckSum OKay\n", __func__); } #endif return RetVal; } static int LCMXO2Family_cpld_verify(CPLDInfo *dev_info) { int i; int result; int current_addr = 0; unsigned int buff[4]={0}; int err = 0; ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_LSC_INIT_ADDRESS); buff[0] = 0x04; ast_jtag_tdi_xfer( 0, LATTICE_INS_LENGTH, &buff[0]); usleep(1000); ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_LSC_READ_INCR_NV); usleep(1000); #ifdef CPLD_DEBUG printf("[%s] dev_info->CF_Line: %d\n", __func__, dev_info->CF_Line); #endif for(i = 0; i < dev_info->CF_Line; i++) { printf("Verify Data: %d/%d (%.2f%%) \r",(i+1), dev_info->CF_Line, (((i+1)/(float)dev_info->CF_Line)*100)); current_addr = (i * LATTICE_COL_SIZE) / 32; memset(buff, 0, sizeof(buff)); ast_jtag_tdo_xfer( 0, LATTICE_COL_SIZE, buff); result = memcmp(buff, &dev_info->CF[current_addr], sizeof(unsigned int)); if ( result ) { err = 1; break; } //usleep(3000); } printf("\n"); if ( err ) { printf("\nVerify CPLD FW Error\n", __func__); } #ifdef CPLD_DEBUG else { printf("\nVerify CPLD FW Pass\n", __func__); } #endif return err; } static int LCMXO2Family_cpld_Start() { unsigned int dr_data[4]={0}; int RetVal = 0; //Enable the Flash (Transparent Mode) #ifdef CPLD_DEBUG printf("[%s] Enter transparent mode!\n", __func__); #endif ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_ISC_ENABLE_X); dr_data[0] = 0x08; ast_jtag_tdi_xfer(0, LATTICE_INS_LENGTH, dr_data); //usleep(3000); //LSC_CHECK_BUSY(0xF0) instruction dr_data[0] = LCMXO2Family_Check_Device_Status(CHECK_BUSY); if ( dr_data[0] != 0x0 ) { printf("[%s] Device Busy\n", __func__); } //usleep(3000); #ifdef CPLD_DEBUG printf("[%s] READ_STATUS(0x3C)!\n", __func__); #endif //READ_STATUS(0x3C) instruction dr_data[0] = LCMXO2Family_Check_Device_Status(CHECK_STATUS); if(dr_data[0] != 0x0) { printf("[%s] Device Busy\n", __func__); } return RetVal; } static int LCMXO2Family_cpld_End() { int RetVal = 0; unsigned int dr_data[4]={0}; ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_ISC_PROGRAM_DONE); #ifdef CPLD_DEBUG printf("[%s] Program DONE bit\n", __func__); #endif //Read CHECK_BUSY dr_data[0] = LCMXO2Family_Check_Device_Status(CHECK_BUSY); #ifdef CPLD_DEBUG printf("[%s] READ_STATUS: %x\n", __func__, dr_data[0]); #endif //Shift in BYPASS(0xFF) instruction ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); #ifdef CPLD_DEBUG printf("[%s] BYPASS(0xFF)\n", __func__); #endif //Exit the programming mode //Shift in ISC DISABLE(0x26) instruction ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_ISC_DISABLE); //Shift in BYPASS(0xFF) instruction ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); return RetVal; } static int LCMXO2Family_cpld_Check_ID() { unsigned int dr_data[4]={0}; int RetVal = -1; int i; //RUNTEST IDLE ast_jtag_run_test_idle( 0, 0, 3); #ifdef CPLD_DEBUG printf("[%s] RUNTEST IDLE\n", __func__); #endif //Check the IDCODE_PUB ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_IDCODE_PUB); dr_data[0] = 0x0; ast_jtag_tdo_xfer( 0, 32, dr_data); #ifdef CPLD_DEBUG printf("[%s] ID Code: %x\n", __func__, dr_data[0]); #endif for ( i = 0; i < ARRAY_SIZE(lattice_device_list); i++ ) { if ( dr_data[0] == lattice_device_list[i].dev_id ) { RetVal = 0; break; } } return RetVal; } static int LCMXO2Family_cpld_Erase(int erase_type) { unsigned int dr_data[4]={0}; int RetVal = 0; ast_jtag_run_test_idle( 0, 0, 3); //Erase the Flash ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_ISC_ERASE); #ifdef CPLD_DEBUG printf("[%s] ERASE(0x0E)!\n", __func__); #endif switch (erase_type) { case Only_CF: dr_data[0] = 0x04; //0x4=CF break; case Both_CF_UFM: dr_data[0] = 0x0C; //0xC=CF and UFM break; } ast_jtag_tdi_xfer( 0, LATTICE_INS_LENGTH, dr_data); dr_data[0] = LCMXO2Family_Check_Device_Status(CHECK_BUSY); if ( dr_data[0] != 0x0 ) { printf("[%s] Device Busy\n", __func__); } #ifdef CPLD_DEBUG //Shift in LSC_READ_STATUS(0x3C) instruction printf("[%s] READ_STATUS!\n", __func__); #endif dr_data[0] = LCMXO2Family_Check_Device_Status(CHECK_STATUS); if ( dr_data[0] != 0x0 ) { printf("Erase Failed\n"); } #ifdef CPLD_DEBUG printf("[%s] Erase Done!\n", __func__); #endif return RetVal; } static int LCMXO2Family_cpld_program(CPLDInfo *dev_info) { int RetVal = 0; unsigned int dr_data[4]={0}; #ifdef CPLD_DEBUG //Program CFG printf("[%s] Program CFG \n", __func__); #endif ast_jtag_run_test_idle( 0, 0, 3); //Shift in LSC_INIT_ADDRESS(0x46) instruction ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_LSC_INIT_ADDRESS); #ifdef CPLD_DEBUG printf("[%s] INIT_ADDRESS(0x46) \n", __func__); #endif LCMXO2Family_SendCFdata(dev_info); if ( dev_info->UFM_Line ) { ast_jtag_run_test_idle( 0, 0, 3); //program UFM ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_LSC_INIT_ADDR_UFM); LCMXO2Family_SendUFMdata(dev_info); } #ifdef CPLD_DEBUG printf("[%s] Update CPLD done \n", __func__); //Program USERCODE printf("[%s] Program USERCODE\n", __func__); #endif ast_jtag_run_test_idle( 0, 0, 3); //Shift in READ USERCODE(0xC0) instruction; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_USERCODE); #ifdef CPLD_DEBUG printf("[%s] READ USERCODE(0xC0)\n", __func__); #endif //Write UserCode dr_data[0] = dev_info->Version; ast_jtag_tdi_xfer(0, 32, dr_data); #ifdef CPLD_DEBUG printf("[%s] Write USERCODE: %x\n", __func__, dr_data[0]); #endif ast_jtag_run_test_idle( 0, 0, 3); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_ISC_PROGRAM_USERCOD); usleep(2000); #ifdef CPLD_DEBUG printf("[%s] PROGRAM USERCODE(0xC2)\n", __func__); #endif //Read the status bit dr_data[0] = LCMXO2Family_Check_Device_Status(CHECK_STATUS); if ( dr_data[0] != 0x0 ) { printf("[%s] Device Busy\n", __func__); } #ifdef CPLD_DEBUG printf("[%s] READ_STATUS: %x\n", __func__, dr_data[0]); #endif return RetVal; } int LCMXO2Family_cpld_Get_Ver(unsigned int *ver) { int RetVal; unsigned int dr_data[4]={0}; RetVal = LCMXO2Family_cpld_Check_ID(); if ( RetVal < 0 ) { printf("[%s] Unknown Device ID!\n", __func__); goto error_exit; } RetVal = LCMXO2Family_cpld_Start(); if ( RetVal < 0 ) { printf("[%s] Enter Transparent mode Error!\n", __func__); goto error_exit; } //Shift in READ USERCODE(0xC0) instruction; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_USERCODE); #ifdef CPLD_DEBUG printf("[%s] READ USERCODE(0xC0)\n", __func__); #endif //Read UserCode dr_data[0] = 0; ast_jtag_tdo_xfer(0, 32, dr_data); *ver = dr_data[0]; RetVal = LCMXO2Family_cpld_End(); if ( RetVal < 0 ) { printf("[%s] Exit Transparent Mode Failed!\n", __func__); } error_exit: return RetVal; } int LCMXO2Family_cpld_update(FILE *jed_fd) { CPLDInfo dev_info = {0}; int cf_size = 0; int ufm_size = 0; int erase_type = 0; int RetVal; #ifdef CPLD_DEBUG printf("[%s]\n",__func__); #endif RetVal = LCMXO2Family_cpld_Check_ID(); if ( RetVal < 0 ) { printf("[%s] Unknown Device ID!\n", __func__); goto error_exit; } //set file pointer to the beginning fseek(jed_fd, 0, SEEK_SET); //get update data size RetVal = LCMXO2Family_Get_Update_Data_Size(jed_fd, &cf_size, &ufm_size); if ( RetVal < 0 ) { printf("[%s] Update Data Size Error!\n", __func__); goto error_exit; } //set file pointer to the beginning fseek(jed_fd, 0, SEEK_SET); //parse info from JED file and calculate checksum RetVal = LCMXO2Family_JED_File_Parser(jed_fd, &dev_info, cf_size, ufm_size); if ( RetVal < 0 ) { printf("[%s] JED file CheckSum Error!\n", __func__); goto error_exit; } RetVal = LCMXO2Family_cpld_Start(); if ( RetVal < 0 ) { printf("[%s] Enter Transparent mode Error!\n", __func__); goto error_exit; } if ( dev_info.UFM_Line ) { erase_type = Both_CF_UFM; } else { erase_type = Only_CF; } RetVal = LCMXO2Family_cpld_Erase(erase_type); if ( RetVal < 0 ) { printf("[%s] Erase failed!\n", __func__); goto error_exit; } RetVal = LCMXO2Family_cpld_program(&dev_info); if ( RetVal < 0 ) { printf("[%s] Program failed!\n", __func__); goto error_exit; } RetVal = LCMXO2Family_cpld_verify(&dev_info); if ( RetVal < 0 ) { printf("[%s] Verify Failed!\n", __func__); goto error_exit; } RetVal = LCMXO2Family_cpld_End(); if ( RetVal < 0 ) { printf("[%s] Exit Transparent Mode Failed!\n", __func__); goto error_exit; } error_exit: if ( NULL != dev_info.CF ) { free(dev_info.CF); } if ( NULL != dev_info.UFM ) { free(dev_info.UFM); } return RetVal; } /*************************************************************************************/ unsigned int jed_file_parse_header(FILE *jed_fd) { //File unsigned char tmp_buf[160]; unsigned int *jed_data; unsigned int row = 0; unsigned char input_char, input_bit; int sdr_array = 0, data_bit = 0, bit_cnt = 0; int cmp_err = 0; //Header paser while(fgets(tmp_buf, 120, jed_fd)!= NULL) { if (debug) printf("%s \n",tmp_buf); if (tmp_buf[0] == 0x4C) { // "L" break; } } } unsigned int jed_file_parser(FILE *jed_fd, unsigned int len, unsigned int *dr_data) { int i = 0; unsigned char input_char, input_bit; int sdr_array = 0, data_bit = 0, bit_cnt = 0; int cmp_err = 0; //Jed row for(i = 0; i < len; i++) { input_char = fgetc(jed_fd); if ((input_char == 0x30) || (input_char == 0x31)) { // "0", "1" if (input_char == 0x30) { input_bit = 0; } else { input_bit = 1; } if (debug) printf("%d",input_bit); dr_data[sdr_array] |= (input_bit << data_bit); data_bit++; bit_cnt++; if((data_bit % 32) == 0) { if (debug) printf(" [%i] : %x \n",sdr_array, dr_data[sdr_array]); data_bit = 0; sdr_array++; } } else if (input_char == 0xd) { i--; } else if (input_char == 0xa) { i--; } else { if (debug) printf("parser errorxx [%x]\n", input_char); break; } } if (debug) printf(" [%i] : %x , Total %d \n",sdr_array, dr_data[sdr_array], bit_cnt); if(bit_cnt != len) { if (debug) printf("File Error \n"); return -1; } return 0; } /* * TODO: Not yet tested at all, need to verify the JED and * change the function accordingly. This function needs * to be changed (minor) to handle all the cases */ int lcmxo2_2000hc_cpld_program(FILE *jed_fd) { int i; unsigned int tdo = 0; unsigned int *dr_data; //file unsigned int *jed_data; unsigned int row = 0; int cmp_err = 0; dr_data = malloc(((424/32) + 1) * sizeof(unsigned int)); jed_data = malloc(((cur_dev->dr_bits/32) + 1) * sizeof(unsigned int)); //RUNTEST IDLE 15 TCK 1.00E-003 SEC; ast_jtag_run_test_idle( 0, 0, 3); //! Check the IDCODE_PUB //SIR 8 TDI (E0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_IDCODE_PUB); //SDR 32 TDI (00000000) // TDO (01285043) // MASK (FFFFFFFF); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer( 0, 32, dr_data); if(dr_data[0] != 0x12BB043) { if (debug) printf("ID Fail : %08x [0x012BB043] \n",dr_data[0]); return -1; } //! Program Bscan register //! Shift in Preload(0x1C) instruction //SIR 8 TDI (1C); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x1C); //SDR 424 TDI (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); memset(dr_data, 0xff, (424/32 + 1) * sizeof(unsigned int)); ast_jtag_tdi_xfer( 0, 424, dr_data); //! Enable the Flash (Transparent Mode) //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (00); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; dr_data[0] = 0x00; ast_jtag_tdi_xfer(0, 8, dr_data); usleep(3000); //! Shift in ISC ERASE(0x0E) instruction //SIR 8 TDI (0E); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x0E); //SDR 8 TDI (01); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; dr_data[0] = 0x01; ast_jtag_tdi_xfer(0, 8, dr_data); usleep(1000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (00) // MASK (C0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (08); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; dr_data[0] = 0x08; ast_jtag_tdi_xfer( 0, 8, dr_data); usleep(3000); //! Check the Key Protection fuses //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00024040); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer( 0, 32, dr_data); //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00010000); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); //! Erase the Flash //! Shift in ISC ERASE(0x0E) instruction //SIR 8 TDI (0E); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x0E); //SDR 8 TDI (0E); //RUNTEST IDLE 2 TCK; dr_data[0] = 0x0E; ast_jtag_tdi_xfer( 0, 8, dr_data); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xF0); //LOOP 800 ; //RUNTEST IDLE 2 TCK 1.00E-002 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; dr_data[0] = 0; for(i = 0; i <800 ; i++) { usleep(2000); ast_jtag_tdo_xfer( 0, 1, dr_data); } //! Read the status bit //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00003000); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); if(dr_data[0] != 0x0) { if (debug) printf("%x [0x0]\n", dr_data[0]); } if (debug) printf("Erase Done \n"); fseek(jed_fd, 0, SEEK_SET); jed_file_parse_header(jed_fd); //! Program CFG if (debug) printf("Program CFG \n"); //! Shift in LSC_INIT_ADDRESS(0x46) instruction //SIR 8 TDI (46); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x46); //SDR 8 TDI (04); //RUNTEST IDLE 2 TCK 1.00E-002 SEC; dr_data[0] = 0x04; ast_jtag_tdo_xfer(0, 32, dr_data); if (debug) printf("Program 3198 .. \n"); // mode = SW_MODE; for(row =0 ; row < cur_dev->row_num; row++) { memset(dr_data, 0, (cur_dev->dr_bits/32) * sizeof(unsigned int)); jed_file_parser(jed_fd, cur_dev->dr_bits, dr_data); //! Shift in LSC_PROG_INCR_NV(0x70) instruction //SIR 8 TDI (70); ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, 0x70); //! Shift in Data Row = 1 //SDR 128 TDI (120600000040000000DCFFFFCDBDFFFF); //RUNTEST IDLE 2 TCK; ast_jtag_tdi_xfer(0, cur_dev->dr_bits, dr_data); usleep(1000); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, 0xF0); //LOOP 10 ; //RUNTEST IDLE 1.00E-003 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; for(i = 0;i < 10; i++) { usleep(3000); dr_data[0] = 0; ast_jtag_tdo_xfer(0, 1, dr_data); if(dr_data[0] == 0) break; } if(dr_data[0] != 0) { if (debug) printf("row %d, Fail [%d] \n", row, dr_data[0]); } else { if (debug) printf("."); } } // mode = HW_MODE; //! Program the UFM if (debug) printf("Program the UFM : 640\n"); //! Shift in LSC_INIT_ADDR_UFM(0x47) instruction //SIR 8 TDI (47); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x47); for(row =0 ; row < 640; row++) { memset(dr_data, 0, (cur_dev->dr_bits/32) * sizeof(unsigned int)); jed_file_parser(jed_fd, cur_dev->dr_bits, dr_data); //! Shift in LSC_PROG_INCR_NV(0x70) instruction //SIR 8 TDI (70); ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, 0x70); //! Shift in Data Row = 1 //SDR 128 TDI (00000000000000000000000000000000); //RUNTEST IDLE 2 TCK; ast_jtag_tdi_xfer(0, cur_dev->dr_bits, dr_data); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(1, LATTICE_INS_LENGTH, 0xF0); //LOOP 10 ; //RUNTEST IDLE 1.00E-003 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; for(i = 0;i < 10; i++) { usleep(3000); dr_data[0] = 0; ast_jtag_tdo_xfer(0, 1, dr_data); if(dr_data[0] == 0) break; } if(dr_data[0] != 0) { if (debug) printf("row %d, Fail [%d] \n",row, dr_data[0]); } else { if (debug) printf("."); } } //! Program USERCODE //! Shift in READ USERCODE(0xC0) instruction //SIR 8 TDI (C0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xC0); //SDR 32 TDI (00000000); dr_data[0] = 0x00000000; ast_jtag_tdi_xfer(0, 32, dr_data); //! Shift in ISC PROGRAM USERCODE(0xC2) instruction //SIR 8 TDI (C2); //RUNTEST IDLE 2 TCK 1.00E-002 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xC2); usleep(2000); //! Read the status bit //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00003000); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); //! Program Feature Rows //! Shift in LSC_INIT_ADDRESS(0x46) instruction //SIR 8 TDI (46); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x46); //SDR 8 TDI (02); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; dr_data[0] = 0x02; ast_jtag_tdi_xfer(0, 8, dr_data); usleep(3000); //! Shift in LSC_PROG_FEATURE(0xE4) instruction //SIR 8 TDI (E4); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xE4); //SDR 64 TDI (0000000000000000); //RUNTEST IDLE 2 TCK; dr_data[0] = 0x00000000; dr_data[1] = 0x00000000; ast_jtag_tdi_xfer(0, 64, dr_data); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xF0); //LOOP 10 ; //RUNTEST IDLE 1.00E-003 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; for(i = 0;i < 10; i++) { usleep(3000); dr_data[0] = 0; ast_jtag_tdo_xfer(0, 1, dr_data); } //! Shift in LSC_READ_FEATURE (0xE7) instruction //SIR 8 TDI (E7); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xE7); //SDR 64 TDI (0000000000000000) // TDO (0000000000000000); dr_data[0] = 0x00000000; dr_data[1] = 0x00000000; ast_jtag_tdo_xfer(0, 64, dr_data); //! Shift in in LSC_PROG_FEABITS(0xF8) instruction //SIR 8 TDI (F8); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xF8); //SDR 16 TDI (0620); //RUNTEST IDLE 2 TCK; dr_data[0] = 0x0620; ast_jtag_tdi_xfer(0, 16, dr_data); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xF0); //LOOP 10 ; //RUNTEST IDLE 1.00E-003 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; for(i = 0;i < 10; i++) { usleep(3000); dr_data[0] = 0; ast_jtag_tdo_xfer(0, 1, dr_data); } //! Shift in in LSC_READ_FEABITS(0xFB) instruction //SIR 8 TDI (FB); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xFB); //SDR 16 TDI (0000) // TDO (0620) // MASK (FFF2); dr_data[0] = 0x0; ast_jtag_tdo_xfer(0, 16, dr_data); //! Program DONE bit //! Shift in ISC PROGRAM DONE(0x5E) instruction //SIR 8 TDI (5E); //RUNTEST IDLE 2 TCK; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x5E); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xF0); //LOOP 10 ; //RUNTEST IDLE 1.00E-003 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; for(i = 0;i < 10; i++) { usleep(3000); dr_data[0] = 0; ast_jtag_tdo_xfer(0, 1, dr_data); } //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (04) // MASK (C4); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xFF); //! Exit the programming mode //! Shift in ISC DISABLE(0x26) instruction //SIR 8 TDI (26); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x26); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF)//; //RUNTEST IDLE 2 TCK 1.00E-001 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xFF); free(jed_data); free(dr_data); return 0; } int lcmxo2_2000hc_cpld_flash_enable(void) { unsigned int data=0; unsigned int *dr_data; unsigned int alloc_size = ((cur_dev->dr_bits /32 + 1) * sizeof(unsigned int) + 4096 ) % 4096; dr_data = (unsigned int *)malloc(alloc_size); if (dr_data == NULL) { return -1;; } //RUNTEST IDLE 15 TCK 1.00E-003 SEC; ast_jtag_run_test_idle( 0, 0, 3); usleep(3000); //! Program Bscan register //! Shift in Preload(0x1C) instruction //SIR 8 TDI (1C); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x1C); //SDR 424 TDI (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); memset(dr_data, 0xff, ((424/32) + 1) * sizeof(unsigned int)); ast_jtag_tdi_xfer(0, 424, dr_data); //! Enable the Flash (Transparent Mode) //! Shift in ISC ENABLE X(0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (00); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x00; ast_jtag_tdi_xfer( 0, 8, &data); usleep(3000); //! Shift in ISC ERASE(0x0E) instruction //SIR 8 TDI (0E); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x0E); //SDR 8 TDI (01); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; data = 0x01; ast_jtag_tdi_xfer(0, 8, &data); usleep(3000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (00) // MASK (C0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (08); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x08; ast_jtag_tdi_xfer( 0, 8, &data); usleep(3000); if (dr_data != NULL) free(dr_data); return 0; } int lcmxo2_2000hc_cpld_flash_disable(void) { //! Exit the programming mode //! Shift in ISC DISABLE(0x26) instruction //SIR 8 TDI (26); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x26); usleep(1000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF); //RUNTEST IDLE 2 TCK 1.00E-001 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); usleep(1000); return 0; } int lcmxo2_2000hc_cpld_ver(unsigned int *ver) { unsigned int data=0; unsigned int *dr_data; unsigned int alloc_size = ((cur_dev->dr_bits /32 + 1) * sizeof(unsigned int) + 4096 ) % 4096; dr_data = (unsigned int *)malloc(alloc_size); if (dr_data == NULL) { return -1;; } //! Verify USERCODE //! Shift in READ USERCODE(0xC0) instruction //SIR 8 TDI (C0); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xC0); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (FFFFFFFF); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); *ver = dr_data[0]; if (dr_data != NULL) free(dr_data); return 0; } /* * TODO: Tested with CPLD programmed against F08_V01.jed * It needs to be tested thoroughly before using it. */ int lcmxo2_2000hc_cpld_verify(FILE *jed_fd) { int i; unsigned int data=0; unsigned int tdo; unsigned int *jed_data; unsigned int *dr_data; unsigned int row = 0; int cmp_err = 0; int parser_err = 0; int cfg_err = 0; int ufm_err = 0; int ret_err = -1; unsigned int alloc_size = ((cur_dev->dr_bits /32 + 1) * sizeof(unsigned int) + 4096 ) % 4096; dr_data = (unsigned int *)malloc(alloc_size); if (dr_data == NULL) { if(debug) printf("memory allocation for dr_data failed.\n"); goto err_handle; } jed_data = (unsigned int *)malloc(alloc_size); if (jed_data == NULL) { if(debug) printf("memory allocation for jed_data failed.\n"); goto err_handle; } //RUNTEST IDLE 15 TCK 1.00E-003 SEC; ast_jtag_run_test_idle( 0, 0, 3); usleep(3000); //! Check the IDCODE_PUB //SIR 8 TDI (E0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_IDCODE_PUB); //SDR 32 TDI (00000000) // TDO (012BB043) // MASK (FFFFFFFF); ast_jtag_tdo_xfer( 0, 32, dr_data); if(dr_data[0] != 0x12BB043) { if (debug) printf("ID Fail : %08x [0x012BB043] \n",dr_data[0]); free(dr_data); } //! Program Bscan register //! Shift in Preload(0x1C) instruction //SIR 8 TDI (1C); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x1C); //SDR 424 TDI (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); memset(dr_data, 0xff, ((424/32) + 1) * sizeof(unsigned int)); ast_jtag_tdi_xfer(0, 424, dr_data); //! Enable the Flash (Transparent Mode) //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (00); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x00; ast_jtag_tdi_xfer( 0, 8, &data); usleep(3000); //! Shift in ISC ERASE(0x0E) instruction //SIR 8 TDI (0E); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x0E); //SDR 8 TDI (01); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; data = 0x01; ast_jtag_tdi_xfer(0, 8, &data); usleep(3000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (00) // MASK (C0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (08); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x08; ast_jtag_tdi_xfer( 0, 8, &data); usleep(3000); //! Verify USERCODE if (debug) printf("Verify USERCODE \n"); //! Shift in READ USERCODE(0xC0) instruction //SIR 8 TDI (C0); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xC0); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (FFFFFFFF); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); if (debug) printf("CPLD USERCODE = 0x%x\n", dr_data[0]); //! Verify the Flash if (debug) printf("Starting to Verify Device . . . This will take a few seconds\n"); //! Shift in LSC_INIT_ADDRESS(0x46) instruction //SIR 8 TDI (46); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x46); //SDR 8 TDI (04); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x04; ast_jtag_tdi_xfer( 0, 8, &data); usleep(3000); //! Shift in LSC_READ_INCR_NV(0x73) instruction //SIR 8 TDI (73); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x73); usleep(3000); fseek(jed_fd, 0, SEEK_SET); jed_file_parse_header(jed_fd); if (debug) printf("Verify CONFIG 3198 \n"); cmp_err = 0; row = 0; //for(row = 0; row < cur_dev->row_num; row++) { for(row = 0; row < 3198; row++) { memset(dr_data, 0, 16); memset(jed_data, 0, 16); parser_err = jed_file_parser(jed_fd, 128, jed_data); if (parser_err == -1) { jed_file_parse_header(jed_fd); parser_err = jed_file_parser(jed_fd, 128, jed_data); if (parser_err == -1) { goto err_handle; } } ast_jtag_tdo_xfer( 0, 128, dr_data); for(i = 0; i < 4; i++) { if(dr_data[i] != jed_data[i]) { cmp_err = 1; goto err_handle; } } //RUNTEST IDLE 2 TCK 1.00E-003 SEC; usleep(3000); } cfg_err = 0; jed_file_parse_header(jed_fd); //! Verify the UFM //! Shift in LSC_INIT_ADDR_UFM(0x47) instruction //SIR 8 TDI (47); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x47); usleep(3000); //! Shift in LSC_READ_INCR_NV(0x73) instruction //SIR 8 TDI (73); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x73); usleep(3000); if (debug) printf("Verify the UFM 640 \n"); //! Shift out Data Row for(row =0 ; row < 640; row++) { memset(dr_data, 0, 16); memset(jed_data, 0, 16); parser_err = jed_file_parser(jed_fd, 128, jed_data); if (parser_err == -1) { jed_file_parse_header(jed_fd); parser_err = jed_file_parser(jed_fd, 128, jed_data); if (parser_err == -1) { goto err_handle; } } ast_jtag_tdo_xfer( 0, 128, dr_data); //for(i = 0; i < (cur_dev->dr_bits /32); i++) { for(i = 0; i < 4; i++) { if(dr_data[i] != jed_data[i]) { cmp_err = 1; goto err_handle; } } //RUNTEST IDLE 2 TCK 1.00E-003 SEC; usleep(3000); } ufm_err = 0; //! Verify USERCODE if (debug) printf("Verify USERCODE \n"); //! Shift in READ USERCODE(0xC0) instruction //SIR 8 TDI (C0); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xC0); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (FFFFFFFF); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); //! Read the status bit //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00003000); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer( 0, 32, dr_data); //! Verify Feature Rows //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00010000); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer( 0, 32, dr_data); //! Shift in LSC_READ_FEATURE (0xE7) instruction //SIR 8 TDI (E7); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xE7); usleep(3000); //SDR 64 TDI (0000000000000000) // TDO (0000000000000000); dr_data[0] = 0x00000000; dr_data[1] = 0x00000000; ast_jtag_tdo_xfer( 0, 64, dr_data); //! Shift in in LSC_READ_FEABITS(0xFB) instruction //SIR 8 TDI (FB); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xFB); usleep(3000); //SDR 16 TDI (0000) // TDO (0620) // MASK (FFF2); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer( 0, 16, dr_data); if (debug) printf("read %x [0x0620] \n", dr_data[0] & 0xffff); //! Read the status bit //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00003000); dr_data[0] = 0x00000000; ast_jtag_tdo_xfer(0, 32, dr_data); //! Verify Done Bit //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (04) // MASK (C4); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); //! Exit the programming mode //! Shift in ISC DISABLE(0x26) instruction //SIR 8 TDI (26); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x26); usleep(1000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF); //RUNTEST IDLE 2 TCK 1.00E-001 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); usleep(1000); //! Verify SRAM DONE Bit //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (04) // MASK (84); tdo = ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); if (!cfg_err && !ufm_err) ret_err = 0; err_handle: if (dr_data != NULL) free(dr_data); if (jed_data != NULL) free(jed_data); if(cmp_err) { if (debug) printf("Verify Error !!\n"); } else { if (debug) printf("Verify Done !!\n"); } if (parser_err) { if (debug) printf("Error while parsing JED file\n"); } else { if (debug) printf("NO Error while parsing JED file\n"); } return ret_err; } /* * TODO: Not tested at all, needs to be changed to handle * CPLD LCMXO2-200HC */ int lcmxo2_2000hc_cpld_erase(void) { int i = 0; unsigned int tdo = 0; unsigned int *sdr_data; unsigned int data=0; unsigned int sdr_array = 0; //RUNTEST IDLE 15 TCK 1.00E-003 SEC; ast_jtag_run_test_idle( 0, 0, 3); //! Check the IDCODE_PUB //SIR 8 TDI (E0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, LCMXO2_IDCODE_PUB); //SDR 32 TDI (00000000) // TDO (01285043) // MASK (FFFFFFFF); data = 0x00000000; ast_jtag_tdo_xfer( 0, 32, &data); if(data != 0x12BB043) { if (debug) printf("ID Fail : %08x [0x012BB043] \n",data); return -1; } //! Program Bscan register //! Shift in Preload(0x1C) instruction //SIR 8 TDI (1C); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, PRELOAD); //SDR 424 TDI (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); sdr_array = 424/32 + 1; sdr_data = malloc(sdr_array * sizeof(unsigned int)); memset(sdr_data, 0xff, sdr_array * sizeof(unsigned int)); ast_jtag_tdi_xfer( 0, 424, sdr_data); free(sdr_data); //! Enable the Flash (Transparent Mode) //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (00); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x00; ast_jtag_tdi_xfer(0, 8, &data); usleep(3000); //! Shift in ISC ERASE(0x0E) instruction //SIR 8 TDI (0E); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x0E); //SDR 8 TDI (01); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; data = 0x01; ast_jtag_tdi_xfer(0, 8, &data); usleep(1000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF) // TDO (00) // MASK (C0); tdo = ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); //! Shift in ISC ENABLE X (0x74) instruction //SIR 8 TDI (74); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x74); //SDR 8 TDI (08); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; data = 0x08; ast_jtag_tdi_xfer( 0, 8, &data); usleep(3000); //! Check the Key Protection fuses //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00024040); data = 0x00000000; ast_jtag_tdo_xfer( 0, 32, &data); //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00010000); data = 0x00000000; ast_jtag_tdo_xfer(0, 32, &data); //! Erase the Flash //! Shift in ISC ERASE(0x0E) instruction //SIR 8 TDI (0E); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x0E); //SDR 8 TDI (0E); //RUNTEST IDLE 2 TCK; data = 0x0E; ast_jtag_tdi_xfer( 0, 8, &data); //! Shift in LSC_CHECK_BUSY(0xF0) instruction //SIR 8 TDI (F0); ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0xF0); //LOOP 800 ; //RUNTEST IDLE 2 TCK 1.00E-002 SEC; //SDR 1 TDI (0) // TDO (0); //ENDLOOP ; data = 0; for(i = 0; i <800 ; i++) { usleep(2000); ast_jtag_tdo_xfer( 0, 1, &data); } //! Read the status bit //! Shift in LSC_READ_STATUS(0x3C) instruction //SIR 8 TDI (3C); //RUNTEST IDLE 2 TCK 1.00E-003 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x3C); usleep(3000); //SDR 32 TDI (00000000) // TDO (00000000) // MASK (00003000); data = 0x00000000; ast_jtag_tdo_xfer(0, 32, &data); //! Exit the programming mode //! Shift in ISC DISABLE(0x26) instruction //SIR 8 TDI (26); //RUNTEST IDLE 2 TCK 1.00E+000 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, 0x26); usleep(3000); //! Shift in BYPASS(0xFF) instruction //SIR 8 TDI (FF); //RUNTEST IDLE 2 TCK 1.00E-001 SEC; ast_jtag_sir_xfer(0, LATTICE_INS_LENGTH, BYPASS); usleep(1000); return 0; }