1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
24 #include "replacements.h"
32 #include "algorithm.h"
33 #include "binarybuffer.h"
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
);
50 int cfi_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
52 #define CFI_MAX_BUS_WIDTH 4
53 #define CFI_MAX_CHIP_WIDTH 4
55 flash_driver_t cfi_flash
=
58 .register_commands
= cfi_register_commands
,
59 .flash_bank_command
= cfi_flash_bank_command
,
61 .protect
= cfi_protect
,
64 .erase_check
= cfi_erase_check
,
65 .protect_check
= cfi_protect_check
,
69 inline u32
flash_address(flash_bank_t
*bank
, int sector
, u32 offset
)
71 /* while the sector list isn't built, only accesses to sector 0 work */
73 return bank
->base
+ offset
* bank
->bus_width
;
78 ERROR("BUG: sector list not yet built");
81 return bank
->base
+ bank
->sectors
[sector
].offset
+ offset
* bank
->bus_width
;
86 void cfi_command(flash_bank_t
*bank
, u8 cmd
, u8
*cmd_buf
)
88 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
91 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
93 for (i
= bank
->bus_width
; i
> 0; i
--)
95 *cmd_buf
++ = (i
& (bank
->chip_width
- 1)) ? 0x0 : cmd
;
100 for (i
= 1; i
<= bank
->bus_width
; i
++)
102 *cmd_buf
++ = (i
& (bank
->chip_width
- 1)) ? 0x0 : cmd
;
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
111 u8
cfi_query_u8(flash_bank_t
*bank
, int sector
, u32 offset
)
113 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
114 target_t
*target
= cfi_info
->target
;
115 u8 data
[CFI_MAX_BUS_WIDTH
];
117 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 1, data
);
119 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
122 return data
[bank
->bus_width
- 1];
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
129 u8
cfi_get_u8(flash_bank_t
*bank
, int sector
, u32 offset
)
131 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
132 target_t
*target
= cfi_info
->target
;
133 u8 data
[CFI_MAX_BUS_WIDTH
];
136 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 1, data
);
138 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
140 for (i
= 0; i
< bank
->bus_width
/ bank
->chip_width
; i
++)
148 for (i
= 0; i
< bank
->bus_width
/ bank
->chip_width
; i
++)
149 value
|= data
[bank
->bus_width
- 1 - i
];
155 u16
cfi_query_u16(flash_bank_t
*bank
, int sector
, u32 offset
)
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];
161 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 2, data
);
163 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
164 return data
[0] | data
[bank
->bus_width
] << 8;
166 return data
[bank
->bus_width
- 1] | data
[(2 * bank
->bus_width
) - 1] << 8;
169 u32
cfi_query_u32(flash_bank_t
*bank
, int sector
, u32 offset
)
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];
175 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 4, data
);
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;
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;
184 void cfi_intel_clear_status_register(flash_bank_t
*bank
)
186 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
187 target_t
*target
= cfi_info
->target
;
190 if (target
->state
!= TARGET_HALTED
)
192 ERROR("BUG: attempted to clear status register while target wasn't halted");
196 cfi_command(bank
, 0x50, command
);
197 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
200 u8
cfi_intel_wait_status_busy(flash_bank_t
*bank
, int timeout
)
204 while ((!((status
= cfi_get_u8(bank
, 0, 0x0)) & 0x80)) && (timeout
-- > 0))
206 DEBUG("status: 0x%x", status
);
210 DEBUG("status: 0x%x", status
);
212 if ((status
& 0x80) != 0x80)
214 ERROR("timeout while waiting for WSM to become ready");
216 else if (status
!= 0x80)
218 ERROR("status register: 0x%x", status
);
220 ERROR("Block Lock-Bit Detected, Operation Abort");
222 ERROR("Program suspended");
224 ERROR("Low Programming Voltage Detected, Operation Aborted");
226 ERROR("Program Error / Error in Setting Lock-Bit");
228 ERROR("Error in Block Erasure or Clear Lock-Bits");
230 ERROR("Block Erase Suspended");
232 cfi_intel_clear_status_register(bank
);
237 int cfi_read_intel_pri_ext(flash_bank_t
*bank
)
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
;
244 cfi_info
->pri_ext
= pri_ext
;
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);
250 if ((pri_ext
->pri
[0] != 'P') || (pri_ext
->pri
[1] != 'R') || (pri_ext
->pri
[2] != 'I'))
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
;
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);
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
);
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);
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
);
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);
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);
277 pri_ext
->num_protection_fields
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0xe);
278 if (pri_ext
->num_protection_fields
!= 1)
280 WARNING("expected one protection register field, but found %i", pri_ext
->num_protection_fields
);
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);
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
);
292 int cfi_intel_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
295 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
296 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
298 printed
= snprintf(buf
, buf_size
, "\nintel primary algorithm extend information:\n");
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
);
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
);
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);
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
);
321 int cfi_register_commands(struct command_context_s
*cmd_ctx
)
323 command_t
*cfi_cmd
= register_command(cmd_ctx
, NULL
, "cfi", NULL
, COMMAND_ANY
, NULL
);
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>");
331 /* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#>
333 int cfi_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
335 cfi_flash_bank_t
*cfi_info
;
339 WARNING("incomplete flash_bank cfi configuration");
340 return ERROR_FLASH_BANK_INVALID
;
343 if ((strtoul(args
[4], NULL
, 0) > CFI_MAX_CHIP_WIDTH
)
344 || (strtoul(args
[3], NULL
, 0) > CFI_MAX_BUS_WIDTH
))
346 ERROR("chip and bus width have to specified in byte");
347 return ERROR_FLASH_BANK_INVALID
;
350 cfi_info
= malloc(sizeof(cfi_flash_bank_t
));
351 bank
->driver_priv
= cfi_info
;
353 cfi_info
->target
= get_target_by_num(strtoul(args
[5], NULL
, 0));
354 if (!cfi_info
->target
)
356 ERROR("no target '%i' configured", args
[5]);
360 cfi_info
->write_algorithm
= NULL
;
362 /* bank wasn't probed yet */
363 cfi_info
->qry
[0] = -1;
368 int cfi_intel_erase(struct flash_bank_s
*bank
, int first
, int last
)
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
;
376 cfi_intel_clear_status_register(bank
);
378 for (i
= first
; i
<= last
; i
++)
380 cfi_command(bank
, 0x20, command
);
381 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
383 cfi_command(bank
, 0xd0, command
);
384 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
386 if (cfi_intel_wait_status_busy(bank
, 1000 * (1 << cfi_info
->block_erase_timeout_typ
)) == 0x80)
387 bank
->sectors
[i
].is_erased
= 1;
390 cfi_command(bank
, 0xff, command
);
391 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
393 ERROR("couldn't erase block %i of flash bank at base 0x%x", i
, bank
->base
);
394 return ERROR_FLASH_OPERATION_FAILED
;
398 cfi_command(bank
, 0xff, command
);
399 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
404 int cfi_erase(struct flash_bank_s
*bank
, int first
, int last
)
406 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
408 if (cfi_info
->target
->state
!= TARGET_HALTED
)
410 return ERROR_TARGET_NOT_HALTED
;
413 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
415 return ERROR_FLASH_SECTOR_INVALID
;
418 if (cfi_info
->qry
[0] != 'Q')
419 return ERROR_FLASH_BANK_NOT_PROBED
;
421 switch(cfi_info
->pri_id
)
425 return cfi_intel_erase(bank
, first
, last
);
428 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
435 int cfi_intel_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
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
;
443 /* if the device supports neither legacy lock/unlock (bit 3) nor
444 * instant individual block locking (bit 5).
446 if (!(pri_ext
->feature_support
& 0x28))
447 return ERROR_FLASH_OPERATION_FAILED
;
449 cfi_intel_clear_status_register(bank
);
451 for (i
= first
; i
<= last
; i
++)
453 cfi_command(bank
, 0x60, command
);
454 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
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;
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;
468 /* Clear lock bits operation may take up to 1.4s */
469 cfi_intel_wait_status_busy(bank
, 1400);
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
475 if ((!set
) && (!(pri_ext
->feature_support
& 0x20)))
477 for (i
= 0; i
< bank
->num_sectors
; i
++)
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)
484 cfi_command(bank
, 0x01, command
);
485 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
488 cfi_intel_wait_status_busy(bank
, 100);
492 cfi_command(bank
, 0xff, command
);
493 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
498 int cfi_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
500 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
502 if (cfi_info
->target
->state
!= TARGET_HALTED
)
504 return ERROR_TARGET_NOT_HALTED
;
507 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
509 return ERROR_FLASH_SECTOR_INVALID
;
512 if (cfi_info
->qry
[0] != 'Q')
513 return ERROR_FLASH_BANK_NOT_PROBED
;
515 switch(cfi_info
->pri_id
)
519 cfi_intel_protect(bank
, set
, first
, last
);
522 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
529 void cfi_add_byte(struct flash_bank_s
*bank
, u8
*word
, u8 byte
)
531 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
532 target_t
*target
= cfi_info
->target
;
536 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
539 for (i
= 0; i
< bank
->bus_width
- 1; i
++)
540 word
[i
] = word
[i
+ 1];
541 word
[bank
->bus_width
- 1] = byte
;
546 for (i
= bank
->bus_width
- 1; i
> 0; i
--)
547 word
[i
] = word
[i
- 1];
552 int cfi_intel_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 address
, u32 count
)
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
];
567 /* algorithm register usage:
568 * r0: source address (in RAM)
569 * r1: target address (in Flash)
571 * r3: flash write command
572 * r4: status byte (returned to host)
573 * r5: busy test pattern
574 * r6: error test pattern
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 */
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 */
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 */
628 cfi_intel_clear_status_register(bank
);
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
;
634 /* flash write code */
635 if (!cfi_info
->write_algorithm
)
637 if (target_alloc_working_area(target
, 4 * 14, &cfi_info
->write_algorithm
) != ERROR_OK
)
639 WARNING("no working area available, can't do block memory writes");
640 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
643 /* write algorithm code to working area */
644 if (bank
->bus_width
== 1)
646 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_8_code
);
648 else if (bank
->bus_width
== 2)
650 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_16_code
);
652 else if (bank
->bus_width
== 4)
654 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_32_code
);
658 return ERROR_FLASH_OPERATION_FAILED
;
662 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
665 if (buffer_size
<= 256)
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
);
671 WARNING("no large enough working area available, can't do block memory writes");
672 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
676 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
677 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
678 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
679 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
680 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
681 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
682 init_reg_param(®_params
[6], "r6", 32, PARAM_OUT
);
684 cfi_command(bank
, 0x40, write_command
);
685 cfi_command(bank
, 0x80, busy_pattern
);
686 cfi_command(bank
, 0x7f, error_pattern
);
690 u32 thisrun_count
= (count
> buffer_size
) ? buffer_size
: count
;
692 target_write_buffer(target
, source
->address
, thisrun_count
, buffer
);
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));
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
)
703 cfi_intel_clear_status_register(bank
);
704 return ERROR_FLASH_OPERATION_FAILED
;
707 if (buf_get_u32(reg_params
[4].value
, 0, 32) & target_buffer_get_u32(target
, error_pattern
))
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
;
715 buffer
+= thisrun_count
;
716 address
+= thisrun_count
;
717 count
-= thisrun_count
;
720 target_free_working_area(target
, source
);
722 destroy_reg_param(®_params
[0]);
723 destroy_reg_param(®_params
[1]);
724 destroy_reg_param(®_params
[2]);
725 destroy_reg_param(®_params
[3]);
726 destroy_reg_param(®_params
[4]);
727 destroy_reg_param(®_params
[5]);
728 destroy_reg_param(®_params
[6]);
733 int cfi_intel_write_word(struct flash_bank_s
*bank
, u8
*word
, u32 address
)
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
;
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
);
744 target
->type
->write_memory(target
, address
, bank
->bus_width
, 1, word
);
746 if (cfi_intel_wait_status_busy(bank
, 1000 * (1 << cfi_info
->word_write_timeout_max
)) != 0x80)
748 cfi_command(bank
, 0xff, command
);
749 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
751 ERROR("couldn't write word at base 0x%x, address %x", bank
->base
, address
);
752 return ERROR_FLASH_OPERATION_FAILED
;
758 int cfi_write_word(struct flash_bank_s
*bank
, u8
*word
, u32 address
)
760 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
761 target_t
*target
= cfi_info
->target
;
763 switch(cfi_info
->pri_id
)
767 return cfi_intel_write_word(bank
, word
, address
);
770 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
774 return ERROR_FLASH_OPERATION_FAILED
;
777 int cfi_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
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 */
783 int align
; /* number of unaligned bytes */
784 u8 current_word
[CFI_MAX_BUS_WIDTH
* 4]; /* word (bus_width size) currently being programmed */
788 if (cfi_info
->target
->state
!= TARGET_HALTED
)
790 return ERROR_TARGET_NOT_HALTED
;
793 if (offset
+ count
> bank
->size
)
794 return ERROR_FLASH_DST_OUT_OF_BANK
;
796 if (cfi_info
->qry
[0] != 'Q')
797 return ERROR_FLASH_BANK_NOT_PROBED
;
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)
803 for (i
= 0; i
< bank
->bus_width
; i
++)
807 /* copy bytes before the first write address */
808 for (i
= 0; i
< align
; ++i
, ++copy_p
)
811 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
812 cfi_add_byte(bank
, current_word
, byte
);
815 /* add bytes from the buffer */
816 for (; (i
< bank
->bus_width
) && (count
> 0); i
++)
818 cfi_add_byte(bank
, current_word
, *buffer
++);
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
)
827 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
828 cfi_add_byte(bank
, current_word
, byte
);
831 retval
= cfi_write_word(bank
, current_word
, write_p
);
832 if (retval
!= ERROR_OK
)
837 /* handle blocks of bus_size aligned bytes */
838 switch(cfi_info
->pri_id
)
840 /* try block writes (fails without working area) */
843 retval
= cfi_intel_write_block(bank
, buffer
, write_p
, count
);
846 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
849 if (retval
!= ERROR_OK
)
851 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
853 /* fall back to memory writes */
854 while (count
> bank
->bus_width
)
856 for (i
= 0; i
< bank
->bus_width
; i
++)
859 for (i
= 0; i
< bank
->bus_width
; i
++)
861 cfi_add_byte(bank
, current_word
, *buffer
++);
864 retval
= cfi_write_word(bank
, current_word
, write_p
);
865 if (retval
!= ERROR_OK
)
867 write_p
+= bank
->bus_width
;
868 count
-= bank
->bus_width
;
875 /* handle unaligned tail bytes */
879 for (i
= 0; i
< bank
->bus_width
; i
++)
882 for (i
= 0; (i
< bank
->bus_width
) && (count
> 0); ++i
, ++copy_p
)
884 cfi_add_byte(bank
, current_word
, *buffer
++);
887 for (; i
< bank
->bus_width
; ++i
, ++copy_p
)
890 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
891 cfi_add_byte(bank
, current_word
, byte
);
893 retval
= cfi_write_word(bank
, current_word
, write_p
);
894 if (retval
!= ERROR_OK
)
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
);
907 int cfi_probe(struct flash_bank_s
*bank
)
909 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
910 target_t
*target
= cfi_info
->target
;
914 cfi_command(bank
, 0x98, command
);
915 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
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);
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]);
923 if ((cfi_info
->qry
[0] != 'Q') || (cfi_info
->qry
[1] != 'R') || (cfi_info
->qry
[2] != 'Y'))
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
;
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);
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
);
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);
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
));
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);
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
));
971 if (((1 << cfi_info
->dev_size
) * bank
->bus_width
/ bank
->chip_width
) != bank
->size
)
973 WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank
->size
, 1 << cfi_info
->dev_size
);
976 if (cfi_info
->num_erase_regions
)
982 cfi_info
->erase_region_info
= malloc(4 * cfi_info
->num_erase_regions
);
984 for (i
= 0; i
< cfi_info
->num_erase_regions
; i
++)
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);
989 num_sectors
+= (cfi_info
->erase_region_info
[i
] & 0xffff) + 1;
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
++)
997 for (j
= 0; j
< (cfi_info
->erase_region_info
[i
] & 0xffff) + 1; j
++)
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;
1010 cfi_info
->erase_region_info
= NULL
;
1013 switch(cfi_info
->pri_id
)
1017 cfi_read_intel_pri_ext(bank
);
1020 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
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
);
1033 int cfi_erase_check(struct flash_bank_s
*bank
)
1035 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1036 target_t
*target
= cfi_info
->target
;
1040 if (!cfi_info
->erase_check_algorithm
)
1042 u32 erase_check_code
[] =
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 */
1051 /* make sure we have a working area */
1052 if (target_alloc_working_area(target
, 20, &cfi_info
->erase_check_algorithm
) != ERROR_OK
)
1054 WARNING("no working area available, falling back to slow memory reads");
1058 u8 erase_check_code_buf
[5 * 4];
1060 for (i
= 0; i
< 5; i
++)
1061 target_buffer_set_u32(target
, erase_check_code_buf
+ (i
*4), erase_check_code
[i
]);
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
);
1068 if (!cfi_info
->erase_check_algorithm
)
1070 u32
*buffer
= malloc(4096);
1072 for (i
= 0; i
< bank
->num_sectors
; i
++)
1074 u32 address
= bank
->base
+ bank
->sectors
[i
].offset
;
1075 u32 size
= bank
->sectors
[i
].size
;
1076 u32 check
= 0xffffffffU
;
1081 u32 thisrun_size
= (size
> 4096) ? 4096 : size
;
1084 target
->type
->read_memory(target
, address
, 4, thisrun_size
/ 4, (u8
*)buffer
);
1086 for (j
= 0; j
< thisrun_size
/ 4; j
++)
1089 if (check
!= 0xffffffff)
1095 size
-= thisrun_size
;
1096 address
+= thisrun_size
;
1099 bank
->sectors
[i
].is_erased
= erased
;
1106 for (i
= 0; i
< bank
->num_sectors
; i
++)
1108 u32 address
= bank
->base
+ bank
->sectors
[i
].offset
;
1109 u32 size
= bank
->sectors
[i
].size
;
1111 reg_param_t reg_params
[3];
1112 armv4_5_algorithm_t armv4_5_info
;
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
;
1118 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1119 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1121 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1122 buf_set_u32(reg_params
[1].value
, 0, 32, size
);
1124 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1125 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
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
;
1130 if (buf_get_u32(reg_params
[2].value
, 0, 32) == 0xff)
1131 bank
->sectors
[i
].is_erased
= 1;
1133 bank
->sectors
[i
].is_erased
= 0;
1135 destroy_reg_param(®_params
[0]);
1136 destroy_reg_param(®_params
[1]);
1137 destroy_reg_param(®_params
[2]);
1144 int cfi_intel_protect_check(struct flash_bank_s
*bank
)
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
];
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
;
1156 cfi_command(bank
, 0x90, command
);
1157 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
1159 for (i
= 0; i
< bank
->num_sectors
; i
++)
1161 u8 block_status
= cfi_get_u8(bank
, i
, 0x2);
1163 if (block_status
& 1)
1164 bank
->sectors
[i
].is_protected
= 1;
1166 bank
->sectors
[i
].is_protected
= 0;
1169 cfi_command(bank
, 0xff, command
);
1170 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1175 int cfi_protect_check(struct flash_bank_s
*bank
)
1177 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1178 target_t
*target
= cfi_info
->target
;
1180 if (cfi_info
->qry
[0] != 'Q')
1181 return ERROR_FLASH_BANK_NOT_PROBED
;
1183 switch(cfi_info
->pri_id
)
1187 return cfi_intel_protect_check(bank
);
1190 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
1197 int cfi_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
1200 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1202 if (cfi_info
->qry
[0] == -1)
1204 printed
= snprintf(buf
, buf_size
, "\ncfi flash bank not probed yet\n");
1208 printed
= snprintf(buf
, buf_size
, "\ncfi information:\n");
1210 buf_size
-= printed
;
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
);
1214 buf_size
-= printed
;
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);
1221 buf_size
-= printed
;
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
);
1226 buf_size
-= printed
;
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
));
1233 buf_size
-= printed
;
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
);
1237 buf_size
-= printed
;
1239 switch(cfi_info
->pri_id
)
1243 cfi_intel_info(bank
, buf
, buf_size
);
1246 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
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)