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 /* clear whole buffer, to ensure bits that exceed the bus_width
94 for (i
= 0; i
< CFI_MAX_BUS_WIDTH
; i
++)
97 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
99 for (i
= bank
->bus_width
; i
> 0; i
--)
101 *cmd_buf
++ = (i
& (bank
->chip_width
- 1)) ? 0x0 : cmd
;
106 for (i
= 1; i
<= bank
->bus_width
; i
++)
108 *cmd_buf
++ = (i
& (bank
->chip_width
- 1)) ? 0x0 : cmd
;
113 /* read unsigned 8-bit value from the bank
114 * flash banks are expected to be made of similar chips
115 * the query result should be the same for all
117 u8
cfi_query_u8(flash_bank_t
*bank
, int sector
, u32 offset
)
119 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
120 target_t
*target
= cfi_info
->target
;
121 u8 data
[CFI_MAX_BUS_WIDTH
];
123 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 1, data
);
125 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
128 return data
[bank
->bus_width
- 1];
131 /* read unsigned 8-bit value from the bank
132 * in case of a bank made of multiple chips,
133 * the individual values are ORed
135 u8
cfi_get_u8(flash_bank_t
*bank
, int sector
, u32 offset
)
137 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
138 target_t
*target
= cfi_info
->target
;
139 u8 data
[CFI_MAX_BUS_WIDTH
];
142 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 1, data
);
144 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
146 for (i
= 0; i
< bank
->bus_width
/ bank
->chip_width
; i
++)
154 for (i
= 0; i
< bank
->bus_width
/ bank
->chip_width
; i
++)
155 value
|= data
[bank
->bus_width
- 1 - i
];
161 u16
cfi_query_u16(flash_bank_t
*bank
, int sector
, u32 offset
)
163 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
164 target_t
*target
= cfi_info
->target
;
165 u8 data
[CFI_MAX_BUS_WIDTH
* 2];
167 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 2, data
);
169 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
170 return data
[0] | data
[bank
->bus_width
] << 8;
172 return data
[bank
->bus_width
- 1] | data
[(2 * bank
->bus_width
) - 1] << 8;
175 u32
cfi_query_u32(flash_bank_t
*bank
, int sector
, u32 offset
)
177 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
178 target_t
*target
= cfi_info
->target
;
179 u8 data
[CFI_MAX_BUS_WIDTH
* 4];
181 target
->type
->read_memory(target
, flash_address(bank
, sector
, offset
), bank
->bus_width
, 4, data
);
183 if (cfi_info
->target
->endianness
== TARGET_LITTLE_ENDIAN
)
184 return data
[0] | data
[bank
->bus_width
] << 8 | data
[bank
->bus_width
* 2] << 16 | data
[bank
->bus_width
* 3] << 24;
186 return data
[bank
->bus_width
- 1] | data
[(2* bank
->bus_width
) - 1] << 8 |
187 data
[(3 * bank
->bus_width
) - 1] << 16 | data
[(4 * bank
->bus_width
) - 1] << 24;
190 void cfi_intel_clear_status_register(flash_bank_t
*bank
)
192 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
193 target_t
*target
= cfi_info
->target
;
196 if (target
->state
!= TARGET_HALTED
)
198 ERROR("BUG: attempted to clear status register while target wasn't halted");
202 cfi_command(bank
, 0x50, command
);
203 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
206 u8
cfi_intel_wait_status_busy(flash_bank_t
*bank
, int timeout
)
210 while ((!((status
= cfi_get_u8(bank
, 0, 0x0)) & 0x80)) && (timeout
-- > 0))
212 DEBUG("status: 0x%x", status
);
216 /* mask out bit 0 (reserved) */
217 status
= status
& 0xfe;
219 DEBUG("status: 0x%x", status
);
221 if ((status
& 0x80) != 0x80)
223 ERROR("timeout while waiting for WSM to become ready");
225 else if (status
!= 0x80)
227 ERROR("status register: 0x%x", status
);
229 ERROR("Block Lock-Bit Detected, Operation Abort");
231 ERROR("Program suspended");
233 ERROR("Low Programming Voltage Detected, Operation Aborted");
235 ERROR("Program Error / Error in Setting Lock-Bit");
237 ERROR("Error in Block Erasure or Clear Lock-Bits");
239 ERROR("Block Erase Suspended");
241 cfi_intel_clear_status_register(bank
);
246 int cfi_read_intel_pri_ext(flash_bank_t
*bank
)
248 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
249 cfi_intel_pri_ext_t
*pri_ext
= malloc(sizeof(cfi_intel_pri_ext_t
));
250 target_t
*target
= cfi_info
->target
;
253 cfi_info
->pri_ext
= pri_ext
;
255 pri_ext
->pri
[0] = cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0);
256 pri_ext
->pri
[1] = cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 1);
257 pri_ext
->pri
[2] = cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 2);
259 if ((pri_ext
->pri
[0] != 'P') || (pri_ext
->pri
[1] != 'R') || (pri_ext
->pri
[2] != 'I'))
261 cfi_command(bank
, 0xf0, command
);
262 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
263 cfi_command(bank
, 0xff, command
);
264 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
265 return ERROR_FLASH_BANK_INVALID
;
268 pri_ext
->major_version
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 3);
269 pri_ext
->minor_version
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 4);
271 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
);
273 pri_ext
->feature_support
= cfi_query_u32(bank
, 0, cfi_info
->pri_addr
+ 5);
274 pri_ext
->suspend_cmd_support
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 9);
275 pri_ext
->blk_status_reg_mask
= cfi_query_u16(bank
, 0, cfi_info
->pri_addr
+ 0xa);
277 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
);
279 pri_ext
->vcc_optimal
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0xc);
280 pri_ext
->vpp_optimal
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0xd);
282 DEBUG("Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x",
283 (pri_ext
->vcc_optimal
& 0xf0) >> 4, pri_ext
->vcc_optimal
& 0x0f,
284 (pri_ext
->vpp_optimal
& 0xf0) >> 4, pri_ext
->vpp_optimal
& 0x0f);
286 pri_ext
->num_protection_fields
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0xe);
287 if (pri_ext
->num_protection_fields
!= 1)
289 WARNING("expected one protection register field, but found %i", pri_ext
->num_protection_fields
);
292 pri_ext
->prot_reg_addr
= cfi_query_u16(bank
, 0, cfi_info
->pri_addr
+ 0xf);
293 pri_ext
->fact_prot_reg_size
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0x11);
294 pri_ext
->user_prot_reg_size
= cfi_query_u8(bank
, 0, cfi_info
->pri_addr
+ 0x12);
296 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
);
301 int cfi_intel_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
304 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
305 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
307 printed
= snprintf(buf
, buf_size
, "\nintel primary algorithm extend information:\n");
311 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
);
315 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
);
319 printed
= snprintf(buf
, buf_size
, "Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x\n",
320 (pri_ext
->vcc_optimal
& 0xf0) >> 4, pri_ext
->vcc_optimal
& 0x0f,
321 (pri_ext
->vpp_optimal
& 0xf0) >> 4, pri_ext
->vpp_optimal
& 0x0f);
325 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
);
330 int cfi_register_commands(struct command_context_s
*cmd_ctx
)
332 /*command_t *cfi_cmd = */register_command(cmd_ctx
, NULL
, "cfi", NULL
, COMMAND_ANY
, NULL
);
334 register_command(cmd_ctx, cfi_cmd, "part_id", cfi_handle_part_id_command, COMMAND_EXEC,
335 "print part id of cfi flash bank <num>");
340 /* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#>
342 int cfi_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
344 cfi_flash_bank_t
*cfi_info
;
348 WARNING("incomplete flash_bank cfi configuration");
349 return ERROR_FLASH_BANK_INVALID
;
352 if ((strtoul(args
[4], NULL
, 0) > CFI_MAX_CHIP_WIDTH
)
353 || (strtoul(args
[3], NULL
, 0) > CFI_MAX_BUS_WIDTH
))
355 ERROR("chip and bus width have to specified in byte");
356 return ERROR_FLASH_BANK_INVALID
;
359 cfi_info
= malloc(sizeof(cfi_flash_bank_t
));
360 bank
->driver_priv
= cfi_info
;
362 cfi_info
->target
= get_target_by_num(strtoul(args
[5], NULL
, 0));
363 if (!cfi_info
->target
)
365 ERROR("no target '%s' configured", args
[5]);
369 cfi_info
->write_algorithm
= NULL
;
371 /* bank wasn't probed yet */
372 cfi_info
->qry
[0] = -1;
377 int cfi_intel_erase(struct flash_bank_s
*bank
, int first
, int last
)
379 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
380 target_t
*target
= cfi_info
->target
;
384 cfi_intel_clear_status_register(bank
);
386 for (i
= first
; i
<= last
; i
++)
388 cfi_command(bank
, 0x20, command
);
389 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
391 cfi_command(bank
, 0xd0, command
);
392 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
394 if (cfi_intel_wait_status_busy(bank
, 1000 * (1 << cfi_info
->block_erase_timeout_typ
)) == 0x80)
395 bank
->sectors
[i
].is_erased
= 1;
398 cfi_command(bank
, 0xff, command
);
399 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
401 ERROR("couldn't erase block %i of flash bank at base 0x%x", i
, bank
->base
);
402 return ERROR_FLASH_OPERATION_FAILED
;
406 cfi_command(bank
, 0xff, command
);
407 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
412 int cfi_erase(struct flash_bank_s
*bank
, int first
, int last
)
414 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
416 if (cfi_info
->target
->state
!= TARGET_HALTED
)
418 return ERROR_TARGET_NOT_HALTED
;
421 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
423 return ERROR_FLASH_SECTOR_INVALID
;
426 if (cfi_info
->qry
[0] != 'Q')
427 return ERROR_FLASH_BANK_NOT_PROBED
;
429 switch(cfi_info
->pri_id
)
433 return cfi_intel_erase(bank
, first
, last
);
436 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
443 int cfi_intel_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
445 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
446 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
447 target_t
*target
= cfi_info
->target
;
452 /* if the device supports neither legacy lock/unlock (bit 3) nor
453 * instant individual block locking (bit 5).
455 if (!(pri_ext
->feature_support
& 0x28))
456 return ERROR_FLASH_OPERATION_FAILED
;
458 cfi_intel_clear_status_register(bank
);
460 for (i
= first
; i
<= last
; i
++)
462 cfi_command(bank
, 0x60, command
);
463 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank
, i
, 0x0), target_buffer_get_u32(target
, command
));
464 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
467 cfi_command(bank
, 0x01, command
);
468 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank
, i
, 0x0), target_buffer_get_u32(target
, command
));
469 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
470 bank
->sectors
[i
].is_protected
= 1;
474 cfi_command(bank
, 0xd0, command
);
475 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank
, i
, 0x0), target_buffer_get_u32(target
, command
));
476 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
477 bank
->sectors
[i
].is_protected
= 0;
480 /* instant individual block locking doesn't require reading of the status register */
481 if (!(pri_ext
->feature_support
& 0x20))
483 /* Clear lock bits operation may take up to 1.4s */
484 cfi_intel_wait_status_busy(bank
, 1400);
489 /* read block lock bit, to verify status */
490 cfi_command(bank
, 0x90, command
);
491 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
492 block_status
= cfi_get_u8(bank
, i
, 0x2);
494 if ((block_status
& 0x1) != set
)
496 ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set
, block_status
);
497 cfi_command(bank
, 0x70, command
);
498 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
499 cfi_intel_wait_status_busy(bank
, 10);
502 return ERROR_FLASH_OPERATION_FAILED
;
512 /* if the device doesn't support individual block lock bits set/clear,
513 * all blocks have been unlocked in parallel, so we set those that should be protected
515 if ((!set
) && (!(pri_ext
->feature_support
& 0x20)))
517 for (i
= 0; i
< bank
->num_sectors
; i
++)
519 cfi_intel_clear_status_register(bank
);
520 cfi_command(bank
, 0x60, command
);
521 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
522 if (bank
->sectors
[i
].is_protected
== 1)
524 cfi_command(bank
, 0x01, command
);
525 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
528 cfi_intel_wait_status_busy(bank
, 100);
532 cfi_command(bank
, 0xff, command
);
533 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
538 int cfi_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
540 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
542 if (cfi_info
->target
->state
!= TARGET_HALTED
)
544 return ERROR_TARGET_NOT_HALTED
;
547 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
549 return ERROR_FLASH_SECTOR_INVALID
;
552 if (cfi_info
->qry
[0] != 'Q')
553 return ERROR_FLASH_BANK_NOT_PROBED
;
555 switch(cfi_info
->pri_id
)
559 cfi_intel_protect(bank
, set
, first
, last
);
562 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
569 void cfi_add_byte(struct flash_bank_s
*bank
, u8
*word
, u8 byte
)
571 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
572 target_t
*target
= cfi_info
->target
;
576 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
579 for (i
= 0; i
< bank
->bus_width
- 1; i
++)
580 word
[i
] = word
[i
+ 1];
581 word
[bank
->bus_width
- 1] = byte
;
586 for (i
= bank
->bus_width
- 1; i
> 0; i
--)
587 word
[i
] = word
[i
- 1];
592 int cfi_intel_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 address
, u32 count
)
594 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
595 target_t
*target
= cfi_info
->target
;
596 reg_param_t reg_params
[7];
597 armv4_5_algorithm_t armv4_5_info
;
598 working_area_t
*source
;
599 u32 buffer_size
= 32768;
600 u8 write_command
[CFI_MAX_BUS_WIDTH
];
601 u8 busy_pattern
[CFI_MAX_BUS_WIDTH
];
602 u8 error_pattern
[CFI_MAX_BUS_WIDTH
];
605 /* algorithm register usage:
606 * r0: source address (in RAM)
607 * r1: target address (in Flash)
609 * r3: flash write command
610 * r4: status byte (returned to host)
611 * r5: busy test pattern
612 * r6: error test pattern
615 u32 word_32_code
[] = {
616 0xe4904004, /* loop: ldr r4, [r0], #4 */
617 0xe5813000, /* str r3, [r1] */
618 0xe5814000, /* str r4, [r1] */
619 0xe5914000, /* busy: ldr r4, [r1] */
620 0xe0047005, /* and r7, r4, r5 */
621 0xe1570005, /* cmp r7, r5 */
622 0x1afffffb, /* bne busy */
623 0xe1140006, /* tst r4, r6 */
624 0x1a000003, /* bne done */
625 0xe2522001, /* subs r2, r2, #1 */
626 0x0a000001, /* beq done */
627 0xe2811004, /* add r1, r1 #4 */
628 0xeafffff2, /* b loop */
629 0xeafffffe, /* done: b -2 */
632 u32 word_16_code
[] = {
633 0xe0d040b2, /* loop: ldrh r4, [r0], #2 */
634 0xe1c130b0, /* strh r3, [r1] */
635 0xe1c140b0, /* strh r4, [r1] */
636 0xe1d140b0, /* busy ldrh r4, [r1] */
637 0xe0047005, /* and r7, r4, r5 */
638 0xe1570005, /* cmp r7, r5 */
639 0x1afffffb, /* bne busy */
640 0xe1140006, /* tst r4, r6 */
641 0x1a000003, /* bne done */
642 0xe2522001, /* subs r2, r2, #1 */
643 0x0a000001, /* beq done */
644 0xe2811002, /* add r1, r1 #2 */
645 0xeafffff2, /* b loop */
646 0xeafffffe, /* done: b -2 */
649 u32 word_8_code
[] = {
650 0xe4d04001, /* loop: ldrb r4, [r0], #1 */
651 0xe5c13000, /* strb r3, [r1] */
652 0xe5c14000, /* strb r4, [r1] */
653 0xe5d14000, /* busy ldrb r4, [r1] */
654 0xe0047005, /* and r7, r4, r5 */
655 0xe1570005, /* cmp r7, r5 */
656 0x1afffffb, /* bne busy */
657 0xe1140006, /* tst r4, r6 */
658 0x1a000003, /* bne done */
659 0xe2522001, /* subs r2, r2, #1 */
660 0x0a000001, /* beq done */
661 0xe2811001, /* add r1, r1 #1 */
662 0xeafffff2, /* b loop */
663 0xeafffffe, /* done: b -2 */
666 cfi_intel_clear_status_register(bank
);
668 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
669 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
670 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
672 /* flash write code */
673 if (!cfi_info
->write_algorithm
)
675 if (target_alloc_working_area(target
, 4 * 14, &cfi_info
->write_algorithm
) != ERROR_OK
)
677 WARNING("no working area available, can't do block memory writes");
678 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
681 /* write algorithm code to working area */
682 if (bank
->bus_width
== 1)
684 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_8_code
);
686 else if (bank
->bus_width
== 2)
688 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_16_code
);
690 else if (bank
->bus_width
== 4)
692 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_32_code
);
696 return ERROR_FLASH_OPERATION_FAILED
;
700 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
703 if (buffer_size
<= 256)
705 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
706 if (cfi_info
->write_algorithm
)
707 target_free_working_area(target
, cfi_info
->write_algorithm
);
709 WARNING("no large enough working area available, can't do block memory writes");
710 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
714 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
715 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
716 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
717 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
718 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
719 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
720 init_reg_param(®_params
[6], "r6", 32, PARAM_OUT
);
722 cfi_command(bank
, 0x40, write_command
);
723 cfi_command(bank
, 0x80, busy_pattern
);
724 cfi_command(bank
, 0x7e, error_pattern
);
728 u32 thisrun_count
= (count
> buffer_size
) ? buffer_size
: count
;
730 target_write_buffer(target
, source
->address
, thisrun_count
, buffer
);
732 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
733 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
734 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
/ bank
->bus_width
);
735 buf_set_u32(reg_params
[3].value
, 0, 32, target_buffer_get_u32(target
, write_command
));
736 buf_set_u32(reg_params
[5].value
, 0, 32, target_buffer_get_u32(target
, busy_pattern
));
737 buf_set_u32(reg_params
[6].value
, 0, 32, target_buffer_get_u32(target
, error_pattern
));
739 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
)
741 cfi_intel_clear_status_register(bank
);
742 return ERROR_FLASH_OPERATION_FAILED
;
745 if (buf_get_u32(reg_params
[4].value
, 0, 32) & target_buffer_get_u32(target
, error_pattern
))
747 /* read status register (outputs debug inforation) */
748 cfi_intel_wait_status_busy(bank
, 100);
749 cfi_intel_clear_status_register(bank
);
750 return ERROR_FLASH_OPERATION_FAILED
;
753 buffer
+= thisrun_count
;
754 address
+= thisrun_count
;
755 count
-= thisrun_count
;
758 target_free_working_area(target
, source
);
760 destroy_reg_param(®_params
[0]);
761 destroy_reg_param(®_params
[1]);
762 destroy_reg_param(®_params
[2]);
763 destroy_reg_param(®_params
[3]);
764 destroy_reg_param(®_params
[4]);
765 destroy_reg_param(®_params
[5]);
766 destroy_reg_param(®_params
[6]);
771 int cfi_intel_write_word(struct flash_bank_s
*bank
, u8
*word
, u32 address
)
773 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
774 target_t
*target
= cfi_info
->target
;
777 cfi_intel_clear_status_register(bank
);
778 cfi_command(bank
, 0x40, command
);
779 target
->type
->write_memory(target
, address
, bank
->bus_width
, 1, command
);
781 target
->type
->write_memory(target
, address
, bank
->bus_width
, 1, word
);
783 if (cfi_intel_wait_status_busy(bank
, 1000 * (1 << cfi_info
->word_write_timeout_max
)) != 0x80)
785 cfi_command(bank
, 0xff, command
);
786 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
788 ERROR("couldn't write word at base 0x%x, address %x", bank
->base
, address
);
789 return ERROR_FLASH_OPERATION_FAILED
;
795 int cfi_write_word(struct flash_bank_s
*bank
, u8
*word
, u32 address
)
797 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
799 switch(cfi_info
->pri_id
)
803 return cfi_intel_write_word(bank
, word
, address
);
806 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
810 return ERROR_FLASH_OPERATION_FAILED
;
813 int cfi_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
815 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
816 target_t
*target
= cfi_info
->target
;
817 u32 address
= bank
->base
+ offset
; /* address of first byte to be programmed */
819 int align
; /* number of unaligned bytes */
820 u8 current_word
[CFI_MAX_BUS_WIDTH
* 4]; /* word (bus_width size) currently being programmed */
824 if (cfi_info
->target
->state
!= TARGET_HALTED
)
826 return ERROR_TARGET_NOT_HALTED
;
829 if (offset
+ count
> bank
->size
)
830 return ERROR_FLASH_DST_OUT_OF_BANK
;
832 if (cfi_info
->qry
[0] != 'Q')
833 return ERROR_FLASH_BANK_NOT_PROBED
;
835 /* start at the first byte of the first word (bus_width size) */
836 write_p
= address
& ~(bank
->bus_width
- 1);
837 if ((align
= address
- write_p
) != 0)
839 for (i
= 0; i
< bank
->bus_width
; i
++)
843 /* copy bytes before the first write address */
844 for (i
= 0; i
< align
; ++i
, ++copy_p
)
847 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
848 cfi_add_byte(bank
, current_word
, byte
);
851 /* add bytes from the buffer */
852 for (; (i
< bank
->bus_width
) && (count
> 0); i
++)
854 cfi_add_byte(bank
, current_word
, *buffer
++);
859 /* if the buffer is already finished, copy bytes after the last write address */
860 for (; (count
== 0) && (i
< bank
->bus_width
); ++i
, ++copy_p
)
863 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
864 cfi_add_byte(bank
, current_word
, byte
);
867 retval
= cfi_write_word(bank
, current_word
, write_p
);
868 if (retval
!= ERROR_OK
)
873 /* handle blocks of bus_size aligned bytes */
874 switch(cfi_info
->pri_id
)
876 /* try block writes (fails without working area) */
879 retval
= cfi_intel_write_block(bank
, buffer
, write_p
, count
);
882 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
883 retval
= ERROR_FLASH_OPERATION_FAILED
;
886 if (retval
!= ERROR_OK
)
888 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
890 /* fall back to memory writes */
891 while (count
> bank
->bus_width
)
893 for (i
= 0; i
< bank
->bus_width
; i
++)
896 for (i
= 0; i
< bank
->bus_width
; i
++)
898 cfi_add_byte(bank
, current_word
, *buffer
++);
901 retval
= cfi_write_word(bank
, current_word
, write_p
);
902 if (retval
!= ERROR_OK
)
904 write_p
+= bank
->bus_width
;
905 count
-= bank
->bus_width
;
912 /* handle unaligned tail bytes */
916 for (i
= 0; i
< bank
->bus_width
; i
++)
919 for (i
= 0; (i
< bank
->bus_width
) && (count
> 0); ++i
, ++copy_p
)
921 cfi_add_byte(bank
, current_word
, *buffer
++);
924 for (; i
< bank
->bus_width
; ++i
, ++copy_p
)
927 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
928 cfi_add_byte(bank
, current_word
, byte
);
930 retval
= cfi_write_word(bank
, current_word
, write_p
);
931 if (retval
!= ERROR_OK
)
935 /* return to read array mode */
936 cfi_command(bank
, 0xf0, current_word
);
937 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, current_word
);
938 cfi_command(bank
, 0xff, current_word
);
939 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, current_word
);
944 int cfi_probe(struct flash_bank_s
*bank
)
946 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
947 target_t
*target
= cfi_info
->target
;
951 cfi_command(bank
, 0x98, command
);
952 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
954 cfi_info
->qry
[0] = cfi_query_u8(bank
, 0, 0x10);
955 cfi_info
->qry
[1] = cfi_query_u8(bank
, 0, 0x11);
956 cfi_info
->qry
[2] = cfi_query_u8(bank
, 0, 0x12);
958 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]);
960 if ((cfi_info
->qry
[0] != 'Q') || (cfi_info
->qry
[1] != 'R') || (cfi_info
->qry
[2] != 'Y'))
962 cfi_command(bank
, 0xf0, command
);
963 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
964 cfi_command(bank
, 0xff, command
);
965 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
966 return ERROR_FLASH_BANK_INVALID
;
969 cfi_info
->pri_id
= cfi_query_u16(bank
, 0, 0x13);
970 cfi_info
->pri_addr
= cfi_query_u16(bank
, 0, 0x15);
971 cfi_info
->alt_id
= cfi_query_u16(bank
, 0, 0x17);
972 cfi_info
->alt_addr
= cfi_query_u16(bank
, 0, 0x19);
974 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
);
976 cfi_info
->vcc_min
= cfi_query_u8(bank
, 0, 0x1b);
977 cfi_info
->vcc_max
= cfi_query_u8(bank
, 0, 0x1c);
978 cfi_info
->vpp_min
= cfi_query_u8(bank
, 0, 0x1d);
979 cfi_info
->vpp_max
= cfi_query_u8(bank
, 0, 0x1e);
980 cfi_info
->word_write_timeout_typ
= cfi_query_u8(bank
, 0, 0x1f);
981 cfi_info
->buf_write_timeout_typ
= cfi_query_u8(bank
, 0, 0x20);
982 cfi_info
->block_erase_timeout_typ
= cfi_query_u8(bank
, 0, 0x21);
983 cfi_info
->chip_erase_timeout_typ
= cfi_query_u8(bank
, 0, 0x22);
984 cfi_info
->word_write_timeout_max
= cfi_query_u8(bank
, 0, 0x23);
985 cfi_info
->buf_write_timeout_max
= cfi_query_u8(bank
, 0, 0x24);
986 cfi_info
->block_erase_timeout_max
= cfi_query_u8(bank
, 0, 0x25);
987 cfi_info
->chip_erase_timeout_max
= cfi_query_u8(bank
, 0, 0x26);
989 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",
990 (cfi_info
->vcc_min
& 0xf0) >> 4, cfi_info
->vcc_min
& 0x0f,
991 (cfi_info
->vcc_max
& 0xf0) >> 4, cfi_info
->vcc_max
& 0x0f,
992 (cfi_info
->vpp_min
& 0xf0) >> 4, cfi_info
->vpp_min
& 0x0f,
993 (cfi_info
->vpp_max
& 0xf0) >> 4, cfi_info
->vpp_max
& 0x0f);
994 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
,
995 1 << cfi_info
->block_erase_timeout_typ
, 1 << cfi_info
->chip_erase_timeout_typ
);
996 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
),
997 (1 << cfi_info
->buf_write_timeout_max
) * (1 << cfi_info
->buf_write_timeout_typ
),
998 (1 << cfi_info
->block_erase_timeout_max
) * (1 << cfi_info
->block_erase_timeout_typ
),
999 (1 << cfi_info
->chip_erase_timeout_max
) * (1 << cfi_info
->chip_erase_timeout_typ
));
1001 cfi_info
->dev_size
= cfi_query_u8(bank
, 0, 0x27);
1002 cfi_info
->interface_desc
= cfi_query_u16(bank
, 0, 0x28);
1003 cfi_info
->max_buf_write_size
= cfi_query_u16(bank
, 0, 0x2a);
1004 cfi_info
->num_erase_regions
= cfi_query_u8(bank
, 0, 0x2c);
1006 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
));
1008 if (((1 << cfi_info
->dev_size
) * bank
->bus_width
/ bank
->chip_width
) != bank
->size
)
1010 WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank
->size
, 1 << cfi_info
->dev_size
);
1013 if (cfi_info
->num_erase_regions
)
1016 int num_sectors
= 0;
1019 cfi_info
->erase_region_info
= malloc(4 * cfi_info
->num_erase_regions
);
1021 for (i
= 0; i
< cfi_info
->num_erase_regions
; i
++)
1023 cfi_info
->erase_region_info
[i
] = cfi_query_u32(bank
, 0, 0x2d + (4 * i
));
1024 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);
1026 num_sectors
+= (cfi_info
->erase_region_info
[i
] & 0xffff) + 1;
1029 bank
->num_sectors
= num_sectors
;
1030 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
1031 for (i
= 0; i
< cfi_info
->num_erase_regions
; i
++)
1034 for (j
= 0; j
< (cfi_info
->erase_region_info
[i
] & 0xffff) + 1; j
++)
1036 bank
->sectors
[sector
].offset
= offset
;
1037 bank
->sectors
[sector
].size
= ((cfi_info
->erase_region_info
[i
] >> 16) * 256) * bank
->bus_width
/ bank
->chip_width
;
1038 offset
+= bank
->sectors
[sector
].size
;
1039 bank
->sectors
[sector
].is_erased
= -1;
1040 bank
->sectors
[sector
].is_protected
= -1;
1047 cfi_info
->erase_region_info
= NULL
;
1050 switch(cfi_info
->pri_id
)
1054 cfi_read_intel_pri_ext(bank
);
1057 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
1061 /* return to read array mode */
1062 cfi_command(bank
, 0xf0, command
);
1063 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1064 cfi_command(bank
, 0xff, command
);
1065 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1070 int cfi_erase_check(struct flash_bank_s
*bank
)
1072 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1073 target_t
*target
= cfi_info
->target
;
1077 if (!cfi_info
->erase_check_algorithm
)
1079 u32 erase_check_code
[] =
1081 0xe4d03001, /* ldrb r3, [r0], #1 */
1082 0xe0022003, /* and r2, r2, r3 */
1083 0xe2511001, /* subs r1, r1, #1 */
1084 0x1afffffb, /* b -4 */
1085 0xeafffffe /* b 0 */
1088 /* make sure we have a working area */
1089 if (target_alloc_working_area(target
, 20, &cfi_info
->erase_check_algorithm
) != ERROR_OK
)
1091 WARNING("no working area available, falling back to slow memory reads");
1095 u8 erase_check_code_buf
[5 * 4];
1097 for (i
= 0; i
< 5; i
++)
1098 target_buffer_set_u32(target
, erase_check_code_buf
+ (i
*4), erase_check_code
[i
]);
1100 /* write algorithm code to working area */
1101 target
->type
->write_memory(target
, cfi_info
->erase_check_algorithm
->address
, 4, 5, erase_check_code_buf
);
1105 if (!cfi_info
->erase_check_algorithm
)
1107 u32
*buffer
= malloc(4096);
1109 for (i
= 0; i
< bank
->num_sectors
; i
++)
1111 u32 address
= bank
->base
+ bank
->sectors
[i
].offset
;
1112 u32 size
= bank
->sectors
[i
].size
;
1113 u32 check
= 0xffffffffU
;
1118 u32 thisrun_size
= (size
> 4096) ? 4096 : size
;
1121 target
->type
->read_memory(target
, address
, 4, thisrun_size
/ 4, (u8
*)buffer
);
1123 for (j
= 0; j
< thisrun_size
/ 4; j
++)
1126 if (check
!= 0xffffffff)
1132 size
-= thisrun_size
;
1133 address
+= thisrun_size
;
1136 bank
->sectors
[i
].is_erased
= erased
;
1143 for (i
= 0; i
< bank
->num_sectors
; i
++)
1145 u32 address
= bank
->base
+ bank
->sectors
[i
].offset
;
1146 u32 size
= bank
->sectors
[i
].size
;
1148 reg_param_t reg_params
[3];
1149 armv4_5_algorithm_t armv4_5_info
;
1151 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1152 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1153 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1155 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1156 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1158 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1159 buf_set_u32(reg_params
[1].value
, 0, 32, size
);
1161 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1162 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
1164 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
)
1165 return ERROR_FLASH_OPERATION_FAILED
;
1167 if (buf_get_u32(reg_params
[2].value
, 0, 32) == 0xff)
1168 bank
->sectors
[i
].is_erased
= 1;
1170 bank
->sectors
[i
].is_erased
= 0;
1172 destroy_reg_param(®_params
[0]);
1173 destroy_reg_param(®_params
[1]);
1174 destroy_reg_param(®_params
[2]);
1181 int cfi_intel_protect_check(struct flash_bank_s
*bank
)
1183 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1184 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
1185 target_t
*target
= cfi_info
->target
;
1186 u8 command
[CFI_MAX_BUS_WIDTH
];
1189 /* check if block lock bits are supported on this device */
1190 if (!(pri_ext
->blk_status_reg_mask
& 0x1))
1191 return ERROR_FLASH_OPERATION_FAILED
;
1193 cfi_command(bank
, 0x90, command
);
1194 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
1196 for (i
= 0; i
< bank
->num_sectors
; i
++)
1198 u8 block_status
= cfi_get_u8(bank
, i
, 0x2);
1200 if (block_status
& 1)
1201 bank
->sectors
[i
].is_protected
= 1;
1203 bank
->sectors
[i
].is_protected
= 0;
1206 cfi_command(bank
, 0xff, command
);
1207 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1212 int cfi_protect_check(struct flash_bank_s
*bank
)
1214 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1216 if (cfi_info
->qry
[0] != 'Q')
1217 return ERROR_FLASH_BANK_NOT_PROBED
;
1219 switch(cfi_info
->pri_id
)
1223 return cfi_intel_protect_check(bank
);
1226 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
1233 int cfi_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
1236 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1238 if (cfi_info
->qry
[0] == -1)
1240 printed
= snprintf(buf
, buf_size
, "\ncfi flash bank not probed yet\n");
1244 printed
= snprintf(buf
, buf_size
, "\ncfi information:\n");
1246 buf_size
-= printed
;
1248 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
);
1250 buf_size
-= printed
;
1252 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,
1253 (cfi_info
->vcc_max
& 0xf0) >> 4, cfi_info
->vcc_max
& 0x0f,
1254 (cfi_info
->vpp_min
& 0xf0) >> 4, cfi_info
->vpp_min
& 0x0f,
1255 (cfi_info
->vpp_max
& 0xf0) >> 4, cfi_info
->vpp_max
& 0x0f);
1257 buf_size
-= printed
;
1259 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
,
1260 1 << cfi_info
->block_erase_timeout_typ
, 1 << cfi_info
->chip_erase_timeout_typ
);
1262 buf_size
-= printed
;
1264 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
),
1265 (1 << cfi_info
->buf_write_timeout_max
) * (1 << cfi_info
->buf_write_timeout_typ
),
1266 (1 << cfi_info
->block_erase_timeout_max
) * (1 << cfi_info
->block_erase_timeout_typ
),
1267 (1 << cfi_info
->chip_erase_timeout_max
) * (1 << cfi_info
->chip_erase_timeout_typ
));
1269 buf_size
-= printed
;
1271 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
);
1273 buf_size
-= printed
;
1275 switch(cfi_info
->pri_id
)
1279 cfi_intel_info(bank
, buf
, buf_size
);
1282 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)