fpga.c 7.76 KB
Newer Older
wdenk's avatar
wdenk committed
1 2 3 4 5
/*
 * (C) Copyright 2002
 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
 * Keith Outwater, keith_outwater@mvis.com.
 *
6
 * SPDX-License-Identifier:	GPL-2.0+
wdenk's avatar
wdenk committed
7 8 9 10 11 12 13 14 15 16 17
 */

/*
 * Virtex2 FPGA configuration support for the GEN860T computer
 */

#include <common.h>
#include <virtex2.h>
#include <command.h>
#include "fpga.h"

18 19
DECLARE_GLOBAL_DATA_PTR;

20
#if defined(CONFIG_FPGA)
wdenk's avatar
wdenk committed
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

#if 0
#define GEN860T_FPGA_DEBUG
#endif

#ifdef GEN860T_FPGA_DEBUG
#define	PRINTF(fmt,args...)	printf (fmt ,##args)
#else
#define	PRINTF(fmt,args...)
#endif

/*
 * Port bit numbers for the Selectmap controls
 */
#define FPGA_INIT_BIT_NUM		22	/* PB22 */
#define FPGA_RESET_BIT_NUM		11	/* PC11 */
#define FPGA_DONE_BIT_NUM		16	/* PB16 */
#define FPGA_PROGRAM_BIT_NUM	7	/* PA7  */

/* Note that these are pointers to code that is in Flash.  They will be
 * relocated at runtime.
 */
Xilinx_Virtex2_Slave_SelectMap_fns fpga_fns = {
	fpga_pre_config_fn,
	fpga_pgm_fn,
	fpga_init_fn,
	fpga_err_fn,
	fpga_done_fn,
	fpga_clk_fn,
	fpga_cs_fn,
	fpga_wr_fn,
	fpga_read_data_fn,
	fpga_write_data_fn,
	fpga_busy_fn,
	fpga_abort_fn,
	fpga_post_config_fn
};

Xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
wdenk's avatar
wdenk committed
60 61 62 63 64
	{Xilinx_Virtex2,
	 slave_selectmap,
	 XILINX_XC2V3000_SIZE,
	 (void *) &fpga_fns,
	 0}
wdenk's avatar
wdenk committed
65 66 67 68 69
};

/*
 * Display FPGA revision information
 */
wdenk's avatar
wdenk committed
70
void print_fpga_revision (void)
wdenk's avatar
wdenk committed
71
{
wdenk's avatar
wdenk committed
72 73 74 75 76 77 78 79 80
	vu_long *rev_p = (vu_long *) 0x60000008;

	printf ("FPGA Revision 0x%.8lx"
		" (Date %.2lx/%.2lx/%.2lx, Status \"%.1lx\", Version %.3lu)\n",
		*rev_p,
		((*rev_p >> 28) & 0xf),
		((*rev_p >> 20) & 0xff),
		((*rev_p >> 12) & 0xff),
		((*rev_p >> 8) & 0xf), (*rev_p & 0xff));
wdenk's avatar
wdenk committed
81 82 83 84 85 86 87 88 89 90
}


/*
 * Perform a simple test of the FPGA to processor interface using the FPGA's
 * inverting bus test register.  The great thing about doing a read/write
 * test on a register that inverts it's contents is that you avoid any
 * problems with bus charging.
 * Return 0 on failure, 1 on success.
 */
