flash/nor/atsame5: add SAME51G18A and SAME51G19A devices
[openocd.git] / src / flash / nor / atsame5.c
index df423491787dc805f7a8f7f1265558b267658b6d..50e56a72ae9f43150f5420d94674e5e6b1d6d15c 100644 (file)
 #include "imp.h"
 #include "helper/binarybuffer.h"
 
+#include <helper/time_support.h>
 #include <target/cortex_m.h>
 
 /* A note to prefixing.
- * Definitions and functions ingerited from at91samd.c without
- * any change retained the original prefix samd_ so they eventualy
+ * Definitions and functions inherited from at91samd.c without
+ * any change retained the original prefix samd_ so they eventually
  * may go to samd_common.h and .c
- * As currently there are olny 3 short functions identical with
+ * As currently there are only 3 short functions identical with
  * the original source, no common file was created. */
 
 #define SAME5_PAGES_PER_BLOCK  16
@@ -112,7 +113,7 @@ struct samd_part {
 };
 
 /* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
- * DS80000748B */
+ * DS80000748K */
 /* Known SAMD51 parts. */
 static const struct samd_part samd51_parts[] = {
        { 0x00, "SAMD51P20A", 1024, 256 },
@@ -133,6 +134,8 @@ static const struct samd_part same51_parts[] = {
        { 0x02, "SAME51J19A", 512, 192 },
        { 0x03, "SAME51J18A", 256, 128 },
        { 0x04, "SAME51J20A", 1024, 256 },
+       { 0x05, "SAME51G19A", 512, 192 },       /* New in rev D */
+       { 0x06, "SAME51G18A", 256, 128 },       /* New in rev D */
 };
 
 /* Known SAME53 parts. */
@@ -230,7 +233,7 @@ static const struct samd_part *samd_find_part(uint32_t id)
 
 static int same5_protect_check(struct flash_bank *bank)
 {
-       int res, prot_block;
+       int res;
        uint32_t lock;
 
        res = target_read_u32(bank->target,
@@ -239,7 +242,7 @@ static int same5_protect_check(struct flash_bank *bank)
                return res;
 
        /* Lock bits are active-low */
-       for (prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
+       for (unsigned int prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
                bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
 
        return ERROR_OK;
@@ -338,19 +341,28 @@ static int same5_probe(struct flash_bank *bank)
 static int same5_wait_and_check_error(struct target *target)
 {
        int ret, ret2;
-       int rep_cnt = 100;
+       /* Table 54-40 lists the maximum erase block time as 200 ms.
+        * Include some margin.
+        */
+       int timeout_ms = 200 * 5;
+       int64_t ts_start = timeval_ms();
        uint16_t intflag;
 
        do {
                ret = target_read_u16(target,
                        SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, &intflag);
-               if (ret == ERROR_OK && intflag & SAME5_NVMCTRL_INTFLAG_DONE)
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("SAM: error reading the NVMCTRL_INTFLAG register");
+                       return ret;
+               }
+               if (intflag & SAME5_NVMCTRL_INTFLAG_DONE)
                        break;
-       } while (--rep_cnt);
+               keep_alive();
+       } while (timeval_ms() - ts_start < timeout_ms);
 
-       if (ret != ERROR_OK) {
-               LOG_ERROR("Can't read NVM INTFLAG");
-               return ret;
+       if (!(intflag & SAME5_NVMCTRL_INTFLAG_DONE)) {
+               LOG_ERROR("SAM: NVM programming timed out");
+               ret = ERROR_FLASH_OPERATION_FAILED;
        }
 #if 0
        if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE)
@@ -559,10 +571,10 @@ static int same5_modify_user_row(struct target *target, uint32_t value,
                        buf_val, buf_mask, 0, 8);
 }
 
-static int same5_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl)
+static int same5_protect(struct flash_bank *bank, int set, unsigned int first,
+               unsigned int last)
 {
        int res = ERROR_OK;
-       int prot_block;
 
        /* We can issue lock/unlock region commands with the target running but
         * the settings won't persist unless we're able to modify the LOCK regions
@@ -572,7 +584,7 @@ static int same5_protect(struct flash_bank *bank, int set, int first_prot_bl, in
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) {
+       for (unsigned int prot_block = first; prot_block <= last; prot_block++) {
                if (set != bank->prot_blocks[prot_block].is_protected) {
                        /* Load an address that is within this protection block (we use offset 0) */
                        res = target_write_u32(bank->target,
@@ -596,7 +608,7 @@ static int same5_protect(struct flash_bank *bank, int set, int first_prot_bl, in
        const uint8_t unlock[4] = { 0xff, 0xff, 0xff, 0xff };
        uint8_t mask[4] = { 0, 0, 0, 0 };
 
-       buf_set_u32(mask, first_prot_bl, last_prot_bl + 1 - first_prot_bl, 0xffffffff);
+       buf_set_u32(mask, first, last + 1 - first, 0xffffffff);
 
        res = same5_modify_user_row_masked(bank->target,
                        set ? lock : unlock, mask, 8, 4);
@@ -611,9 +623,10 @@ exit:
        return res;
 }
 
-static int same5_erase(struct flash_bank *bank, int first_sect, int last_sect)
+static int same5_erase(struct flash_bank *bank, unsigned int first,
+               unsigned int last)
 {
-       int res, s;
+       int res;
        struct samd_info *chip = (struct samd_info *)bank->driver_priv;
 
        if (bank->target->state != TARGET_HALTED) {
@@ -626,7 +639,7 @@ static int same5_erase(struct flash_bank *bank, int first_sect, int last_sect)
                return ERROR_FLASH_BANK_NOT_PROBED;
 
        /* For each sector to be erased */
-       for (s = first_sect; s <= last_sect; s++) {
+       for (unsigned int s = first; s <= last; s++) {
                res = same5_erase_block(bank->target, bank->sectors[s].offset);
                if (res != ERROR_OK) {
                        LOG_ERROR("SAM: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
@@ -720,9 +733,7 @@ static int same5_write(struct flash_bank *bank, const uint8_t *buffer,
        }
 
 free_pb:
-       if (pb)
-               free(pb);
-
+       free(pb);
        return res;
 }
 
@@ -731,7 +742,7 @@ FLASH_BANK_COMMAND_HANDLER(same5_flash_bank_command)
 {
        if (bank->base != SAMD_FLASH) {
                LOG_ERROR("Address " TARGET_ADDR_FMT " invalid bank address (try "
-                       "0x%08" PRIx32 "[same5] )", bank->base, SAMD_FLASH);
+                       "0x%08x[same5] )", bank->base, SAMD_FLASH);
                return ERROR_FAIL;
        }
 
@@ -765,9 +776,9 @@ COMMAND_HANDLER(same5_handle_chip_erase_command)
         * perform the erase. */
        int res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
        if (res == ERROR_OK)
-               command_print(CMD_CTX, "chip erase started");
+               command_print(CMD, "chip erase started");
        else
-               command_print(CMD_CTX, "write to DSU CTRL failed");
+               command_print(CMD, "write to DSU CTRL failed");
 
        return res;
 }
@@ -781,7 +792,7 @@ COMMAND_HANDLER(same5_handle_userpage_command)
                return ERROR_FAIL;
 
        if (CMD_ARGC > 2) {
-               command_print(CMD_CTX, "Too much Arguments given.");
+               command_print(CMD, "Too much Arguments given.");
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
@@ -806,7 +817,7 @@ COMMAND_HANDLER(same5_handle_userpage_command)
        int res2 = target_read_memory(target, SAMD_USER_ROW, 4, 2, buffer);
        if (res2 == ERROR_OK) {
                uint64_t value = target_buffer_get_u64(target, buffer);
-               command_print(CMD_CTX, "USER PAGE: 0x%016"PRIX64, value);
+               command_print(CMD, "USER PAGE: 0x%016"PRIX64, value);
        } else {
                LOG_ERROR("USER PAGE could not be read.");
        }
@@ -829,7 +840,7 @@ COMMAND_HANDLER(same5_handle_bootloader_command)
                unsigned long size = strtoul(CMD_ARGV[0], NULL, 0);
                uint32_t code = (size + 8191) / 8192;
                if (code > 15) {
-                       command_print(CMD_CTX, "Invalid bootloader size.  Please "
+                       command_print(CMD, "Invalid bootloader size.  Please "
                                                "see datasheet for a list valid sizes.");
                        return ERROR_COMMAND_SYNTAX_ERROR;
                }
@@ -842,7 +853,7 @@ COMMAND_HANDLER(same5_handle_bootloader_command)
        if (res2 == ERROR_OK) {
                uint32_t code = (val >> 26) & 0xf; /* grab size code */
                uint32_t size = (15 - code) * 8192;
-               command_print(CMD_CTX, "Bootloader protected in the first %"
+               command_print(CMD, "Bootloader protected in the first %"
                                      PRIu32 " bytes", size);
        }
 
@@ -896,7 +907,7 @@ static const struct command_registration same5_exec_command_handlers[] = {
                .usage = "",
                .handler = samd_handle_reset_deassert,
                .mode = COMMAND_EXEC,
-               .help = "Deasert internal reset held by DSU."
+               .help = "Deassert internal reset held by DSU."
        },
        {
                .name = "chip-erase",

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)