flash/nor/stm32: Eliminate working area leak
[fw/openocd] / src / flash / nor / fm4.c
index 917ff0186b809ba59a5486131911ebbccba68e48..f5eab9c5b39c39444f08de3956344213bd4e1b8b 100644 (file)
@@ -3,8 +3,10 @@
  *
  * Copyright (c) 2015 Andreas Färber
  *
+ * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
  * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
  * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
+ * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
  */
 
 #ifdef HAVE_CONFIG_H
@@ -26,6 +28,8 @@
 #define WDG_LCK (WDG_BASE + 0xC00)
 
 enum fm4_variant {
+       mb9bfx64,
+       mb9bfx65,
        mb9bfx66,
        mb9bfx67,
        mb9bfx68,
@@ -33,6 +37,8 @@ enum fm4_variant {
        s6e2cx8,
        s6e2cx9,
        s6e2cxa,
+
+       s6e2dx,
 };
 
 struct fm4_flash_bank {
@@ -266,7 +272,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2);
                uint32_t addr = bank->base + offset;
 
-               LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32,
+               LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
                        MIN(halfwords * 2, byte_count), data_workarea->address);
 
                retval = target_write_buffer(target, data_workarea->address,
@@ -342,6 +348,12 @@ static int mb9bf_probe(struct flash_bank *bank)
        int i;
 
        switch (fm4_bank->variant) {
+       case mb9bfx64:
+               bank->num_sectors = 8;
+               break;
+       case mb9bfx65:
+               bank->num_sectors = 10;
+               break;
        case mb9bfx66:
                bank->num_sectors = 12;
                break;
@@ -449,6 +461,32 @@ static int s6e2cc_probe(struct flash_bank *bank)
        return ERROR_OK;
 }
 
+static int s6e2dh_probe(struct flash_bank *bank)
+{
+       uint32_t flash_addr = bank->base;
+       int i;
+
+       bank->num_sectors = 10;
+       bank->sectors = calloc(bank->num_sectors,
+                               sizeof(struct flash_sector));
+       for (i = 0; i < bank->num_sectors; i++) {
+               if (i < 4)
+                       bank->sectors[i].size = 8 * 1024;
+               else if (i == 4)
+                       bank->sectors[i].size = 32 * 1024;
+               else
+                       bank->sectors[i].size = 64 * 1024;
+               bank->sectors[i].offset = flash_addr - bank->base;
+               bank->sectors[i].is_erased = -1;
+               bank->sectors[i].is_protected = -1;
+
+               bank->size += bank->sectors[i].size;
+               flash_addr += bank->sectors[i].size;
+       }
+
+       return ERROR_OK;
+}
+
 static int fm4_probe(struct flash_bank *bank)
 {
        struct fm4_flash_bank *fm4_bank = bank->driver_priv;
@@ -463,6 +501,8 @@ static int fm4_probe(struct flash_bank *bank)
        }
 
        switch (fm4_bank->variant) {
+       case mb9bfx64:
+       case mb9bfx65:
        case mb9bfx66:
        case mb9bfx67:
        case mb9bfx68:
@@ -473,6 +513,9 @@ static int fm4_probe(struct flash_bank *bank)
        case s6e2cxa:
                retval = s6e2cc_probe(bank);
                break;
+       case s6e2dx:
+               retval = s6e2dh_probe(bank);
+               break;
        default:
                return ERROR_FLASH_OPER_UNSUPPORTED;
        }
@@ -510,6 +553,12 @@ static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size
        }
 
        switch (fm4_bank->variant) {
+       case mb9bfx64:
+               name = "MB9BFx64";
+               break;
+       case mb9bfx65:
+               name = "MB9BFx65";
+               break;
        case mb9bfx66:
                name = "MB9BFx66";
                break;
@@ -528,6 +577,9 @@ static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size
        case s6e2cxa:
                name = "S6E2CxA";
                break;
+       case s6e2dx:
+               name = "S6E2Dx";
+               break;
        default:
                name = "unknown";
                break;
@@ -568,7 +620,11 @@ static int mb9bf_bank_setup(struct flash_bank *bank, const char *variant)
 {
        struct fm4_flash_bank *fm4_bank = bank->driver_priv;
 
-       if (fm4_name_match(variant, "MB9BFx66")) {
+       if (fm4_name_match(variant, "MB9BFx64")) {
+               fm4_bank->variant = mb9bfx64;
+       } else if (fm4_name_match(variant, "MB9BFx65")) {
+               fm4_bank->variant = mb9bfx65;
+       } else if (fm4_name_match(variant, "MB9BFx66")) {
                fm4_bank->variant = mb9bfx66;
        } else if (fm4_name_match(variant, "MB9BFx67")) {
                fm4_bank->variant = mb9bfx67;
@@ -624,7 +680,10 @@ FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command)
                ret = mb9bf_bank_setup(bank, variant);
        else if (fm4_name_match(variant, "S6E2Cx"))
                ret = s6e2cc_bank_setup(bank, variant);
-       else {
+       else if (fm4_name_match(variant, "S6E2Dx")) {
+               fm4_bank->variant = s6e2dx;
+               ret = ERROR_OK;
+       } else {
                LOG_WARNING("Family %s not recognized.", variant);
                ret = ERROR_FLASH_OPER_UNSUPPORTED;
        }
@@ -656,7 +715,9 @@ struct flash_driver fm4_flash = {
        .probe = fm4_probe,
        .auto_probe = fm4_auto_probe,
        .protect_check = fm4_protect_check,
+       .read = default_flash_read,
        .erase = fm4_flash_erase,
        .erase_check = default_flash_blank_check,
        .write = fm4_flash_write,
+       .free_driver_priv = default_flash_free_driver_priv,
 };