xref: /openbmc/u-boot/drivers/fpga/lattice.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
23b8ac464SStefano Babic /*
33b8ac464SStefano Babic  * (C) Copyright 2010
43b8ac464SStefano Babic  * Stefano Babic, DENX Software Engineering, sbabic@denx.de.
53b8ac464SStefano Babic  *
63b8ac464SStefano Babic  * (C) Copyright 2002
73b8ac464SStefano Babic  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
83b8ac464SStefano Babic  *
93b8ac464SStefano Babic  * ispVM functions adapted from Lattice's ispmVMEmbedded code:
103b8ac464SStefano Babic  * Copyright 2009 Lattice Semiconductor Corp.
113b8ac464SStefano Babic  */
123b8ac464SStefano Babic 
133b8ac464SStefano Babic #include <common.h>
143b8ac464SStefano Babic #include <malloc.h>
153b8ac464SStefano Babic #include <fpga.h>
163b8ac464SStefano Babic #include <lattice.h>
173b8ac464SStefano Babic 
183b8ac464SStefano Babic static lattice_board_specific_func *pfns;
19fb2d6efbSWolfgang Denk static const char *fpga_image;
203b8ac464SStefano Babic static unsigned long read_bytes;
213b8ac464SStefano Babic static unsigned long bufsize;
223b8ac464SStefano Babic static unsigned short expectedCRC;
233b8ac464SStefano Babic 
243b8ac464SStefano Babic /*
253b8ac464SStefano Babic  * External variables and functions declared in ivm_core.c module.
263b8ac464SStefano Babic  */
273b8ac464SStefano Babic extern unsigned short g_usCalculatedCRC;
283b8ac464SStefano Babic extern unsigned short g_usDataType;
293b8ac464SStefano Babic extern unsigned char *g_pucIntelBuffer;
303b8ac464SStefano Babic extern unsigned char *g_pucHeapMemory;
313b8ac464SStefano Babic extern unsigned short g_iHeapCounter;
323b8ac464SStefano Babic extern unsigned short g_iHEAPSize;
333b8ac464SStefano Babic extern unsigned short g_usIntelDataIndex;
343b8ac464SStefano Babic extern unsigned short g_usIntelBufferSize;
353b8ac464SStefano Babic extern char *const g_szSupportedVersions[];
363b8ac464SStefano Babic 
373b8ac464SStefano Babic 
383b8ac464SStefano Babic /*
393b8ac464SStefano Babic  * ispVMDelay
403b8ac464SStefano Babic  *
413b8ac464SStefano Babic  * Users must implement a delay to observe a_usTimeDelay, where
423b8ac464SStefano Babic  * bit 15 of the a_usTimeDelay defines the unit.
433b8ac464SStefano Babic  *      1 = milliseconds
443b8ac464SStefano Babic  *      0 = microseconds
453b8ac464SStefano Babic  * Example:
463b8ac464SStefano Babic  *      a_usTimeDelay = 0x0001 = 1 microsecond delay.
473b8ac464SStefano Babic  *      a_usTimeDelay = 0x8001 = 1 millisecond delay.
483b8ac464SStefano Babic  *
493b8ac464SStefano Babic  * This subroutine is called upon to provide a delay from 1 millisecond to a few
503b8ac464SStefano Babic  * hundreds milliseconds each time.
513b8ac464SStefano Babic  * It is understood that due to a_usTimeDelay is defined as unsigned short, a 16
523b8ac464SStefano Babic  * bits integer, this function is restricted to produce a delay to 64000
533b8ac464SStefano Babic  * micro-seconds or 32000 milli-second maximum. The VME file will never pass on
543b8ac464SStefano Babic  * to this function a delay time > those maximum number. If it needs more than
553b8ac464SStefano Babic  * those maximum, the VME file will launch the delay function several times to
563b8ac464SStefano Babic  * realize a larger delay time cummulatively.
573b8ac464SStefano Babic  * It is perfectly alright to provide a longer delay than required. It is not
583b8ac464SStefano Babic  * acceptable if the delay is shorter.
593b8ac464SStefano Babic  */
ispVMDelay(unsigned short delay)603b8ac464SStefano Babic void ispVMDelay(unsigned short delay)
613b8ac464SStefano Babic {
623b8ac464SStefano Babic 	if (delay & 0x8000)
633b8ac464SStefano Babic 		delay = (delay & ~0x8000) * 1000;
643b8ac464SStefano Babic 	udelay(delay);
653b8ac464SStefano Babic }
663b8ac464SStefano Babic 
writePort(unsigned char a_ucPins,unsigned char a_ucValue)673b8ac464SStefano Babic void writePort(unsigned char a_ucPins, unsigned char a_ucValue)
683b8ac464SStefano Babic {
693b8ac464SStefano Babic 	a_ucValue = a_ucValue ? 1 : 0;
703b8ac464SStefano Babic 
713b8ac464SStefano Babic 	switch (a_ucPins) {
723b8ac464SStefano Babic 	case g_ucPinTDI:
733b8ac464SStefano Babic 		pfns->jtag_set_tdi(a_ucValue);
743b8ac464SStefano Babic 		break;
753b8ac464SStefano Babic 	case g_ucPinTCK:
763b8ac464SStefano Babic 		pfns->jtag_set_tck(a_ucValue);
773b8ac464SStefano Babic 		break;
783b8ac464SStefano Babic 	case g_ucPinTMS:
793b8ac464SStefano Babic 		pfns->jtag_set_tms(a_ucValue);
803b8ac464SStefano Babic 		break;
813b8ac464SStefano Babic 	default:
823b8ac464SStefano Babic 		printf("%s: requested unknown pin\n", __func__);
833b8ac464SStefano Babic 	}
843b8ac464SStefano Babic }
853b8ac464SStefano Babic 
readPort(void)863b8ac464SStefano Babic unsigned char readPort(void)
873b8ac464SStefano Babic {
883b8ac464SStefano Babic 	return pfns->jtag_get_tdo();
893b8ac464SStefano Babic }
903b8ac464SStefano Babic 
sclock(void)913b8ac464SStefano Babic void sclock(void)
923b8ac464SStefano Babic {
933b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x01);
943b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x00);
953b8ac464SStefano Babic }
963b8ac464SStefano Babic 
calibration(void)973b8ac464SStefano Babic void calibration(void)
983b8ac464SStefano Babic {
993b8ac464SStefano Babic 	/* Apply 2 pulses to TCK. */
1003b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x00);
1013b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x01);
1023b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x00);
1033b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x01);
1043b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x00);
1053b8ac464SStefano Babic 
1063b8ac464SStefano Babic 	ispVMDelay(0x8001);
1073b8ac464SStefano Babic 
1083b8ac464SStefano Babic 	/* Apply 2 pulses to TCK. */
1093b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x01);
1103b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x00);
1113b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x01);
1123b8ac464SStefano Babic 	writePort(g_ucPinTCK, 0x00);
1133b8ac464SStefano Babic }
1143b8ac464SStefano Babic 
1153b8ac464SStefano Babic /*
1163b8ac464SStefano Babic  * GetByte
1173b8ac464SStefano Babic  *
1183b8ac464SStefano Babic  * Returns a byte to the caller. The returned byte depends on the
1193b8ac464SStefano Babic  * g_usDataType register. If the HEAP_IN bit is set, then the byte
1203b8ac464SStefano Babic  * is returned from the HEAP. If the LHEAP_IN bit is set, then
1213b8ac464SStefano Babic  * the byte is returned from the intelligent buffer. Otherwise,
1223b8ac464SStefano Babic  * the byte is returned directly from the VME file.
1233b8ac464SStefano Babic  */
GetByte(void)1243b8ac464SStefano Babic unsigned char GetByte(void)
1253b8ac464SStefano Babic {
1263b8ac464SStefano Babic 	unsigned char ucData;
1273b8ac464SStefano Babic 	unsigned int block_size = 4 * 1024;
1283b8ac464SStefano Babic 
1293b8ac464SStefano Babic 	if (g_usDataType & HEAP_IN) {
1303b8ac464SStefano Babic 
1313b8ac464SStefano Babic 		/*
1323b8ac464SStefano Babic 		 * Get data from repeat buffer.
1333b8ac464SStefano Babic 		 */
1343b8ac464SStefano Babic 
1353b8ac464SStefano Babic 		if (g_iHeapCounter > g_iHEAPSize) {
1363b8ac464SStefano Babic 
1373b8ac464SStefano Babic 			/*
1383b8ac464SStefano Babic 			 * Data over-run.
1393b8ac464SStefano Babic 			 */
1403b8ac464SStefano Babic 
1413b8ac464SStefano Babic 			return 0xFF;
1423b8ac464SStefano Babic 		}
1433b8ac464SStefano Babic 
1443b8ac464SStefano Babic 		ucData = g_pucHeapMemory[g_iHeapCounter++];
1453b8ac464SStefano Babic 	} else if (g_usDataType & LHEAP_IN) {
1463b8ac464SStefano Babic 
1473b8ac464SStefano Babic 		/*
1483b8ac464SStefano Babic 		 * Get data from intel buffer.
1493b8ac464SStefano Babic 		 */
1503b8ac464SStefano Babic 
1513b8ac464SStefano Babic 		if (g_usIntelDataIndex >= g_usIntelBufferSize) {
1523b8ac464SStefano Babic 			return 0xFF;
1533b8ac464SStefano Babic 		}
1543b8ac464SStefano Babic 
1553b8ac464SStefano Babic 		ucData = g_pucIntelBuffer[g_usIntelDataIndex++];
1563b8ac464SStefano Babic 	} else {
1573b8ac464SStefano Babic 		if (read_bytes == bufsize) {
1583b8ac464SStefano Babic 			return 0xFF;
1593b8ac464SStefano Babic 		}
1603b8ac464SStefano Babic 		ucData = *fpga_image++;
1613b8ac464SStefano Babic 		read_bytes++;
1623b8ac464SStefano Babic 
1633b8ac464SStefano Babic 		if (!(read_bytes % block_size)) {
1643b8ac464SStefano Babic 			printf("Downloading FPGA %ld/%ld completed\r",
1653b8ac464SStefano Babic 				read_bytes,
1663b8ac464SStefano Babic 				bufsize);
1673b8ac464SStefano Babic 		}
1683b8ac464SStefano Babic 
1693b8ac464SStefano Babic 		if (expectedCRC != 0) {
1703b8ac464SStefano Babic 			ispVMCalculateCRC32(ucData);
1713b8ac464SStefano Babic 		}
1723b8ac464SStefano Babic 	}
1733b8ac464SStefano Babic 
1743b8ac464SStefano Babic 	return ucData;
1753b8ac464SStefano Babic }
1763b8ac464SStefano Babic 
ispVM(void)1773b8ac464SStefano Babic signed char ispVM(void)
1783b8ac464SStefano Babic {
1793b8ac464SStefano Babic 	char szFileVersion[9]      = { 0 };
1803b8ac464SStefano Babic 	signed char cRetCode         = 0;
1813b8ac464SStefano Babic 	signed char cIndex           = 0;
1823b8ac464SStefano Babic 	signed char cVersionIndex    = 0;
1833b8ac464SStefano Babic 	unsigned char ucReadByte     = 0;
1843b8ac464SStefano Babic 	unsigned short crc;
1853b8ac464SStefano Babic 
1863b8ac464SStefano Babic 	g_pucHeapMemory		= NULL;
1873b8ac464SStefano Babic 	g_iHeapCounter		= 0;
1883b8ac464SStefano Babic 	g_iHEAPSize		= 0;
1893b8ac464SStefano Babic 	g_usIntelDataIndex	= 0;
1903b8ac464SStefano Babic 	g_usIntelBufferSize	= 0;
1913b8ac464SStefano Babic 	g_usCalculatedCRC = 0;
1923b8ac464SStefano Babic 	expectedCRC   = 0;
1933b8ac464SStefano Babic 	ucReadByte = GetByte();
1943b8ac464SStefano Babic 	switch (ucReadByte) {
1953b8ac464SStefano Babic 	case FILE_CRC:
1963b8ac464SStefano Babic 		crc = (unsigned char)GetByte();
1973b8ac464SStefano Babic 		crc <<= 8;
1983b8ac464SStefano Babic 		crc |= GetByte();
1993b8ac464SStefano Babic 		expectedCRC = crc;
2003b8ac464SStefano Babic 
2013b8ac464SStefano Babic 		for (cIndex = 0; cIndex < 8; cIndex++)
2023b8ac464SStefano Babic 			szFileVersion[cIndex] = GetByte();
2033b8ac464SStefano Babic 
2043b8ac464SStefano Babic 		break;
2053b8ac464SStefano Babic 	default:
2063b8ac464SStefano Babic 		szFileVersion[0] = (signed char) ucReadByte;
2073b8ac464SStefano Babic 		for (cIndex = 1; cIndex < 8; cIndex++)
2083b8ac464SStefano Babic 			szFileVersion[cIndex] = GetByte();
2093b8ac464SStefano Babic 
2103b8ac464SStefano Babic 		break;
2113b8ac464SStefano Babic 	}
2123b8ac464SStefano Babic 
2133b8ac464SStefano Babic 	/*
2143b8ac464SStefano Babic 	 *
2153b8ac464SStefano Babic 	 * Compare the VME file version against the supported version.
2163b8ac464SStefano Babic 	 *
2173b8ac464SStefano Babic 	 */
2183b8ac464SStefano Babic 
2193b8ac464SStefano Babic 	for (cVersionIndex = 0; g_szSupportedVersions[cVersionIndex] != 0;
2203b8ac464SStefano Babic 		cVersionIndex++) {
2213b8ac464SStefano Babic 		for (cIndex = 0; cIndex < 8; cIndex++) {
2223b8ac464SStefano Babic 			if (szFileVersion[cIndex] !=
2233b8ac464SStefano Babic 				g_szSupportedVersions[cVersionIndex][cIndex]) {
2243b8ac464SStefano Babic 				cRetCode = VME_VERSION_FAILURE;
2253b8ac464SStefano Babic 				break;
2263b8ac464SStefano Babic 			}
2273b8ac464SStefano Babic 			cRetCode = 0;
2283b8ac464SStefano Babic 		}
2293b8ac464SStefano Babic 
2303b8ac464SStefano Babic 		if (cRetCode == 0) {
2313b8ac464SStefano Babic 			break;
2323b8ac464SStefano Babic 		}
2333b8ac464SStefano Babic 	}
2343b8ac464SStefano Babic 
2353b8ac464SStefano Babic 	if (cRetCode < 0) {
2363b8ac464SStefano Babic 		return VME_VERSION_FAILURE;
2373b8ac464SStefano Babic 	}
2383b8ac464SStefano Babic 
2393b8ac464SStefano Babic 	printf("VME file checked: starting downloading to FPGA\n");
2403b8ac464SStefano Babic 
2413b8ac464SStefano Babic 	ispVMStart();
2423b8ac464SStefano Babic 
2433b8ac464SStefano Babic 	cRetCode = ispVMCode();
2443b8ac464SStefano Babic 
2453b8ac464SStefano Babic 	ispVMEnd();
2463b8ac464SStefano Babic 	ispVMFreeMem();
2473b8ac464SStefano Babic 	puts("\n");
2483b8ac464SStefano Babic 
2493b8ac464SStefano Babic 	if (cRetCode == 0 && expectedCRC != 0 &&
2503b8ac464SStefano Babic 			(expectedCRC != g_usCalculatedCRC)) {
2513b8ac464SStefano Babic 		printf("Expected CRC:   0x%.4X\n", expectedCRC);
2523b8ac464SStefano Babic 		printf("Calculated CRC: 0x%.4X\n", g_usCalculatedCRC);
2533b8ac464SStefano Babic 		return VME_CRC_FAILURE;
2543b8ac464SStefano Babic 	}
2553b8ac464SStefano Babic 	return cRetCode;
2563b8ac464SStefano Babic }
2573b8ac464SStefano Babic 
lattice_validate(Lattice_desc * desc,const char * fn)2583b8ac464SStefano Babic static int lattice_validate(Lattice_desc *desc, const char *fn)
2593b8ac464SStefano Babic {
260472d5460SYork Sun 	int ret_val = false;
2613b8ac464SStefano Babic 
2623b8ac464SStefano Babic 	if (desc) {
2633b8ac464SStefano Babic 		if ((desc->family > min_lattice_type) &&
2643b8ac464SStefano Babic 			(desc->family < max_lattice_type)) {
2653b8ac464SStefano Babic 			if ((desc->iface > min_lattice_iface_type) &&
2663b8ac464SStefano Babic 				(desc->iface < max_lattice_iface_type)) {
2673b8ac464SStefano Babic 				if (desc->size) {
268472d5460SYork Sun 					ret_val = true;
2693b8ac464SStefano Babic 				} else {
2703b8ac464SStefano Babic 					printf("%s: NULL part size\n", fn);
2713b8ac464SStefano Babic 				}
2723b8ac464SStefano Babic 			} else {
2733b8ac464SStefano Babic 				printf("%s: Invalid Interface type, %d\n",
2743b8ac464SStefano Babic 					fn, desc->iface);
2753b8ac464SStefano Babic 			}
2763b8ac464SStefano Babic 		} else {
2773b8ac464SStefano Babic 			printf("%s: Invalid family type, %d\n",
2783b8ac464SStefano Babic 				fn, desc->family);
2793b8ac464SStefano Babic 		}
2803b8ac464SStefano Babic 	} else {
2813b8ac464SStefano Babic 		printf("%s: NULL descriptor!\n", fn);
2823b8ac464SStefano Babic 	}
2833b8ac464SStefano Babic 
2843b8ac464SStefano Babic 	return ret_val;
2853b8ac464SStefano Babic }
2863b8ac464SStefano Babic 
lattice_load(Lattice_desc * desc,const void * buf,size_t bsize)287fb2d6efbSWolfgang Denk int lattice_load(Lattice_desc *desc, const void *buf, size_t bsize)
2883b8ac464SStefano Babic {
2893b8ac464SStefano Babic 	int ret_val = FPGA_FAIL;
2903b8ac464SStefano Babic 
2913b8ac464SStefano Babic 	if (!lattice_validate(desc, (char *)__func__)) {
2923b8ac464SStefano Babic 		printf("%s: Invalid device descriptor\n", __func__);
2933b8ac464SStefano Babic 	} else {
2943b8ac464SStefano Babic 		pfns = desc->iface_fns;
2953b8ac464SStefano Babic 
2963b8ac464SStefano Babic 		switch (desc->family) {
2973b8ac464SStefano Babic 		case Lattice_XP2:
2983b8ac464SStefano Babic 			fpga_image = buf;
2993b8ac464SStefano Babic 			read_bytes = 0;
3003b8ac464SStefano Babic 			bufsize = bsize;
3013b8ac464SStefano Babic 			debug("%s: Launching the Lattice ISPVME Loader:"
302b89c708bSMarek Vasut 				" addr %p size 0x%lx...\n",
3033b8ac464SStefano Babic 				__func__, fpga_image, bufsize);
3043b8ac464SStefano Babic 			ret_val = ispVM();
3053b8ac464SStefano Babic 			if (ret_val)
3063b8ac464SStefano Babic 				printf("%s: error %d downloading FPGA image\n",
3073b8ac464SStefano Babic 					__func__, ret_val);
3083b8ac464SStefano Babic 			else
3093b8ac464SStefano Babic 				puts("FPGA downloaded successfully\n");
3103b8ac464SStefano Babic 			break;
3113b8ac464SStefano Babic 		default:
3123b8ac464SStefano Babic 			printf("%s: Unsupported family type, %d\n",
3133b8ac464SStefano Babic 					__func__, desc->family);
3143b8ac464SStefano Babic 		}
3153b8ac464SStefano Babic 	}
3163b8ac464SStefano Babic 
3173b8ac464SStefano Babic 	return ret_val;
3183b8ac464SStefano Babic }
3193b8ac464SStefano Babic 
lattice_dump(Lattice_desc * desc,const void * buf,size_t bsize)320fb2d6efbSWolfgang Denk int lattice_dump(Lattice_desc *desc, const void *buf, size_t bsize)
3213b8ac464SStefano Babic {
3223b8ac464SStefano Babic 	puts("Dump not supported for Lattice FPGA\n");
3233b8ac464SStefano Babic 
3243b8ac464SStefano Babic 	return FPGA_FAIL;
3253b8ac464SStefano Babic 
3263b8ac464SStefano Babic }
3273b8ac464SStefano Babic 
lattice_info(Lattice_desc * desc)3283b8ac464SStefano Babic int lattice_info(Lattice_desc *desc)
3293b8ac464SStefano Babic {
3303b8ac464SStefano Babic 	int ret_val = FPGA_FAIL;
3313b8ac464SStefano Babic 
3323b8ac464SStefano Babic 	if (lattice_validate(desc, (char *)__func__)) {
3333b8ac464SStefano Babic 		printf("Family:        \t");
3343b8ac464SStefano Babic 		switch (desc->family) {
3353b8ac464SStefano Babic 		case Lattice_XP2:
3363b8ac464SStefano Babic 			puts("XP2\n");
3373b8ac464SStefano Babic 			break;
3383b8ac464SStefano Babic 			/* Add new family types here */
3393b8ac464SStefano Babic 		default:
3403b8ac464SStefano Babic 			printf("Unknown family type, %d\n", desc->family);
3413b8ac464SStefano Babic 		}
3423b8ac464SStefano Babic 
3433b8ac464SStefano Babic 		puts("Interface type:\t");
3443b8ac464SStefano Babic 		switch (desc->iface) {
3453b8ac464SStefano Babic 		case lattice_jtag_mode:
3463b8ac464SStefano Babic 			puts("JTAG Mode\n");
3473b8ac464SStefano Babic 			break;
3483b8ac464SStefano Babic 			/* Add new interface types here */
3493b8ac464SStefano Babic 		default:
3503b8ac464SStefano Babic 			printf("Unsupported interface type, %d\n", desc->iface);
3513b8ac464SStefano Babic 		}
3523b8ac464SStefano Babic 
3533b8ac464SStefano Babic 		printf("Device Size:   \t%d bytes\n",
3543b8ac464SStefano Babic 				desc->size);
3553b8ac464SStefano Babic 
3563b8ac464SStefano Babic 		if (desc->iface_fns) {
3573b8ac464SStefano Babic 			printf("Device Function Table @ 0x%p\n",
3583b8ac464SStefano Babic 				desc->iface_fns);
3593b8ac464SStefano Babic 			switch (desc->family) {
3603b8ac464SStefano Babic 			case Lattice_XP2:
3613b8ac464SStefano Babic 				break;
3623b8ac464SStefano Babic 				/* Add new family types here */
3633b8ac464SStefano Babic 			default:
3643b8ac464SStefano Babic 				break;
3653b8ac464SStefano Babic 			}
3663b8ac464SStefano Babic 		} else {
3673b8ac464SStefano Babic 			puts("No Device Function Table.\n");
3683b8ac464SStefano Babic 		}
3693b8ac464SStefano Babic 
3703b8ac464SStefano Babic 		if (desc->desc)
3713b8ac464SStefano Babic 			printf("Model:         \t%s\n", desc->desc);
3723b8ac464SStefano Babic 
3733b8ac464SStefano Babic 		ret_val = FPGA_SUCCESS;
3743b8ac464SStefano Babic 	} else {
3753b8ac464SStefano Babic 		printf("%s: Invalid device descriptor\n", __func__);
3763b8ac464SStefano Babic 	}
3773b8ac464SStefano Babic 
3783b8ac464SStefano Babic 	return ret_val;
3793b8ac464SStefano Babic }
380