1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2022 by Daniel Anselmi *
6 ***************************************************************************/
12 #include <jtag/jtag.h>
13 #include <jtag/adapter.h>
14 #include <helper/system.h>
15 #include <helper/log.h>
31 struct intel_pld_device
{
33 unsigned int boundary_scan_length
;
35 enum intel_family_e family
;
38 struct intel_device_parameters_elem
{
40 unsigned int boundary_scan_length
;
42 enum intel_family_e family
;
45 static const struct intel_device_parameters_elem intel_device_parameters
[] = {
46 {0x020f10dd, 603, 226, INTEL_CYCLONEIII
}, /* EP3C5 EP3C10 */
47 {0x020f20dd, 1080, 409, INTEL_CYCLONEIII
}, /* EP3C16 */
48 {0x020f30dd, 732, 286, INTEL_CYCLONEIII
}, /* EP3C25 */
49 {0x020f40dd, 1632, 604, INTEL_CYCLONEIII
}, /* EP3C40 */
50 {0x020f50dd, 1164, 442, INTEL_CYCLONEIII
}, /* EP3C55 */
51 {0x020f60dd, 1314, 502, INTEL_CYCLONEIII
}, /* EP3C80 */
52 {0x020f70dd, 1620, 613, INTEL_CYCLONEIII
}, /* EP3C120*/
53 {0x027010dd, 1314, 226, INTEL_CYCLONEIII
}, /* EP3CLS70 */
54 {0x027000dd, 1314, 226, INTEL_CYCLONEIII
}, /* EP3CLS100 */
55 {0x027030dd, 1314, 409, INTEL_CYCLONEIII
}, /* EP3CLS150 */
56 {0x027020dd, 1314, 409, INTEL_CYCLONEIII
}, /* EP3CLS200 */
58 {0x020f10dd, 603, 226, INTEL_CYCLONEIV
}, /* EP4CE6 EP4CE10 */
59 {0x020f20dd, 1080, 409, INTEL_CYCLONEIV
}, /* EP4CE15 */
60 {0x020f30dd, 732, 286, INTEL_CYCLONEIV
}, /* EP4CE22 */
61 {0x020f40dd, 1632, 604, INTEL_CYCLONEIV
}, /* EP4CE30 EP4CE40 */
62 {0x020f50dd, 1164, 442, INTEL_CYCLONEIV
}, /* EP4CE55 */
63 {0x020f60dd, 1314, 502, INTEL_CYCLONEIV
}, /* EP4CE75 */
64 {0x020f70dd, 1620, 613, INTEL_CYCLONEIV
}, /* EP4CE115 */
65 {0x028010dd, 260, 229, INTEL_CYCLONEIV
}, /* EP4CGX15 */
66 {0x028120dd, 494, 463, INTEL_CYCLONEIV
}, /* EP4CGX22 */
67 {0x028020dd, 494, 463, INTEL_CYCLONEIV
}, /* EP4CGX30 */
68 {0x028230dd, 1006, 943, INTEL_CYCLONEIV
}, /* EP4CGX30 */
69 {0x028130dd, 1006, 943, INTEL_CYCLONEIV
}, /* EP4CGX50 */
70 {0x028030dd, 1006, 943, INTEL_CYCLONEIV
}, /* EP4CGX75 */
71 {0x028140dd, 1495, 1438, INTEL_CYCLONEIV
}, /* EP4CGX110 */
72 {0x028040dd, 1495, 1438, INTEL_CYCLONEIV
}, /* EP4CGX150 */
74 {0x02b150dd, 864, 163, INTEL_CYCLONEV
}, /* 5CEBA2F23 5CEBA2F17 5CEFA2M13 5CEFA2F23 5CEBA2U15 5CEFA2U19 5CEBA2U19 */
75 {0x02d020dd, 1485, 19, INTEL_CYCLONEV
}, /* 5CSXFC6D6F31 5CSTFD6D5F31 5CSEBA6U23 5CSEMA6U23 5CSEBA6U19 5CSEBA6U23
76 5CSEBA6U19 5CSEMA6F31 5CSXFC6C6U23 */
77 {0x02b040dd, 1728, -1, INTEL_CYCLONEV
}, /* 5CGXFC9EF35 5CGXBC9AU19 5CGXBC9CF23 5CGTFD9CF23 5CGXFC9AU19 5CGXFC9CF23
78 5CGXFC9EF31 5CGXFC9DF27 5CGXBC9DF27 5CGXBC9EF31 5CGTFD9EF31 5CGTFD9EF35
79 5CGTFD9AU19 5CGXBC9EF35 5CGTFD9DF27 */
80 {0x02b050dd, 864, 163, INTEL_CYCLONEV
}, /* 5CEFA4U19 5CEFA4F23 5CEFA4M13 5CEBA4F17 5CEBA4U15 5CEBA4U19 5CEBA4F23 */
81 {0x02b030dd, 1488, 19, INTEL_CYCLONEV
}, /* 5CGXBC7CU19 5CGTFD7CU19 5CGTFD7DF27 5CGXFC7BM15 5CGXFC7DF27 5CGXFC7DF31
82 5CGTFD7CF23 5CGXBC7CF23 5CGXBC7DF31 5CGTFD7BM15 5CGXFC7CU19 5CGTFD7DF31
83 5CGXBC7BM15 5CGXFC7CF23 5CGXBC7DF27 */
84 {0x02d120dd, 1485, -1, INTEL_CYCLONEV
}, /* 5CSEBA5U23 5CSEBA5U23 5CSTFD5D5F31 5CSEBA5U19 5CSXFC5D6F31 5CSEMA5U23
85 5CSEMA5F31 5CSXFC5C6U23 5CSEBA5U19 */
86 {0x02b220dd, 1104, 19, INTEL_CYCLONEV
}, /* 5CEBA5U19 5CEFA5U19 5CEFA5M13 5CEBA5F23 5CEFA5F23 */
87 {0x02b020dd, 1104, 19, INTEL_CYCLONEV
}, /* 5CGXBC5CU19 5CGXFC5F6M11 5CGXFC5CM13 5CGTFD5CF23 5CGXBC5CF23 5CGTFD5CF27
88 5CGTFD5F5M11 5CGXFC5CF27 5CGXFC5CU19 5CGTFD5CM13 5CGXFC5CF23 5CGXBC5CF27
90 {0x02d010dd, 1197, -1, INTEL_CYCLONEV
}, /* 5CSEBA4U23 5CSXFC4C6U23 5CSEMA4U23 5CSEBA4U23 5CSEBA4U19 5CSEBA4U19
92 {0x02b120dd, 1104, 19, INTEL_CYCLONEV
}, /* 5CGXFC4CM13 5CGXFC4CU19 5CGXFC4F6M11 5CGXBC4CU19 5CGXFC4CF27 5CGXBC4CF23
93 5CGXBC4CF27 5CGXFC4CF23 */
94 {0x02b140dd, 1728, -1, INTEL_CYCLONEV
}, /* 5CEFA9F31 5CEBA9F31 5CEFA9F27 5CEBA9U19 5CEBA9F27 5CEFA9U19 5CEBA9F23
96 {0x02b010dd, 720, 19, INTEL_CYCLONEV
}, /* 5CGXFC3U15 5CGXBC3U15 5CGXFC3F23 5CGXFC3U19 5CGXBC3U19 5CGXBC3F23 */
97 {0x02b130dd, 1488, 19, INTEL_CYCLONEV
}, /* 5CEFA7F31 5CEBA7F27 5CEBA7M15 5CEFA7U19 5CEBA7F23 5CEFA7F23 5CEFA7F27
98 5CEFA7M15 5CEBA7U19 5CEBA7F31 */
99 {0x02d110dd, 1197, -1, INTEL_CYCLONEV
}, /* 5CSEBA2U23 5CSEMA2U23 5CSEBA2U23 5CSEBA2U19 5CSEBA2U19 */
101 {0x020f10dd, 603, 226, INTEL_CYCLONE10
}, /* 10CL006E144 10CL006U256 10CL010M164 10CL010U256 10CL010E144 */
102 {0x020f20dd, 1080, 409, INTEL_CYCLONE10
}, /* 10CL016U256 10CL016E144 10CL016U484 10CL016F484 10CL016M164 */
103 {0x020f30dd, 732, 286, INTEL_CYCLONE10
}, /* 10CL025U256 10CL025E144 */
104 {0x020f40dd, 1632, 604, INTEL_CYCLONE10
}, /* 10CL040F484 10CL040U484 */
105 {0x020f50dd, 1164, 442, INTEL_CYCLONE10
}, /* 10CL055F484 10CL055U484 */
106 {0x020f60dd, 1314, 502, INTEL_CYCLONE10
}, /* 10CL080F484 10CL080F780 10CL080U484 */
107 {0x020f70dd, 1620, 613, INTEL_CYCLONE10
}, /* 10CL120F484 10CL120F780 */
109 {0x02e120dd, 1339, -1, INTEL_CYCLONE10
}, /* 10CX085U484 10CX085F672 */
110 {0x02e320dd, 1339, -1, INTEL_CYCLONE10
}, /* 10CX105F780 10CX105U484 10CX105F672 */
111 {0x02e720dd, 1339, -1, INTEL_CYCLONE10
}, /* 10CX150F672 10CX150F780 10CX150U484 */
112 {0x02ef20dd, 1339, -1, INTEL_CYCLONE10
}, /* 10CX220F672 10CX220F780 10CX220U484 */
114 {0x025120dd, 1227, 1174, INTEL_ARRIAII
}, /* EP2AGX45 */
115 {0x025020dd, 1227, -1, INTEL_ARRIAII
}, /* EP2AGX65 */
116 {0x025130dd, 1467, -1, INTEL_ARRIAII
}, /* EP2AGX95 */
117 {0x025030dd, 1467, -1, INTEL_ARRIAII
}, /* EP2AGX125 */
118 {0x025140dd, 1971, -1, INTEL_ARRIAII
}, /* EP2AGX190 */
119 {0x025040dd, 1971, -1, INTEL_ARRIAII
}, /* EP2AGX260 */
120 {0x024810dd, 2274, -1, INTEL_ARRIAII
}, /* EP2AGZ225 */
121 {0x0240a0dd, 2682, -1, INTEL_ARRIAII
}, /* EP2AGZ300 */
122 {0x024820dd, 2682, -1, INTEL_ARRIAII
}, /* EP2AGZ350 */
125 static int intel_fill_device_parameters(struct intel_pld_device
*intel_info
)
127 for (size_t i
= 0; i
< ARRAY_SIZE(intel_device_parameters
); ++i
) {
128 if (intel_device_parameters
[i
].id
== intel_info
->tap
->idcode
&&
129 intel_info
->family
== intel_device_parameters
[i
].family
) {
130 if (intel_info
->boundary_scan_length
== 0)
131 intel_info
->boundary_scan_length
= intel_device_parameters
[i
].boundary_scan_length
;
133 if (intel_info
->checkpos
== -1)
134 intel_info
->checkpos
= intel_device_parameters
[i
].checkpos
;
143 static int intel_check_for_unique_id(struct intel_pld_device
*intel_info
)
146 for (size_t i
= 0; i
< ARRAY_SIZE(intel_device_parameters
); ++i
) {
147 if (intel_device_parameters
[i
].id
== intel_info
->tap
->idcode
) {
149 intel_info
->family
= intel_device_parameters
[i
].family
;
153 return (found
== 1) ? ERROR_OK
: ERROR_FAIL
;
156 static int intel_check_config(struct intel_pld_device
*intel_info
)
158 if (!intel_info
->tap
->hasidcode
) {
159 LOG_ERROR("no IDCODE");
163 if (intel_info
->family
== INTEL_UNKNOWN
) {
164 if (intel_check_for_unique_id(intel_info
) != ERROR_OK
) {
165 LOG_ERROR("id is ambiguous, please specify family");
170 if (intel_info
->boundary_scan_length
== 0 || intel_info
->checkpos
== -1) {
171 int ret
= intel_fill_device_parameters(intel_info
);
176 if (intel_info
->checkpos
>= 0 && (unsigned int)intel_info
->checkpos
>= intel_info
->boundary_scan_length
) {
177 LOG_ERROR("checkpos has to be smaller than scan length %d < %u",
178 intel_info
->checkpos
, intel_info
->boundary_scan_length
);
185 static int intel_read_file(struct raw_bit_file
*bit_file
, const char *filename
)
187 if (!filename
|| !bit_file
)
188 return ERROR_COMMAND_SYNTAX_ERROR
;
190 /* check if binary .bin or ascii .bit/.hex */
191 const char *file_ending_pos
= strrchr(filename
, '.');
192 if (!file_ending_pos
) {
193 LOG_ERROR("Unable to detect filename suffix");
194 return ERROR_PLD_FILE_LOAD_FAILED
;
197 if (strcasecmp(file_ending_pos
, ".rbf") == 0)
198 return cpld_read_raw_bit_file(bit_file
, filename
);
200 LOG_ERROR("Unable to detect filetype");
201 return ERROR_PLD_FILE_LOAD_FAILED
;
204 static int intel_set_instr(struct jtag_tap
*tap
, uint16_t new_instr
)
206 struct scan_field field
;
207 field
.num_bits
= tap
->ir_length
;
208 void *t
= calloc(DIV_ROUND_UP(field
.num_bits
, 8), 1);
210 LOG_ERROR("Out of memory");
214 buf_set_u32(t
, 0, field
.num_bits
, new_instr
);
215 field
.in_value
= NULL
;
216 jtag_add_ir_scan(tap
, &field
, TAP_IDLE
);
222 static int intel_load(struct pld_device
*pld_device
, const char *filename
)
224 unsigned int speed
= adapter_get_speed_khz();
228 unsigned int cycles
= DIV_ROUND_UP(speed
, 200);
232 if (!pld_device
|| !pld_device
->driver_priv
)
235 struct intel_pld_device
*intel_info
= pld_device
->driver_priv
;
236 if (!intel_info
|| !intel_info
->tap
)
238 struct jtag_tap
*tap
= intel_info
->tap
;
240 int retval
= intel_check_config(intel_info
);
241 if (retval
!= ERROR_OK
)
244 struct raw_bit_file bit_file
;
245 retval
= intel_read_file(&bit_file
, filename
);
246 if (retval
!= ERROR_OK
)
249 if (retval
!= ERROR_OK
)
252 retval
= intel_set_instr(tap
, 0x002);
253 if (retval
!= ERROR_OK
) {
257 jtag_add_runtest(speed
, TAP_IDLE
);
258 retval
= jtag_execute_queue();
259 if (retval
!= ERROR_OK
) {
264 /* shift in the bitstream */
265 struct scan_field field
;
266 field
.num_bits
= bit_file
.length
* 8;
267 field
.out_value
= bit_file
.data
;
268 field
.in_value
= NULL
;
270 jtag_add_dr_scan(tap
, 1, &field
, TAP_DRPAUSE
);
271 retval
= jtag_execute_queue();
273 if (retval
!= ERROR_OK
)
276 retval
= intel_set_instr(tap
, 0x004);
277 if (retval
!= ERROR_OK
)
279 jtag_add_runtest(cycles
, TAP_IDLE
);
280 retval
= jtag_execute_queue();
281 if (retval
!= ERROR_OK
)
284 if (intel_info
->boundary_scan_length
!= 0) {
285 uint8_t *buf
= calloc(DIV_ROUND_UP(intel_info
->boundary_scan_length
, 8), 1);
287 LOG_ERROR("Out of memory");
291 field
.num_bits
= intel_info
->boundary_scan_length
;
292 field
.out_value
= buf
;
293 field
.in_value
= buf
;
294 jtag_add_dr_scan(tap
, 1, &field
, TAP_DRPAUSE
);
295 retval
= jtag_execute_queue();
296 if (retval
!= ERROR_OK
) {
301 if (intel_info
->checkpos
!= -1)
302 retval
= ((buf
[intel_info
->checkpos
/ 8] & (1 << (intel_info
->checkpos
% 8)))) ?
303 ERROR_OK
: ERROR_FAIL
;
305 if (retval
!= ERROR_OK
) {
306 LOG_ERROR("Check failed");
311 retval
= intel_set_instr(tap
, 0x003);
312 if (retval
!= ERROR_OK
)
314 switch (intel_info
->family
) {
315 case INTEL_CYCLONEIII
:
316 case INTEL_CYCLONEIV
:
317 jtag_add_runtest(5 * speed
+ 512, TAP_IDLE
);
320 jtag_add_runtest(5 * speed
+ 512, TAP_IDLE
);
322 case INTEL_CYCLONE10
:
323 jtag_add_runtest(DIV_ROUND_UP(512ul * speed
, 125ul) + 512, TAP_IDLE
);
326 jtag_add_runtest(DIV_ROUND_UP(64ul * speed
, 125ul) + 512, TAP_IDLE
);
329 LOG_ERROR("unknown family");
333 retval
= intel_set_instr(tap
, BYPASS
);
334 if (retval
!= ERROR_OK
)
336 jtag_add_runtest(speed
, TAP_IDLE
);
337 return jtag_execute_queue();
340 COMMAND_HANDLER(intel_set_bscan_command_handler
)
343 unsigned int boundary_scan_length
;
346 return ERROR_COMMAND_SYNTAX_ERROR
;
348 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], dev_id
);
349 struct pld_device
*pld_device
= get_pld_device_by_num(dev_id
);
351 command_print(CMD
, "pld device '#%s' is out of bounds", CMD_ARGV
[0]);
355 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[1], boundary_scan_length
);
357 struct intel_pld_device
*intel_info
= pld_device
->driver_priv
;
362 intel_info
->boundary_scan_length
= boundary_scan_length
;
367 COMMAND_HANDLER(intel_set_check_pos_command_handler
)
373 return ERROR_COMMAND_SYNTAX_ERROR
;
375 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], dev_id
);
376 struct pld_device
*pld_device
= get_pld_device_by_num(dev_id
);
378 command_print(CMD
, "pld device '#%s' is out of bounds", CMD_ARGV
[0]);
382 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], checkpos
);
384 struct intel_pld_device
*intel_info
= pld_device
->driver_priv
;
389 intel_info
->checkpos
= checkpos
;
395 PLD_DEVICE_COMMAND_HANDLER(intel_pld_device_command
)
397 if (CMD_ARGC
< 2 || CMD_ARGC
> 3)
398 return ERROR_COMMAND_SYNTAX_ERROR
;
400 struct jtag_tap
*tap
= jtag_tap_by_string(CMD_ARGV
[1]);
402 command_print(CMD
, "Tap: %s does not exist", CMD_ARGV
[1]);
406 struct intel_pld_device
*intel_info
= malloc(sizeof(struct intel_pld_device
));
408 LOG_ERROR("Out of memory");
412 enum intel_family_e family
= INTEL_UNKNOWN
;
415 if (strcmp(CMD_ARGV
[2], "cycloneiii") == 0) {
416 family
= INTEL_CYCLONEIII
;
417 } else if (strcmp(CMD_ARGV
[2], "cycloneiv") == 0) {
418 family
= INTEL_CYCLONEIV
;
419 } else if (strcmp(CMD_ARGV
[2], "cyclonev") == 0) {
420 family
= INTEL_CYCLONEV
;
421 } else if (strcmp(CMD_ARGV
[2], "cyclone10") == 0) {
422 family
= INTEL_CYCLONE10
;
423 } else if (strcmp(CMD_ARGV
[2], "arriaii") == 0) {
424 family
= INTEL_ARRIAII
;
426 command_print(CMD
, "unknown family");
431 intel_info
->tap
= tap
;
432 intel_info
->boundary_scan_length
= 0;
433 intel_info
->checkpos
= -1;
434 intel_info
->family
= family
;
436 pld
->driver_priv
= intel_info
;
441 static const struct command_registration intel_exec_command_handlers
[] = {
444 .mode
= COMMAND_EXEC
,
445 .handler
= intel_set_bscan_command_handler
,
446 .help
= "set boundary scan register length of FPGA",
447 .usage
= "num_pld len",
449 .name
= "set_check_pos",
450 .mode
= COMMAND_EXEC
,
451 .handler
= intel_set_check_pos_command_handler
,
452 .help
= "set check_pos of FPGA",
453 .usage
= "num_pld pos",
455 COMMAND_REGISTRATION_DONE
458 static const struct command_registration intel_command_handler
[] = {
462 .help
= "intel specific commands",
464 .chain
= intel_exec_command_handlers
,
466 COMMAND_REGISTRATION_DONE
469 struct pld_driver intel_pld
= {
471 .commands
= intel_command_handler
,
472 .pld_device_command
= &intel_pld_device_command
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)