bd7577e3667888dd32023a7505e49d76399f4fba
[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 "ocl.h"
25 #include "flash.h"
26 #include "embeddedice.h"
27
28
29 typedef struct ocl_priv_s
30 {
31 arm_jtag_t *jtag_info;
32 unsigned int buflen;
33 unsigned int bufalign;
34 } ocl_priv_t;
35
36 static int ocl_erase_check(struct flash_bank_s *bank)
37 {
38 return ERROR_OK;
39 }
40
41 static int ocl_protect_check(struct flash_bank_s *bank)
42 {
43 return ERROR_OK;
44 }
45
46 /* flash_bank ocl 0 0 0 0 <target#> */
47 FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
48 {
49 int retval;
50 armv4_5_common_t *armv4_5;
51 arm7_9_common_t *arm7_9;
52 ocl_priv_t *ocl;
53
54 if (argc < 6)
55 {
56 LOG_WARNING("incomplete flash_bank ocl configuration");
57 return ERROR_FLASH_BANK_INVALID;
58 }
59
60 if ((retval = arm7_9_get_arch_pointers(bank->target, &armv4_5, &arm7_9)) != ERROR_OK)
61 return retval;
62
63 ocl = bank->driver_priv = malloc(sizeof(ocl_priv_t));
64 ocl->jtag_info = &arm7_9->jtag_info;
65 ocl->buflen = 0;
66 ocl->bufalign = 1;
67
68 return ERROR_OK;
69 }
70
71 static int ocl_erase(struct flash_bank_s *bank, int first, int last)
72 {
73 ocl_priv_t *ocl = bank->driver_priv;
74 int retval;
75 uint32_t dcc_buffer[3];
76
77 /* check preconditions */
78 if (bank->num_sectors == 0)
79 return ERROR_FLASH_BANK_NOT_PROBED;
80
81 if (bank->target->state != TARGET_RUNNING)
82 {
83 LOG_ERROR("target has to be running to communicate with the loader");
84 return ERROR_TARGET_NOT_RUNNING;
85 }
86
87 if ((first == 0) && (last == bank->num_sectors - 1))
88 {
89 dcc_buffer[0] = OCL_ERASE_ALL;
90 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
91 return retval;
92 }
93 else
94 {
95 dcc_buffer[0] = OCL_ERASE_BLOCK;
96 dcc_buffer[1] = first;
97 dcc_buffer[2] = last;
98 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))
99 return retval;
100 }
101
102 /* wait for response, fixed timeout of 1 s */
103 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
104 {
105 if (retval == ERROR_TARGET_TIMEOUT)
106 LOG_ERROR("loader not responding");
107 return retval;
108 }
109
110 /* receive response */
111 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1) != ERROR_OK))
112 return retval;
113
114 if (dcc_buffer[1] != OCL_CMD_DONE)
115 {
116 if (dcc_buffer[0] == OCL_ERASE_ALL)
117 LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
118 else
119 LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]);
120 return ERROR_FLASH_OPERATION_FAILED;
121 }
122
123 return ERROR_OK;
124 }
125
126 static int ocl_protect(struct flash_bank_s *bank, int set, int first, int last)
127 {
128 return ERROR_OK;
129 }
130
131 static int ocl_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
132 {
133 ocl_priv_t *ocl = bank->driver_priv;
134 int retval;
135 uint32_t *dcc_buffer;
136 uint32_t *dcc_bufptr;
137 int byteofs;
138 int runlen;
139 uint32_t chksum;
140
141 int i;
142
143 /* check preconditions */
144 if (ocl->buflen == 0 || ocl->bufalign == 0)
145 return ERROR_FLASH_BANK_NOT_PROBED;
146
147 if (bank->target->state != TARGET_RUNNING)
148 {
149 LOG_ERROR("target has to be running to communicate with the loader");
150 return ERROR_TARGET_NOT_RUNNING;
151 }
152
153 /* allocate buffer for max. ocl buffer + overhead */
154 dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
155
156 while (count)
157 {
158 if (count + (offset % ocl->bufalign) > ocl->buflen)
159 runlen = ocl->buflen - (offset % ocl->bufalign);
160 else
161 runlen = count;
162
163 dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
164 dcc_buffer[1] = offset;
165 dcc_bufptr = &dcc_buffer[2];
166
167 *dcc_bufptr = 0xffffffff;
168 byteofs = (offset % ocl->bufalign) % 4;
169 chksum = OCL_CHKS_INIT;
170
171 /* copy data to DCC buffer in proper byte order and properly aligned */
172 for (i = 0; i < runlen; i++)
173 {
174 switch (byteofs++)
175 {
176 case 0:
177 *dcc_bufptr &= *(buffer++) | 0xffffff00;
178 break;
179 case 1:
180 *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
181 break;
182 case 2:
183 *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
184 break;
185 case 3:
186 *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
187 chksum ^= *(dcc_bufptr++);
188 *dcc_bufptr = 0xffffffff;
189 byteofs = 0;
190 break;
191 }
192 }
193
194 /* add the remaining word to checksum */
195 if (byteofs)
196 chksum ^= *(dcc_bufptr++);
197
198 *(dcc_bufptr++) = chksum;
199
200 /* send the data */
201 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)
202 {
203 free(dcc_buffer);
204 return retval;
205 }
206
207 /* wait for response, fixed timeout of 1 s */
208 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
209 {
210 if (retval == ERROR_TARGET_TIMEOUT)
211 LOG_ERROR("loader not responding");
212 free(dcc_buffer);
213 return retval;
214 }
215
216 /* receive response */
217 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
218 {
219 free(dcc_buffer);
220 return retval;
221 }
222
223 if (dcc_buffer[0] != OCL_CMD_DONE)
224 {
225 LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
226 free(dcc_buffer);
227 return ERROR_FLASH_OPERATION_FAILED;
228 }
229
230 count -= runlen;
231 offset += runlen;
232 }
233
234 free(dcc_buffer);
235 return ERROR_OK;
236 }
237
238 static int ocl_probe(struct flash_bank_s *bank)
239 {
240 ocl_priv_t *ocl = bank->driver_priv;
241 int retval;
242 uint32_t dcc_buffer[1];
243 int sectsize;
244 int i;
245
246 /* purge pending data in DCC */
247 embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
248
249 dcc_buffer[0] = OCL_PROBE;
250 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
251 return retval;
252
253 /* wait for response, fixed timeout of 1 s */
254 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
255 {
256 if (retval == ERROR_TARGET_TIMEOUT)
257 LOG_ERROR("loader not responding");
258 return retval;
259 }
260
261 /* receive response */
262 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
263 return retval;
264
265 if (dcc_buffer[0] != OCL_CMD_DONE)
266 {
267 LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
268 return ERROR_FLASH_OPERATION_FAILED;
269 }
270
271 /* receive and fill in parameters, detection of loader is important, receive it one by one */
272 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
273 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
274 return retval;
275 bank->base = dcc_buffer[0];
276
277 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
278 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
279 return retval;
280 bank->size = dcc_buffer[0];
281
282 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
283 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
284 return retval;
285 bank->num_sectors = dcc_buffer[0];
286
287 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
288 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
289 return retval;
290 ocl->buflen = dcc_buffer[0] & 0xffff;
291 ocl->bufalign = dcc_buffer[0] >> 16;
292
293 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
294 if (bank->num_sectors == 0)
295 {
296 LOG_ERROR("number of sectors shall be non zero value");
297 return ERROR_FLASH_BANK_INVALID;
298 }
299 if (bank->size % bank->num_sectors) {
300 LOG_ERROR("bank size not divisible by number of sectors");
301 return ERROR_FLASH_BANK_INVALID;
302 }
303 sectsize = bank->size / bank->num_sectors;
304 for (i = 0; i < bank->num_sectors; i++)
305 {
306 bank->sectors[i].offset = i * sectsize;
307 bank->sectors[i].size = sectsize;
308 bank->sectors[i].is_erased = -1;
309 bank->sectors[i].is_protected = -1;
310 }
311
312 if (ocl->bufalign == 0)
313 ocl->bufalign = 1;
314
315 if (ocl->buflen == 0)
316 {
317 LOG_ERROR("buflen shall be non zero value");
318 return ERROR_FLASH_BANK_INVALID;
319 }
320
321 if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))
322 {
323 LOG_ERROR("buflen is not multiple of bufalign");
324 return ERROR_FLASH_BANK_INVALID;
325 }
326
327 if (ocl->buflen % 4)
328 {
329 LOG_ERROR("buflen shall be divisible by 4");
330 return ERROR_FLASH_BANK_INVALID;
331 }
332
333 return ERROR_OK;
334 }
335
336 static int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size)
337 {
338 return ERROR_OK;
339 }
340
341 static int ocl_auto_probe(struct flash_bank_s *bank)
342 {
343 ocl_priv_t *ocl = bank->driver_priv;
344
345 if (ocl->buflen == 0 || ocl->bufalign == 0)
346 return ERROR_FLASH_BANK_NOT_PROBED;
347
348 return ERROR_OK;
349 }
350
351 struct flash_driver ocl_flash = {
352 .name = "ocl",
353 .flash_bank_command = &ocl_flash_bank_command,
354 .erase = &ocl_erase,
355 .protect = &ocl_protect,
356 .write = &ocl_write,
357 .probe = &ocl_probe,
358 .erase_check = &ocl_erase_check,
359 .protect_check = &ocl_protect_check,
360 .info = &ocl_info,
361 .auto_probe = &ocl_auto_probe,
362 };

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)