1 /*
2 * XCFxxP Flash PROM JTAG programming algorithms
3 *
4 * Copyright (C) 2010 Joris van Rantwijk
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Programming sequences are based on the Xilinx 1532 BSDL files.
12 *
13 * Note: Some XCFP features are not supported (such as multiple revisions).
14 * The special PROM registers are written to always select revision 00.
15 * The default is slave serial mode (FPGA in master serial mode).
16 * A few other configuration modes may be selected by calling
17 * setXxxMode() before programming.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdexcept>
23 #include "jtag.h"
24 #include "progalgxcfp.h"
25 #include "utilities.h"
26
27
28 /* Device identification */
29 #define IDCODE_IS_XCF08P(id) (((id) & 0x0FFFFFFF) == 0x05057093)
30 #define IDCODE_IS_XCF16P(id) (((id) & 0x0FFFFFFF) == 0x05058093)
31 #define IDCODE_IS_XCF32P(id) (((id) & 0x0FFFFFFF) == 0x05059093)
32
33
34 /* Note: XCFxxP devices have instruction_length == 16 */
35 static const byte BYPASS[2] = { 0xff, 0xff };
36 static const byte IDCODE[2] = { 0xfe, 0x00 };
37 static const byte ISC_ENABLE[2] = { 0xe8, 0x00 };
38 static const byte ISC_DISABLE[2] = { 0xf0, 0x00 };
39 static const byte ISC_PROGRAM[2] = { 0xea, 0x00 };
40 static const byte ISC_READ[2] = { 0xf8, 0x00 };
41 static const byte ISC_ERASE[2] = { 0xec, 0x00 };
42 static const byte ISC_ADDRESS_SHIFT[2] = { 0xeb, 0x00 };
43 static const byte ISC_DATA_SHIFT[2] = { 0xed, 0x00 };
44 static const byte XSC_CONFIG[2] = { 0xee, 0x00 };
45 static const byte XSC_OP_STATUS[2] = { 0xe3, 0x00 };
46 static const byte XSC_UNLOCK[2] = { 0x55, 0xaa };
47 static const byte XSC_DATA_BTC[2] = { 0xf2, 0x00 };
48 static const byte XSC_DATA_CCB[2] = { 0x0c, 0x00 };
49 static const byte XSC_DATA_SUCR[2] = { 0x0e, 0x00 };
50 static const byte XSC_DATA_DONE[2] = { 0x09, 0x00 };
51
52
ProgAlgXCFP(Jtag & j,unsigned long id)53 ProgAlgXCFP::ProgAlgXCFP(Jtag &j, unsigned long id)
54 {
55 jtag = &j;
56 idcode = id;
57
58 // size of one array in bytes
59 block_size = 0x100000;
60
61 if (IDCODE_IS_XCF08P(idcode))
62 narray = 1;
63 else if (IDCODE_IS_XCF16P(idcode))
64 narray = 2;
65 else if (IDCODE_IS_XCF32P(idcode))
66 narray = 4;
67 else
68 {
69 fprintf(stderr, "Unknown XCF device ID 0x%08lx\n", idcode);
70 throw std::invalid_argument("Unknown XCF device");
71 }
72
73 // default to slave serial mode (FPGA running in master serial mode)
74 ccbParallelMode = false;
75 ccbMasterMode = false;
76 ccbFastClock = true;
77 ccbExternalClock = true;
78
79 fprintf(stderr, "ProgAlgXCFP $Rev: 760 $\n");
80 }
81
82
getSize() const83 unsigned int ProgAlgXCFP::getSize() const
84 {
85 // return storage capacity in bits
86 return narray * block_size * 8;
87 }
88
erase()89 int ProgAlgXCFP::erase()
90 {
91 return erase((1<<narray) -1);
92 }
93
erase(int array_mask)94 int ProgAlgXCFP::erase(int array_mask)
95 {
96 Timer timer;
97 byte data[3];
98 byte xcstatus[1];
99 int ret = 0;
100
101 jtag->tapTestLogicReset();
102 jtag->Usleep(1000);
103
104 ret = verify_idcode();
105 if (ret)
106 return ret;
107
108 enable();
109
110 data[0] = 0x30 | array_mask;
111 data[1] = 0x00;
112 data[2] = 0x00;
113
114 jtag->shiftIR(XSC_UNLOCK);
115 jtag->shiftDR(data, 0, 24);
116 jtag->cycleTCK(1);
117
118 if(jtag->getVerbose())
119 {
120 fprintf(stderr, "Erasing");
121 fflush(stderr);
122 }
123
124 // The ERASE command fails when state goes through READY-TEST-IDLE between
125 // instruction and data.
126 jtag->setPostIRState(Jtag::EXIT1_IR);
127
128 jtag->shiftIR(ISC_ERASE);
129 jtag->shiftDR(data, 0, 24);
130 jtag->Usleep(10000);
131
132 // restore default
133 jtag->setPostIRState(Jtag::RUN_TEST_IDLE);
134
135 for (int i = 0; i < 280; i++)
136 {
137 // we use 280 loops of 500 ms instead of 14000 loops of 10 ms
138 jtag->Usleep(490000);
139 if (jtag->getVerbose())
140 {
141 fprintf(stderr, ".");
142 fflush(stderr);
143 }
144 jtag->shiftIR(XSC_OP_STATUS);
145 jtag->Usleep(10000);
146 jtag->shiftDR(0, xcstatus, 8);
147 if (xcstatus[0] & 0x04)
148 break;
149 }
150
151 if (xcstatus[0] == 0x36)
152 {
153 if (jtag->getVerbose())
154 fprintf(stderr, "done!");
155 }
156 else
157 {
158 ret = 1;
159 fprintf(stderr, "\nErase failed (status=0x%02x)! Aborting\n", xcstatus[0]);
160 }
161
162 disable();
163
164 if (jtag->getVerbose())
165 fprintf(stderr, "Erase time %.3f s\n", timer.elapsed());
166
167 return ret;
168 }
169
170
program(BitFile & file)171 int ProgAlgXCFP::program(BitFile &file)
172 {
173 Timer timer;
174 byte data[32];
175 byte xcstatus[1];
176 int ret = 0;
177
178 if (file.getOffset() != 0 ||
179 (file.getRLength() != 0 && file.getRLength() != file.getLengthBytes()))
180 throw std::invalid_argument("XCFP does not yet support bitfile subranges");
181
182 jtag->tapTestLogicReset();
183 jtag->Usleep(1000);
184
185 ret = verify_idcode();
186 if (ret)
187 return ret;
188
189 enable();
190
191 unsigned int used_blocks = (file.getLengthBytes() + block_size - 1) / block_size;
192 if (used_blocks == 0)
193 used_blocks = 1;
194 if (used_blocks > narray)
195 {
196 fprintf(stderr, "Program does not fit in PROM, clipping\n");
197 used_blocks = narray;
198 }
199
200 for (unsigned int k = 0; k < used_blocks; k++)
201 {
202 for (unsigned int i = 0; i < 32768; i++)
203 {
204 unsigned int p = k * block_size + i * 32;
205
206 // no need to program after end of bitfile
207 if (p >= file.getLengthBytes())
208 break;
209
210 if (jtag->getVerbose())
211 {
212 fprintf(stderr, "\rProgramming frames 0x%06x to 0x%06x ",
213 p, p+31);
214 fflush(stderr);
215 }
216
217 jtag->shiftIR(ISC_DATA_SHIFT);
218 if (p + 32 <= file.getLengthBytes())
219 {
220 jtag->shiftDR(file.getData() + p, 0, 256);
221 }
222 else
223 {
224 memset(data, 0xff, 32);
225 if (p < file.getLengthBytes())
226 memcpy(data, file.getData() + p, file.getLengthBytes() - p);
227 jtag->shiftDR(data, 0, 256);
228 }
229 jtag->cycleTCK(1);
230
231 if (i == 0)
232 {
233 jtag->longToByteArray(p, data);
234 jtag->shiftIR(ISC_ADDRESS_SHIFT);
235 jtag->shiftDR(data, 0, 24);
236 jtag->cycleTCK(1);
237 }
238
239 jtag->shiftIR(ISC_PROGRAM);
240 jtag->Usleep((i == 0) ? 1000 : 25);
241
242 for (int t = 0; t < 100; t++)
243 {
244 jtag->shiftIR(XSC_OP_STATUS);
245 jtag->shiftDR(0, xcstatus, 8);
246 if (xcstatus[0] & 0x04)
247 break;
248 }
249 if (xcstatus[0] != 0x36)
250 {
251 ret = 1;
252 fprintf(stderr,"\nProgramming failed! Aborting\n");
253 break;
254 }
255 }
256 }
257
258 if (ret == 0)
259 {
260 unsigned long btc_data = 0xffffffe0 | ((used_blocks-1) << 2);
261
262 if (jtag->getVerbose())
263 fprintf(stderr, "\nProgramming BTC=0x%08lx\n", btc_data);
264
265 jtag->longToByteArray(btc_data, data);
266 jtag->shiftIR(XSC_DATA_BTC);
267 jtag->shiftDR(data, 0, 32);
268 jtag->cycleTCK(1);
269 jtag->shiftIR(ISC_PROGRAM);
270 jtag->Usleep(1000);
271
272 jtag->shiftIR(XSC_DATA_BTC);
273 jtag->cycleTCK(1);
274 jtag->shiftDR(0, data, 32);
275 if (jtag->byteArrayToLong(data) != btc_data)
276 {
277 fprintf(stderr,"Programming BTC failed! Aborting\n");
278 ret = 1;
279 }
280 }
281
282 if (ret == 0)
283 {
284 uint16_t ccb_data = encodeCCB();
285
286 if (jtag->getVerbose())
287 fprintf(stderr, "Programming CCB=0x%04x\n", ccb_data);
288
289 jtag->shortToByteArray(ccb_data, data);
290 jtag->shiftIR(XSC_DATA_CCB);
291 jtag->shiftDR(data, 0, 16);
292 jtag->cycleTCK(1);
293 jtag->shiftIR(ISC_PROGRAM);
294 jtag->Usleep(1000);
295
296 jtag->shiftIR(XSC_DATA_CCB);
297 jtag->cycleTCK(1);
298 jtag->shiftDR(0, data, 16);
299 if (jtag->byteArrayToShort(data) != ccb_data)
300 {
301 fprintf(stderr,"Programming CCB failed! Aborting\n");
302 ret = 1;
303 }
304 }
305
306 if (ret == 0)
307 {
308 uint16_t sucr_data = 0xfffc;
309
310 if (jtag->getVerbose())
311 fprintf(stderr, "Programming SUCR=0x%04x\n", sucr_data);
312
313 jtag->shortToByteArray(sucr_data, data);
314 jtag->shiftIR(XSC_DATA_SUCR);
315 jtag->shiftDR(data, 0, 16);
316 jtag->cycleTCK(1);
317 jtag->shiftIR(ISC_PROGRAM);
318 jtag->Usleep(1000);
319
320 jtag->shiftIR(XSC_DATA_SUCR);
321 jtag->cycleTCK(1);
322 jtag->shiftDR(0, data, 16);
323 if (jtag->byteArrayToShort(data) != sucr_data)
324 {
325 fprintf(stderr,"Programming SUCR failed! Aborting\n");
326 ret = 1;
327 }
328 }
329
330 if (ret == 0)
331 {
332 byte done_data = 0xc0 | (0x0f & (0x0f << narray));
333
334 if (jtag->getVerbose())
335 fprintf(stderr, "Programming DONE=0x%02x\n", done_data);
336
337 data[0] = done_data;
338 jtag->shiftIR(XSC_DATA_DONE);
339 jtag->shiftDR(data, 0, 8);
340 jtag->cycleTCK(1);
341 jtag->shiftIR(ISC_PROGRAM);
342 jtag->Usleep(1000);
343
344 jtag->shiftIR(XSC_DATA_DONE);
345 jtag->cycleTCK(1);
346 jtag->shiftDR(0, data, 8);
347 if (data[0] != done_data)
348 {
349 fprintf(stderr,"Programming DONE failed! Aborting\n");
350 ret = 1;
351 }
352 else
353 {
354 if (jtag->getVerbose())
355 fprintf(stderr, "finished\n");
356 }
357 }
358
359 disable();
360
361 if (jtag->getVerbose())
362 fprintf(stderr, "Programming time %.3f s\n", timer.elapsed());
363
364 return ret;
365 }
366
367
verify(BitFile & file)368 int ProgAlgXCFP::verify(BitFile &file)
369 {
370 Timer timer;
371 byte data[32];
372 int ret = 0;
373
374 if (file.getOffset() != 0 ||
375 (file.getRLength() != 0 && file.getRLength() != file.getLengthBytes()))
376 throw std::invalid_argument("XCFP does not yet support bitfile subranges");
377
378 jtag->tapTestLogicReset();
379 jtag->Usleep(1000);
380
381 ret = verify_idcode();
382 if (ret)
383 return ret;
384
385 enable();
386
387 unsigned int used_blocks = (file.getLengthBytes() + block_size - 1) / block_size;
388 if (used_blocks == 0)
389 used_blocks = 1;
390 if (used_blocks > narray)
391 {
392 fprintf(stderr, "Program does not fit in PROM, clipping\n");
393 used_blocks = narray;
394 }
395
396 for (unsigned int k = 0; k < used_blocks; k++)
397 {
398 jtag->longToByteArray(k * block_size, data);
399 jtag->shiftIR(ISC_ADDRESS_SHIFT);
400 jtag->shiftDR(data, 0, 24);
401 jtag->cycleTCK(1);
402
403 for (unsigned int i = 0; i < 32768; i++)
404 {
405 unsigned int p = k * block_size + i * 32;
406 unsigned int n = 32;
407 if (p >= file.getLengthBytes())
408 break;
409 if (p + n > file.getLengthBytes())
410 n = file.getLengthBytes() - p;
411
412 if (jtag->getVerbose()) {
413 fprintf(stderr, "\rVerifying frames 0x%06x to 0x%06x ",
414 p, p+n-1);
415 fflush(stderr);
416 }
417 jtag->shiftIR(ISC_READ);
418 jtag->Usleep(25);
419
420 jtag->shiftIR(ISC_DATA_SHIFT);
421 jtag->cycleTCK(1);
422 jtag->shiftDR(0, data, 256);
423
424 if (memcmp(data, file.getData() + p, n))
425 {
426 ret = 1;
427 fprintf(stderr, "\nVerify failed at frame 0x%06x to 0x%06x\n",
428 p, p+n-1);
429 break;
430 }
431 }
432
433 if (ret)
434 break;
435 }
436
437 if (jtag->getVerbose())
438 fprintf(stderr, "\nVerifying BTC ");
439 unsigned long btc_data = 0xffffffe0 | ((used_blocks-1) << 2);
440 jtag->shiftIR(XSC_DATA_BTC);
441 jtag->cycleTCK(1);
442 jtag->shiftDR(0, data, 32);
443 if (jtag->getVerbose())
444 fprintf(stderr, "= 0x%08lx\n", jtag->byteArrayToLong(data));
445 if (jtag->byteArrayToLong(data) != btc_data)
446 {
447 fprintf(stderr, "Unexpected value in BTC register\n");
448 ret = 1;
449 }
450
451 if (jtag->getVerbose())
452 fprintf(stderr, "Verifying CCB ");
453 jtag->shiftIR(XSC_DATA_CCB);
454 jtag->cycleTCK(1);
455 jtag->shiftDR(0, data, 16);
456 if (jtag->getVerbose())
457 fprintf(stderr, "= 0x%04x\n", jtag->byteArrayToShort(data));
458 if (jtag->byteArrayToShort(data) != encodeCCB())
459 {
460 fprintf(stderr, "Unexpected value in CCB register\n");
461 ret = 1;
462 }
463
464 if (jtag->getVerbose())
465 fprintf(stderr, "Verifying SUCR ");
466 jtag->shiftIR(XSC_DATA_SUCR);
467 jtag->cycleTCK(1);
468 jtag->shiftDR(0, data, 16);
469 if (jtag->getVerbose())
470 fprintf(stderr, "= 0x%02x%02x\n", data[1], data[0]);
471 if (data[0] != 0xfc || data[1] != 0xff)
472 {
473 fprintf(stderr, "Unexpected value in SUCR register\n");
474 ret = 1;
475 }
476
477 if (jtag->getVerbose())
478 fprintf(stderr, "Verifying DONE ");
479 byte done_data = 0xc0 | (0x0f & (0x0f << narray));
480 jtag->shiftIR(XSC_DATA_DONE);
481 jtag->cycleTCK(1);
482 jtag->shiftDR(0, data, 8);
483 if (jtag->getVerbose())
484 fprintf(stderr, "= 0x%02x\n", data[0]);
485 if (data[0] != done_data)
486 {
487 fprintf(stderr, "Unexpected value in DONE register\n");
488 ret = 1;
489 }
490
491 disable();
492
493 if (jtag->getVerbose() && ret == 0)
494 fprintf(stderr, "Success!\n");
495
496 if (jtag->getVerbose())
497 fprintf(stderr, "Verify time %.3f s\n", timer.elapsed());
498
499 return ret;
500 }
501
502
read(BitFile & file)503 int ProgAlgXCFP::read(BitFile &file)
504 {
505 Timer timer;
506 byte data[32];
507 int ret = 0;
508
509 if (file.getOffset() != 0 ||
510 (file.getRLength() != 0 && file.getRLength() != getSize() / 8))
511 throw std::invalid_argument("XCFP does not yet support bitfile subranges");
512
513 timer.start();
514
515 jtag->tapTestLogicReset();
516 jtag->Usleep(1000);
517
518 ret = verify_idcode();
519 if (ret)
520 return ret;
521
522 enable();
523
524 jtag->shiftIR(XSC_DATA_BTC);
525 jtag->cycleTCK(1);
526 jtag->shiftDR(0, data, 32);
527 unsigned long btc_data = jtag->byteArrayToLong(data);
528 if (jtag->getVerbose())
529 fprintf(stderr, "BTC = 0x%08lx\n", btc_data);
530
531 unsigned int first_block = btc_data & 0x03;
532 unsigned int last_block = (btc_data & 0x0c) >> 2;
533
534 if (jtag->getVerbose())
535 fprintf(stderr, "BTC: first_block=%u, last_block=%u, content_len=%u bytes\n", first_block, last_block, (last_block + 1 - first_block) * block_size);
536
537 if (first_block > last_block || last_block >= narray)
538 {
539 fprintf(stderr, "Invalid data in BTC register: first_block=%u, last_block=%u\n", first_block, last_block);
540 fprintf(stderr, "Reading failed.\n");
541 return 1;
542 }
543
544 file.setLength((last_block - first_block + 1) * 32768 * 256);
545
546 for (unsigned int k = first_block; k <= last_block; k++)
547 {
548 jtag->longToByteArray(k * block_size, data);
549 jtag->shiftIR(ISC_ADDRESS_SHIFT);
550 jtag->shiftDR(data, 0, 24);
551 jtag->cycleTCK(1);
552
553 for (unsigned int i = 0; i < 32768; i++)
554 {
555 if (jtag->getVerbose())
556 {
557 fprintf(stderr, "\rReading frames 0x%06x to 0x%06x ",
558 k*block_size+i*32,k*block_size+i*32+31);
559 fflush(stderr);
560 }
561 jtag->shiftIR(ISC_READ);
562 jtag->Usleep(25);
563
564 unsigned int p = (k - first_block) * block_size + i * 32;
565 jtag->shiftIR(ISC_DATA_SHIFT);
566 jtag->cycleTCK(1);
567 jtag->shiftDR(0, file.getData() + p, 256);
568 }
569 }
570
571 if (jtag->getVerbose())
572 fprintf(stderr, "done\n");
573
574 jtag->shiftIR(XSC_DATA_CCB);
575 jtag->cycleTCK(1);
576 jtag->shiftDR(0, data, 16);
577 if (jtag->getVerbose())
578 fprintf(stderr, "CCB = 0x%04x\n", jtag->byteArrayToShort(data));
579
580 decodeCCB(jtag->byteArrayToShort(data));
581 if (jtag->getVerbose())
582 fprintf(stderr, "CCB: %s, %s, %s, %s\n",
583 ccbMasterMode ? "master" : "slave",
584 ccbParallelMode ? "parallel" : "serial",
585 ccbExternalClock ? "extclk" : "intclk",
586 ccbFastClock ? "fastclk" : "slowclk" );
587
588 jtag->shiftIR(XSC_DATA_DONE);
589 jtag->cycleTCK(1);
590 jtag->shiftDR(0, data, 8);
591 if (jtag->getVerbose())
592 fprintf(stderr, "DONE = 0x%02x\n", data[0]);
593
594 jtag->shiftIR(XSC_DATA_SUCR);
595 jtag->cycleTCK(1);
596 jtag->shiftDR(0, data, 16);
597 if (jtag->getVerbose())
598 fprintf(stderr, "SUCR = 0x%02x%02x\n", data[1], data[0]);
599
600 disable();
601
602 if (jtag->getVerbose())
603 fprintf(stderr, "Read time %.3f s\n", timer.elapsed());
604
605 return ret;
606 }
607
608
reconfig(void)609 void ProgAlgXCFP::reconfig(void)
610 {
611 jtag->shiftIR(XSC_CONFIG);
612 jtag->cycleTCK(1);
613 jtag->shiftIR(BYPASS);
614 jtag->cycleTCK(1);
615 jtag->tapTestLogicReset();
616 }
617
618
verify_idcode()619 int ProgAlgXCFP::verify_idcode()
620 {
621 byte data[4];
622 jtag->shiftIR(IDCODE);
623 jtag->cycleTCK(1);
624 jtag->shiftDR(0, data, 32);
625 unsigned long devid = jtag->byteArrayToLong(data);
626 if ((devid & 0x0fffffff) != (idcode & 0x0fffffff))
627 {
628 fprintf(stderr, "Failed to verify ID code, got 0x%08lx expected 0x%08lx\n", devid, idcode);
629 return 1;
630 }
631 return 0;
632 }
633
634
enable()635 void ProgAlgXCFP::enable()
636 {
637 byte data[1] = { 0x00 };
638 jtag->shiftIR(ISC_ENABLE);
639 jtag->shiftDR(data, 0, 8);
640 jtag->cycleTCK(1);
641 }
642
643
disable()644 void ProgAlgXCFP::disable()
645 {
646 jtag->shiftIR(ISC_DISABLE);
647 jtag->Usleep(1000);
648 jtag->shiftIR(BYPASS);
649 jtag->cycleTCK(1);
650 jtag->tapTestLogicReset();
651 }
652
653
encodeCCB() const654 uint16_t ProgAlgXCFP::encodeCCB() const
655 {
656 // The CCB register in the XCFnnP PROM deteremines the FPGA configuration
657 // mode, i.e. parallel or serial, master or slave, config clock, etc.
658 // See xcf32p_1532.bsd.
659 uint16_t ccb = 0xffc0;
660 ccb |= ccbParallelMode ? 0x00 : 0x06;
661 ccb |= ccbMasterMode ? 0x00 : 0x08;
662 ccb |= ccbFastClock ? 0x30 : 0x10;
663 ccb |= ccbExternalClock ? 0x01 : 0x00;
664 return ccb;
665 }
666
667
decodeCCB(uint16_t ccb)668 void ProgAlgXCFP::decodeCCB(uint16_t ccb)
669 {
670 ccbParallelMode = ((ccb & 0x06) == 0x00);
671 ccbMasterMode = ((ccb & 0x08) == 0x00);
672 ccbFastClock = ((ccb & 0x20) == 0x20);
673 ccbExternalClock = ((ccb & 0x01) == 0x01);
674 }
675
676