1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * Copyright (c) 2015 Andreas Färber
8 * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
9 * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
10 * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
11 * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
19 #include <helper/binarybuffer.h>
20 #include <target/algorithm.h>
21 #include <target/armv7m.h>
23 #define FLASH_BASE 0x40000000
24 #define FASZR (FLASH_BASE + 0x000)
25 #define DFCTRLR (FLASH_BASE + 0x030)
26 #define DFCTRLR_DFE (1UL << 0)
28 #define WDG_BASE 0x40011000
29 #define WDG_CTL (WDG_BASE + 0x008)
30 #define WDG_LCK (WDG_BASE + 0xC00)
46 struct fm4_flash_bank
{
47 enum fm4_variant variant
;
52 static int fm4_disable_hw_watchdog(struct target
*target
)
56 retval
= target_write_u32(target
, WDG_LCK
, 0x1ACCE551);
57 if (retval
!= ERROR_OK
)
60 retval
= target_write_u32(target
, WDG_LCK
, 0xE5331AAE);
61 if (retval
!= ERROR_OK
)
64 retval
= target_write_u32(target
, WDG_CTL
, 0);
65 if (retval
!= ERROR_OK
)
71 static int fm4_enter_flash_cpu_programming_mode(struct target
*target
)
76 /* FASZR ASZ = CPU programming mode */
77 retval
= target_write_u32(target
, FASZR
, 0x00000001);
78 if (retval
!= ERROR_OK
)
80 retval
= target_read_u32(target
, FASZR
, &u32_value
);
81 if (retval
!= ERROR_OK
)
87 static int fm4_enter_flash_cpu_rom_mode(struct target
*target
)
92 /* FASZR ASZ = CPU ROM mode */
93 retval
= target_write_u32(target
, FASZR
, 0x00000002);
94 if (retval
!= ERROR_OK
)
96 retval
= target_read_u32(target
, FASZR
, &u32_value
);
97 if (retval
!= ERROR_OK
)
103 static int fm4_flash_erase(struct flash_bank
*bank
, unsigned int first
,
106 struct target
*target
= bank
->target
;
107 struct working_area
*workarea
;
108 struct reg_param reg_params
[4];
109 struct armv7m_algorithm armv7m_algo
;
112 const uint8_t erase_sector_code
[] = {
113 #include "../../../contrib/loaders/flash/fm4/erase.inc"
116 if (target
->state
!= TARGET_HALTED
) {
117 LOG_WARNING("Cannot communicate... target not halted.");
118 return ERROR_TARGET_NOT_HALTED
;
121 LOG_DEBUG("Spansion FM4 erase sectors %u to %u", first
, last
);
123 retval
= fm4_disable_hw_watchdog(target
);
124 if (retval
!= ERROR_OK
)
127 retval
= fm4_enter_flash_cpu_programming_mode(target
);
128 if (retval
!= ERROR_OK
)
131 retval
= target_alloc_working_area(target
, sizeof(erase_sector_code
),
133 if (retval
!= ERROR_OK
) {
134 LOG_ERROR("No working area available.");
135 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
138 retval
= target_write_buffer(target
, workarea
->address
,
139 sizeof(erase_sector_code
), erase_sector_code
);
140 if (retval
!= ERROR_OK
)
143 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
144 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
146 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
147 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
148 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
149 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
151 for (unsigned int sector
= first
; sector
<= last
; sector
++) {
152 uint32_t addr
= bank
->base
+ bank
->sectors
[sector
].offset
;
155 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
156 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
157 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
159 retval
= target_run_algorithm(target
,
161 ARRAY_SIZE(reg_params
), reg_params
,
162 workarea
->address
, 0,
164 if (retval
!= ERROR_OK
) {
165 LOG_ERROR("Error executing flash sector erase "
166 "programming algorithm");
167 retval
= ERROR_FLASH_OPERATION_FAILED
;
171 result
= buf_get_u32(reg_params
[3].value
, 0, 32);
173 LOG_ERROR("Timeout error from flash sector erase programming algorithm");
174 retval
= ERROR_FLASH_OPERATION_FAILED
;
176 } else if (result
!= 0) {
177 LOG_ERROR("Unexpected error %" PRIu32
" from flash sector erase programming algorithm", result
);
178 retval
= ERROR_FLASH_OPERATION_FAILED
;
186 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
187 destroy_reg_param(®_params
[i
]);
190 target_free_working_area(target
, workarea
);
193 if (retval
!= ERROR_OK
)
194 fm4_enter_flash_cpu_rom_mode(target
);
196 retval
= fm4_enter_flash_cpu_rom_mode(target
);
201 static int fm4_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
202 uint32_t offset
, uint32_t byte_count
)
204 struct target
*target
= bank
->target
;
205 struct working_area
*code_workarea
, *data_workarea
;
206 struct reg_param reg_params
[6];
207 struct armv7m_algorithm armv7m_algo
;
208 uint32_t halfword_count
= DIV_ROUND_UP(byte_count
, 2);
211 int retval
, retval2
= ERROR_OK
;
212 const uint8_t write_block_code
[] = {
213 #include "../../../contrib/loaders/flash/fm4/write.inc"
216 LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32
" (%" PRIu32
" bytes)",
220 LOG_ERROR("offset 0x%" PRIx32
" breaks required 2-byte alignment",
222 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
224 if (byte_count
& 0x1) {
225 LOG_WARNING("length %" PRIu32
" is not 2-byte aligned, rounding up",
229 if (target
->state
!= TARGET_HALTED
) {
230 LOG_WARNING("Cannot communicate... target not halted.");
231 return ERROR_TARGET_NOT_HALTED
;
234 retval
= fm4_disable_hw_watchdog(target
);
235 if (retval
!= ERROR_OK
)
238 retval
= target_alloc_working_area(target
, sizeof(write_block_code
),
240 if (retval
!= ERROR_OK
) {
241 LOG_ERROR("No working area available for write code.");
242 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
244 retval
= target_write_buffer(target
, code_workarea
->address
,
245 sizeof(write_block_code
), write_block_code
);
246 if (retval
!= ERROR_OK
)
249 retval
= target_alloc_working_area(target
,
250 MIN(halfword_count
* 2, target_get_working_area_avail(target
)),
252 if (retval
!= ERROR_OK
) {
253 LOG_ERROR("No working area available for write data.");
254 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
258 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
259 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
261 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
262 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
263 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
264 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
265 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
);
266 init_reg_param(®_params
[5], "r5", 32, PARAM_IN
);
268 retval
= fm4_enter_flash_cpu_programming_mode(target
);
269 if (retval
!= ERROR_OK
)
272 while (byte_count
> 0) {
273 uint32_t halfwords
= MIN(halfword_count
, data_workarea
->size
/ 2);
274 uint32_t addr
= bank
->base
+ offset
;
276 LOG_DEBUG("copying %" PRIu32
" bytes to SRAM " TARGET_ADDR_FMT
,
277 MIN(halfwords
* 2, byte_count
), data_workarea
->address
);
279 retval
= target_write_buffer(target
, data_workarea
->address
,
280 MIN(halfwords
* 2, byte_count
), buffer
);
281 if (retval
!= ERROR_OK
) {
282 LOG_ERROR("Error writing data buffer");
283 retval
= ERROR_FLASH_OPERATION_FAILED
;
287 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRIu32
"x)",
288 addr
, addr
+ halfwords
* 2 - 1, halfwords
);
290 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
291 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
292 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
293 buf_set_u32(reg_params
[3].value
, 0, 32, data_workarea
->address
);
294 buf_set_u32(reg_params
[4].value
, 0, 32, halfwords
);
296 retval
= target_run_algorithm(target
,
298 ARRAY_SIZE(reg_params
), reg_params
,
299 code_workarea
->address
, 0,
300 5 * 60 * 1000, &armv7m_algo
);
301 if (retval
!= ERROR_OK
) {
302 LOG_ERROR("Error executing flash sector erase "
303 "programming algorithm");
304 retval
= ERROR_FLASH_OPERATION_FAILED
;
308 result
= buf_get_u32(reg_params
[5].value
, 0, 32);
310 LOG_ERROR("Timeout error from flash write "
311 "programming algorithm");
312 retval
= ERROR_FLASH_OPERATION_FAILED
;
314 } else if (result
!= 0) {
315 LOG_ERROR("Unexpected error %" PRIu32
" from flash write "
316 "programming algorithm", result
);
317 retval
= ERROR_FLASH_OPERATION_FAILED
;
322 halfword_count
-= halfwords
;
323 offset
+= halfwords
* 2;
324 buffer
+= halfwords
* 2;
325 byte_count
-= MIN(halfwords
* 2, byte_count
);
331 retval2
= fm4_enter_flash_cpu_rom_mode(target
);
334 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
335 destroy_reg_param(®_params
[i
]);
337 target_free_working_area(target
, data_workarea
);
340 target_free_working_area(target
, code_workarea
);
342 if (retval
!= ERROR_OK
)
347 static int mb9bf_probe(struct flash_bank
*bank
)
349 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
350 uint32_t flash_addr
= bank
->base
;
352 switch (fm4_bank
->variant
) {
354 bank
->num_sectors
= 8;
357 bank
->num_sectors
= 10;
360 bank
->num_sectors
= 12;
363 bank
->num_sectors
= 16;
366 bank
->num_sectors
= 20;
369 return ERROR_FLASH_OPER_UNSUPPORTED
;
372 LOG_DEBUG("%u sectors", bank
->num_sectors
);
373 bank
->sectors
= calloc(bank
->num_sectors
,
374 sizeof(struct flash_sector
));
375 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
377 bank
->sectors
[i
].size
= 8 * 1024;
379 bank
->sectors
[i
].size
= 32 * 1024;
381 bank
->sectors
[i
].size
= 64 * 1024;
382 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
383 bank
->sectors
[i
].is_erased
= -1;
384 bank
->sectors
[i
].is_protected
= -1;
386 bank
->size
+= bank
->sectors
[i
].size
;
387 flash_addr
+= bank
->sectors
[i
].size
;
393 static void s6e2cc_init_sector(struct flash_sector
*sector
, int sa
)
396 sector
->size
= 8 * 1024;
398 sector
->size
= 32 * 1024;
400 sector
->size
= 64 * 1024;
402 sector
->is_erased
= -1;
403 sector
->is_protected
= -1;
406 static int s6e2cc_probe(struct flash_bank
*bank
)
408 struct target
*target
= bank
->target
;
409 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
411 uint32_t flash_addr
= bank
->base
;
413 unsigned int i
, num_extra_sectors
, num_sectors
;
415 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
416 if (retval
!= ERROR_OK
)
418 if (u32_value
& DFCTRLR_DFE
) {
419 LOG_WARNING("Dual Flash mode is not implemented.");
420 return ERROR_FLASH_OPER_UNSUPPORTED
;
423 switch (fm4_bank
->variant
) {
425 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
428 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
434 return ERROR_FLASH_OPER_UNSUPPORTED
;
436 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
437 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
439 LOG_DEBUG("%u sectors", bank
->num_sectors
);
440 bank
->sectors
= calloc(bank
->num_sectors
,
441 sizeof(struct flash_sector
));
442 for (i
= 0; i
< num_sectors
; i
++) {
444 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
445 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
447 bank
->size
+= bank
->sectors
[i
].size
;
448 flash_addr
+= bank
->sectors
[i
].size
;
451 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
452 for (; i
< bank
->num_sectors
; i
++) {
453 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
454 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
455 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
458 * Don't increase bank->size for these sectors
459 * to avoid an overlap between Flash Macros #0 and #1.
461 flash_addr
+= bank
->sectors
[i
].size
;
467 static int s6e2dh_probe(struct flash_bank
*bank
)
469 uint32_t flash_addr
= bank
->base
;
471 bank
->num_sectors
= 10;
472 bank
->sectors
= calloc(bank
->num_sectors
,
473 sizeof(struct flash_sector
));
474 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
476 bank
->sectors
[i
].size
= 8 * 1024;
478 bank
->sectors
[i
].size
= 32 * 1024;
480 bank
->sectors
[i
].size
= 64 * 1024;
481 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
482 bank
->sectors
[i
].is_erased
= -1;
483 bank
->sectors
[i
].is_protected
= -1;
485 bank
->size
+= bank
->sectors
[i
].size
;
486 flash_addr
+= bank
->sectors
[i
].size
;
492 static int fm4_probe(struct flash_bank
*bank
)
494 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
497 if (fm4_bank
->probed
)
500 if (bank
->target
->state
!= TARGET_HALTED
) {
501 LOG_WARNING("Cannot communicate... target not halted.");
502 return ERROR_TARGET_NOT_HALTED
;
505 switch (fm4_bank
->variant
) {
511 retval
= mb9bf_probe(bank
);
516 retval
= s6e2cc_probe(bank
);
519 retval
= s6e2dh_probe(bank
);
522 return ERROR_FLASH_OPER_UNSUPPORTED
;
524 if (retval
!= ERROR_OK
)
527 fm4_bank
->probed
= true;
532 static int fm4_auto_probe(struct flash_bank
*bank
)
534 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
536 if (fm4_bank
->probed
)
539 return fm4_probe(bank
);
542 static int fm4_get_info_command(struct flash_bank
*bank
, struct command_invocation
*cmd
)
544 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
547 if (bank
->target
->state
!= TARGET_HALTED
) {
548 LOG_WARNING("Cannot communicate... target not halted.");
549 return ERROR_TARGET_NOT_HALTED
;
552 switch (fm4_bank
->variant
) {
585 switch (fm4_bank
->variant
) {
589 command_print_sameline(cmd
, "%s MainFlash Macro #%i", name
, fm4_bank
->macro_nr
);
592 command_print_sameline(cmd
, "%s MainFlash", name
);
599 static bool fm4_name_match(const char *s
, const char *pattern
)
604 /* If the match string is shorter, ignore excess */
607 /* Use x as wildcard */
608 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
615 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
617 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
619 if (fm4_name_match(variant
, "MB9BFx64")) {
620 fm4_bank
->variant
= MB9BFX64
;
621 } else if (fm4_name_match(variant
, "MB9BFx65")) {
622 fm4_bank
->variant
= MB9BFX65
;
623 } else if (fm4_name_match(variant
, "MB9BFx66")) {
624 fm4_bank
->variant
= MB9BFX66
;
625 } else if (fm4_name_match(variant
, "MB9BFx67")) {
626 fm4_bank
->variant
= MB9BFX67
;
627 } else if (fm4_name_match(variant
, "MB9BFx68")) {
628 fm4_bank
->variant
= MB9BFX68
;
630 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
631 return ERROR_FLASH_OPER_UNSUPPORTED
;
637 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
639 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
641 if (fm4_name_match(variant
, "S6E2Cx8")) {
642 fm4_bank
->variant
= S6E2CX8
;
643 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
644 fm4_bank
->variant
= S6E2CX9
;
645 } else if (fm4_name_match(variant
, "S6E2CxA")) {
646 fm4_bank
->variant
= S6E2CXA
;
648 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
649 return ERROR_FLASH_OPER_UNSUPPORTED
;
655 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
657 struct fm4_flash_bank
*fm4_bank
;
662 return ERROR_COMMAND_SYNTAX_ERROR
;
664 variant
= CMD_ARGV
[6];
666 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
668 return ERROR_FLASH_OPERATION_FAILED
;
670 fm4_bank
->probed
= false;
671 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
673 bank
->driver_priv
= fm4_bank
;
675 if (fm4_name_match(variant
, "MB9BF"))
676 ret
= mb9bf_bank_setup(bank
, variant
);
677 else if (fm4_name_match(variant
, "S6E2Cx"))
678 ret
= s6e2cc_bank_setup(bank
, variant
);
679 else if (fm4_name_match(variant
, "S6E2Dx")) {
680 fm4_bank
->variant
= S6E2DX
;
683 LOG_WARNING("Family %s not recognized.", variant
);
684 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
691 const struct flash_driver fm4_flash
= {
693 .flash_bank_command
= fm4_flash_bank_command
,
694 .info
= fm4_get_info_command
,
696 .auto_probe
= fm4_auto_probe
,
697 .read
= default_flash_read
,
698 .erase
= fm4_flash_erase
,
699 .erase_check
= default_flash_blank_check
,
700 .write
= fm4_flash_write
,
701 .free_driver_priv
= default_flash_free_driver_priv
,
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)