pld: give devices a name for referencing in scripts
[openocd.git] / src / pld / efinix.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
14 #include "pld.h"
15 #include "raw_bit.h"
16
17 #define PROGRAM 0x4
18 #define ENTERUSER 0x7
19
20 #define TRAILING_ZEROS 4000
21 #define RUNTEST_START_CYCLES 100
22 #define RUNTEST_FINISH_CYCLES 100
23
24 struct efinix_pld_device {
25 struct jtag_tap *tap;
26 };
27
28 static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
29 {
30 FILE *input_file = fopen(filename, "r");
31 if (!input_file) {
32 LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));
33 return ERROR_PLD_FILE_LOAD_FAILED;
34 }
35
36 fseek(input_file, 0, SEEK_END);
37 long length = ftell(input_file);
38 fseek(input_file, 0, SEEK_SET);
39
40 if (length < 0 || ((length % 3))) {
41 fclose(input_file);
42 LOG_ERROR("Failed to get length from file %s: %s", filename, strerror(errno));
43 return ERROR_PLD_FILE_LOAD_FAILED;
44 }
45 bit_file->length = DIV_ROUND_UP(length, 3);
46
47 bit_file->data = malloc(bit_file->length);
48 if (!bit_file->data) {
49 fclose(input_file);
50 LOG_ERROR("Out of memory");
51 return ERROR_PLD_FILE_LOAD_FAILED;
52 }
53
54 bool end_detected = false;
55 char buffer[3];
56 for (size_t idx = 0; !end_detected && idx < bit_file->length; ++idx) {
57 size_t read_count = fread(buffer, sizeof(char), 3, input_file);
58 end_detected = feof(input_file);
59 if ((read_count == 3 && buffer[2] != '\n') ||
60 (read_count != 3 && !end_detected) ||
61 (read_count != 2 && end_detected)) {
62 fclose(input_file);
63 free(bit_file->data);
64 bit_file->data = NULL;
65 LOG_ERROR("unexpected line length");
66 return ERROR_PLD_FILE_LOAD_FAILED;
67 }
68
69 if (!isxdigit(buffer[0]) || !isxdigit(buffer[1])) {
70 fclose(input_file);
71 free(bit_file->data);
72 bit_file->data = NULL;
73 LOG_ERROR("unexpected char in hex string");
74 return ERROR_PLD_FILE_LOAD_FAILED;
75 }
76 unhexify(&bit_file->data[idx], buffer, 2);
77 }
78
79 fclose(input_file);
80
81 return ERROR_OK;
82 }
83
84 static int efinix_read_file(struct raw_bit_file *bit_file, const char *filename)
85 {
86 if (!filename || !bit_file)
87 return ERROR_COMMAND_SYNTAX_ERROR;
88
89 /* check if binary .bin or ascii .bit/.hex */
90 const char *file_ending_pos = strrchr(filename, '.');
91 if (!file_ending_pos) {
92 LOG_ERROR("Unable to detect filename suffix");
93 return ERROR_PLD_FILE_LOAD_FAILED;
94 }
95
96 if (strcasecmp(file_ending_pos, ".bin") == 0) {
97 return cpld_read_raw_bit_file(bit_file, filename);
98 } else if ((strcasecmp(file_ending_pos, ".bit") == 0) ||
99 (strcasecmp(file_ending_pos, ".hex") == 0)) {
100 return efinix_read_bit_file(bit_file, filename);
101 }
102
103 LOG_ERROR("Unable to detect filetype");
104 return ERROR_PLD_FILE_LOAD_FAILED;
105 }
106
107 static int efinix_set_instr(struct jtag_tap *tap, uint8_t new_instr)
108 {
109 struct scan_field field;
110 field.num_bits = tap->ir_length;
111 void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
112 if (!t) {
113 LOG_ERROR("Out of memory");
114 return ERROR_FAIL;
115 }
116 field.out_value = t;
117 buf_set_u32(t, 0, field.num_bits, new_instr);
118 field.in_value = NULL;
119 jtag_add_ir_scan(tap, &field, TAP_IDLE);
120 free(t);
121 return ERROR_OK;
122 }
123
124 static int efinix_load(struct pld_device *pld_device, const char *filename)
125 {
126 struct raw_bit_file bit_file;
127 struct scan_field field[2];
128
129 if (!pld_device || !pld_device->driver_priv)
130 return ERROR_FAIL;
131
132 struct efinix_pld_device *efinix_info = pld_device->driver_priv;
133 if (!efinix_info || !efinix_info->tap)
134 return ERROR_FAIL;
135 struct jtag_tap *tap = efinix_info->tap;
136
137 jtag_add_tlr();
138
139 int retval = efinix_set_instr(tap, PROGRAM);
140 if (retval != ERROR_OK)
141 return retval;
142 jtag_add_runtest(RUNTEST_START_CYCLES, TAP_IDLE);
143 retval = efinix_set_instr(tap, PROGRAM); /* fix for T20 */
144 if (retval != ERROR_OK)
145 return retval;
146 retval = jtag_execute_queue();
147 if (retval != ERROR_OK)
148 return retval;
149
150 retval = efinix_read_file(&bit_file, filename);
151 if (retval != ERROR_OK)
152 return retval;
153
154 for (size_t i = 0; i < bit_file.length; i++)
155 bit_file.data[i] = flip_u32(bit_file.data[i], 8);
156
157 /* shift in the bitstream */
158 field[0].num_bits = bit_file.length * 8;
159 field[0].out_value = bit_file.data;
160 field[0].in_value = NULL;
161
162 /* followed by zeros */
163 field[1].num_bits = TRAILING_ZEROS;
164 uint8_t *buf = calloc(TRAILING_ZEROS / 8, 1);
165 if (!buf) {
166 free(bit_file.data);
167 LOG_ERROR("Out of memory");
168 return ERROR_FAIL;
169 }
170 field[1].out_value = buf;
171 field[1].in_value = NULL;
172
173 jtag_add_dr_scan(tap, 2, field, TAP_DRPAUSE);
174 retval = jtag_execute_queue();
175 free(bit_file.data);
176 free(buf);
177 if (retval != ERROR_OK)
178 return retval;
179
180 retval = efinix_set_instr(tap, ENTERUSER);
181 if (retval != ERROR_OK)
182 return retval;
183
184 /* entering RUN/TEST for 100 cycles */
185 jtag_add_runtest(RUNTEST_FINISH_CYCLES, TAP_IDLE);
186 retval = jtag_execute_queue();
187
188 return retval;
189 }
190
191 PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
192 {
193 if (CMD_ARGC != 4)
194 return ERROR_COMMAND_SYNTAX_ERROR;
195
196 if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
197 return ERROR_COMMAND_SYNTAX_ERROR;
198
199 struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[3]);
200 if (!tap) {
201 command_print(CMD, "Tap: %s does not exist", CMD_ARGV[3]);
202 return ERROR_FAIL;
203 }
204
205 struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
206 if (!efinix_info) {
207 LOG_ERROR("Out of memory");
208 return ERROR_FAIL;
209 }
210 efinix_info->tap = tap;
211
212 pld->driver_priv = efinix_info;
213
214 return ERROR_OK;
215 }
216
217 struct pld_driver efinix_pld = {
218 .name = "efinix",
219 .pld_create_command = &efinix_pld_create_command,
220 .load = &efinix_load,
221 };

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)