lattice.c 8.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*
 * (C) Copyright 2010
 * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
 *
 * (C) Copyright 2002
 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
 *
 * ispVM functions adapted from Lattice's ispmVMEmbedded code:
 * Copyright 2009 Lattice Semiconductor Corp.
 *
11
 * SPDX-License-Identifier:	GPL-2.0+
12 13 14 15 16 17 18 19
 */

#include <common.h>
#include <malloc.h>
#include <fpga.h>
#include <lattice.h>

static lattice_board_specific_func *pfns;
20
static const char *fpga_image;
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
static unsigned long read_bytes;
static unsigned long bufsize;
static unsigned short expectedCRC;

/*
 * External variables and functions declared in ivm_core.c module.
 */
extern unsigned short g_usCalculatedCRC;
extern unsigned short g_usDataType;
extern unsigned char *g_pucIntelBuffer;
extern unsigned char *g_pucHeapMemory;
extern unsigned short g_iHeapCounter;
extern unsigned short g_iHEAPSize;
extern unsigned short g_usIntelDataIndex;
extern unsigned short g_usIntelBufferSize;
extern char *const g_szSupportedVersions[];


/*
 * ispVMDelay
 *
 * Users must implement a delay to observe a_usTimeDelay, where
 * bit 15 of the a_usTimeDelay defines the unit.
 *      1 = milliseconds
 *      0 = microseconds
 * Example:
 *      a_usTimeDelay = 0x0001 = 1 microsecond delay.
 *      a_usTimeDelay = 0x8001 = 1 millisecond delay.
 *
 * This subroutine is called upon to provide a delay from 1 millisecond to a few
 * hundreds milliseconds each time.
 * It is understood that due to a_usTimeDelay is defined as unsigned short, a 16
 * bits integer, this function is restricted to produce a delay to 64000
 * micro-seconds or 32000 milli-second maximum. The VME file will never pass on
 * to this function a delay time > those maximum number. If it needs more than
 * those maximum, the VME file will launch the delay function several times to
 * realize a larger delay time cummulatively.
 * It is perfectly alright to provide a longer delay than required. It is not
 * acceptable if the delay is shorter.
 */
void ispVMDelay(unsigned short delay)
{
	if (delay & 0x8000)
		delay = (delay & ~0x8000) * 1000;
	udelay(delay);
}

void writePort(unsigned char a_ucPins, unsigned char a_ucValue)
{
	a_ucValue = a_ucValue ? 1 : 0;

	switch (a_ucPins) {
	case g_ucPinTDI:
		pfns->jtag_set_tdi(a_ucValue);
		break;
	case g_ucPinTCK:
		pfns->jtag_set_tck(a_ucValue);
		break;
	case g_ucPinTMS:
		pfns->jtag_set_tms(a_ucValue);
		break;
	default:
		printf("%s: requested unknown pin\n", __func__);
	}
}

unsigned char readPort(void)
{
	return pfns->jtag_get_tdo();
}

void sclock(void)
{
	writePort(g_ucPinTCK, 0x01);
	writePort(g_ucPinTCK, 0x00);
}

void calibration(void)
{
	/* Apply 2 pulses to TCK. */
	writePort(g_ucPinTCK, 0x00);
	writePort(g_ucPinTCK, 0x01);
	writePort(g_ucPinTCK, 0x00);
	writePort(g_ucPinTCK, 0x01);
	writePort(g_ucPinTCK, 0x00);

	ispVMDelay(0x8001);

	/* Apply 2 pulses to TCK. */
	writePort(g_ucPinTCK, 0x01);
	writePort(g_ucPinTCK, 0x00);
	writePort(g_ucPinTCK, 0x01);
	writePort(g_ucPinTCK, 0x00);
}

/*
 * GetByte
 *
 * Returns a byte to the caller. The returned byte depends on the
 * g_usDataType 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.
 */
unsigned char GetByte(void)
{
	unsigned char ucData;
	unsigned int block_size = 4 * 1024;

	if (g_usDataType & HEAP_IN) {

		/*
		 * Get data from repeat buffer.
		 */

		if (g_iHeapCounter > g_iHEAPSize) {

			/*
			 * Data over-run.
			 */

			return 0xFF;
		}

		ucData = g_pucHeapMemory[g_iHeapCounter++];
	} else if (g_usDataType & LHEAP_IN) {

		/*
		 * Get data from intel buffer.
		 */

		if (g_usIntelDataIndex >= g_usIntelBufferSize) {
			return 0xFF;
		}

		ucData = g_pucIntelBuffer[g_usIntelDataIndex++];
	} else {
		if (read_bytes == bufsize) {
			return 0xFF;
		}
		ucData = *fpga_image++;
		read_bytes++;

		if (!(read_bytes % block_size)) {
			printf("Downloading FPGA %ld/%ld completed\r",
				read_bytes,
				bufsize);
		}

		if (expectedCRC != 0) {
			ispVMCalculateCRC32(ucData);
		}
	}

	return ucData;
}

