825f455f660db2467ef259c034b9d0b0d340418f
[openocd.git] / src / flash / ocl.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
3 * chromy@asix.cz *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25
26 #include "ocl.h"
27
28 #include "flash.h"
29 #include "target.h"
30 #include "log.h"
31 #include "binarybuffer.h"
32 #include "types.h"
33 #include "embeddedice.h"
34 #include "arm7_9_common.h"
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 int ocl_register_commands(struct command_context_s *cmd_ctx);
41 int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
42 int ocl_erase(struct flash_bank_s *bank, int first, int last);
43 int ocl_protect(struct flash_bank_s *bank, int set, int first, int last);
44 int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
45 int ocl_probe(struct flash_bank_s *bank);
46 int ocl_erase_check(struct flash_bank_s *bank);
47 int ocl_protect_check(struct flash_bank_s *bank);
48 int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size);
49 int ocl_auto_probe(struct flash_bank_s *bank);
50
51 flash_driver_t ocl_flash =
52 {
53 .name = "ocl",
54 .register_commands = ocl_register_commands,
55 .flash_bank_command = ocl_flash_bank_command,
56 .erase = ocl_erase,
57 .protect = ocl_protect,
58 .write = ocl_write,
59 .probe = ocl_probe,
60 .erase_check = ocl_erase_check,
61 .protect_check = ocl_protect_check,
62 .info = ocl_info,
63 .auto_probe = ocl_auto_probe
64 };
65
66 typedef struct ocl_priv_s
67 {
68 arm_jtag_t *jtag_info;
69 int buflen;
70 int bufalign;
71 } ocl_priv_t;
72
73 int ocl_register_commands(struct command_context_s *cmd_ctx)
74 {
75 return ERROR_OK;
76 }
77
78 int ocl_erase_check(struct flash_bank_s *bank)
79 {
80 return ERROR_OK;
81 }
82
83 int ocl_protect_check(struct flash_bank_s *bank)
84 {
85 return ERROR_OK;
86 }
87
88 /* flash_bank ocl 0 0 0 0 <target#> */
89 int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
90 {
91 int retval;
92 armv4_5_common_t *armv4_5;
93 arm7_9_common_t *arm7_9;
94 ocl_priv_t *ocl;
95
96 if (argc < 6)
97 {
98 LOG_WARNING("incomplete flash_bank ocl configuration");
99 return ERROR_FLASH_BANK_INVALID;
100 }
101
102 if ((retval = arm7_9_get_arch_pointers(bank->target, &armv4_5, &arm7_9)) != ERROR_OK)
103 return retval;
104
105 ocl = bank->driver_priv = malloc(sizeof(ocl_priv_t));
106 ocl->jtag_info = &arm7_9->jtag_info;
107 ocl->buflen = 0;
108 ocl->bufalign = 1;
109
110 return ERROR_OK;
111 }
112
113 int ocl_erase(struct flash_bank_s *bank, int first, int last)
114 {
115 ocl_priv_t *ocl = bank->driver_priv;
116 int retval;
117 u32 dcc_buffer[3];
118
119 /* check preconditions */
120 if (bank->num_sectors == 0)
121 return ERROR_FLASH_BANK_NOT_PROBED;
122
123 if (bank->target->state != TARGET_RUNNING)
124 {
125 LOG_ERROR("target has to be running to communicate with the loader");
126 return ERROR_TARGET_NOT_RUNNING;
127 }
128
129 if ((first == 0) && (last == bank->num_sectors - 1))
130 {
131 dcc_buffer[0] = OCL_ERASE_ALL;
132 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
133 return retval;
134 }
135 else
136 {
137 dcc_buffer[0] = OCL_ERASE_BLOCK;
138 dcc_buffer[1] = first;
139 dcc_buffer[2] = last;
140 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))
141 return retval;
142 }
143
144 /* wait for response, fixed timeout of 1 s */
145 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
146 {
147 if (retval == ERROR_TARGET_TIMEOUT)
148 LOG_ERROR("loader not responding");
149 return retval;
150 }
151
152 /* receive response */
153 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer+1, 1) != ERROR_OK))
154 return retval;
155
156 if (dcc_buffer[1] != OCL_CMD_DONE)
157 {
158 if (dcc_buffer[0] == OCL_ERASE_ALL)
159 LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08X", dcc_buffer[1]);
160 else
161 LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08X", dcc_buffer[1]);
162 return ERROR_FLASH_OPERATION_FAILED;
163 }
164
165 return ERROR_OK;
166 }
167
168 int ocl_protect(struct flash_bank_s *bank, int set, int first, int last)
169 {
170 return ERROR_OK;
171 }
172
173 int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
174 {
175 ocl_priv_t *ocl = bank->driver_priv;
176 int retval;
177 u32 *dcc_buffer;
178 u32 *dcc_bufptr;
179 int byteofs;
180 int runlen;
181 u32 chksum;
182
183 int i;
184
185 /* check preconditions */
186 if (ocl->buflen == 0 || ocl->bufalign==0)
187 return ERROR_FLASH_BANK_NOT_PROBED;
188
189 if (bank->target->state != TARGET_RUNNING)
190 {
191 LOG_ERROR("target has to be running to communicate with the loader");
192 return ERROR_TARGET_NOT_RUNNING;
193 }
194
195 /* allocate buffer for max. ocl buffer + overhead */
196 dcc_buffer = malloc(sizeof(u32)*(ocl->buflen/4+3));
197
198 while (count)
199 {
200 if (count + (offset % ocl->bufalign) > ocl->buflen)
201 runlen = ocl->buflen - (offset % ocl->bufalign);
202 else
203 runlen = count;
204
205 dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
206 dcc_buffer[1] = offset;
207 dcc_bufptr = &dcc_buffer[2];
208
209 *dcc_bufptr = 0xffffffff;
210 byteofs = (offset % ocl->bufalign) % 4;
211 chksum = OCL_CHKS_INIT;
212
213 /* copy data to DCC buffer in proper byte order and properly aligned */
214 for (i=0; i<runlen; i++)
215 {
216 switch (byteofs++)
217 {
218 case 0:
219 *dcc_bufptr &= *(buffer++) | 0xffffff00;
220 break;
221 case 1:
222 *dcc_bufptr &= ((*(buffer++))<<8) | 0xffff00ff;
223 break;
224 case 2:
225 *dcc_bufptr &= ((*(buffer++))<<16) | 0xff00ffff;
226 break;
227 case 3:
228 *dcc_bufptr &= ((*(buffer++))<<24) | 0x00ffffff;
229 chksum ^= *(dcc_bufptr++);
230 *dcc_bufptr = 0xffffffff;
231 byteofs = 0;
232 break;
233 }
234 }
235
236 /* add the remaining word to checksum */
237 if (byteofs)
238 chksum ^= *(dcc_bufptr++);
239
240 *(dcc_bufptr++) = chksum;
241
242 /* send the data */
243 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)
244 {
245 free(dcc_buffer);
246 return retval;
247 }
248
249 /* wait for response, fixed timeout of 1 s */
250 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
251 {
252 if (retval == ERROR_TARGET_TIMEOUT)
253 LOG_ERROR("loader not responding");
254 free(dcc_buffer);
255 return retval;
256 }
257
258 /* receive response */
259 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
260 {
261 free(dcc_buffer);
262 return retval;
263 }
264
265 if (dcc_buffer[0] != OCL_CMD_DONE)
266 {
267 LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08X", dcc_buffer[0]);
268 free(dcc_buffer);
269 return ERROR_FLASH_OPERATION_FAILED;
270 }
271
272 count -= runlen;
273 offset += runlen;
274 }
275
276 free(dcc_buffer);
277 return ERROR_OK;
278 }
279
280 int ocl_probe(struct flash_bank_s *bank)
281 {
282 ocl_priv_t *ocl = bank->driver_priv;
283 int retval;
284 u32 dcc_buffer[1];
285 int sectsize;
286 int i;
287
288 /* purge pending data in DCC */
289 embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
290
291 dcc_buffer[0] = OCL_PROBE;
292 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
293 return retval;
294
295 /* wait for response, fixed timeout of 1 s */
296 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
297 {
298 if (retval == ERROR_TARGET_TIMEOUT)
299 LOG_ERROR("loader not responding");
300 return retval;
301 }
302
303 /* receive response */
304 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
305 return retval;
306
307 if (dcc_buffer[0] != OCL_CMD_DONE)
308 {
309 LOG_ERROR("loader response to OCL_PROBE 0x%08X", dcc_buffer[0]);
310 return ERROR_FLASH_OPERATION_FAILED;
311 }
312
313 /* receive and fill in parameters, detection of loader is important, receive it one by one */
314 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
315 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
316 return retval;
317 bank->base = dcc_buffer[0];
318
319 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
320 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
321 return retval;
322 bank->size = dcc_buffer[0];
323
324 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
325 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
326 return retval;
327 bank->num_sectors = dcc_buffer[0];
328
329 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
330 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
331 return retval;
332 ocl->buflen = dcc_buffer[0] & 0xffff;
333 ocl->bufalign = dcc_buffer[0] >> 16;
334
335 bank->sectors = realloc(bank->sectors, sizeof(flash_sector_t)*bank->num_sectors);
336 if (bank->num_sectors == 0)
337 {
338 LOG_ERROR("number of sectors shall be non zero value");
339 return ERROR_FLASH_BANK_INVALID;
340 }
341 if (bank->size % bank->num_sectors) {
342 LOG_ERROR("bank size not divisible by number of sectors");
343 return ERROR_FLASH_BANK_INVALID;
344 }
345 sectsize = bank->size / bank->num_sectors;
346 for (i=0; i<bank->num_sectors; i++)
347 {
348 bank->sectors[i].offset = i * sectsize;
349 bank->sectors[i].size = sectsize;
350 bank->sectors[i].is_erased = -1;
351 bank->sectors[i].is_protected = -1;
352 }
353
354 if (ocl->bufalign == 0)
355 ocl->bufalign = 1;
356
357 if (ocl->buflen == 0)
358 {
359 LOG_ERROR("buflen shall be non zero value");
360 return ERROR_FLASH_BANK_INVALID;
361 }
362
363 if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))
364 {
365 LOG_ERROR("buflen is not multiple of bufalign");
366 return ERROR_FLASH_BANK_INVALID;
367 }
368
369 if (ocl->buflen % 4)
370 {
371 LOG_ERROR("buflen shall be divisible by 4");
372 return ERROR_FLASH_BANK_INVALID;
373 }
374
375 return ERROR_OK;
376 }
377
378 int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size)
379 {
380 return ERROR_OK;
381 }
382
383 int ocl_auto_probe(struct flash_bank_s *bank)
384 {
385 ocl_priv_t *ocl = bank->driver_priv;
386
387 if (ocl->buflen == 0 || ocl->bufalign==0)
388 return ERROR_FLASH_BANK_NOT_PROBED;
389
390 return ERROR_OK;
391 }

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)