4 * Copyright (c) 2015 Andreas Färber
6 * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
7 * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
8 * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
9 * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
17 #include <helper/binarybuffer.h>
18 #include <target/algorithm.h>
19 #include <target/armv7m.h>
21 #define FLASH_BASE 0x40000000
22 #define FASZR (FLASH_BASE + 0x000)
23 #define DFCTRLR (FLASH_BASE + 0x030)
24 #define DFCTRLR_DFE (1UL << 0)
26 #define WDG_BASE 0x40011000
27 #define WDG_CTL (WDG_BASE + 0x008)
28 #define WDG_LCK (WDG_BASE + 0xC00)
44 struct fm4_flash_bank
{
45 enum fm4_variant variant
;
50 static int fm4_disable_hw_watchdog(struct target
*target
)
54 retval
= target_write_u32(target
, WDG_LCK
, 0x1ACCE551);
55 if (retval
!= ERROR_OK
)
58 retval
= target_write_u32(target
, WDG_LCK
, 0xE5331AAE);
59 if (retval
!= ERROR_OK
)
62 retval
= target_write_u32(target
, WDG_CTL
, 0);
63 if (retval
!= ERROR_OK
)
69 static int fm4_enter_flash_cpu_programming_mode(struct target
*target
)
74 /* FASZR ASZ = CPU programming mode */
75 retval
= target_write_u32(target
, FASZR
, 0x00000001);
76 if (retval
!= ERROR_OK
)
78 retval
= target_read_u32(target
, FASZR
, &u32_value
);
79 if (retval
!= ERROR_OK
)
85 static int fm4_enter_flash_cpu_rom_mode(struct target
*target
)
90 /* FASZR ASZ = CPU ROM mode */
91 retval
= target_write_u32(target
, FASZR
, 0x00000002);
92 if (retval
!= ERROR_OK
)
94 retval
= target_read_u32(target
, FASZR
, &u32_value
);
95 if (retval
!= ERROR_OK
)
101 static int fm4_flash_erase(struct flash_bank
*bank
, int first
, int last
)
103 struct target
*target
= bank
->target
;
104 struct working_area
*workarea
;
105 struct reg_param reg_params
[4];
106 struct armv7m_algorithm armv7m_algo
;
109 const uint8_t erase_sector_code
[] = {
110 #include "../../../contrib/loaders/flash/fm4/erase.inc"
113 if (target
->state
!= TARGET_HALTED
) {
114 LOG_WARNING("Cannot communicate... target not halted.");
115 return ERROR_TARGET_NOT_HALTED
;
118 LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first
, last
);
120 retval
= fm4_disable_hw_watchdog(target
);
121 if (retval
!= ERROR_OK
)
124 retval
= fm4_enter_flash_cpu_programming_mode(target
);
125 if (retval
!= ERROR_OK
)
128 retval
= target_alloc_working_area(target
, sizeof(erase_sector_code
),
130 if (retval
!= ERROR_OK
) {
131 LOG_ERROR("No working area available.");
132 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
135 retval
= target_write_buffer(target
, workarea
->address
,
136 sizeof(erase_sector_code
), erase_sector_code
);
137 if (retval
!= ERROR_OK
)
140 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
141 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
143 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
144 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
145 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
146 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
148 for (sector
= first
; sector
<= last
; sector
++) {
149 uint32_t addr
= bank
->base
+ bank
->sectors
[sector
].offset
;
152 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
153 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
154 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
156 retval
= target_run_algorithm(target
,
158 ARRAY_SIZE(reg_params
), reg_params
,
159 workarea
->address
, 0,
161 if (retval
!= ERROR_OK
) {
162 LOG_ERROR("Error executing flash sector erase "
163 "programming algorithm");
164 retval
= ERROR_FLASH_OPERATION_FAILED
;
168 result
= buf_get_u32(reg_params
[3].value
, 0, 32);
170 LOG_ERROR("Timeout error from flash sector erase programming algorithm");
171 retval
= ERROR_FLASH_OPERATION_FAILED
;
173 } else if (result
!= 0) {
174 LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result
);
175 retval
= ERROR_FLASH_OPERATION_FAILED
;
180 bank
->sectors
[sector
].is_erased
= 1;
185 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
186 destroy_reg_param(®_params
[i
]);
189 target_free_working_area(target
, workarea
);
192 if (retval
!= ERROR_OK
)
193 fm4_enter_flash_cpu_rom_mode(target
);
195 retval
= fm4_enter_flash_cpu_rom_mode(target
);
200 static int fm4_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
201 uint32_t offset
, uint32_t byte_count
)
203 struct target
*target
= bank
->target
;
204 struct working_area
*code_workarea
, *data_workarea
;
205 struct reg_param reg_params
[6];
206 struct armv7m_algorithm armv7m_algo
;
207 uint32_t halfword_count
= DIV_ROUND_UP(byte_count
, 2);
211 const uint8_t write_block_code
[] = {
212 #include "../../../contrib/loaders/flash/fm4/write.inc"
215 LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32
" (%" PRId32
" bytes)",
219 LOG_ERROR("offset 0x%" PRIx32
" breaks required 2-byte alignment",
221 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
223 if (byte_count
& 0x1) {
224 LOG_WARNING("length %" PRId32
" is not 2-byte aligned, rounding up",
228 if (target
->state
!= TARGET_HALTED
) {
229 LOG_WARNING("Cannot communicate... target not halted.");
230 return ERROR_TARGET_NOT_HALTED
;
233 retval
= fm4_disable_hw_watchdog(target
);
234 if (retval
!= ERROR_OK
)
237 retval
= target_alloc_working_area(target
, sizeof(write_block_code
),
239 if (retval
!= ERROR_OK
) {
240 LOG_ERROR("No working area available for write code.");
241 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
243 retval
= target_write_buffer(target
, code_workarea
->address
,
244 sizeof(write_block_code
), write_block_code
);
245 if (retval
!= ERROR_OK
)
248 retval
= target_alloc_working_area(target
,
249 MIN(halfword_count
* 2, target_get_working_area_avail(target
)),
251 if (retval
!= ERROR_OK
) {
252 LOG_ERROR("No working area available for write data.");
253 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
257 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
258 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
260 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
261 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
262 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
263 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
264 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
);
265 init_reg_param(®_params
[5], "r5", 32, PARAM_IN
);
267 retval
= fm4_enter_flash_cpu_programming_mode(target
);
268 if (retval
!= ERROR_OK
)
271 while (byte_count
> 0) {
272 uint32_t halfwords
= MIN(halfword_count
, data_workarea
->size
/ 2);
273 uint32_t addr
= bank
->base
+ offset
;
275 LOG_DEBUG("copying %" PRId32
" bytes to SRAM 0x%08" PRIx32
,
276 MIN(halfwords
* 2, byte_count
), data_workarea
->address
);
278 retval
= target_write_buffer(target
, data_workarea
->address
,
279 MIN(halfwords
* 2, byte_count
), buffer
);
280 if (retval
!= ERROR_OK
) {
281 LOG_ERROR("Error writing data buffer");
282 retval
= ERROR_FLASH_OPERATION_FAILED
;
286 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRId32
"x)",
287 addr
, addr
+ halfwords
* 2 - 1, halfwords
);
289 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
290 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
291 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
292 buf_set_u32(reg_params
[3].value
, 0, 32, data_workarea
->address
);
293 buf_set_u32(reg_params
[4].value
, 0, 32, halfwords
);
295 retval
= target_run_algorithm(target
,
297 ARRAY_SIZE(reg_params
), reg_params
,
298 code_workarea
->address
, 0,
299 5 * 60 * 1000, &armv7m_algo
);
300 if (retval
!= ERROR_OK
) {
301 LOG_ERROR("Error executing flash sector erase "
302 "programming algorithm");
303 retval
= ERROR_FLASH_OPERATION_FAILED
;
307 result
= buf_get_u32(reg_params
[5].value
, 0, 32);
309 LOG_ERROR("Timeout error from flash write "
310 "programming algorithm");
311 retval
= ERROR_FLASH_OPERATION_FAILED
;
313 } else if (result
!= 0) {
314 LOG_ERROR("Unexpected error %d from flash write "
315 "programming algorithm", result
);
316 retval
= ERROR_FLASH_OPERATION_FAILED
;
321 halfword_count
-= halfwords
;
322 offset
+= halfwords
* 2;
323 buffer
+= halfwords
* 2;
324 byte_count
-= MIN(halfwords
* 2, byte_count
);
330 retval
= fm4_enter_flash_cpu_rom_mode(target
);
333 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
334 destroy_reg_param(®_params
[i
]);
336 target_free_working_area(target
, data_workarea
);
339 target_free_working_area(target
, code_workarea
);
344 static int mb9bf_probe(struct flash_bank
*bank
)
346 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
347 uint32_t flash_addr
= bank
->base
;
350 switch (fm4_bank
->variant
) {
352 bank
->num_sectors
= 8;
355 bank
->num_sectors
= 10;
358 bank
->num_sectors
= 12;
361 bank
->num_sectors
= 16;
364 bank
->num_sectors
= 20;
367 return ERROR_FLASH_OPER_UNSUPPORTED
;
370 LOG_DEBUG("%d sectors", bank
->num_sectors
);
371 bank
->sectors
= calloc(bank
->num_sectors
,
372 sizeof(struct flash_sector
));
373 for (i
= 0; i
< bank
->num_sectors
; i
++) {
375 bank
->sectors
[i
].size
= 8 * 1024;
377 bank
->sectors
[i
].size
= 32 * 1024;
379 bank
->sectors
[i
].size
= 64 * 1024;
380 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
381 bank
->sectors
[i
].is_erased
= -1;
382 bank
->sectors
[i
].is_protected
= -1;
384 bank
->size
+= bank
->sectors
[i
].size
;
385 flash_addr
+= bank
->sectors
[i
].size
;
391 static void s6e2cc_init_sector(struct flash_sector
*sector
, int sa
)
394 sector
->size
= 8 * 1024;
396 sector
->size
= 32 * 1024;
398 sector
->size
= 64 * 1024;
400 sector
->is_erased
= -1;
401 sector
->is_protected
= -1;
404 static int s6e2cc_probe(struct flash_bank
*bank
)
406 struct target
*target
= bank
->target
;
407 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
409 uint32_t flash_addr
= bank
->base
;
410 int i
, retval
, num_sectors
, num_extra_sectors
;
412 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
413 if (retval
!= ERROR_OK
)
415 if (u32_value
& DFCTRLR_DFE
) {
416 LOG_WARNING("Dual Flash mode is not implemented.");
417 return ERROR_FLASH_OPER_UNSUPPORTED
;
420 switch (fm4_bank
->variant
) {
422 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
425 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
431 return ERROR_FLASH_OPER_UNSUPPORTED
;
433 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
434 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
436 LOG_DEBUG("%d sectors", bank
->num_sectors
);
437 bank
->sectors
= calloc(bank
->num_sectors
,
438 sizeof(struct flash_sector
));
439 for (i
= 0; i
< num_sectors
; i
++) {
441 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
442 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
444 bank
->size
+= bank
->sectors
[i
].size
;
445 flash_addr
+= bank
->sectors
[i
].size
;
448 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
449 for (; i
< bank
->num_sectors
; i
++) {
450 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
451 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
452 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
455 * Don't increase bank->size for these sectors
456 * to avoid an overlap between Flash Macros #0 and #1.
458 flash_addr
+= bank
->sectors
[i
].size
;
464 static int s6e2dh_probe(struct flash_bank
*bank
)
466 uint32_t flash_addr
= bank
->base
;
469 bank
->num_sectors
= 10;
470 bank
->sectors
= calloc(bank
->num_sectors
,
471 sizeof(struct flash_sector
));
472 for (i
= 0; i
< bank
->num_sectors
; i
++) {
474 bank
->sectors
[i
].size
= 8 * 1024;
476 bank
->sectors
[i
].size
= 32 * 1024;
478 bank
->sectors
[i
].size
= 64 * 1024;
479 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
480 bank
->sectors
[i
].is_erased
= -1;
481 bank
->sectors
[i
].is_protected
= -1;
483 bank
->size
+= bank
->sectors
[i
].size
;
484 flash_addr
+= bank
->sectors
[i
].size
;
490 static int fm4_probe(struct flash_bank
*bank
)
492 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
495 if (fm4_bank
->probed
)
498 if (bank
->target
->state
!= TARGET_HALTED
) {
499 LOG_WARNING("Cannot communicate... target not halted.");
500 return ERROR_TARGET_NOT_HALTED
;
503 switch (fm4_bank
->variant
) {
509 retval
= mb9bf_probe(bank
);
514 retval
= s6e2cc_probe(bank
);
517 retval
= s6e2dh_probe(bank
);
520 return ERROR_FLASH_OPER_UNSUPPORTED
;
522 if (retval
!= ERROR_OK
)
525 fm4_bank
->probed
= true;
530 static int fm4_auto_probe(struct flash_bank
*bank
)
532 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
534 if (fm4_bank
->probed
)
537 return fm4_probe(bank
);
540 static int fm4_protect_check(struct flash_bank
*bank
)
545 static int fm4_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
547 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
550 if (bank
->target
->state
!= TARGET_HALTED
) {
551 LOG_WARNING("Cannot communicate... target not halted.");
552 return ERROR_TARGET_NOT_HALTED
;
555 switch (fm4_bank
->variant
) {
588 switch (fm4_bank
->variant
) {
592 snprintf(buf
, buf_size
, "%s MainFlash Macro #%i",
593 name
, fm4_bank
->macro_nr
);
596 snprintf(buf
, buf_size
, "%s MainFlash", name
);
603 static bool fm4_name_match(const char *s
, const char *pattern
)
608 /* If the match string is shorter, ignore excess */
611 /* Use x as wildcard */
612 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
619 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
621 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
623 if (fm4_name_match(variant
, "MB9BFx64")) {
624 fm4_bank
->variant
= mb9bfx64
;
625 } else if (fm4_name_match(variant
, "MB9BFx65")) {
626 fm4_bank
->variant
= mb9bfx65
;
627 } else if (fm4_name_match(variant
, "MB9BFx66")) {
628 fm4_bank
->variant
= mb9bfx66
;
629 } else if (fm4_name_match(variant
, "MB9BFx67")) {
630 fm4_bank
->variant
= mb9bfx67
;
631 } else if (fm4_name_match(variant
, "MB9BFx68")) {
632 fm4_bank
->variant
= mb9bfx68
;
634 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
635 return ERROR_FLASH_OPER_UNSUPPORTED
;
641 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
643 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
645 if (fm4_name_match(variant
, "S6E2Cx8")) {
646 fm4_bank
->variant
= s6e2cx8
;
647 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
648 fm4_bank
->variant
= s6e2cx9
;
649 } else if (fm4_name_match(variant
, "S6E2CxA")) {
650 fm4_bank
->variant
= s6e2cxa
;
652 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
653 return ERROR_FLASH_OPER_UNSUPPORTED
;
659 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
661 struct fm4_flash_bank
*fm4_bank
;
666 return ERROR_COMMAND_SYNTAX_ERROR
;
668 variant
= CMD_ARGV
[6];
670 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
672 return ERROR_FLASH_OPERATION_FAILED
;
674 fm4_bank
->probed
= false;
675 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
677 bank
->driver_priv
= fm4_bank
;
679 if (fm4_name_match(variant
, "MB9BF"))
680 ret
= mb9bf_bank_setup(bank
, variant
);
681 else if (fm4_name_match(variant
, "S6E2Cx"))
682 ret
= s6e2cc_bank_setup(bank
, variant
);
683 else if (fm4_name_match(variant
, "S6E2Dx")) {
684 fm4_bank
->variant
= s6e2dx
;
687 LOG_WARNING("Family %s not recognized.", variant
);
688 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
695 static const struct command_registration fm4_exec_command_handlers
[] = {
696 COMMAND_REGISTRATION_DONE
699 static const struct command_registration fm4_command_handlers
[] = {
703 .help
= "fm4 flash command group",
705 .chain
= fm4_exec_command_handlers
,
707 COMMAND_REGISTRATION_DONE
710 struct flash_driver fm4_flash
= {
712 .commands
= fm4_command_handlers
,
713 .flash_bank_command
= fm4_flash_bank_command
,
714 .info
= fm4_get_info_command
,
716 .auto_probe
= fm4_auto_probe
,
717 .protect_check
= fm4_protect_check
,
718 .read
= default_flash_read
,
719 .erase
= fm4_flash_erase
,
720 .erase_check
= default_flash_blank_check
,
721 .write
= fm4_flash_write
,