jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / atsame5.c
index eac7847dca807d911ade60e0f88a56250565e761..c590081fcc7f575814f882cff9ada7e3a5158197 100644 (file)
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2017 by Tomas Vanek                                    *
  *   vanekt@fbl.cz                                                        *
@@ -5,19 +7,6 @@
  *   Based on at91samd.c                                                   *
  *   Copyright (C) 2013 by Andrey Yurovsky                                 *
  *   Andrey Yurovsky <yurovsky@gmail.com>                                  *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "imp.h"
 #include "helper/binarybuffer.h"
 
+#include <helper/time_support.h>
+#include <jtag/jtag.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
 #define SAMD_GET_DEVSEL(id) (id & 0xFF)
 
 /* Bits to mask user row */
-#define NVMUSERROW_SAM_E5_D5_MASK      ((uint64_t)0x7FFF00FF3C007FFF)
+#define NVMUSERROW_SAM_E5_D5_MASK      0x7FFF00FF3C007FFFULL
 
 struct samd_part {
        uint8_t id;
@@ -112,7 +103,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 +124,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. */
@@ -142,6 +135,9 @@ static const struct samd_part same53_parts[] = {
        { 0x04, "SAME53J20A", 1024, 256 },
        { 0x05, "SAME53J19A", 512, 192 },
        { 0x06, "SAME53J18A", 256, 128 },
+       { 0x55, "LAN9255/ZMX020", 1024, 256 },
+       { 0x56, "LAN9255/ZMX019", 512, 192 },
+       { 0x57, "LAN9255/ZMX018", 256, 128 },
 };
 
 /* Known SAME54 parts. */
@@ -217,7 +213,7 @@ static const struct samd_part *samd_find_part(uint32_t id)
 {
        uint8_t devsel = SAMD_GET_DEVSEL(id);
        const struct samd_family *family = samd_find_family(id);
-       if (family == NULL)
+       if (!family)
                return NULL;
 
        for (unsigned i = 0; i < family->num_parts; i++) {
@@ -230,7 +226,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 +235,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;
@@ -284,7 +280,7 @@ static int same5_probe(struct flash_bank *bank)
        }
 
        part = samd_find_part(id);
-       if (part == NULL) {
+       if (!part) {
                LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
                return ERROR_FAIL;
        }
@@ -338,19 +334,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 +564,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 +577,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 +601,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 +616,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 +632,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 +726,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 +735,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;
        }
 
@@ -786,11 +790,12 @@ COMMAND_HANDLER(same5_handle_userpage_command)
        }
 
        if (CMD_ARGC >= 1) {
-               uint64_t mask = NVMUSERROW_SAM_E5_D5_MASK;
-               uint64_t value = strtoull(CMD_ARGV[0], NULL, 0);
+               uint64_t value, mask = NVMUSERROW_SAM_E5_D5_MASK;
+               COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], value);
 
                if (CMD_ARGC == 2) {
-                       uint64_t mask_temp = strtoull(CMD_ARGV[1], NULL, 0);
+                       uint64_t mask_temp;
+                       COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], mask_temp);
                        mask &= mask_temp;
                }
 
@@ -826,7 +831,9 @@ COMMAND_HANDLER(same5_handle_bootloader_command)
                return ERROR_FAIL;
 
        if (CMD_ARGC >= 1) {
-               unsigned long size = strtoul(CMD_ARGV[0], NULL, 0);
+               unsigned long size;
+
+               COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[0], size);
                uint32_t code = (size + 8191) / 8192;
                if (code > 15) {
                        command_print(CMD, "Invalid bootloader size.  Please "

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)