- added a PLD (programmable logic device) subsystem for FPGA, CPLD etc. configuration
[openocd.git] / src / flash / cfi.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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 "cfi.h"
27
28 #include "flash.h"
29 #include "target.h"
30 #include "log.h"
31 #include "armv4_5.h"
32 #include "algorithm.h"
33 #include "binarybuffer.h"
34 #include "types.h"
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 int cfi_register_commands(struct command_context_s *cmd_ctx);
41 int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
42 int cfi_erase(struct flash_bank_s *bank, int first, int last);
43 int cfi_protect(struct flash_bank_s *bank, int set, int first, int last);
44 int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
45 int cfi_probe(struct flash_bank_s *bank);
46 int cfi_erase_check(struct flash_bank_s *bank);
47 int cfi_protect_check(struct flash_bank_s *bank);
48 int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size);
49
50 int cfi_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
51
52 #define CFI_MAX_BUS_WIDTH 4
53 #define CFI_MAX_CHIP_WIDTH 4
54
55 flash_driver_t cfi_flash =
56 {
57 .name = "cfi",
58 .register_commands = cfi_register_commands,
59 .flash_bank_command = cfi_flash_bank_command,
60 .erase = cfi_erase,
61 .protect = cfi_protect,
62 .write = cfi_write,
63 .probe = cfi_probe,
64 .erase_check = cfi_erase_check,
65 .protect_check = cfi_protect_check,
66 .info = cfi_info
67 };
68
69 inline u32 flash_address(flash_bank_t *bank, int sector, u32 offset)
70 {
71 /* while the sector list isn't built, only accesses to sector 0 work */
72 if (sector == 0)
73 return bank->base + offset * bank->bus_width;
74 else
75 {
76 if (!bank->sectors)
77 {
78 ERROR("BUG: sector list not yet built");
79 exit(-1);
80 }
81 return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;
82 }
83
84 }
85
86 void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
87 {
88 cfi_flash_bank_t *cfi_info = bank->driver_priv;
89 int i;
90
91 if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN)
92 {
93 for (i = bank->bus_width; i > 0; i--)
94 {
95 *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
96 }
97 }
98 else
99 {
100 for (i = 1; i <= bank->bus_width; i++)
101 {
102 *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
103 }
104 }
105 }
106
107 /* read unsigned 8-bit value from the bank
108 * flash banks are expected to be made of similar chips
109 * the query result should be the same for all
110 */
111 u8 cfi_query_u8(flash_bank_t *bank, int sector, u32 offset)
112 {
113 cfi_flash_bank_t *cfi_info = bank->driver_priv;
114 target_t *target = cfi_info->target;
115 u8 data[CFI_MAX_BUS_WIDTH];
116
117 target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);
118
119 if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN)
120 return data[0];
121 else
122 return data[bank->bus_width - 1];
123 }
124
125 /* read unsigned 8-bit value from the bank
126 * in case of a bank made of multiple chips,
127 * the individual values are ORed
128 */
129 u8 cfi_get_u8(flash_bank_t *bank, int sector, u32 offset)
130 {
131 cfi_flash_bank_t *cfi_info = bank->driver_priv;
132 target_t *target = cfi_info->target;
133 u8 data[CFI_MAX_BUS_WIDTH];
134 int i;
135
136 target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);
137
138 if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN)
139 {
140 for (i = 0; i < bank->bus_width / bank->chip_width; i++)
141 data[0] |= data[i];
142
143 return data[0];
144 }
145 else
146 {
147 u8 value = 0;
148 for (i = 0; i < bank->bus_width / bank->chip_width; i++)
149 value |= data[bank->bus_width - 1 - i];
150
151 return value;
152 }
153 }
154
155 u16 cfi_query_u16(flash_bank_t *bank, int sector, u32 offset)
156 {
157 cfi_flash_bank_t *cfi_info = bank->driver_priv;
158 target_t *target = cfi_info->target;
159 u8 data[CFI_MAX_BUS_WIDTH * 2];
160
161 target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data);
162
163 if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN)
164 return data[0] | data[bank->bus_width] << 8;
165 else
166 return data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;
167 }
168
169 u32 cfi_query_u32(flash_bank_t *bank, int sector, u32 offset)
170 {
171 cfi_flash_bank_t *cfi_info = bank->driver_priv;
172 target_t *target = cfi_info->target;
173 u8 data[CFI_MAX_BUS_WIDTH * 4];
174
175 target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data);
176
177 if (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN)
178 return data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;
179 else
180 return data[bank->bus_width - 1] | data[(2* bank->bus_width) - 1] << 8 |
181 data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;
182 }
183
184 void cfi_intel_clear_status_register(flash_bank_t *bank)
185 {
186 cfi_flash_bank_t *cfi_info = bank->driver_priv;
187 target_t *target = cfi_info->target;
188 u8 command[8];
189
190 if (target->state != TARGET_HALTED)
191 {
192 ERROR("BUG: attempted to clear status register while target wasn't halted");
193 exit(-1);
194 }
195
196 cfi_command(bank, 0x50, command);
197 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
198 }
199
200 u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)
201 {
202 u8 status;
203
204 while ((!((status = cfi_get_u8(bank, 0, 0x0)) & 0x80)) && (timeout-- > 0))
205 {
206 DEBUG("status: 0x%x", status);
207 usleep(1000);
208 }
209
210 DEBUG("status: 0x%x", status);
211
212 if ((status & 0x80) != 0x80)
213 {
214 ERROR("timeout while waiting for WSM to become ready");
215 }
216 else if (status != 0x80)
217 {
218 ERROR("status register: 0x%x", status);
219 if (status & 0x2)
220 ERROR("Block Lock-Bit Detected, Operation Abort");
221 if (status & 0x4)
222 ERROR("Program suspended");
223 if (status & 0x8)
224 ERROR("Low Programming Voltage Detected, Operation Aborted");
225 if (status & 0x10)
226 ERROR("Program Error / Error in Setting Lock-Bit");
227 if (status & 0x20)
228 ERROR("Error in Block Erasure or Clear Lock-Bits");
229 if (status & 0x40)
230 ERROR("Block Erase Suspended");
231
232 cfi_intel_clear_status_register(bank);
233 }
234
235 return status;
236 }
237 int cfi_read_intel_pri_ext(flash_bank_t *bank)
238 {
239 cfi_flash_bank_t *cfi_info = bank->driver_priv;
240 cfi_intel_pri_ext_t *pri_ext = malloc(sizeof(cfi_intel_pri_ext_t));
241 target_t *target = cfi_info->target;
242 u8 command[8];
243
244 cfi_info->pri_ext = pri_ext;
245
246 pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
247 pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
248 pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);
249
250 if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
251 {
252 cfi_command(bank, 0xf0, command);
253 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
254 cfi_command(bank, 0xff, command);
255 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
256 return ERROR_FLASH_BANK_INVALID;
257 }
258
259 pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
260 pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);
261
262 DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
263
264 pri_ext->feature_support = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5);
265 pri_ext->suspend_cmd_support = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);
266 pri_ext->blk_status_reg_mask = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa);
267
268 DEBUG("feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);
269
270 pri_ext->vcc_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc);
271 pri_ext->vpp_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd);
272
273 DEBUG("Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x",
274 (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
275 (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
276
277 pri_ext->num_protection_fields = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe);
278 if (pri_ext->num_protection_fields != 1)
279 {
280 WARNING("expected one protection register field, but found %i", pri_ext->num_protection_fields);
281 }
282
283 pri_ext->prot_reg_addr = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf);
284 pri_ext->fact_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11);
285 pri_ext->user_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12);
286
287 DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
288
289 return ERROR_OK;
290 }
291
292 int cfi_intel_info(struct flash_bank_s *bank, char *buf, int buf_size)
293 {
294 int printed;
295 cfi_flash_bank_t *cfi_info = bank->driver_priv;
296 cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
297
298 printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n");
299 buf += printed;
300 buf_size -= printed;
301
302 printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
303 buf += printed;
304 buf_size -= printed;
305
306 printed = snprintf(buf, buf_size, "feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);
307 buf += printed;
308 buf_size -= printed;
309
310 printed = snprintf(buf, buf_size, "Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x\n",
311 (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
312 (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
313 buf += printed;
314 buf_size -= printed;
315
316 printed = snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i\n", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
317
318 return ERROR_OK;
319 }
320
321 int cfi_register_commands(struct command_context_s *cmd_ctx)
322 {
323 command_t *cfi_cmd = register_command(cmd_ctx, NULL, "cfi", NULL, COMMAND_ANY, NULL);
324 /*
325 register_command(cmd_ctx, cfi_cmd, "part_id", cfi_handle_part_id_command, COMMAND_EXEC,
326 "print part id of cfi flash bank <num>");
327 */
328 return ERROR_OK;
329 }
330
331 /* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#>
332 */
333 int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
334 {
335 cfi_flash_bank_t *cfi_info;
336
337 if (argc < 6)
338 {
339 WARNING("incomplete flash_bank cfi configuration");
340 return ERROR_FLASH_BANK_INVALID;
341 }
342
343 if ((strtoul(args[4], NULL, 0) > CFI_MAX_CHIP_WIDTH)
344 || (strtoul(args[3], NULL, 0) > CFI_MAX_BUS_WIDTH))
345 {
346 ERROR("chip and bus width have to specified in byte");
347 return ERROR_FLASH_BANK_INVALID;
348 }
349
350 cfi_info = malloc(sizeof(cfi_flash_bank_t));
351 bank->driver_priv = cfi_info;
352
353 cfi_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
354 if (!cfi_info->target)
355 {
356 ERROR("no target '%i' configured", args[5]);
357 exit(-1);
358 }
359
360 cfi_info->write_algorithm = NULL;
361
362 /* bank wasn't probed yet */
363 cfi_info->qry[0] = -1;
364
365 return ERROR_OK;
366 }
367
368 int cfi_intel_erase(struct flash_bank_s *bank, int first, int last)
369 {
370 cfi_flash_bank_t *cfi_info = bank->driver_priv;
371 cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
372 target_t *target = cfi_info->target;
373 u8 command[8];
374 int i;
375
376 cfi_intel_clear_status_register(bank);
377
378 for (i = first; i <= last; i++)
379 {
380 cfi_command(bank, 0x20, command);
381 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
382
383 cfi_command(bank, 0xd0, command);
384 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
385
386 if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == 0x80)
387 bank->sectors[i].is_erased = 1;
388 else
389 {
390 cfi_command(bank, 0xff, command);
391 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
392
393 ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);
394 return ERROR_FLASH_OPERATION_FAILED;
395 }
396 }
397
398 cfi_command(bank, 0xff, command);
399 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
400
401 return ERROR_OK;
402 }
403
404 int cfi_erase(struct flash_bank_s *bank, int first, int last)
405 {
406 cfi_flash_bank_t *cfi_info = bank->driver_priv;
407
408 if (cfi_info->target->state != TARGET_HALTED)
409 {
410 return ERROR_TARGET_NOT_HALTED;
411 }
412
413 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
414 {
415 return ERROR_FLASH_SECTOR_INVALID;
416 }
417
418 if (cfi_info->qry[0] != 'Q')
419 return ERROR_FLASH_BANK_NOT_PROBED;
420
421 switch(cfi_info->pri_id)
422 {
423 case 1:
424 case 3:
425 return cfi_intel_erase(bank, first, last);
426 break;
427 default:
428 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
429 break;
430 }
431
432 return ERROR_OK;
433 }
434
435 int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
436 {
437 cfi_flash_bank_t *cfi_info = bank->driver_priv;
438 cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
439 target_t *target = cfi_info->target;
440 u8 command[8];
441 int i;
442
443 /* if the device supports neither legacy lock/unlock (bit 3) nor
444 * instant individual block locking (bit 5).
445 */
446 if (!(pri_ext->feature_support & 0x28))
447 return ERROR_FLASH_OPERATION_FAILED;
448
449 cfi_intel_clear_status_register(bank);
450
451 for (i = first; i <= last; i++)
452 {
453 cfi_command(bank, 0x60, command);
454 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
455 if (set)
456 {
457 cfi_command(bank, 0x01, command);
458 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
459 bank->sectors[i].is_protected = 1;
460 }
461 else
462 {
463 cfi_command(bank, 0xd0, command);
464 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
465 bank->sectors[i].is_protected = 0;
466 }
467
468 /* Clear lock bits operation may take up to 1.4s */
469 cfi_intel_wait_status_busy(bank, 1400);
470 }
471
472 /* if the device doesn't support individual block lock bits set/clear,
473 * all blocks have been unlocked in parallel, so we set those that should be protected
474 */
475 if ((!set) && (!(pri_ext->feature_support & 0x20)))
476 {
477 for (i = 0; i < bank->num_sectors; i++)
478 {
479 cfi_intel_clear_status_register(bank);
480 cfi_command(bank, 0x60, command);
481 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
482 if (bank->sectors[i].is_protected == 1)
483 {
484 cfi_command(bank, 0x01, command);
485 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
486 }
487
488 cfi_intel_wait_status_busy(bank, 100);
489 }
490 }
491
492 cfi_command(bank, 0xff, command);
493 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
494
495 return ERROR_OK;
496 }
497
498 int cfi_protect(struct flash_bank_s *bank, int set, int first, int last)
499 {
500 cfi_flash_bank_t *cfi_info = bank->driver_priv;
501
502 if (cfi_info->target->state != TARGET_HALTED)
503 {
504 return ERROR_TARGET_NOT_HALTED;
505 }
506
507 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
508 {
509 return ERROR_FLASH_SECTOR_INVALID;
510 }
511
512 if (cfi_info->qry[0] != 'Q')
513 return ERROR_FLASH_BANK_NOT_PROBED;
514
515 switch(cfi_info->pri_id)
516 {
517 case 1:
518 case 3:
519 cfi_intel_protect(bank, set, first, last);
520 break;
521 default:
522 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
523 break;
524 }
525
526 return ERROR_OK;
527 }
528
529 void cfi_add_byte(struct flash_bank_s *bank, u8 *word, u8 byte)
530 {
531 cfi_flash_bank_t *cfi_info = bank->driver_priv;
532 target_t *target = cfi_info->target;
533
534 int i;
535
536 if (target->endianness == TARGET_LITTLE_ENDIAN)
537 {
538 /* shift bytes */
539 for (i = 0; i < bank->bus_width - 1; i++)
540 word[i] = word[i + 1];
541 word[bank->bus_width - 1] = byte;
542 }
543 else
544 {
545 /* shift bytes */
546 for (i = bank->bus_width - 1; i > 0; i--)
547 word[i] = word[i - 1];
548 word[0] = byte;
549 }
550 }
551
552 int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)
553 {
554 cfi_flash_bank_t *cfi_info = bank->driver_priv;
555 cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
556 target_t *target = cfi_info->target;
557 reg_param_t reg_params[7];
558 armv4_5_algorithm_t armv4_5_info;
559 working_area_t *source;
560 u32 buffer_size = 32768;
561 u8 write_command[CFI_MAX_BUS_WIDTH];
562 u8 busy_pattern[CFI_MAX_BUS_WIDTH];
563 u8 error_pattern[CFI_MAX_BUS_WIDTH];
564 int i;
565 int retval;
566
567 /* algorithm register usage:
568 * r0: source address (in RAM)
569 * r1: target address (in Flash)
570 * r2: count
571 * r3: flash write command
572 * r4: status byte (returned to host)
573 * r5: busy test pattern
574 * r6: error test pattern
575 */
576
577 u32 word_32_code[] = {
578 0xe4904004, /* loop: ldr r4, [r0], #4 */
579 0xe5813000, /* str r3, [r1] */
580 0xe5814000, /* str r4, [r1] */
581 0xe5914000, /* busy: ldr r4, [r1] */
582 0xe0047005, /* and r7, r4, r5 */
583 0xe1570005, /* cmp r7, r5 */
584 0x1afffffb, /* bne busy */
585 0xe1140006, /* tst r4, r6 */
586 0x1a000003, /* bne done */
587 0xe2522001, /* subs r2, r2, #1 */
588 0x0a000001, /* beq done */
589 0xe2811004, /* add r1, r1 #4 */
590 0xeafffff2, /* b loop */
591 0xeafffffe, /* done: b -2 */
592 };
593
594 u32 word_16_code[] = {
595 0xe0d040b2, /* loop: ldrh r4, [r0], #2 */
596 0xe1c130b0, /* strh r3, [r1] */
597 0xe1c140b0, /* strh r4, [r1] */
598 0xe1d140b0, /* busy ldrh r4, [r1] */
599 0xe0047005, /* and r7, r4, r5 */
600 0xe1570005, /* cmp r7, r5 */
601 0x1afffffb, /* bne busy */
602 0xe1140006, /* tst r4, r6 */
603 0x1a000003, /* bne done */
604 0xe2522001, /* subs r2, r2, #1 */
605 0x0a000001, /* beq done */
606 0xe2811002, /* add r1, r1 #2 */
607 0xeafffff2, /* b loop */
608 0xeafffffe, /* done: b -2 */
609 };
610
611 u32 word_8_code[] = {
612 0xe4d04001, /* loop: ldrb r4, [r0], #1 */
613 0xe5c13000, /* strb r3, [r1] */
614 0xe5c14000, /* strb r4, [r1] */
615 0xe5d14000, /* busy ldrb r4, [r1] */
616 0xe0047005, /* and r7, r4, r5 */
617 0xe1570005, /* cmp r7, r5 */
618 0x1afffffb, /* bne busy */
619 0xe1140006, /* tst r4, r6 */
620 0x1a000003, /* bne done */
621 0xe2522001, /* subs r2, r2, #1 */
622 0x0a000001, /* beq done */
623 0xe2811001, /* add r1, r1 #1 */
624 0xeafffff2, /* b loop */
625 0xeafffffe, /* done: b -2 */
626 };
627
628 cfi_intel_clear_status_register(bank);
629
630 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
631 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
632 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
633
634 /* flash write code */
635 if (!cfi_info->write_algorithm)
636 {
637 if (target_alloc_working_area(target, 4 * 14, &cfi_info->write_algorithm) != ERROR_OK)
638 {
639 WARNING("no working area available, can't do block memory writes");
640 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
641 };
642
643 /* write algorithm code to working area */
644 if (bank->bus_width == 1)
645 {
646 target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_8_code);
647 }
648 else if (bank->bus_width == 2)
649 {
650 target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_16_code);
651 }
652 else if (bank->bus_width == 4)
653 {
654 target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_32_code);
655 }
656 else
657 {
658 return ERROR_FLASH_OPERATION_FAILED;
659 }
660 }
661
662 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
663 {
664 buffer_size /= 2;
665 if (buffer_size <= 256)
666 {
667 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
668 if (cfi_info->write_algorithm)
669 target_free_working_area(target, cfi_info->write_algorithm);
670
671 WARNING("no large enough working area available, can't do block memory writes");
672 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
673 }
674 };
675
676 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
677 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
678 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
679 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
680 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
681 init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
682 init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
683
684 cfi_command(bank, 0x40, write_command);
685 cfi_command(bank, 0x80, busy_pattern);
686 cfi_command(bank, 0x7f, error_pattern);
687
688 while (count > 0)
689 {
690 u32 thisrun_count = (count > buffer_size) ? buffer_size : count;
691
692 target_write_buffer(target, source->address, thisrun_count, buffer);
693
694 buf_set_u32(reg_params[0].value, 0, 32, source->address);
695 buf_set_u32(reg_params[1].value, 0, 32, address);
696 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
697 buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32));
698 buf_set_u32(reg_params[5].value, 0, 32, buf_get_u32(busy_pattern, 0, 32));
699 buf_set_u32(reg_params[6].value, 0, 32, buf_get_u32(error_pattern, 0, 32));
700
701 if ((retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + (13 * 4), 10000, &armv4_5_info)) != ERROR_OK)
702 {
703 cfi_intel_clear_status_register(bank);
704 return ERROR_FLASH_OPERATION_FAILED;
705 }
706
707 if (buf_get_u32(reg_params[4].value, 0, 32) & target_buffer_get_u32(target, error_pattern))
708 {
709 /* read status register (outputs debug inforation) */
710 cfi_intel_wait_status_busy(bank, 100);
711 cfi_intel_clear_status_register(bank);
712 return ERROR_FLASH_OPERATION_FAILED;
713 }
714
715 buffer += thisrun_count;
716 address += thisrun_count;
717 count -= thisrun_count;
718 }
719
720 target_free_working_area(target, source);
721
722 destroy_reg_param(&reg_params[0]);
723 destroy_reg_param(&reg_params[1]);
724 destroy_reg_param(&reg_params[2]);
725 destroy_reg_param(&reg_params[3]);
726 destroy_reg_param(&reg_params[4]);
727 destroy_reg_param(&reg_params[5]);
728 destroy_reg_param(&reg_params[6]);
729
730 return ERROR_OK;
731 }
732
733 int cfi_intel_write_word(struct flash_bank_s *bank, u8 *word, u32 address)
734 {
735 cfi_flash_bank_t *cfi_info = bank->driver_priv;
736 cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
737 target_t *target = cfi_info->target;
738 u8 command[8];
739
740 cfi_intel_clear_status_register(bank);
741 cfi_command(bank, 0x40, command);
742 target->type->write_memory(target, address, bank->bus_width, 1, command);
743
744 target->type->write_memory(target, address, bank->bus_width, 1, word);
745
746 if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != 0x80)
747 {
748 cfi_command(bank, 0xff, command);
749 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
750
751 ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);
752 return ERROR_FLASH_OPERATION_FAILED;
753 }
754
755 return ERROR_OK;
756 }
757
758 int cfi_write_word(struct flash_bank_s *bank, u8 *word, u32 address)
759 {
760 cfi_flash_bank_t *cfi_info = bank->driver_priv;
761 target_t *target = cfi_info->target;
762
763 switch(cfi_info->pri_id)
764 {
765 case 1:
766 case 3:
767 return cfi_intel_write_word(bank, word, address);
768 break;
769 default:
770 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
771 break;
772 }
773
774 return ERROR_FLASH_OPERATION_FAILED;
775 }
776
777 int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
778 {
779 cfi_flash_bank_t *cfi_info = bank->driver_priv;
780 target_t *target = cfi_info->target;
781 u32 address = bank->base + offset; /* address of first byte to be programmed */
782 u32 write_p, copy_p;
783 int align; /* number of unaligned bytes */
784 u8 current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being programmed */
785 int i;
786 int retval;
787
788 if (cfi_info->target->state != TARGET_HALTED)
789 {
790 return ERROR_TARGET_NOT_HALTED;
791 }
792
793 if (offset + count > bank->size)
794 return ERROR_FLASH_DST_OUT_OF_BANK;
795
796 if (cfi_info->qry[0] != 'Q')
797 return ERROR_FLASH_BANK_NOT_PROBED;
798
799 /* start at the first byte of the first word (bus_width size) */
800 write_p = address & ~(bank->bus_width - 1);
801 if ((align = address - write_p) != 0)
802 {
803 for (i = 0; i < bank->bus_width; i++)
804 current_word[i] = 0;
805 copy_p = write_p;
806
807 /* copy bytes before the first write address */
808 for (i = 0; i < align; ++i, ++copy_p)
809 {
810 u8 byte;
811 target->type->read_memory(target, copy_p, 1, 1, &byte);
812 cfi_add_byte(bank, current_word, byte);
813 }
814
815 /* add bytes from the buffer */
816 for (; (i < bank->bus_width) && (count > 0); i++)
817 {
818 cfi_add_byte(bank, current_word, *buffer++);
819 count--;
820 copy_p++;
821 }
822
823 /* if the buffer is already finished, copy bytes after the last write address */
824 for (; (count == 0) && (i < bank->bus_width); ++i, ++copy_p)
825 {
826 u8 byte;
827 target->type->read_memory(target, copy_p, 1, 1, &byte);
828 cfi_add_byte(bank, current_word, byte);
829 }
830
831 retval = cfi_write_word(bank, current_word, write_p);
832 if (retval != ERROR_OK)
833 return retval;
834 write_p = copy_p;
835 }
836
837 /* handle blocks of bus_size aligned bytes */
838 switch(cfi_info->pri_id)
839 {
840 /* try block writes (fails without working area) */
841 case 1:
842 case 3:
843 retval = cfi_intel_write_block(bank, buffer, write_p, count);
844 break;
845 default:
846 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
847 break;
848 }
849 if (retval != ERROR_OK)
850 {
851 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
852 {
853 /* fall back to memory writes */
854 while (count > bank->bus_width)
855 {
856 for (i = 0; i < bank->bus_width; i++)
857 current_word[i] = 0;
858
859 for (i = 0; i < bank->bus_width; i++)
860 {
861 cfi_add_byte(bank, current_word, *buffer++);
862 }
863
864 retval = cfi_write_word(bank, current_word, write_p);
865 if (retval != ERROR_OK)
866 return retval;
867 write_p += bank->bus_width;
868 count -= bank->bus_width;
869 }
870 }
871 else
872 return retval;
873 }
874
875 /* handle unaligned tail bytes */
876 if (count > 0)
877 {
878 copy_p = write_p;
879 for (i = 0; i < bank->bus_width; i++)
880 current_word[i] = 0;
881
882 for (i = 0; (i < bank->bus_width) && (count > 0); ++i, ++copy_p)
883 {
884 cfi_add_byte(bank, current_word, *buffer++);
885 count--;
886 }
887 for (; i < bank->bus_width; ++i, ++copy_p)
888 {
889 u8 byte;
890 target->type->read_memory(target, copy_p, 1, 1, &byte);
891 cfi_add_byte(bank, current_word, byte);
892 }
893 retval = cfi_write_word(bank, current_word, write_p);
894 if (retval != ERROR_OK)
895 return retval;
896 }
897
898 /* return to read array mode */
899 cfi_command(bank, 0xf0, current_word);
900 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);
901 cfi_command(bank, 0xff, current_word);
902 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);
903
904 return ERROR_OK;
905 }
906
907 int cfi_probe(struct flash_bank_s *bank)
908 {
909 cfi_flash_bank_t *cfi_info = bank->driver_priv;
910 target_t *target = cfi_info->target;
911 u8 command[8];
912
913
914 cfi_command(bank, 0x98, command);
915 target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
916
917 cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
918 cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
919 cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
920
921 DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
922
923 if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
924 {
925 cfi_command(bank, 0xf0, command);
926 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
927 cfi_command(bank, 0xff, command);
928 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
929 return ERROR_FLASH_BANK_INVALID;
930 }
931
932 cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);
933 cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);
934 cfi_info->alt_id = cfi_query_u16(bank, 0, 0x17);
935 cfi_info->alt_addr = cfi_query_u16(bank, 0, 0x19);
936
937 DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
938
939 cfi_info->vcc_min = cfi_query_u8(bank, 0, 0x1b);
940 cfi_info->vcc_max = cfi_query_u8(bank, 0, 0x1c);
941 cfi_info->vpp_min = cfi_query_u8(bank, 0, 0x1d);
942 cfi_info->vpp_max = cfi_query_u8(bank, 0, 0x1e);
943 cfi_info->word_write_timeout_typ = cfi_query_u8(bank, 0, 0x1f);
944 cfi_info->buf_write_timeout_typ = cfi_query_u8(bank, 0, 0x20);
945 cfi_info->block_erase_timeout_typ = cfi_query_u8(bank, 0, 0x21);
946 cfi_info->chip_erase_timeout_typ = cfi_query_u8(bank, 0, 0x22);
947 cfi_info->word_write_timeout_max = cfi_query_u8(bank, 0, 0x23);
948 cfi_info->buf_write_timeout_max = cfi_query_u8(bank, 0, 0x24);
949 cfi_info->block_erase_timeout_max = cfi_query_u8(bank, 0, 0x25);
950 cfi_info->chip_erase_timeout_max = cfi_query_u8(bank, 0, 0x26);
951
952 DEBUG("Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x",
953 (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
954 (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
955 (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
956 (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
957 DEBUG("typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
958 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
959 DEBUG("max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
960 (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
961 (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
962 (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
963
964 cfi_info->dev_size = cfi_query_u8(bank, 0, 0x27);
965 cfi_info->interface_desc = cfi_query_u16(bank, 0, 0x28);
966 cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);
967 cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);
968
969 DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));
970
971 if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)
972 {
973 WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);
974 }
975
976 if (cfi_info->num_erase_regions)
977 {
978 int i;
979 int num_sectors = 0;
980 int sector = 0;
981 u32 offset = 0;
982 cfi_info->erase_region_info = malloc(4 * cfi_info->num_erase_regions);
983
984 for (i = 0; i < cfi_info->num_erase_regions; i++)
985 {
986 cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));
987 DEBUG("erase region[%i]: %i blocks of size 0x%x", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256);
988
989 num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;
990 }
991
992 bank->num_sectors = num_sectors;
993 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
994 for (i = 0; i < cfi_info->num_erase_regions; i++)
995 {
996 int j;
997 for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++)
998 {
999 bank->sectors[sector].offset = offset;
1000 bank->sectors[sector].size = ((cfi_info->erase_region_info[i] >> 16) * 256) * bank->bus_width / bank->chip_width;
1001 offset += bank->sectors[sector].size;
1002 bank->sectors[sector].is_erased = -1;
1003 bank->sectors[sector].is_protected = -1;
1004 sector++;
1005 }
1006 }
1007 }
1008 else
1009 {
1010 cfi_info->erase_region_info = NULL;
1011 }
1012
1013 switch(cfi_info->pri_id)
1014 {
1015 case 1:
1016 case 3:
1017 cfi_read_intel_pri_ext(bank);
1018 break;
1019 default:
1020 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
1021 break;
1022 }
1023
1024 /* return to read array mode */
1025 cfi_command(bank, 0xf0, command);
1026 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
1027 cfi_command(bank, 0xff, command);
1028 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
1029
1030 return ERROR_OK;
1031 }
1032
1033 int cfi_erase_check(struct flash_bank_s *bank)
1034 {
1035 cfi_flash_bank_t *cfi_info = bank->driver_priv;
1036 target_t *target = cfi_info->target;
1037 int i;
1038 int retval;
1039
1040 if (!cfi_info->erase_check_algorithm)
1041 {
1042 u32 erase_check_code[] =
1043 {
1044 0xe4d03001, /* ldrb r3, [r0], #1 */
1045 0xe0022003, /* and r2, r2, r3 */
1046 0xe2511001, /* subs r1, r1, #1 */
1047 0x1afffffb, /* b -4 */
1048 0xeafffffe /* b 0 */
1049 };
1050
1051 /* make sure we have a working area */
1052 if (target_alloc_working_area(target, 20, &cfi_info->erase_check_algorithm) != ERROR_OK)
1053 {
1054 WARNING("no working area available, falling back to slow memory reads");
1055 }
1056 else
1057 {
1058 u8 erase_check_code_buf[5 * 4];
1059
1060 for (i = 0; i < 5; i++)
1061 target_buffer_set_u32(target, erase_check_code_buf + (i*4), erase_check_code[i]);
1062
1063 /* write algorithm code to working area */
1064 target->type->write_memory(target, cfi_info->erase_check_algorithm->address, 4, 5, erase_check_code_buf);
1065 }
1066 }
1067
1068 if (!cfi_info->erase_check_algorithm)
1069 {
1070 u32 *buffer = malloc(4096);
1071
1072 for (i = 0; i < bank->num_sectors; i++)
1073 {
1074 u32 address = bank->base + bank->sectors[i].offset;
1075 u32 size = bank->sectors[i].size;
1076 u32 check = 0xffffffffU;
1077 int erased = 1;
1078
1079 while (size > 0)
1080 {
1081 u32 thisrun_size = (size > 4096) ? 4096 : size;
1082 int j;
1083
1084 target->type->read_memory(target, address, 4, thisrun_size / 4, (u8*)buffer);
1085
1086 for (j = 0; j < thisrun_size / 4; j++)
1087 check &= buffer[j];
1088
1089 if (check != 0xffffffff)
1090 {
1091 erased = 0;
1092 break;
1093 }
1094
1095 size -= thisrun_size;
1096 address += thisrun_size;
1097 }
1098
1099 bank->sectors[i].is_erased = erased;
1100 }
1101
1102 free(buffer);
1103 }
1104 else
1105 {
1106 for (i = 0; i < bank->num_sectors; i++)
1107 {
1108 u32 address = bank->base + bank->sectors[i].offset;
1109 u32 size = bank->sectors[i].size;
1110
1111 reg_param_t reg_params[3];
1112 armv4_5_algorithm_t armv4_5_info;
1113
1114 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
1115 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
1116 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
1117
1118 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1119 buf_set_u32(reg_params[0].value, 0, 32, address);
1120
1121 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1122 buf_set_u32(reg_params[1].value, 0, 32, size);
1123
1124 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
1125 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
1126
1127 if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, cfi_info->erase_check_algorithm->address, cfi_info->erase_check_algorithm->address + 0x10, 10000, &armv4_5_info)) != ERROR_OK)
1128 return ERROR_FLASH_OPERATION_FAILED;
1129
1130 if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)
1131 bank->sectors[i].is_erased = 1;
1132 else
1133 bank->sectors[i].is_erased = 0;
1134
1135 destroy_reg_param(&reg_params[0]);
1136 destroy_reg_param(&reg_params[1]);
1137 destroy_reg_param(&reg_params[2]);
1138 }
1139 }
1140
1141 return ERROR_OK;
1142 }
1143
1144 int cfi_intel_protect_check(struct flash_bank_s *bank)
1145 {
1146 cfi_flash_bank_t *cfi_info = bank->driver_priv;
1147 cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
1148 target_t *target = cfi_info->target;
1149 u8 command[CFI_MAX_BUS_WIDTH];
1150 int i;
1151
1152 /* check if block lock bits are supported on this device */
1153 if (!(pri_ext->blk_status_reg_mask & 0x1))
1154 return ERROR_FLASH_OPERATION_FAILED;
1155
1156 cfi_command(bank, 0x90, command);
1157 target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
1158
1159 for (i = 0; i < bank->num_sectors; i++)
1160 {
1161 u8 block_status = cfi_get_u8(bank, i, 0x2);
1162
1163 if (block_status & 1)
1164 bank->sectors[i].is_protected = 1;
1165 else
1166 bank->sectors[i].is_protected = 0;
1167 }
1168
1169 cfi_command(bank, 0xff, command);
1170 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
1171
1172 return ERROR_OK;
1173 }
1174
1175 int cfi_protect_check(struct flash_bank_s *bank)
1176 {
1177 cfi_flash_bank_t *cfi_info = bank->driver_priv;
1178 target_t *target = cfi_info->target;
1179
1180 if (cfi_info->qry[0] != 'Q')
1181 return ERROR_FLASH_BANK_NOT_PROBED;
1182
1183 switch(cfi_info->pri_id)
1184 {
1185 case 1:
1186 case 3:
1187 return cfi_intel_protect_check(bank);
1188 break;
1189 default:
1190 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
1191 break;
1192 }
1193
1194 return ERROR_OK;
1195 }
1196
1197 int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size)
1198 {
1199 int printed;
1200 cfi_flash_bank_t *cfi_info = bank->driver_priv;
1201
1202 if (cfi_info->qry[0] == -1)
1203 {
1204 printed = snprintf(buf, buf_size, "\ncfi flash bank not probed yet\n");
1205 return ERROR_OK;
1206 }
1207
1208 printed = snprintf(buf, buf_size, "\ncfi information:\n");
1209 buf += printed;
1210 buf_size -= printed;
1211
1212 printed = snprintf(buf, buf_size, "qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x\n", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
1213 buf += printed;
1214 buf_size -= printed;
1215
1216 printed = snprintf(buf, buf_size, "Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x\n", (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
1217 (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
1218 (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
1219 (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
1220 buf += printed;
1221 buf_size -= printed;
1222
1223 printed = snprintf(buf, buf_size, "typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u\n", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
1224 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
1225 buf += printed;
1226 buf_size -= printed;
1227
1228 printed = snprintf(buf, buf_size, "max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u\n", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
1229 (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
1230 (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
1231 (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
1232 buf += printed;
1233 buf_size -= printed;
1234
1235 printed = snprintf(buf, buf_size, "size: 0x%x, interface desc: %i, max buffer write size: %x\n", 1 << cfi_info->dev_size, cfi_info->interface_desc, cfi_info->max_buf_write_size);
1236 buf += printed;
1237 buf_size -= printed;
1238
1239 switch(cfi_info->pri_id)
1240 {
1241 case 1:
1242 case 3:
1243 cfi_intel_info(bank, buf, buf_size);
1244 break;
1245 default:
1246 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
1247 break;
1248 }
1249
1250 return ERROR_OK;
1251 }

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)