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 '%i' 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 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
381 target_t
*target
= cfi_info
->target
;
385 cfi_intel_clear_status_register(bank
);
387 for (i
= first
; i
<= last
; i
++)
389 cfi_command(bank
, 0x20, command
);
390 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
392 cfi_command(bank
, 0xd0, command
);
393 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
395 if (cfi_intel_wait_status_busy(bank
, 1000 * (1 << cfi_info
->block_erase_timeout_typ
)) == 0x80)
396 bank
->sectors
[i
].is_erased
= 1;
399 cfi_command(bank
, 0xff, command
);
400 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
402 ERROR("couldn't erase block %i of flash bank at base 0x%x", i
, bank
->base
);
403 return ERROR_FLASH_OPERATION_FAILED
;
407 cfi_command(bank
, 0xff, command
);
408 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
413 int cfi_erase(struct flash_bank_s
*bank
, int first
, int last
)
415 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
417 if (cfi_info
->target
->state
!= TARGET_HALTED
)
419 return ERROR_TARGET_NOT_HALTED
;
422 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
424 return ERROR_FLASH_SECTOR_INVALID
;
427 if (cfi_info
->qry
[0] != 'Q')
428 return ERROR_FLASH_BANK_NOT_PROBED
;
430 switch(cfi_info
->pri_id
)
434 return cfi_intel_erase(bank
, first
, last
);
437 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
444 int cfi_intel_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
446 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
447 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
448 target_t
*target
= cfi_info
->target
;
453 /* if the device supports neither legacy lock/unlock (bit 3) nor
454 * instant individual block locking (bit 5).
456 if (!(pri_ext
->feature_support
& 0x28))
457 return ERROR_FLASH_OPERATION_FAILED
;
459 cfi_intel_clear_status_register(bank
);
461 for (i
= first
; i
<= last
; i
++)
463 cfi_command(bank
, 0x60, command
);
464 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank
, i
, 0x0), target_buffer_get_u32(target
, command
));
465 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
468 cfi_command(bank
, 0x01, command
);
469 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank
, i
, 0x0), target_buffer_get_u32(target
, command
));
470 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
471 bank
->sectors
[i
].is_protected
= 1;
475 cfi_command(bank
, 0xd0, command
);
476 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank
, i
, 0x0), target_buffer_get_u32(target
, command
));
477 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
478 bank
->sectors
[i
].is_protected
= 0;
481 /* instant individual block locking doesn't require reading of the status register */
482 if (!(pri_ext
->feature_support
& 0x20))
484 /* Clear lock bits operation may take up to 1.4s */
485 cfi_intel_wait_status_busy(bank
, 1400);
490 /* read block lock bit, to verify status */
491 cfi_command(bank
, 0x90, command
);
492 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
493 block_status
= cfi_get_u8(bank
, i
, 0x2);
495 if ((block_status
& 0x1) != set
)
497 ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set
, block_status
);
498 cfi_command(bank
, 0x70, command
);
499 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
500 cfi_intel_wait_status_busy(bank
, 10);
503 return ERROR_FLASH_OPERATION_FAILED
;
513 /* if the device doesn't support individual block lock bits set/clear,
514 * all blocks have been unlocked in parallel, so we set those that should be protected
516 if ((!set
) && (!(pri_ext
->feature_support
& 0x20)))
518 for (i
= 0; i
< bank
->num_sectors
; i
++)
520 cfi_intel_clear_status_register(bank
);
521 cfi_command(bank
, 0x60, command
);
522 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
523 if (bank
->sectors
[i
].is_protected
== 1)
525 cfi_command(bank
, 0x01, command
);
526 target
->type
->write_memory(target
, flash_address(bank
, i
, 0x0), bank
->bus_width
, 1, command
);
529 cfi_intel_wait_status_busy(bank
, 100);
533 cfi_command(bank
, 0xff, command
);
534 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
539 int cfi_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
541 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
543 if (cfi_info
->target
->state
!= TARGET_HALTED
)
545 return ERROR_TARGET_NOT_HALTED
;
548 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
550 return ERROR_FLASH_SECTOR_INVALID
;
553 if (cfi_info
->qry
[0] != 'Q')
554 return ERROR_FLASH_BANK_NOT_PROBED
;
556 switch(cfi_info
->pri_id
)
560 cfi_intel_protect(bank
, set
, first
, last
);
563 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
570 void cfi_add_byte(struct flash_bank_s
*bank
, u8
*word
, u8 byte
)
572 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
573 target_t
*target
= cfi_info
->target
;
577 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
580 for (i
= 0; i
< bank
->bus_width
- 1; i
++)
581 word
[i
] = word
[i
+ 1];
582 word
[bank
->bus_width
- 1] = byte
;
587 for (i
= bank
->bus_width
- 1; i
> 0; i
--)
588 word
[i
] = word
[i
- 1];
593 int cfi_intel_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 address
, u32 count
)
595 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
596 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
597 target_t
*target
= cfi_info
->target
;
598 reg_param_t reg_params
[7];
599 armv4_5_algorithm_t armv4_5_info
;
600 working_area_t
*source
;
601 u32 buffer_size
= 32768;
602 u8 write_command
[CFI_MAX_BUS_WIDTH
];
603 u8 busy_pattern
[CFI_MAX_BUS_WIDTH
];
604 u8 error_pattern
[CFI_MAX_BUS_WIDTH
];
608 /* algorithm register usage:
609 * r0: source address (in RAM)
610 * r1: target address (in Flash)
612 * r3: flash write command
613 * r4: status byte (returned to host)
614 * r5: busy test pattern
615 * r6: error test pattern
618 u32 word_32_code
[] = {
619 0xe4904004, /* loop: ldr r4, [r0], #4 */
620 0xe5813000, /* str r3, [r1] */
621 0xe5814000, /* str r4, [r1] */
622 0xe5914000, /* busy: ldr r4, [r1] */
623 0xe0047005, /* and r7, r4, r5 */
624 0xe1570005, /* cmp r7, r5 */
625 0x1afffffb, /* bne busy */
626 0xe1140006, /* tst r4, r6 */
627 0x1a000003, /* bne done */
628 0xe2522001, /* subs r2, r2, #1 */
629 0x0a000001, /* beq done */
630 0xe2811004, /* add r1, r1 #4 */
631 0xeafffff2, /* b loop */
632 0xeafffffe, /* done: b -2 */
635 u32 word_16_code
[] = {
636 0xe0d040b2, /* loop: ldrh r4, [r0], #2 */
637 0xe1c130b0, /* strh r3, [r1] */
638 0xe1c140b0, /* strh r4, [r1] */
639 0xe1d140b0, /* busy ldrh r4, [r1] */
640 0xe0047005, /* and r7, r4, r5 */
641 0xe1570005, /* cmp r7, r5 */
642 0x1afffffb, /* bne busy */
643 0xe1140006, /* tst r4, r6 */
644 0x1a000003, /* bne done */
645 0xe2522001, /* subs r2, r2, #1 */
646 0x0a000001, /* beq done */
647 0xe2811002, /* add r1, r1 #2 */
648 0xeafffff2, /* b loop */
649 0xeafffffe, /* done: b -2 */
652 u32 word_8_code
[] = {
653 0xe4d04001, /* loop: ldrb r4, [r0], #1 */
654 0xe5c13000, /* strb r3, [r1] */
655 0xe5c14000, /* strb r4, [r1] */
656 0xe5d14000, /* busy ldrb r4, [r1] */
657 0xe0047005, /* and r7, r4, r5 */
658 0xe1570005, /* cmp r7, r5 */
659 0x1afffffb, /* bne busy */
660 0xe1140006, /* tst r4, r6 */
661 0x1a000003, /* bne done */
662 0xe2522001, /* subs r2, r2, #1 */
663 0x0a000001, /* beq done */
664 0xe2811001, /* add r1, r1 #1 */
665 0xeafffff2, /* b loop */
666 0xeafffffe, /* done: b -2 */
669 cfi_intel_clear_status_register(bank
);
671 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
672 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
673 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
675 /* flash write code */
676 if (!cfi_info
->write_algorithm
)
678 if (target_alloc_working_area(target
, 4 * 14, &cfi_info
->write_algorithm
) != ERROR_OK
)
680 WARNING("no working area available, can't do block memory writes");
681 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
684 /* write algorithm code to working area */
685 if (bank
->bus_width
== 1)
687 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_8_code
);
689 else if (bank
->bus_width
== 2)
691 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_16_code
);
693 else if (bank
->bus_width
== 4)
695 target_write_buffer(target
, cfi_info
->write_algorithm
->address
, 14 * 4, (u8
*)word_32_code
);
699 return ERROR_FLASH_OPERATION_FAILED
;
703 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
706 if (buffer_size
<= 256)
708 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
709 if (cfi_info
->write_algorithm
)
710 target_free_working_area(target
, cfi_info
->write_algorithm
);
712 WARNING("no large enough working area available, can't do block memory writes");
713 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
717 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
718 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
719 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
720 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
721 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
722 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
723 init_reg_param(®_params
[6], "r6", 32, PARAM_OUT
);
725 cfi_command(bank
, 0x40, write_command
);
726 cfi_command(bank
, 0x80, busy_pattern
);
727 cfi_command(bank
, 0x7e, error_pattern
);
731 u32 thisrun_count
= (count
> buffer_size
) ? buffer_size
: count
;
733 target_write_buffer(target
, source
->address
, thisrun_count
, buffer
);
735 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
736 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
737 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
/ bank
->bus_width
);
738 buf_set_u32(reg_params
[3].value
, 0, 32, target_buffer_get_u32(target
, write_command
));
739 buf_set_u32(reg_params
[5].value
, 0, 32, target_buffer_get_u32(target
, busy_pattern
));
740 buf_set_u32(reg_params
[6].value
, 0, 32, target_buffer_get_u32(target
, error_pattern
));
742 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
)
744 cfi_intel_clear_status_register(bank
);
745 return ERROR_FLASH_OPERATION_FAILED
;
748 if (buf_get_u32(reg_params
[4].value
, 0, 32) & target_buffer_get_u32(target
, error_pattern
))
750 /* read status register (outputs debug inforation) */
751 cfi_intel_wait_status_busy(bank
, 100);
752 cfi_intel_clear_status_register(bank
);
753 return ERROR_FLASH_OPERATION_FAILED
;
756 buffer
+= thisrun_count
;
757 address
+= thisrun_count
;
758 count
-= thisrun_count
;
761 target_free_working_area(target
, source
);
763 destroy_reg_param(®_params
[0]);
764 destroy_reg_param(®_params
[1]);
765 destroy_reg_param(®_params
[2]);
766 destroy_reg_param(®_params
[3]);
767 destroy_reg_param(®_params
[4]);
768 destroy_reg_param(®_params
[5]);
769 destroy_reg_param(®_params
[6]);
774 int cfi_intel_write_word(struct flash_bank_s
*bank
, u8
*word
, u32 address
)
776 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
777 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
778 target_t
*target
= cfi_info
->target
;
781 cfi_intel_clear_status_register(bank
);
782 cfi_command(bank
, 0x40, command
);
783 target
->type
->write_memory(target
, address
, bank
->bus_width
, 1, command
);
785 target
->type
->write_memory(target
, address
, bank
->bus_width
, 1, word
);
787 if (cfi_intel_wait_status_busy(bank
, 1000 * (1 << cfi_info
->word_write_timeout_max
)) != 0x80)
789 cfi_command(bank
, 0xff, command
);
790 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
792 ERROR("couldn't write word at base 0x%x, address %x", bank
->base
, address
);
793 return ERROR_FLASH_OPERATION_FAILED
;
799 int cfi_write_word(struct flash_bank_s
*bank
, u8
*word
, u32 address
)
801 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
802 target_t
*target
= cfi_info
->target
;
804 switch(cfi_info
->pri_id
)
808 return cfi_intel_write_word(bank
, word
, address
);
811 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
815 return ERROR_FLASH_OPERATION_FAILED
;
818 int cfi_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
820 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
821 target_t
*target
= cfi_info
->target
;
822 u32 address
= bank
->base
+ offset
; /* address of first byte to be programmed */
824 int align
; /* number of unaligned bytes */
825 u8 current_word
[CFI_MAX_BUS_WIDTH
* 4]; /* word (bus_width size) currently being programmed */
829 if (cfi_info
->target
->state
!= TARGET_HALTED
)
831 return ERROR_TARGET_NOT_HALTED
;
834 if (offset
+ count
> bank
->size
)
835 return ERROR_FLASH_DST_OUT_OF_BANK
;
837 if (cfi_info
->qry
[0] != 'Q')
838 return ERROR_FLASH_BANK_NOT_PROBED
;
840 /* start at the first byte of the first word (bus_width size) */
841 write_p
= address
& ~(bank
->bus_width
- 1);
842 if ((align
= address
- write_p
) != 0)
844 for (i
= 0; i
< bank
->bus_width
; i
++)
848 /* copy bytes before the first write address */
849 for (i
= 0; i
< align
; ++i
, ++copy_p
)
852 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
853 cfi_add_byte(bank
, current_word
, byte
);
856 /* add bytes from the buffer */
857 for (; (i
< bank
->bus_width
) && (count
> 0); i
++)
859 cfi_add_byte(bank
, current_word
, *buffer
++);
864 /* if the buffer is already finished, copy bytes after the last write address */
865 for (; (count
== 0) && (i
< bank
->bus_width
); ++i
, ++copy_p
)
868 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
869 cfi_add_byte(bank
, current_word
, byte
);
872 retval
= cfi_write_word(bank
, current_word
, write_p
);
873 if (retval
!= ERROR_OK
)
878 /* handle blocks of bus_size aligned bytes */
879 switch(cfi_info
->pri_id
)
881 /* try block writes (fails without working area) */
884 retval
= cfi_intel_write_block(bank
, buffer
, write_p
, count
);
887 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
890 if (retval
!= ERROR_OK
)
892 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
894 /* fall back to memory writes */
895 while (count
> bank
->bus_width
)
897 for (i
= 0; i
< bank
->bus_width
; i
++)
900 for (i
= 0; i
< bank
->bus_width
; i
++)
902 cfi_add_byte(bank
, current_word
, *buffer
++);
905 retval
= cfi_write_word(bank
, current_word
, write_p
);
906 if (retval
!= ERROR_OK
)
908 write_p
+= bank
->bus_width
;
909 count
-= bank
->bus_width
;
916 /* handle unaligned tail bytes */
920 for (i
= 0; i
< bank
->bus_width
; i
++)
923 for (i
= 0; (i
< bank
->bus_width
) && (count
> 0); ++i
, ++copy_p
)
925 cfi_add_byte(bank
, current_word
, *buffer
++);
928 for (; i
< bank
->bus_width
; ++i
, ++copy_p
)
931 target
->type
->read_memory(target
, copy_p
, 1, 1, &byte
);
932 cfi_add_byte(bank
, current_word
, byte
);
934 retval
= cfi_write_word(bank
, current_word
, write_p
);
935 if (retval
!= ERROR_OK
)
939 /* return to read array mode */
940 cfi_command(bank
, 0xf0, current_word
);
941 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, current_word
);
942 cfi_command(bank
, 0xff, current_word
);
943 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, current_word
);
948 int cfi_probe(struct flash_bank_s
*bank
)
950 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
951 target_t
*target
= cfi_info
->target
;
955 cfi_command(bank
, 0x98, command
);
956 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
958 cfi_info
->qry
[0] = cfi_query_u8(bank
, 0, 0x10);
959 cfi_info
->qry
[1] = cfi_query_u8(bank
, 0, 0x11);
960 cfi_info
->qry
[2] = cfi_query_u8(bank
, 0, 0x12);
962 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]);
964 if ((cfi_info
->qry
[0] != 'Q') || (cfi_info
->qry
[1] != 'R') || (cfi_info
->qry
[2] != 'Y'))
966 cfi_command(bank
, 0xf0, command
);
967 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
968 cfi_command(bank
, 0xff, command
);
969 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
970 return ERROR_FLASH_BANK_INVALID
;
973 cfi_info
->pri_id
= cfi_query_u16(bank
, 0, 0x13);
974 cfi_info
->pri_addr
= cfi_query_u16(bank
, 0, 0x15);
975 cfi_info
->alt_id
= cfi_query_u16(bank
, 0, 0x17);
976 cfi_info
->alt_addr
= cfi_query_u16(bank
, 0, 0x19);
978 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
);
980 cfi_info
->vcc_min
= cfi_query_u8(bank
, 0, 0x1b);
981 cfi_info
->vcc_max
= cfi_query_u8(bank
, 0, 0x1c);
982 cfi_info
->vpp_min
= cfi_query_u8(bank
, 0, 0x1d);
983 cfi_info
->vpp_max
= cfi_query_u8(bank
, 0, 0x1e);
984 cfi_info
->word_write_timeout_typ
= cfi_query_u8(bank
, 0, 0x1f);
985 cfi_info
->buf_write_timeout_typ
= cfi_query_u8(bank
, 0, 0x20);
986 cfi_info
->block_erase_timeout_typ
= cfi_query_u8(bank
, 0, 0x21);
987 cfi_info
->chip_erase_timeout_typ
= cfi_query_u8(bank
, 0, 0x22);
988 cfi_info
->word_write_timeout_max
= cfi_query_u8(bank
, 0, 0x23);
989 cfi_info
->buf_write_timeout_max
= cfi_query_u8(bank
, 0, 0x24);
990 cfi_info
->block_erase_timeout_max
= cfi_query_u8(bank
, 0, 0x25);
991 cfi_info
->chip_erase_timeout_max
= cfi_query_u8(bank
, 0, 0x26);
993 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",
994 (cfi_info
->vcc_min
& 0xf0) >> 4, cfi_info
->vcc_min
& 0x0f,
995 (cfi_info
->vcc_max
& 0xf0) >> 4, cfi_info
->vcc_max
& 0x0f,
996 (cfi_info
->vpp_min
& 0xf0) >> 4, cfi_info
->vpp_min
& 0x0f,
997 (cfi_info
->vpp_max
& 0xf0) >> 4, cfi_info
->vpp_max
& 0x0f);
998 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
,
999 1 << cfi_info
->block_erase_timeout_typ
, 1 << cfi_info
->chip_erase_timeout_typ
);
1000 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
),
1001 (1 << cfi_info
->buf_write_timeout_max
) * (1 << cfi_info
->buf_write_timeout_typ
),
1002 (1 << cfi_info
->block_erase_timeout_max
) * (1 << cfi_info
->block_erase_timeout_typ
),
1003 (1 << cfi_info
->chip_erase_timeout_max
) * (1 << cfi_info
->chip_erase_timeout_typ
));
1005 cfi_info
->dev_size
= cfi_query_u8(bank
, 0, 0x27);
1006 cfi_info
->interface_desc
= cfi_query_u16(bank
, 0, 0x28);
1007 cfi_info
->max_buf_write_size
= cfi_query_u16(bank
, 0, 0x2a);
1008 cfi_info
->num_erase_regions
= cfi_query_u8(bank
, 0, 0x2c);
1010 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
));
1012 if (((1 << cfi_info
->dev_size
) * bank
->bus_width
/ bank
->chip_width
) != bank
->size
)
1014 WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank
->size
, 1 << cfi_info
->dev_size
);
1017 if (cfi_info
->num_erase_regions
)
1020 int num_sectors
= 0;
1023 cfi_info
->erase_region_info
= malloc(4 * cfi_info
->num_erase_regions
);
1025 for (i
= 0; i
< cfi_info
->num_erase_regions
; i
++)
1027 cfi_info
->erase_region_info
[i
] = cfi_query_u32(bank
, 0, 0x2d + (4 * i
));
1028 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);
1030 num_sectors
+= (cfi_info
->erase_region_info
[i
] & 0xffff) + 1;
1033 bank
->num_sectors
= num_sectors
;
1034 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
1035 for (i
= 0; i
< cfi_info
->num_erase_regions
; i
++)
1038 for (j
= 0; j
< (cfi_info
->erase_region_info
[i
] & 0xffff) + 1; j
++)
1040 bank
->sectors
[sector
].offset
= offset
;
1041 bank
->sectors
[sector
].size
= ((cfi_info
->erase_region_info
[i
] >> 16) * 256) * bank
->bus_width
/ bank
->chip_width
;
1042 offset
+= bank
->sectors
[sector
].size
;
1043 bank
->sectors
[sector
].is_erased
= -1;
1044 bank
->sectors
[sector
].is_protected
= -1;
1051 cfi_info
->erase_region_info
= NULL
;
1054 switch(cfi_info
->pri_id
)
1058 cfi_read_intel_pri_ext(bank
);
1061 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
1065 /* return to read array mode */
1066 cfi_command(bank
, 0xf0, command
);
1067 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1068 cfi_command(bank
, 0xff, command
);
1069 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1074 int cfi_erase_check(struct flash_bank_s
*bank
)
1076 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1077 target_t
*target
= cfi_info
->target
;
1081 if (!cfi_info
->erase_check_algorithm
)
1083 u32 erase_check_code
[] =
1085 0xe4d03001, /* ldrb r3, [r0], #1 */
1086 0xe0022003, /* and r2, r2, r3 */
1087 0xe2511001, /* subs r1, r1, #1 */
1088 0x1afffffb, /* b -4 */
1089 0xeafffffe /* b 0 */
1092 /* make sure we have a working area */
1093 if (target_alloc_working_area(target
, 20, &cfi_info
->erase_check_algorithm
) != ERROR_OK
)
1095 WARNING("no working area available, falling back to slow memory reads");
1099 u8 erase_check_code_buf
[5 * 4];
1101 for (i
= 0; i
< 5; i
++)
1102 target_buffer_set_u32(target
, erase_check_code_buf
+ (i
*4), erase_check_code
[i
]);
1104 /* write algorithm code to working area */
1105 target
->type
->write_memory(target
, cfi_info
->erase_check_algorithm
->address
, 4, 5, erase_check_code_buf
);
1109 if (!cfi_info
->erase_check_algorithm
)
1111 u32
*buffer
= malloc(4096);
1113 for (i
= 0; i
< bank
->num_sectors
; i
++)
1115 u32 address
= bank
->base
+ bank
->sectors
[i
].offset
;
1116 u32 size
= bank
->sectors
[i
].size
;
1117 u32 check
= 0xffffffffU
;
1122 u32 thisrun_size
= (size
> 4096) ? 4096 : size
;
1125 target
->type
->read_memory(target
, address
, 4, thisrun_size
/ 4, (u8
*)buffer
);
1127 for (j
= 0; j
< thisrun_size
/ 4; j
++)
1130 if (check
!= 0xffffffff)
1136 size
-= thisrun_size
;
1137 address
+= thisrun_size
;
1140 bank
->sectors
[i
].is_erased
= erased
;
1147 for (i
= 0; i
< bank
->num_sectors
; i
++)
1149 u32 address
= bank
->base
+ bank
->sectors
[i
].offset
;
1150 u32 size
= bank
->sectors
[i
].size
;
1152 reg_param_t reg_params
[3];
1153 armv4_5_algorithm_t armv4_5_info
;
1155 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1156 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1157 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1159 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1160 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1162 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1163 buf_set_u32(reg_params
[1].value
, 0, 32, size
);
1165 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1166 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
1168 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
)
1169 return ERROR_FLASH_OPERATION_FAILED
;
1171 if (buf_get_u32(reg_params
[2].value
, 0, 32) == 0xff)
1172 bank
->sectors
[i
].is_erased
= 1;
1174 bank
->sectors
[i
].is_erased
= 0;
1176 destroy_reg_param(®_params
[0]);
1177 destroy_reg_param(®_params
[1]);
1178 destroy_reg_param(®_params
[2]);
1185 int cfi_intel_protect_check(struct flash_bank_s
*bank
)
1187 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1188 cfi_intel_pri_ext_t
*pri_ext
= cfi_info
->pri_ext
;
1189 target_t
*target
= cfi_info
->target
;
1190 u8 command
[CFI_MAX_BUS_WIDTH
];
1193 /* check if block lock bits are supported on this device */
1194 if (!(pri_ext
->blk_status_reg_mask
& 0x1))
1195 return ERROR_FLASH_OPERATION_FAILED
;
1197 cfi_command(bank
, 0x90, command
);
1198 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x55), bank
->bus_width
, 1, command
);
1200 for (i
= 0; i
< bank
->num_sectors
; i
++)
1202 u8 block_status
= cfi_get_u8(bank
, i
, 0x2);
1204 if (block_status
& 1)
1205 bank
->sectors
[i
].is_protected
= 1;
1207 bank
->sectors
[i
].is_protected
= 0;
1210 cfi_command(bank
, 0xff, command
);
1211 target
->type
->write_memory(target
, flash_address(bank
, 0, 0x0), bank
->bus_width
, 1, command
);
1216 int cfi_protect_check(struct flash_bank_s
*bank
)
1218 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1219 target_t
*target
= cfi_info
->target
;
1221 if (cfi_info
->qry
[0] != 'Q')
1222 return ERROR_FLASH_BANK_NOT_PROBED
;
1224 switch(cfi_info
->pri_id
)
1228 return cfi_intel_protect_check(bank
);
1231 ERROR("cfi primary command set %i unsupported", cfi_info
->pri_id
);
1238 int cfi_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
1241 cfi_flash_bank_t
*cfi_info
= bank
->driver_priv
;
1243 if (cfi_info
->qry
[0] == -1)
1245 printed
= snprintf(buf
, buf_size
, "\ncfi flash bank not probed yet\n");
1249 printed
= snprintf(buf
, buf_size
, "\ncfi information:\n");
1251 buf_size
-= printed
;
1253 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
);
1255 buf_size
-= printed
;
1257 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,
1258 (cfi_info
->vcc_max
& 0xf0) >> 4, cfi_info
->vcc_max
& 0x0f,
1259 (cfi_info
->vpp_min
& 0xf0) >> 4, cfi_info
->vpp_min
& 0x0f,
1260 (cfi_info
->vpp_max
& 0xf0) >> 4, cfi_info
->vpp_max
& 0x0f);
1262 buf_size
-= printed
;
1264 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
,
1265 1 << cfi_info
->block_erase_timeout_typ
, 1 << cfi_info
->chip_erase_timeout_typ
);
1267 buf_size
-= printed
;
1269 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
),
1270 (1 << cfi_info
->buf_write_timeout_max
) * (1 << cfi_info
->buf_write_timeout_typ
),
1271 (1 << cfi_info
->block_erase_timeout_max
) * (1 << cfi_info
->block_erase_timeout_typ
),
1272 (1 << cfi_info
->chip_erase_timeout_max
) * (1 << cfi_info
->chip_erase_timeout_typ
));
1274 buf_size
-= printed
;
1276 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
);
1278 buf_size
-= printed
;
1280 switch(cfi_info
->pri_id
)
1284 cfi_intel_info(bank
, buf
, buf_size
);
1287 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)