target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / flash / nor / fm4.c
index 0f8de8caeb128bc965b098d26420c832621988c8..979ae84d0113f85cbb513affe755264b19fdb7b8 100644 (file)
@@ -1,8 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /*
  * Spansion FM4 flash
  *
  * 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
 #define WDG_LCK (WDG_BASE + 0xC00)
 
 enum fm4_variant {
-       mb9bfx64,
-       mb9bfx65,
-       mb9bfx66,
-       mb9bfx67,
-       mb9bfx68,
-
-       s6e2cx8,
-       s6e2cx9,
-       s6e2cxa,
+       MB9BFX64,
+       MB9BFX65,
+       MB9BFX66,
+       MB9BFX67,
+       MB9BFX68,
+
+       S6E2CX8,
+       S6E2CX9,
+       S6E2CXA,
+
+       S6E2DX,
 };
 
 struct fm4_flash_bank {
@@ -95,14 +100,15 @@ static int fm4_enter_flash_cpu_rom_mode(struct target *target)
        return ERROR_OK;
 }
 
-static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
+static int fm4_flash_erase(struct flash_bank *bank, unsigned int first,
+               unsigned int last)
 {
        struct target *target = bank->target;
        struct working_area *workarea;
        struct reg_param reg_params[4];
        struct armv7m_algorithm armv7m_algo;
        unsigned i;
-       int retval, sector;
+       int retval;
        const uint8_t erase_sector_code[] = {
 #include "../../../contrib/loaders/flash/fm4/erase.inc"
        };
@@ -112,7 +118,7 @@ static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first, last);
+       LOG_DEBUG("Spansion FM4 erase sectors %u to %u", first, last);
 
        retval = fm4_disable_hw_watchdog(target);
        if (retval != ERROR_OK)
@@ -142,7 +148,7 @@ static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
        init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
        init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
 
-       for (sector = first; sector <= last; sector++) {
+       for (unsigned int sector = first; sector <= last; sector++) {
                uint32_t addr = bank->base + bank->sectors[sector].offset;
                uint32_t result;
 
@@ -168,13 +174,11 @@ static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
                        retval = ERROR_FLASH_OPERATION_FAILED;
                        goto err_run_ret;
                } else if (result != 0) {
-                       LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result);
+                       LOG_ERROR("Unexpected error %" PRIu32 " from flash sector erase programming algorithm", result);
                        retval = ERROR_FLASH_OPERATION_FAILED;
                        goto err_run_ret;
                } else
                        retval = ERROR_OK;
-
-               bank->sectors[sector].is_erased = 1;
        }
 
 err_run_ret:
@@ -204,12 +208,12 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
        uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2);
        uint32_t result;
        unsigned i;
-       int retval;
+       int retval, retval2 = ERROR_OK;
        const uint8_t write_block_code[] = {
 #include "../../../contrib/loaders/flash/fm4/write.inc"
        };
 
-       LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32 " (%" PRId32 " bytes)",
+       LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32 " (%" PRIu32 " bytes)",
                offset, byte_count);
 
        if (offset & 0x1) {
@@ -218,7 +222,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
                return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
        }
        if (byte_count & 0x1) {
-               LOG_WARNING("length %" PRId32 " is not 2-byte aligned, rounding up",
+               LOG_WARNING("length %" PRIu32 " is not 2-byte aligned, rounding up",
                        byte_count);
        }
 
@@ -269,7 +273,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 %" PRIu32 " bytes to SRAM " TARGET_ADDR_FMT,
                        MIN(halfwords * 2, byte_count), data_workarea->address);
 
                retval = target_write_buffer(target, data_workarea->address,
@@ -280,7 +284,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
                        goto err_write_data;
                }
 
-               LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRId32 "x)",
+               LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRIu32 "x)",
                        addr, addr + halfwords * 2 - 1, halfwords);
 
                buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
@@ -308,7 +312,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
                        retval = ERROR_FLASH_OPERATION_FAILED;
                        goto err_run_ret;
                } else if (result != 0) {
-                       LOG_ERROR("Unexpected error %d from flash write "
+                       LOG_ERROR("Unexpected error %" PRIu32 " from flash write "
                                "programming algorithm", result);
                        retval = ERROR_FLASH_OPERATION_FAILED;
                        goto err_run_ret;
@@ -324,7 +328,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
 err_run_ret:
 err_run:
 err_write_data:
-       retval = fm4_enter_flash_cpu_rom_mode(target);
+       retval2 = fm4_enter_flash_cpu_rom_mode(target);
 
 err_flash_mode:
        for (i = 0; i < ARRAY_SIZE(reg_params); i++)
@@ -335,39 +339,40 @@ err_alloc_data:
 err_write_code:
        target_free_working_area(target, code_workarea);
 
-       return retval;
+       if (retval != ERROR_OK)
+               return retval;
+       return retval2;
 }
 
 static int mb9bf_probe(struct flash_bank *bank)
 {
        struct fm4_flash_bank *fm4_bank = bank->driver_priv;
        uint32_t flash_addr = bank->base;
-       int i;
 
        switch (fm4_bank->variant) {
-       case mb9bfx64:
+       case MB9BFX64:
                bank->num_sectors = 8;
                break;
-       case mb9bfx65:
+       case MB9BFX65:
                bank->num_sectors = 10;
                break;
-       case mb9bfx66:
+       case MB9BFX66:
                bank->num_sectors = 12;
                break;
-       case mb9bfx67:
+       case MB9BFX67:
                bank->num_sectors = 16;
                break;
-       case mb9bfx68:
+       case MB9BFX68:
                bank->num_sectors = 20;
                break;
        default:
                return ERROR_FLASH_OPER_UNSUPPORTED;
        }
 
-       LOG_DEBUG("%d sectors", bank->num_sectors);
+       LOG_DEBUG("%u sectors", bank->num_sectors);
        bank->sectors = calloc(bank->num_sectors,
                                sizeof(struct flash_sector));
-       for (i = 0; i < bank->num_sectors; i++) {
+       for (unsigned int i = 0; i < bank->num_sectors; i++) {
                if (i < 4)
                        bank->sectors[i].size = 8 * 1024;
                else if (i == 4)
@@ -404,7 +409,8 @@ static int s6e2cc_probe(struct flash_bank *bank)
        struct fm4_flash_bank *fm4_bank = bank->driver_priv;
        uint32_t u32_value;
        uint32_t flash_addr = bank->base;
-       int i, retval, num_sectors, num_extra_sectors;
+       int retval;
+       unsigned int i, num_extra_sectors, num_sectors;
 
        retval = target_read_u32(target, DFCTRLR, &u32_value);
        if (retval != ERROR_OK)
@@ -415,13 +421,13 @@ static int s6e2cc_probe(struct flash_bank *bank)
        }
 
        switch (fm4_bank->variant) {
-       case s6e2cx8:
+       case S6E2CX8:
                num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 0;
                break;
-       case s6e2cx9:
+       case S6E2CX9:
                num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 12;
                break;
-       case s6e2cxa:
+       case S6E2CXA:
                num_sectors = 20;
                break;
        default:
@@ -430,7 +436,7 @@ static int s6e2cc_probe(struct flash_bank *bank)
        num_extra_sectors = (fm4_bank->macro_nr == 0) ? 1 : 4;
        bank->num_sectors = num_sectors + num_extra_sectors;
 
-       LOG_DEBUG("%d sectors", bank->num_sectors);
+       LOG_DEBUG("%u sectors", bank->num_sectors);
        bank->sectors = calloc(bank->num_sectors,
                                sizeof(struct flash_sector));
        for (i = 0; i < num_sectors; i++) {
@@ -458,6 +464,31 @@ 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;
+
+       bank->num_sectors = 10;
+       bank->sectors = calloc(bank->num_sectors,
+                               sizeof(struct flash_sector));
+       for (unsigned int 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;
@@ -472,18 +503,21 @@ static int fm4_probe(struct flash_bank *bank)
        }
 
        switch (fm4_bank->variant) {
-       case mb9bfx64:
-       case mb9bfx65:
-       case mb9bfx66:
-       case mb9bfx67:
-       case mb9bfx68:
+       case MB9BFX64:
+       case MB9BFX65:
+       case MB9BFX66:
+       case MB9BFX67:
+       case MB9BFX68:
                retval = mb9bf_probe(bank);
                break;
-       case s6e2cx8:
-       case s6e2cx9:
-       case s6e2cxa:
+       case S6E2CX8:
+       case S6E2CX9:
+       case S6E2CXA:
                retval = s6e2cc_probe(bank);
                break;
+       case S6E2DX:
+               retval = s6e2dh_probe(bank);
+               break;
        default:
                return ERROR_FLASH_OPER_UNSUPPORTED;
        }
@@ -505,12 +539,7 @@ static int fm4_auto_probe(struct flash_bank *bank)
        return fm4_probe(bank);
 }
 
-static int fm4_protect_check(struct flash_bank *bank)
-{
-       return ERROR_OK;
-}
-
-static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
+static int fm4_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
 {
        struct fm4_flash_bank *fm4_bank = bank->driver_priv;
        const char *name;
@@ -521,44 +550,46 @@ static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size
        }
 
        switch (fm4_bank->variant) {
-       case mb9bfx64:
+       case MB9BFX64:
                name = "MB9BFx64";
                break;
-       case mb9bfx65:
+       case MB9BFX65:
                name = "MB9BFx65";
                break;
-       case mb9bfx66:
+       case MB9BFX66:
                name = "MB9BFx66";
                break;
-       case mb9bfx67:
+       case MB9BFX67:
                name = "MB9BFx67";
                break;
-       case mb9bfx68:
+       case MB9BFX68:
                name = "MB9BFx68";
                break;
-       case s6e2cx8:
+       case S6E2CX8:
                name = "S6E2Cx8";
                break;
-       case s6e2cx9:
+       case S6E2CX9:
                name = "S6E2Cx9";
                break;
-       case s6e2cxa:
+       case S6E2CXA:
                name = "S6E2CxA";
                break;
+       case S6E2DX:
+               name = "S6E2Dx";
+               break;
        default:
                name = "unknown";
                break;
        }
 
        switch (fm4_bank->variant) {
-       case s6e2cx8:
-       case s6e2cx9:
-       case s6e2cxa:
-               snprintf(buf, buf_size, "%s MainFlash Macro #%i",
-                       name, fm4_bank->macro_nr);
+       case S6E2CX8:
+       case S6E2CX9:
+       case S6E2CXA:
+               command_print_sameline(cmd, "%s MainFlash Macro #%i", name, fm4_bank->macro_nr);
                break;
        default:
-               snprintf(buf, buf_size, "%s MainFlash", name);
+               command_print_sameline(cmd, "%s MainFlash", name);
                break;
        }
 
@@ -586,15 +617,15 @@ 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, "MB9BFx64")) {
-               fm4_bank->variant = mb9bfx64;
+               fm4_bank->variant = MB9BFX64;
        } else if (fm4_name_match(variant, "MB9BFx65")) {
-               fm4_bank->variant = mb9bfx65;
+               fm4_bank->variant = MB9BFX65;
        } else if (fm4_name_match(variant, "MB9BFx66")) {
-               fm4_bank->variant = mb9bfx66;
+               fm4_bank->variant = MB9BFX66;
        } else if (fm4_name_match(variant, "MB9BFx67")) {
-               fm4_bank->variant = mb9bfx67;
+               fm4_bank->variant = MB9BFX67;
        } else if (fm4_name_match(variant, "MB9BFx68")) {
-               fm4_bank->variant = mb9bfx68;
+               fm4_bank->variant = MB9BFX68;
        } else {
                LOG_WARNING("MB9BF variant %s not recognized.", variant);
                return ERROR_FLASH_OPER_UNSUPPORTED;
@@ -608,11 +639,11 @@ static int s6e2cc_bank_setup(struct flash_bank *bank, const char *variant)
        struct fm4_flash_bank *fm4_bank = bank->driver_priv;
 
        if (fm4_name_match(variant, "S6E2Cx8")) {
-               fm4_bank->variant = s6e2cx8;
+               fm4_bank->variant = S6E2CX8;
        } else if (fm4_name_match(variant, "S6E2Cx9")) {
-               fm4_bank->variant = s6e2cx9;
+               fm4_bank->variant = S6E2CX9;
        } else if (fm4_name_match(variant, "S6E2CxA")) {
-               fm4_bank->variant = s6e2cxa;
+               fm4_bank->variant = S6E2CXA;
        } else {
                LOG_WARNING("S6E2CC variant %s not recognized.", variant);
                return ERROR_FLASH_OPER_UNSUPPORTED;
@@ -645,7 +676,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;
        }
@@ -654,30 +688,15 @@ FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command)
        return ret;
 }
 
-static const struct command_registration fm4_exec_command_handlers[] = {
-       COMMAND_REGISTRATION_DONE
-};
-
-static const struct command_registration fm4_command_handlers[] = {
-       {
-               .name = "fm4",
-               .mode = COMMAND_ANY,
-               .help = "fm4 flash command group",
-               .usage = "",
-               .chain = fm4_exec_command_handlers,
-       },
-       COMMAND_REGISTRATION_DONE
-};
-
-struct flash_driver fm4_flash = {
+const struct flash_driver fm4_flash = {
        .name = "fm4",
-       .commands = fm4_command_handlers,
        .flash_bank_command = fm4_flash_bank_command,
        .info = fm4_get_info_command,
        .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,
 };

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)