wdenk's avatar
wdenk committed
91
int test_fpga_ibtr (void)
wdenk's avatar
wdenk committed
92
{
wdenk's avatar
wdenk committed
93
	vu_long *ibtr_p = (vu_long *) 0x60000010;
wdenk's avatar
wdenk committed
94 95 96 97 98 99 100 101
	vu_long readback;
	vu_long compare;
	int i;
	int j;
	int k;
	int pass = 1;

	static const ulong bitpattern[] = {
wdenk's avatar
wdenk committed
102 103 104 105 106 107 108 109 110
		0xdeadbeef,	/* magic ID pattern for debug   */
		0x00000001,	/* single bit                                   */
		0x00000003,	/* two adjacent bits                    */
		0x00000007,	/* three adjacent bits                  */
		0x0000000F,	/* four adjacent bits                   */
		0x00000005,	/* two non-adjacent bits                */
		0x00000015,	/* three non-adjacent bits              */
		0x00000055,	/* four non-adjacent bits               */
		0xaaaaaaaa,	/* alternating 1/0                              */
wdenk's avatar
wdenk committed
111 112 113 114
	};

	for (i = 0; i < 1024; i++) {
		for (j = 0; j < 31; j++) {
wdenk's avatar
wdenk committed
115 116 117
			for (k = 0;
			     k < sizeof (bitpattern) / sizeof (bitpattern[0]);
			     k++) {
wdenk's avatar
wdenk committed
118 119 120
				*ibtr_p = compare = (bitpattern[k] << j);
				readback = *ibtr_p;
				if (readback != ~compare) {
wdenk's avatar
wdenk committed
121
					printf ("%s:%d: FPGA test fail: expected 0x%.8lx" " actual 0x%.8lx\n", __FUNCTION__, __LINE__, ~compare, readback);
wdenk's avatar
wdenk committed
122 123 124 125
					pass = 0;
					break;
				}
			}
wdenk's avatar
wdenk committed
126 127
			if (!pass)
				break;
wdenk's avatar
wdenk committed
128
		}
wdenk's avatar
wdenk committed
129 130
		if (!pass)
			break;
wdenk's avatar
wdenk committed
131 132
	}
	if (pass) {
wdenk's avatar
wdenk committed
133 134 135 136
		printf ("FPGA inverting bus test passed\n");
		print_fpga_revision ();
	} else {
		printf ("** FPGA inverting bus test failed\n");
wdenk's avatar
wdenk committed
137 138 139 140 141 142 143 144
	}
	return pass;
}


/*
 * Set the active-low FPGA reset signal.
 */
wdenk's avatar
wdenk committed
145
void fpga_reset (int assert)
wdenk's avatar
wdenk committed
146
{
147
	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
wdenk's avatar
wdenk committed
148

wdenk's avatar
wdenk committed
149
	PRINTF ("%s:%d: RESET ", __FUNCTION__, __LINE__);
wdenk's avatar
wdenk committed
150 151
	if (assert) {
		immap->im_ioport.iop_pcdat &= ~(0x8000 >> FPGA_RESET_BIT_NUM);
wdenk's avatar
wdenk committed
152 153
		PRINTF ("asserted\n");
	} else {
wdenk's avatar
wdenk committed
154
		immap->im_ioport.iop_pcdat |= (0x8000 >> FPGA_RESET_BIT_NUM);
wdenk's avatar
wdenk committed
155
		PRINTF ("deasserted\n");
wdenk's avatar
wdenk committed
156 157 158 159 160 161 162 163
	}
}


/*
 * Initialize the SelectMap interface.  We assume that the mode and the
 * initial state of all of the port pins have already been set!
 */
wdenk's avatar
wdenk committed
164
void fpga_selectmap_init (void)
wdenk's avatar
wdenk committed
165
{
wdenk's avatar
wdenk committed
166 167
	PRINTF ("%s:%d: Initialize SelectMap interface\n", __FUNCTION__,
		__LINE__);
York Sun's avatar
York Sun committed
168
	fpga_pgm_fn(false, false, 0);	/* make sure program pin is inactive */
wdenk's avatar
wdenk committed
169 170 171 172 173 174
}


/*
 * Initialize the fpga.  Return 1 on success, 0 on failure.
 */
