target: rtt: include rtt.h
[openocd.git] / src / pld / gowin.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2022 by Daniel Anselmi *
5 * danselmi@gmx.ch *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <jtag/jtag.h>
13 #include <jtag/adapter.h>
14 #include <helper/bits.h>
15 #include "pld.h"
16 #include "raw_bit.h"
17
18 #define NO_OP 0x02
19 #define ERASE_SRAM 0x05
20 #define SRAM_ERASE_DONE 0x09
21 #define IDCODE 0x11
22 #define ADDRESS_INITIALIZATION 0x12
23 #define READ_USERCODE 0x13
24 #define CONFIG_ENABLE 0x15
25 #define TRANSFER_CONFIGURATION_DATA 0x17
26 #define CONFIG_DISABLE 0x3A
27 #define RELOAD 0x3C
28 #define STATUS_REGISTER 0x41
29 #define ERASE_FLASH 0x75
30 #define ENABLE_2ND_FLASH 0x78
31
32 #define STAUS_MASK_MEMORY_ERASE BIT(5)
33 #define STAUS_MASK_SYSTEM_EDIT_MODE BIT(7)
34
35 struct gowin_pld_device {
36 struct jtag_tap *tap;
37 };
38
39 struct gowin_bit_file {
40 struct raw_bit_file raw_file;
41 size_t capacity;
42 uint32_t id;
43 uint16_t stored_checksum;
44 int compressed;
45 int crc_en;
46 uint16_t checksum;
47 uint8_t replace8x;
48 uint8_t replace4x;
49 uint8_t replace2x;
50 };
51
52 static uint64_t gowin_read_fs_file_bitsequence(const char *bits, int length)
53 {
54 uint64_t res = 0;
55 for (int i = 0; i < length; i++)
56 res = (res << 1) | (*bits++ == '1' ? 1 : 0);
57 return res;
58 }
59
60 static int gowin_add_byte_to_bit_file(struct gowin_bit_file *bit_file, uint8_t byte)
61 {
62 if (bit_file->raw_file.length + 1 > bit_file->capacity) {
63 uint8_t *buffer;
64 if (bit_file->raw_file.data)
65 buffer = realloc(bit_file->raw_file.data, bit_file->capacity + 8192);
66 else
67 buffer = malloc(8192);
68 if (!buffer) {
69 LOG_ERROR("Out of memory");
70 return ERROR_FAIL;
71 }
72 bit_file->raw_file.data = buffer;
73 bit_file->capacity += 8192;
74 }
75
76 bit_file->raw_file.data[bit_file->raw_file.length++] = byte;
77
78 return ERROR_OK;
79 }
80
81 static int gowin_read_fs_file_header(struct gowin_bit_file *bit_file, FILE *stream)
82 {
83 if (!bit_file)
84 return ERROR_FAIL;
85
86 int end_of_header = 0;
87 while (!end_of_header) {
88 char buffer[256];
89 char *line = fgets(buffer, 256, stream);
90 if (!line || feof(stream) || ferror(stream))
91 return ERROR_FAIL;
92
93 if (line[0] == '/')
94 continue;
95
96 size_t line_length = strlen(line);
97 if (line[line_length - 1] != '\n')
98 return ERROR_FAIL;
99 line_length--;
100
101 for (unsigned int i = 0; i < line_length; i += 8) {
102 uint8_t byte = gowin_read_fs_file_bitsequence(line + i, 8);
103 int retval = gowin_add_byte_to_bit_file(bit_file, byte);
104 if (retval != ERROR_OK)
105 return retval;
106 }
107
108 uint8_t key = gowin_read_fs_file_bitsequence(line, 8);
109 line += 8;
110 uint64_t value = gowin_read_fs_file_bitsequence(line, line_length - 8);
111
112 if (key == 0x06) {
113 bit_file->id = value & 0xffffffff;
114 } else if (key == 0x3B) {
115 end_of_header = 1;
116 bit_file->crc_en = (value & BIT(23)) ? 1 : 0;
117 }
118 }
119
120 return ERROR_OK;
121 }
122
123 static int gowin_read_fs_file(struct gowin_bit_file *bit_file, const char *filename)
124 {
125 FILE *input_file = fopen(filename, "r");
126
127 if (!input_file) {
128 LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
129 return ERROR_PLD_FILE_LOAD_FAILED;
130 }
131
132 int retval = gowin_read_fs_file_header(bit_file, input_file);
133 if (retval != ERROR_OK) {
134 free(bit_file->raw_file.data);
135 fclose(input_file);
136 return retval;
137 }
138
139 char digits_buffer[9]; /* 8 + 1 trailing zero */
140 do {
141 char *digits = fgets(digits_buffer, 9, input_file);
142 if (feof(input_file))
143 break;
144 if (!digits || ferror(input_file)) {
145 free(bit_file->raw_file.data);
146 fclose(input_file);
147 return ERROR_FAIL;
148 }
149 if (digits[0] == '\n')
150 continue;
151
152 if (strlen(digits) != 8) {
153 free(bit_file->raw_file.data);
154 fclose(input_file);
155 return ERROR_FAIL;
156 }
157 uint8_t byte = gowin_read_fs_file_bitsequence(digits, 8);
158 retval = gowin_add_byte_to_bit_file(bit_file, byte);
159 if (retval != ERROR_OK) {
160 free(bit_file->raw_file.data);
161 fclose(input_file);
162 return ERROR_FAIL;
163 }
164 } while (1);
165
166 fclose(input_file);
167 return ERROR_OK;
168 }
169
170 static int gowin_read_file(struct gowin_bit_file *bit_file, const char *filename, bool *is_fs)
171 {
172 memset(bit_file, 0, sizeof(struct gowin_bit_file));
173
174 if (!filename || !bit_file)
175 return ERROR_COMMAND_SYNTAX_ERROR;
176
177 const char *file_suffix_pos = strrchr(filename, '.');
178 if (!file_suffix_pos) {
179 LOG_ERROR("Unable to detect filename suffix");
180 return ERROR_PLD_FILE_LOAD_FAILED;
181 }
182
183 /* check if binary .bin or ascii .fs */
184 if (strcasecmp(file_suffix_pos, ".bin") == 0) {
185 *is_fs = false;
186 return cpld_read_raw_bit_file(&bit_file->raw_file, filename);
187 } else if (strcasecmp(file_suffix_pos, ".fs") == 0) {
188 *is_fs = true;
189 return gowin_read_fs_file(bit_file, filename);
190 }
191
192 LOG_ERROR("Filetype not supported, expecting .fs or .bin file");
193 return ERROR_PLD_FILE_LOAD_FAILED;
194 }
195
196 static int gowin_set_instr(struct jtag_tap *tap, uint8_t new_instr)
197 {
198 struct scan_field field;
199 field.num_bits = tap->ir_length;
200 void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
201 if (!t) {
202 LOG_ERROR("Out of memory");
203 return ERROR_FAIL;
204 }
205 field.out_value = t;
206 buf_set_u32(t, 0, field.num_bits, new_instr);
207 field.in_value = NULL;
208 jtag_add_ir_scan(tap, &field, TAP_IDLE);
209 jtag_add_runtest(3, TAP_IDLE);
210 free(t);
211 return ERROR_OK;
212 }
213
214 static int gowin_read_register(struct jtag_tap *tap, uint32_t reg, uint32_t *result)
215 {
216 struct scan_field field;
217
218 int retval = gowin_set_instr(tap, reg);
219 if (retval != ERROR_OK)
220 return retval;
221 retval = jtag_execute_queue();
222 if (retval != ERROR_OK)
223 return retval;
224
225 uint8_t buf[4] = {0};
226 field.check_mask = NULL;
227 field.check_value = NULL;
228 field.num_bits = 32;
229 field.out_value = buf;
230 field.in_value = buf;
231
232 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
233 retval = jtag_execute_queue();
234 *result = le_to_h_u32(buf);
235 return retval;
236 }
237
238 static int gowin_check_status_flag(struct jtag_tap *tap, uint32_t mask, uint32_t flag)
239 {
240 uint32_t status = 0;
241
242 int retries = 0;
243 do {
244 int retval = gowin_read_register(tap, STATUS_REGISTER, &status);
245 if (retval != ERROR_OK)
246 return retval;
247 if (retries++ == 100000)
248 return ERROR_FAIL;
249 } while ((status & mask) != flag);
250
251 return ERROR_OK;
252 }
253
254 static int gowin_enable_config(struct jtag_tap *tap)
255 {
256 int retval = gowin_set_instr(tap, CONFIG_ENABLE);
257 if (retval != ERROR_OK)
258 return retval;
259 retval = jtag_execute_queue();
260 if (retval != ERROR_OK)
261 return retval;
262
263 return gowin_check_status_flag(tap, STAUS_MASK_SYSTEM_EDIT_MODE, STAUS_MASK_SYSTEM_EDIT_MODE);
264 }
265
266 static int gowin_disable_config(struct jtag_tap *tap)
267 {
268 int retval = gowin_set_instr(tap, CONFIG_DISABLE);
269 if (retval != ERROR_OK)
270 return retval;
271 retval = jtag_execute_queue();
272 if (retval != ERROR_OK)
273 return retval;
274
275 return gowin_check_status_flag(tap, STAUS_MASK_SYSTEM_EDIT_MODE, 0);
276 }
277
278 static int gowin_reload(struct jtag_tap *tap)
279 {
280 int retval = gowin_set_instr(tap, RELOAD);
281 if (retval != ERROR_OK)
282 return retval;
283 retval = gowin_set_instr(tap, NO_OP);
284 if (retval != ERROR_OK)
285 return retval;
286 return jtag_execute_queue();
287 }
288
289 static int gowin_runtest_idle(struct jtag_tap *tap, unsigned int frac_sec)
290 {
291 int speed = adapter_get_speed_khz() * 1000;
292 int cycles = DIV_ROUND_UP(speed, frac_sec);
293 jtag_add_runtest(cycles, TAP_IDLE);
294 return jtag_execute_queue();
295 }
296
297 static int gowin_erase_sram(struct jtag_tap *tap, bool tx_erase_done)
298 {
299 /* config is already enabled */
300 int retval = gowin_set_instr(tap, ERASE_SRAM);
301 if (retval != ERROR_OK)
302 return retval;
303 retval = gowin_set_instr(tap, NO_OP);
304 if (retval != ERROR_OK)
305 return retval;
306
307 /* Delay or Run Test 2~10ms */
308 /* 10 ms is worst case for GW2A-55 */
309 jtag_add_sleep(10000);
310 retval = jtag_execute_queue();
311 if (retval != ERROR_OK)
312 return retval;
313
314 retval = gowin_check_status_flag(tap, STAUS_MASK_MEMORY_ERASE,
315 STAUS_MASK_MEMORY_ERASE);
316 if (retval != ERROR_OK)
317 return retval;
318
319 if (tx_erase_done) {
320 retval = gowin_set_instr(tap, SRAM_ERASE_DONE);
321 if (retval != ERROR_OK)
322 return retval;
323 retval = gowin_set_instr(tap, NO_OP);
324 if (retval != ERROR_OK)
325 return retval;
326 retval = jtag_execute_queue();
327 if (retval != ERROR_OK)
328 return retval;
329 /* gen clock cycles in RUN/IDLE for 500us -> 1/500us = 2000/s */
330 retval = gowin_runtest_idle(tap, 2000);
331 if (retval != ERROR_OK)
332 return retval;
333 }
334
335 retval = gowin_set_instr(tap, NO_OP);
336 if (retval != ERROR_OK)
337 return retval;
338 return jtag_execute_queue();
339 }
340
341 static int gowin_load_to_sram(struct pld_device *pld_device, const char *filename)
342 {
343 if (!pld_device)
344 return ERROR_FAIL;
345
346 struct gowin_pld_device *gowin_info = pld_device->driver_priv;
347
348 if (!gowin_info || !gowin_info->tap)
349 return ERROR_FAIL;
350 struct jtag_tap *tap = gowin_info->tap;
351
352 bool is_fs = false;
353 struct gowin_bit_file bit_file;
354 int retval = gowin_read_file(&bit_file, filename, &is_fs);
355 if (retval != ERROR_OK)
356 return retval;
357
358 for (unsigned int i = 0; i < bit_file.raw_file.length; i++)
359 bit_file.raw_file.data[i] = flip_u32(bit_file.raw_file.data[i], 8);
360
361 uint32_t id;
362 retval = gowin_read_register(tap, IDCODE, &id);
363 if (retval != ERROR_OK) {
364 free(bit_file.raw_file.data);
365 return retval;
366 }
367
368 if (is_fs && id != bit_file.id) {
369 free(bit_file.raw_file.data);
370 LOG_ERROR("Id on device (0x%8.8" PRIx32 ") and id in bit-stream (0x%8.8" PRIx32 ") don't match.",
371 id, bit_file.id);
372 return ERROR_FAIL;
373 }
374
375 retval = gowin_enable_config(tap);
376 if (retval != ERROR_OK) {
377 free(bit_file.raw_file.data);
378 return retval;
379 }
380
381 retval = gowin_erase_sram(tap, false);
382 if (retval != ERROR_OK) {
383 free(bit_file.raw_file.data);
384 return retval;
385 }
386
387 retval = gowin_set_instr(tap, ADDRESS_INITIALIZATION);
388 if (retval != ERROR_OK) {
389 free(bit_file.raw_file.data);
390 return retval;
391 }
392 retval = gowin_set_instr(tap, TRANSFER_CONFIGURATION_DATA);
393 if (retval != ERROR_OK) {
394 free(bit_file.raw_file.data);
395 return retval;
396 }
397
398 /* scan out the bitstream */
399 struct scan_field field;
400 field.num_bits = bit_file.raw_file.length * 8;
401 field.out_value = bit_file.raw_file.data;
402 field.in_value = bit_file.raw_file.data;
403 jtag_add_dr_scan(gowin_info->tap, 1, &field, TAP_IDLE);
404 jtag_add_runtest(3, TAP_IDLE);
405
406 retval = jtag_execute_queue();
407 if (retval != ERROR_OK) {
408 free(bit_file.raw_file.data);
409 return retval;
410 }
411
412 retval = gowin_disable_config(tap);
413 free(bit_file.raw_file.data);
414 if (retval != ERROR_OK)
415 return retval;
416
417 retval = gowin_set_instr(gowin_info->tap, NO_OP);
418 if (retval != ERROR_OK)
419 return retval;
420
421 retval = jtag_execute_queue();
422
423 return retval;
424 }
425
426 static int gowin_read_register_command(struct pld_device *pld_device, uint32_t cmd, uint32_t *value)
427 {
428 if (!pld_device)
429 return ERROR_FAIL;
430
431 struct gowin_pld_device *gowin_info = pld_device->driver_priv;
432
433 if (!gowin_info || !gowin_info->tap)
434 return ERROR_FAIL;
435
436 return gowin_read_register(gowin_info->tap, cmd, value);
437 }
438
439 static int gowin_reload_command(struct pld_device *pld_device)
440 {
441 if (!pld_device)
442 return ERROR_FAIL;
443
444 struct gowin_pld_device *gowin_info = pld_device->driver_priv;
445
446 if (!gowin_info || !gowin_info->tap)
447 return ERROR_FAIL;
448
449 return gowin_reload(gowin_info->tap);
450 }
451
452 COMMAND_HANDLER(gowin_read_status_command_handler)
453 {
454 int dev_id;
455
456 if (CMD_ARGC != 1)
457 return ERROR_COMMAND_SYNTAX_ERROR;
458
459 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
460 struct pld_device *device = get_pld_device_by_num(dev_id);
461 if (!device) {
462 command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
463 return ERROR_FAIL;
464 }
465
466 uint32_t status = 0;
467 int retval = gowin_read_register_command(device, STATUS_REGISTER, &status);
468
469 if (retval == ERROR_OK)
470 command_print(CMD, "0x%8.8" PRIx32, status);
471
472 return retval;
473 }
474
475 COMMAND_HANDLER(gowin_read_user_register_command_handler)
476 {
477 int dev_id;
478
479 if (CMD_ARGC != 1)
480 return ERROR_COMMAND_SYNTAX_ERROR;
481
482 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
483 struct pld_device *device = get_pld_device_by_num(dev_id);
484 if (!device) {
485 command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
486 return ERROR_FAIL;
487 }
488
489 uint32_t user_reg = 0;
490 int retval = gowin_read_register_command(device, READ_USERCODE, &user_reg);
491
492 if (retval == ERROR_OK)
493 command_print(CMD, "0x%8.8" PRIx32, user_reg);
494
495 return retval;
496 }
497
498 COMMAND_HANDLER(gowin_reload_command_handler)
499 {
500 int dev_id;
501
502 if (CMD_ARGC != 1)
503 return ERROR_COMMAND_SYNTAX_ERROR;
504
505 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
506 struct pld_device *device = get_pld_device_by_num(dev_id);
507 if (!device) {
508 command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[0]);
509 return ERROR_FAIL;
510 }
511
512 return gowin_reload_command(device);
513 }
514
515 static const struct command_registration gowin_exec_command_handlers[] = {
516 {
517 .name = "read_status",
518 .mode = COMMAND_EXEC,
519 .handler = gowin_read_status_command_handler,
520 .help = "reading status register from FPGA",
521 .usage = "num_pld",
522 }, {
523 .name = "read_user",
524 .mode = COMMAND_EXEC,
525 .handler = gowin_read_user_register_command_handler,
526 .help = "reading user register from FPGA",
527 .usage = "num_pld",
528 }, {
529 .name = "reload",
530 .mode = COMMAND_EXEC,
531 .handler = gowin_reload_command_handler,
532 .help = "reloading bitstream from flash to SRAM",
533 .usage = "num_pld",
534 },
535 COMMAND_REGISTRATION_DONE
536 };
537
538 static const struct command_registration gowin_command_handler[] = {
539 {
540 .name = "gowin",
541 .mode = COMMAND_ANY,
542 .help = "gowin specific commands",
543 .usage = "",
544 .chain = gowin_exec_command_handlers
545 },
546 COMMAND_REGISTRATION_DONE
547 };
548
549 PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
550 {
551 struct jtag_tap *tap;
552
553 struct gowin_pld_device *gowin_info;
554
555 if (CMD_ARGC != 2)
556 return ERROR_COMMAND_SYNTAX_ERROR;
557
558 tap = jtag_tap_by_string(CMD_ARGV[1]);
559 if (!tap) {
560 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
561 return ERROR_FAIL;
562 }
563
564 gowin_info = malloc(sizeof(struct gowin_pld_device));
565 if (!gowin_info) {
566 LOG_ERROR("Out of memory");
567 return ERROR_FAIL;
568 }
569 gowin_info->tap = tap;
570
571 pld->driver_priv = gowin_info;
572
573 return ERROR_OK;
574 }
575
576 struct pld_driver gowin_pld = {
577 .name = "gowin",
578 .commands = gowin_command_handler,
579 .pld_device_command = &gowin_pld_device_command,
580 .load = &gowin_load_to_sram,
581 };

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)