jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / ocl.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2007 by Pavel Chromy *
5 * chromy@asix.cz *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "imp.h"
13 #include "ocl.h"
14 #include <target/embeddedice.h>
15
16 struct ocl_priv {
17 struct arm_jtag *jtag_info;
18 unsigned int buflen;
19 unsigned int bufalign;
20 };
21
22 /* flash_bank ocl 0 0 0 0 <target#> */
23 FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
24 {
25 struct arm7_9_common *arm7_9;
26 struct ocl_priv *ocl;
27
28 if (CMD_ARGC < 6)
29 return ERROR_COMMAND_SYNTAX_ERROR;
30
31 arm7_9 = target_to_arm7_9(bank->target);
32 if (!is_arm7_9(arm7_9))
33 return ERROR_TARGET_INVALID;
34
35 ocl = bank->driver_priv = malloc(sizeof(struct ocl_priv));
36 ocl->jtag_info = &arm7_9->jtag_info;
37 ocl->buflen = 0;
38 ocl->bufalign = 1;
39
40 return ERROR_OK;
41 }
42
43 static int ocl_erase(struct flash_bank *bank, unsigned int first,
44 unsigned int last)
45 {
46 struct ocl_priv *ocl = bank->driver_priv;
47 int retval;
48 uint32_t dcc_buffer[3];
49
50 /* check preconditions */
51 if (bank->num_sectors == 0)
52 return ERROR_FLASH_BANK_NOT_PROBED;
53
54 if (bank->target->state != TARGET_RUNNING) {
55 LOG_ERROR("target has to be running to communicate with the loader");
56 return ERROR_TARGET_NOT_RUNNING;
57 }
58
59 if ((first == 0) && (last == bank->num_sectors - 1)) {
60 dcc_buffer[0] = OCL_ERASE_ALL;
61 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
62 if (retval != ERROR_OK)
63 return retval;
64 } else {
65 dcc_buffer[0] = OCL_ERASE_BLOCK;
66 dcc_buffer[1] = first;
67 dcc_buffer[2] = last;
68 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3);
69 if (retval != ERROR_OK)
70 return retval;
71 }
72
73 /* wait for response, fixed timeout of 1 s */
74 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
75 if (retval != ERROR_OK)
76 return retval;
77
78 /* receive response */
79 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
80 if (retval != ERROR_OK)
81 return retval;
82
83 if (dcc_buffer[1] != OCL_CMD_DONE) {
84 if (dcc_buffer[0] == OCL_ERASE_ALL)
85 LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
86 else
87 LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]);
88 return ERROR_FLASH_OPERATION_FAILED;
89 }
90
91 return ERROR_OK;
92 }
93
94 static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
95 {
96 struct ocl_priv *ocl = bank->driver_priv;
97 int retval;
98 uint32_t *dcc_buffer;
99 uint32_t *dcc_bufptr;
100 int byteofs;
101 int runlen;
102 uint32_t chksum;
103
104 int i;
105
106 /* check preconditions */
107 if (ocl->buflen == 0 || ocl->bufalign == 0)
108 return ERROR_FLASH_BANK_NOT_PROBED;
109
110 if (bank->target->state != TARGET_RUNNING) {
111 LOG_ERROR("target has to be running to communicate with the loader");
112 return ERROR_TARGET_NOT_RUNNING;
113 }
114
115 /* allocate buffer for max. ocl buffer + overhead */
116 dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
117
118 while (count) {
119 if (count + (offset % ocl->bufalign) > ocl->buflen)
120 runlen = ocl->buflen - (offset % ocl->bufalign);
121 else
122 runlen = count;
123
124 dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
125 dcc_buffer[1] = offset;
126 dcc_bufptr = &dcc_buffer[2];
127
128 *dcc_bufptr = 0xffffffff;
129 byteofs = (offset % ocl->bufalign) % 4;
130 chksum = OCL_CHKS_INIT;
131
132 /* copy data to DCC buffer in proper byte order and properly aligned */
133 for (i = 0; i < runlen; i++) {
134 switch (byteofs++) {
135 case 0:
136 *dcc_bufptr &= *(buffer++) | 0xffffff00;
137 break;
138 case 1:
139 *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
140 break;
141 case 2:
142 *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
143 break;
144 case 3:
145 *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
146 chksum ^= *(dcc_bufptr++);
147 *dcc_bufptr = 0xffffffff;
148 byteofs = 0;
149 break;
150 }
151 }
152
153 /* add the remaining word to checksum */
154 if (byteofs)
155 chksum ^= *(dcc_bufptr++);
156
157 *(dcc_bufptr++) = chksum;
158
159 /* send the data */
160 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer);
161 if (retval != ERROR_OK) {
162 free(dcc_buffer);
163 return retval;
164 }
165
166 /* wait for response, fixed timeout of 1 s */
167 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
168 if (retval != ERROR_OK) {
169 free(dcc_buffer);
170 return retval;
171 }
172
173 /* receive response */
174 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
175 if (retval != ERROR_OK) {
176 free(dcc_buffer);
177 return retval;
178 }
179
180 if (dcc_buffer[0] != OCL_CMD_DONE) {
181 LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
182 free(dcc_buffer);
183 return ERROR_FLASH_OPERATION_FAILED;
184 }
185
186 count -= runlen;
187 offset += runlen;
188 }
189
190 free(dcc_buffer);
191 return ERROR_OK;
192 }
193
194 static int ocl_probe(struct flash_bank *bank)
195 {
196 struct ocl_priv *ocl = bank->driver_priv;
197 int retval;
198 uint32_t dcc_buffer[1];
199 int sectsize;
200
201 /* purge pending data in DCC */
202 embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
203
204 dcc_buffer[0] = OCL_PROBE;
205 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
206 if (retval != ERROR_OK)
207 return retval;
208
209 /* wait for response, fixed timeout of 1 s */
210 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
211 if (retval != ERROR_OK)
212 return retval;
213
214 /* receive response */
215 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
216 if (retval != ERROR_OK)
217 return retval;
218
219 if (dcc_buffer[0] != OCL_CMD_DONE) {
220 LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
221 return ERROR_FLASH_OPERATION_FAILED;
222 }
223
224 /* receive and fill in parameters, detection of loader is important, receive it one by one */
225 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
226 if (retval != ERROR_OK)
227 return retval;
228 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
229 if (retval != ERROR_OK)
230 return retval;
231 bank->base = dcc_buffer[0];
232
233 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
234 if (retval != ERROR_OK)
235 return retval;
236 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
237 if (retval != ERROR_OK)
238 return retval;
239 bank->size = dcc_buffer[0];
240
241 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
242 if (retval != ERROR_OK)
243 return retval;
244 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
245 if (retval != ERROR_OK)
246 return retval;
247 bank->num_sectors = dcc_buffer[0];
248
249 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
250 if (retval != ERROR_OK)
251 return retval;
252 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
253 if (retval != ERROR_OK)
254 return retval;
255 ocl->buflen = dcc_buffer[0] & 0xffff;
256 ocl->bufalign = dcc_buffer[0] >> 16;
257
258 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
259 if (bank->num_sectors == 0) {
260 LOG_ERROR("number of sectors shall be non zero value");
261 return ERROR_FLASH_BANK_INVALID;
262 }
263 if (bank->size % bank->num_sectors) {
264 LOG_ERROR("bank size not divisible by number of sectors");
265 return ERROR_FLASH_BANK_INVALID;
266 }
267 sectsize = bank->size / bank->num_sectors;
268 for (unsigned int i = 0; i < bank->num_sectors; i++) {
269 bank->sectors[i].offset = i * sectsize;
270 bank->sectors[i].size = sectsize;
271 bank->sectors[i].is_erased = -1;
272 bank->sectors[i].is_protected = -1;
273 }
274
275 if (ocl->bufalign == 0)
276 ocl->bufalign = 1;
277
278 if (ocl->buflen == 0) {
279 LOG_ERROR("buflen shall be non zero value");
280 return ERROR_FLASH_BANK_INVALID;
281 }
282
283 if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) {
284 LOG_ERROR("buflen is not multiple of bufalign");
285 return ERROR_FLASH_BANK_INVALID;
286 }
287
288 if (ocl->buflen % 4) {
289 LOG_ERROR("buflen shall be divisible by 4");
290 return ERROR_FLASH_BANK_INVALID;
291 }
292
293 return ERROR_OK;
294 }
295
296 static int ocl_auto_probe(struct flash_bank *bank)
297 {
298 struct ocl_priv *ocl = bank->driver_priv;
299
300 if (ocl->buflen == 0 || ocl->bufalign == 0)
301 return ERROR_FLASH_BANK_NOT_PROBED;
302
303 return ERROR_OK;
304 }
305
306 const struct flash_driver ocl_flash = {
307 .name = "ocl",
308 .flash_bank_command = ocl_flash_bank_command,
309 .erase = ocl_erase,
310 .write = ocl_write,
311 .read = default_flash_read,
312 .probe = ocl_probe,
313 .erase_check = default_flash_blank_check,
314 .auto_probe = ocl_auto_probe,
315 .free_driver_priv = default_flash_free_driver_priv,
316 };

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)