wdenk's avatar
wdenk committed
175
int gen860t_init_fpga (void)
wdenk's avatar
wdenk committed
176 177 178
{
	int i;

Peter Tyser's avatar
Peter Tyser committed
179 180 181
	PRINTF ("%s:%d: Initialize FPGA interface\n",
		__FUNCTION__, __LINE__);
	fpga_init ();
wdenk's avatar
wdenk committed
182
	fpga_selectmap_init ();
wdenk's avatar
wdenk committed
183

wdenk's avatar
wdenk committed
184 185 186
	for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
		PRINTF ("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i);
		fpga_add (fpga_xilinx, &fpga[i]);
wdenk's avatar
wdenk committed
187
	}
wdenk's avatar
wdenk committed
188
	return 1;
wdenk's avatar
wdenk committed
189 190 191 192 193 194
}


/*
 * Set the FPGA's active-low SelectMap program line to the specified level
 */
wdenk's avatar
wdenk committed
195
int fpga_pgm_fn (int assert, int flush, int cookie)
wdenk's avatar
wdenk committed
196
{
197
	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
wdenk's avatar
wdenk committed
198

wdenk's avatar
wdenk committed
199
	PRINTF ("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
wdenk's avatar
wdenk committed
200 201

	if (assert) {
wdenk's avatar
wdenk committed
202 203 204 205 206 207 208
		immap->im_ioport.iop_padat &=
			~(0x8000 >> FPGA_PROGRAM_BIT_NUM);
		PRINTF ("asserted\n");
	} else {
		immap->im_ioport.iop_padat |=
			(0x8000 >> FPGA_PROGRAM_BIT_NUM);
		PRINTF ("deasserted\n");
wdenk's avatar
wdenk committed
209 210 211 212 213 214 215 216 217
	}
	return assert;
}


/*
 * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
 * asserted (low).
 */
wdenk's avatar
wdenk committed
218
int fpga_init_fn (int cookie)
wdenk's avatar
wdenk committed
219
{
220
	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
wdenk's avatar
wdenk committed
221

wdenk's avatar
wdenk committed
222 223 224
	PRINTF ("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
	if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_INIT_BIT_NUM)) {
		PRINTF ("high\n");
wdenk's avatar
wdenk committed
225
		return 0;
wdenk's avatar
wdenk committed
226 227
	} else {
		PRINTF ("low\n");
wdenk's avatar
wdenk committed
228 229 230 231 232 233 234 235
		return 1;
	}
}


/*
 * Test the state of the active-high FPGA DONE pin
 */
wdenk's avatar
wdenk committed
236
int fpga_done_fn (int cookie)
wdenk's avatar
wdenk committed
237
{
238
	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
wdenk's avatar
wdenk committed
239

wdenk's avatar
wdenk committed
240
	PRINTF ("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
wdenk's avatar
wdenk committed
241
	if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_DONE_BIT_NUM)) {
wdenk's avatar
wdenk committed
242
		PRINTF ("high\n");
wdenk's avatar
wdenk committed
243
		return FPGA_SUCCESS;
wdenk's avatar
wdenk committed
244 245
	} else {
		PRINTF ("low\n");
wdenk's avatar
wdenk committed
246 247 248 249 250 251 252 253
		return FPGA_FAIL;
	}
}


/*
 * Read FPGA SelectMap data.
 */
wdenk's avatar
wdenk committed
254
int fpga_read_data_fn (unsigned char *data, int cookie)
wdenk's avatar
wdenk committed
255
{
wdenk's avatar
wdenk committed
256
	vu_char *p = (vu_char *) SELECTMAP_BASE;
wdenk's avatar
wdenk committed
257 258 259

	*data = *p;
#if 0
wdenk's avatar
wdenk committed
260
	PRINTF ("%s: Read 0x%x into 0x%p\n", __FUNCTION__, (int) data, data);
wdenk's avatar
wdenk committed
261
#endif
wdenk's avatar
wdenk committed
262
	return (int) data;
wdenk's avatar
wdenk committed
263 264 265 266 267 268
}


/*
 * Write data to the FPGA SelectMap port
 */