signed char ispVM(void)
{
	char szFileVersion[9]      = { 0 };
	signed char cRetCode         = 0;
	signed char cIndex           = 0;
	signed char cVersionIndex    = 0;
	unsigned char ucReadByte     = 0;
	unsigned short crc;

	g_pucHeapMemory		= NULL;
	g_iHeapCounter		= 0;
	g_iHEAPSize		= 0;
	g_usIntelDataIndex	= 0;
	g_usIntelBufferSize	= 0;
	g_usCalculatedCRC = 0;
	expectedCRC   = 0;
	ucReadByte = GetByte();
	switch (ucReadByte) {
	case FILE_CRC:
		crc = (unsigned char)GetByte();
		crc <<= 8;
		crc |= GetByte();
		expectedCRC = crc;

		for (cIndex = 0; cIndex < 8; cIndex++)
			szFileVersion[cIndex] = GetByte();

		break;
	default:
		szFileVersion[0] = (signed char) ucReadByte;
		for (cIndex = 1; cIndex < 8; cIndex++)
			szFileVersion[cIndex] = GetByte();

		break;
	}

	/*
	 *
	 * Compare the VME file version against the supported version.
	 *
	 */

	for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0;
		cVersionIndex++) {
		for (cIndex = 0; cIndex < 8; cIndex++) {
			if (szFileVersion[cIndex] !=
				g_szSupportedVersions[cVersionIndex][cIndex]) {
				cRetCode = VME_VERSION_FAILURE;
				break;
			}
			cRetCode = 0;
		}

		if (cRetCode == 0) {
			break;
		}
	}

	if (cRetCode < 0) {
		return VME_VERSION_FAILURE;
	}

	printf("VME file checked: starting downloading to FPGA\n");

	ispVMStart();

	cRetCode = ispVMCode();

	ispVMEnd();
	ispVMFreeMem();
	puts("\n");

	if (cRetCode == 0 && expectedCRC != 0 &&
			(expectedCRC != g_usCalculatedCRC)) {
		printf("Expected CRC:   0x%.4X\n", expectedCRC);
		printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC);
		return VME_CRC_FAILURE;
	}
	return cRetCode;
}

static int lattice_validate(Lattice_desc *desc, const char *fn)
{
York Sun's avatar
York Sun committed
261
	int ret_val = false;
262 263 264 265 266 267 268

	if (desc) {
		if ((desc->family > min_lattice_type) &&
			(desc->family < max_lattice_type)) {
			if ((desc->iface > min_lattice_iface_type) &&
				(desc->iface < max_lattice_iface_type)) {
				if (desc->size) {
York Sun's avatar
York Sun committed
269
					ret_val = true;
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
				} else {
					printf("%s: NULL part size\n", fn);
				}
			} else {
				printf("%s: Invalid Interface type, %d\n",
					fn, desc->iface);
			}
		} else {
			printf("%s: Invalid family type, %d\n",
				fn, desc->family);
		}
	} else {
		printf("%s: NULL descriptor!\n", fn);
	}

	return ret_val;
}

288
int lattice_load(Lattice_desc *desc, const void *buf, size_t bsize)
289 290 291 292 293 294 295 296 297 298 299 300 301 302
{
	int ret_val = FPGA_FAIL;

	if (!lattice_validate(desc, (char *)__func__)) {
		printf("%s: Invalid device descriptor\n", __func__);
	} else {
		pfns = desc->iface_fns;

		switch (desc->family) {
		case Lattice_XP2:
			fpga_image = buf;
			read_bytes = 0;
			bufsize = bsize;
			debug("%s: Launching the Lattice ISPVME Loader:"
303
				" addr %p size 0x%lx...\n",
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
				__func__, fpga_image, bufsize);
			ret_val = ispVM();
			if (ret_val)
				printf("%s: error %d downloading FPGA image\n",
					__func__, ret_val);
			else
				puts("FPGA downloaded successfully\n");
			break;
		default:
			printf("%s: Unsupported family type, %d\n",
					__func__, desc->family);
		}
	}

	return ret_val;
}

321
int lattice_dump(Lattice_desc *desc, const void *buf, size_t bsize)
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
{
	puts("Dump not supported for Lattice FPGA\n");

	return FPGA_FAIL;

}

int lattice_info(Lattice_desc *desc)
{
	int ret_val = FPGA_FAIL;

	if (lattice_validate(desc, (char *)__func__)) {
		printf("Family:        \t");
		switch (desc->family) {
		case Lattice_XP2:
			puts("XP2\n");
			break;
			/* Add new family types here */
		default:
			printf("Unknown family type, %d\n", desc->family);
		}

		puts("Interface type:\t");
		switch (desc->iface) {
		case lattice_jtag_mode:
			puts("JTAG Mode\n");
			break;
			/* Add new interface types here */
		default:
			printf("Unsupported interface type, %d\n", desc->iface);
		}

		printf("Device Size:   \t%d bytes\n",
				desc->size);

		if (desc->iface_fns) {
			printf("Device Function Table @ 0x%p\n",
				desc->iface_fns);
			switch (desc->family) {
			case Lattice_XP2:
				break;
				/* Add new family types here */
			default:
				break;
			}
		} else {
			puts("No Device Function Table.\n");
		}

		if (desc->desc)
			printf("Model:         \t%s\n", desc->desc);

		ret_val = FPGA_SUCCESS;
	} else {
		printf("%s: Invalid device descriptor\n", __func__);
	}

	return ret_val;
}