wdenk's avatar
wdenk committed
269
int fpga_write_data_fn (unsigned char data, int flush, int cookie)
wdenk's avatar
wdenk committed
270
{
wdenk's avatar
wdenk committed
271
	vu_char *p = (vu_char *) SELECTMAP_BASE;
wdenk's avatar
wdenk committed
272 273

#if 0
wdenk's avatar
wdenk committed
274
	PRINTF ("%s: Write Data 0x%x\n", __FUNCTION__, (int) data);
wdenk's avatar
wdenk committed
275 276
#endif
	*p = data;
wdenk's avatar
wdenk committed
277
	return (int) data;
wdenk's avatar
wdenk committed
278 279 280 281 282 283
}


/*
 * Abort and FPGA operation
 */
wdenk's avatar
wdenk committed
284
int fpga_abort_fn (int cookie)
wdenk's avatar
wdenk committed
285
{
wdenk's avatar
wdenk committed
286 287
	PRINTF ("%s:%d: FPGA program sequence aborted\n",
		__FUNCTION__, __LINE__);
wdenk's avatar
wdenk committed
288 289 290 291 292 293 294 295 296
	return FPGA_FAIL;
}


/*
 * FPGA pre-configuration function. Just make sure that
 * FPGA reset is asserted to keep the FPGA from starting up after
 * configuration.
 */
wdenk's avatar
wdenk committed
297
int fpga_pre_config_fn (int cookie)
wdenk's avatar
wdenk committed
298
{
wdenk's avatar
wdenk committed
299
	PRINTF ("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
York Sun's avatar
York Sun committed
300
	fpga_reset(true);
wdenk's avatar
wdenk committed
301 302 303 304 305 306 307 308
	return 0;
}


/*
 * FPGA post configuration function. Blip the FPGA reset line and then see if
 * the FPGA appears to be running.
 */
wdenk's avatar
wdenk committed
309
int fpga_post_config_fn (int cookie)
wdenk's avatar
wdenk committed
310 311 312
{
	int rc;

wdenk's avatar
wdenk committed
313
	PRINTF ("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
York Sun's avatar
York Sun committed
314
	fpga_reset(true);
wdenk's avatar
wdenk committed
315
	udelay (1000);
York Sun's avatar
York Sun committed
316
	fpga_reset(false);
wdenk's avatar
wdenk committed
317 318 319 320 321 322
	udelay (1000);

	/*
	 * Use the FPGA,s inverting bus test register to do a simple test of the
	 * processor interface.
	 */
wdenk's avatar
wdenk committed
323
	rc = test_fpga_ibtr ();
wdenk's avatar
wdenk committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337
	return rc;
}


/*
 * Clock, chip select and write signal assert functions and error check
 * and busy functions.  These are only stubs because the GEN860T selectmap
 * interface handles sequencing of control signals automatically (it uses
 * a memory-mapped interface to the FPGA SelectMap port).  The design of
 * the interface guarantees that the SelectMap port cannot be overrun so
 * no busy check is needed.  A configuration error is signalled by INIT
 * going low during configuration, so there is no need for a separate error
 * function.
 */
wdenk's avatar
wdenk committed
338
int fpga_clk_fn (int assert_clk, int flush, int cookie)
wdenk's avatar
wdenk committed
339 340 341 342
{
	return assert_clk;
}

wdenk's avatar
wdenk committed
343
int fpga_cs_fn (int assert_cs, int flush, int cookie)
wdenk's avatar
wdenk committed
344 345 346 347
{
	return assert_cs;
}

wdenk's avatar
wdenk committed
348
int fpga_wr_fn (int assert_write, int flush, int cookie)
wdenk's avatar
wdenk committed
349 350 351 352
{
	return assert_write;
}

wdenk's avatar
wdenk committed
353
int fpga_err_fn (int cookie)
wdenk's avatar
wdenk committed
354 355 356 357
{
	return 0;
}

wdenk's avatar
wdenk committed
358
int fpga_busy_fn (int cookie)
wdenk's avatar
wdenk committed
359 360 361 362
{
	return 0;
}
#endif