SPI table updates (some new devices and new info) 73/4773/5
authorAndreas Bolsch <hyphen0break@gmail.com>
Sun, 18 Nov 2018 16:08:20 +0000 (17:08 +0100)
committerTomas Vanek <vanekt@fbl.cz>
Thu, 29 Nov 2018 08:18:24 +0000 (08:18 +0000)
read_cmd, qread_cmd, pprog_cmd added as some recent high densities devices
use variants for 4-byte addressing.

Some new flash and FRAM device ids added. FRAMs don't have write pages nor
erase commands or sector sizes. The corresponding entries are marked as
"not used" (i. e. zero). Checks in existing SPI flash drivers added to
handle these cases gracefully.

Change-Id: I5104bce7c815ac22f98bc32c1bb6db66b984404a
Signed-off-by: Andreas Bolsch <hyphen0break@gmail.com>
Reviewed-on: http://openocd.zylin.com/4773
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
src/flash/nor/ath79.c
src/flash/nor/jtagspi.c
src/flash/nor/lpcspifi.c
src/flash/nor/mrvlqspi.c
src/flash/nor/spi.c
src/flash/nor/spi.h
src/flash/nor/stmsmi.c

index c5f9eed52f7e4be1ea3568b5be062d3c7c122647..d73a4916fac1d2ebaf4147302dff9b533c823285 100644 (file)
@@ -522,6 +522,9 @@ static int ath79_erase(struct flash_bank *bank, int first, int last)
                return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
+       if (ath79_info->dev->erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        for (sector = first; sector <= last; sector++) {
                if (bank->sectors[sector].is_protected) {
                        LOG_ERROR("Flash sector %d protected", sector);
@@ -560,7 +563,11 @@ static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer,
                address,
        };
        int retval;
-       uint32_t i;
+       uint32_t i, pagesize;
+
+       /* if no write pagesize, use reasonable default */
+       pagesize = ath79_info->dev->pagesize ?
+               ath79_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
 
        if (address & 0xff) {
                LOG_ERROR("ath79_write_page: unaligned write address: %08x",
@@ -573,7 +580,7 @@ static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer,
        }
        if (len > ath79_info->dev->pagesize) {
                LOG_ERROR("ath79_write_page: len bigger than page size %d: %d",
-                         ath79_info->dev->pagesize, len);
+                       pagesize, len);
                return ERROR_FAIL;
        }
 
@@ -611,12 +618,16 @@ static int ath79_write_buffer(struct flash_bank *bank, const uint8_t *buffer,
                              uint32_t address, uint32_t len)
 {
        struct ath79_flash_bank *ath79_info = bank->driver_priv;
-       const uint32_t page_size = ath79_info->dev->pagesize;
+       uint32_t page_size;
        int retval;
 
        LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
                  __func__, address, len);
 
+       /* if no valid page_size, use reasonable default */
+       page_size = ath79_info->dev->pagesize ?
+               ath79_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
+
        while (len > 0) {
                int page_len = len > page_size ? page_size : len;
 
@@ -775,6 +786,7 @@ static int ath79_probe(struct flash_bank *bank)
        struct ath79_flash_bank *ath79_info = bank->driver_priv;
        struct flash_sector *sectors;
        uint32_t id = 0; /* silence uninitialized warning */
+       uint32_t pagesize, sectorsize;
        const struct ath79_target *target_device;
        int retval;
 
@@ -820,16 +832,27 @@ static int ath79_probe(struct flash_bank *bank)
 
        /* Set correct size value */
        bank->size = ath79_info->dev->size_in_bytes;
+       if (bank->size <= (1UL << 16))
+               LOG_WARNING("device needs 2-byte addresses - not implemented");
+       if (bank->size > (1UL << 24))
+               LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
+
+       /* if no sectors, treat whole bank as single sector */
+       sectorsize = ath79_info->dev->sectorsize ?
+               ath79_info->dev->sectorsize : ath79_info->dev->size_in_bytes;
 
        /* create and fill sectors array */
-       bank->num_sectors =
-               ath79_info->dev->size_in_bytes / ath79_info->dev->sectorsize;
+       bank->num_sectors = ath79_info->dev->size_in_bytes / sectorsize;
        sectors = calloc(1, sizeof(struct flash_sector) * bank->num_sectors);
        if (!sectors) {
                LOG_ERROR("not enough memory");
                return ERROR_FAIL;
        }
-       ath79_info->spi.page_buf = malloc(ath79_info->dev->pagesize);
+
+       /* if no write pagesize, use reasonable default */
+       pagesize = ath79_info->dev->pagesize ? ath79_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
+
+       ath79_info->spi.page_buf = malloc(pagesize);
        if (!ath79_info->spi.page_buf) {
                LOG_ERROR("not enough memory");
                free(sectors);
@@ -837,8 +860,8 @@ static int ath79_probe(struct flash_bank *bank)
        }
 
        for (int sector = 0; sector < bank->num_sectors; sector++) {
-               sectors[sector].offset = sector * ath79_info->dev->sectorsize;
-               sectors[sector].size = ath79_info->dev->sectorsize;
+               sectors[sector].offset = sector * sectorsize;
+               sectors[sector].size = sectorsize;
                sectors[sector].is_erased = 0;
                sectors[sector].is_protected = 1;
        }
index c5c565f2a19301f8a602fea1166126ffb6a9d6b0..0750fdfd5039d07ec0e45081bcf14e856c17499f 100644 (file)
@@ -166,7 +166,7 @@ static int jtagspi_probe(struct flash_bank *bank)
        struct jtagspi_flash_bank *info = bank->driver_priv;
        struct flash_sector *sectors;
        uint8_t in_buf[3];
-       uint32_t id;
+       uint32_t id, sectorsize;
 
        if (info->probed)
                free(bank->sectors);
@@ -199,10 +199,17 @@ static int jtagspi_probe(struct flash_bank *bank)
 
        /* Set correct size value */
        bank->size = info->dev->size_in_bytes;
+       if (bank->size <= (1UL << 16))
+               LOG_WARNING("device needs 2-byte addresses - not implemented");
+       if (bank->size > (1UL << 24))
+               LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
+
+       /* if no sectors, treat whole bank as single sector */
+       sectorsize = info->dev->sectorsize ?
+               info->dev->sectorsize : info->dev->size_in_bytes;
 
        /* create and fill sectors array */
-       bank->num_sectors =
-               info->dev->size_in_bytes / info->dev->sectorsize;
+       bank->num_sectors = info->dev->size_in_bytes / sectorsize;
        sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
        if (sectors == NULL) {
                LOG_ERROR("not enough memory");
@@ -210,8 +217,8 @@ static int jtagspi_probe(struct flash_bank *bank)
        }
 
        for (int sector = 0; sector < bank->num_sectors; sector++) {
-               sectors[sector].offset = sector * info->dev->sectorsize;
-               sectors[sector].size = info->dev->sectorsize;
+               sectors[sector].offset = sector * sectorsize;
+               sectors[sector].size = sectorsize;
                sectors[sector].is_erased = -1;
                sectors[sector].is_protected = 0;
        }
@@ -269,6 +276,9 @@ static int jtagspi_bulk_erase(struct flash_bank *bank)
        int retval;
        int64_t t0 = timeval_ms();
 
+       if (info->dev->chip_erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        retval = jtagspi_write_enable(bank);
        if (retval != ERROR_OK)
                return retval;
@@ -328,6 +338,9 @@ static int jtagspi_erase(struct flash_bank *bank, int first, int last)
                        LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
        }
 
+       if (info->dev->erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        for (sector = first; sector <= last; sector++) {
                retval = jtagspi_sector_erase(bank, sector);
                if (retval != ERROR_OK) {
@@ -376,16 +389,19 @@ static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
 {
        struct jtagspi_flash_bank *info = bank->driver_priv;
        int retval;
-       uint32_t n;
+       uint32_t n, pagesize;
 
        if (!(info->probed)) {
                LOG_ERROR("Flash bank not yet probed.");
                return ERROR_FLASH_BANK_NOT_PROBED;
        }
 
-       for (n = 0; n < count; n += info->dev->pagesize) {
+       /* if no write pagesize, use reasonable default */
+       pagesize = info->dev->pagesize ? info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
+
+       for (n = 0; n < count; n += pagesize) {
                retval = jtagspi_page_write(bank, buffer + n, offset + n,
-                               MIN(count - n, info->dev->pagesize));
+                               MIN(count - n, pagesize));
                if (retval != ERROR_OK) {
                        LOG_ERROR("page write error");
                        return retval;
index 828c60ca6e0e0bd9ecd8337d7773f625d6e19792..a50584f7759ccbce9129123692e3c745b2ee15b9 100644 (file)
@@ -387,6 +387,9 @@ static int lpcspifi_bulk_erase(struct flash_bank *bank)
        uint32_t value;
        int retval = ERROR_OK;
 
+       if (lpcspifi_info->dev->chip_erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        retval = lpcspifi_set_sw_mode(bank);
 
        if (retval == ERROR_OK)
@@ -460,6 +463,9 @@ static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
                        LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase.");
        }
 
+       if (lpcspifi_info->dev->erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        retval = lpcspifi_set_hw_mode(bank);
        if (retval != ERROR_OK)
                return retval;
@@ -613,7 +619,9 @@ static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
                }
        }
 
-       page_size = lpcspifi_info->dev->pagesize;
+       /* if no valid page_size, use reasonable default */
+       page_size = lpcspifi_info->dev->pagesize ?
+               lpcspifi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
 
        retval = lpcspifi_set_hw_mode(bank);
        if (retval != ERROR_OK)
@@ -839,6 +847,7 @@ static int lpcspifi_probe(struct flash_bank *bank)
        struct flash_sector *sectors;
        uint32_t id = 0; /* silence uninitialized warning */
        int retval;
+       uint32_t sectorsize;
 
        /* If we've already probed, we should be fine to skip this time. */
        if (lpcspifi_info->probed)
@@ -876,10 +885,17 @@ static int lpcspifi_probe(struct flash_bank *bank)
 
        /* Set correct size value */
        bank->size = lpcspifi_info->dev->size_in_bytes;
+       if (bank->size <= (1UL << 16))
+               LOG_WARNING("device needs 2-byte addresses - not implemented");
+       if (bank->size > (1UL << 24))
+               LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
+
+       /* if no sectors, treat whole bank as single sector */
+       sectorsize = lpcspifi_info->dev->sectorsize ?
+               lpcspifi_info->dev->sectorsize : lpcspifi_info->dev->size_in_bytes;
 
        /* create and fill sectors array */
-       bank->num_sectors =
-               lpcspifi_info->dev->size_in_bytes / lpcspifi_info->dev->sectorsize;
+       bank->num_sectors = lpcspifi_info->dev->size_in_bytes / sectorsize;
        sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
        if (sectors == NULL) {
                LOG_ERROR("not enough memory");
@@ -887,8 +903,8 @@ static int lpcspifi_probe(struct flash_bank *bank)
        }
 
        for (int sector = 0; sector < bank->num_sectors; sector++) {
-               sectors[sector].offset = sector * lpcspifi_info->dev->sectorsize;
-               sectors[sector].size = lpcspifi_info->dev->sectorsize;
+               sectors[sector].offset = sector * sectorsize;
+               sectors[sector].size = sectorsize;
                sectors[sector].is_erased = -1;
                sectors[sector].is_protected = 0;
        }
index 132e5f36b3de7ac574c84a6cd4e817341bd4eb05..cb2cfdbd553da56173f77e2b150427680ad1c1b2 100644 (file)
@@ -503,6 +503,9 @@ static int mrvlqspi_bulk_erase(struct flash_bank *bank)
        int retval;
        struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
 
+       if (mrvlqspi_info->dev->chip_erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        /* Set flash write enable */
        retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE);
        if (retval != ERROR_OK)
@@ -570,6 +573,9 @@ static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last)
                                " Falling back to sector-by-sector erase.");
        }
 
+       if (mrvlqspi_info->dev->erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        for (sector = first; sector <= last; sector++) {
                retval = mrvlqspi_block_erase(bank,
                                sector * mrvlqspi_info->dev->sectorsize);
@@ -619,7 +625,9 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer,
                }
        }
 
-       page_size = mrvlqspi_info->dev->pagesize;
+       /* if no valid page_size, use reasonable default */
+       page_size = mrvlqspi_info->dev->pagesize ?
+               mrvlqspi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
 
        /* See contrib/loaders/flash/mrvlqspi.S for src */
        static const uint8_t mrvlqspi_flash_write_code[] = {
@@ -826,6 +834,7 @@ static int mrvlqspi_probe(struct flash_bank *bank)
        uint32_t id = 0;
        int retval;
        struct flash_sector *sectors;
+       uint32_t sectorsize;
 
        /* If we've already probed, we should be fine to skip this time. */
        if (mrvlqspi_info->probed)
@@ -859,12 +868,20 @@ static int mrvlqspi_probe(struct flash_bank *bank)
        LOG_INFO("Found flash device \'%s\' ID 0x%08" PRIx32,
                mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id);
 
+
        /* Set correct size value */
        bank->size = mrvlqspi_info->dev->size_in_bytes;
+       if (bank->size <= (1UL << 16))
+               LOG_WARNING("device needs 2-byte addresses - not implemented");
+       if (bank->size > (1UL << 24))
+               LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
+
+       /* if no sectors, treat whole bank as single sector */
+       sectorsize = mrvlqspi_info->dev->sectorsize ?
+               mrvlqspi_info->dev->sectorsize : mrvlqspi_info->dev->size_in_bytes;
 
        /* create and fill sectors array */
-       bank->num_sectors = mrvlqspi_info->dev->size_in_bytes /
-                                       mrvlqspi_info->dev->sectorsize;
+       bank->num_sectors = mrvlqspi_info->dev->size_in_bytes / sectorsize;
        sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
        if (sectors == NULL) {
                LOG_ERROR("not enough memory");
@@ -872,9 +889,8 @@ static int mrvlqspi_probe(struct flash_bank *bank)
        }
 
        for (int sector = 0; sector < bank->num_sectors; sector++) {
-               sectors[sector].offset =
-                               sector * mrvlqspi_info->dev->sectorsize;
-               sectors[sector].size = mrvlqspi_info->dev->sectorsize;
+               sectors[sector].offset = sector * sectorsize;
+               sectors[sector].size = sectorsize;
                sectors[sector].is_erased = -1;
                sectors[sector].is_protected = 0;
        }
index 273e8508fecb375258beb13726d5c1a9bf7fd382..e899fd0703216087fb3d6a2da0e2550464f97ca0 100644 (file)
@@ -1,4 +1,7 @@
 /***************************************************************************
+ *   Copyright (C) 2018 by Andreas Bolsch                                  *
+ *   andreas.bolsch@mni.thm.de                                             *
+ *                                                                         *
  *   Copyright (C) 2012 by George Harris                                   *
  *   george@luminairecoffee.com                                            *
  *                                                                         *
  /* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
   * from device datasheets and Linux SPI flash drivers. */
 const struct flash_device flash_devices[] = {
-       /* name, erase_cmd, chip_erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
-       FLASH_ID("st m25p05",           0xd8, 0xc7, 0x00102020, 0x80,  0x8000,  0x10000),
-       FLASH_ID("st m25p10",           0xd8, 0xc7, 0x00112020, 0x80,  0x8000,  0x20000),
-       FLASH_ID("st m25p20",           0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
-       FLASH_ID("st m25p40",           0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
-       FLASH_ID("st m25p80",           0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
-       FLASH_ID("st m25p16",           0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
-       FLASH_ID("st m25p32",           0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
-       FLASH_ID("st m25p64",           0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
-       FLASH_ID("st m25p128",          0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
-       FLASH_ID("st m45pe10",          0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
-       FLASH_ID("st m45pe20",          0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
-       FLASH_ID("st m45pe40",          0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
-       FLASH_ID("st m45pe80",          0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
-       FLASH_ID("sp s25fl004",         0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
-       FLASH_ID("sp s25fl008",         0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
-       FLASH_ID("sp s25fl016",         0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
-       FLASH_ID("sp s25fl116k",        0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
-       FLASH_ID("sp s25fl032",         0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
-       FLASH_ID("sp s25fl132k",        0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
-       FLASH_ID("sp s25fl064",         0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
-       FLASH_ID("sp s25fl164k",        0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
-       FLASH_ID("sp s25fl128",         0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
-       FLASH_ID("sp s25fl256",         0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
-       FLASH_ID("atmel 25f512",        0x52, 0xc7, 0x0065001f, 0x80,  0x8000,  0x10000),
-       FLASH_ID("atmel 25f1024",       0x52, 0x62, 0x0060001f, 0x100, 0x8000,  0x20000),
-       FLASH_ID("atmel 25f2048",       0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
-       FLASH_ID("atmel 25f4096",       0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
-       FLASH_ID("atmel 25fs040",       0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
-       FLASH_ID("mac 25l512",          0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
-       FLASH_ID("mac 25l1005",         0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
-       FLASH_ID("mac 25l2005",         0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
-       FLASH_ID("mac 25l4005",         0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
-       FLASH_ID("mac 25l8005",         0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
-       FLASH_ID("mac 25l1605",         0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
-       FLASH_ID("mac 25l3205",         0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
-       FLASH_ID("mac 25l6405",         0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
-       FLASH_ID("micron n25q064",      0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
-       FLASH_ID("micron n25q128",      0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
-       FLASH_ID("micron n25q256 3v",   0xd8, 0xc7, 0x0019ba20, 0x100, 0x10000, 0x2000000),
-       FLASH_ID("micron n25q256 1.8v", 0xd8, 0xc7, 0x0019bb20, 0x100, 0x10000, 0x2000000),
-       FLASH_ID("win w25q80bv",        0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
-       FLASH_ID("win w25q32fv",        0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
-       FLASH_ID("win w25q32dw",        0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000),
-       FLASH_ID("win w25q64cv",        0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
-       FLASH_ID("win w25q128fv",       0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
-       FLASH_ID("gd gd25q20",          0x20, 0xc7, 0x00c84012, 0x100, 0x1000,  0x80000),
-       FLASH_ID("gd gd25q16c",         0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
-       FLASH_ID("gd gd25q32c",         0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
-       FLASH_ID("gd gd25q128c",        0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
-       FLASH_ID(NULL,                  0,    0,    0,          0,     0,       0)
+       /* name, read_cmd, qread_cmd, pprog_cmd, erase_cmd, chip_erase_cmd, device_id,
+        * pagesize, sectorsize, size_in_bytes */
+       FLASH_ID("st m25p05",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00102020, 0x80,  0x8000,  0x10000),
+       FLASH_ID("st m25p10",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00112020, 0x80,  0x8000,  0x20000),
+       FLASH_ID("st m25p20",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
+       FLASH_ID("st m25p40",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
+       FLASH_ID("st m25p80",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
+       FLASH_ID("st m25p16",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
+       FLASH_ID("st m25p32",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
+       FLASH_ID("st m25p64",           0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
+       FLASH_ID("st m25p128",          0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
+       FLASH_ID("st m45pe10",          0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
+       FLASH_ID("st m45pe20",          0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
+       FLASH_ID("st m45pe40",          0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
+       FLASH_ID("st m45pe80",          0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
+       FLASH_ID("sp s25fl004",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
+       FLASH_ID("sp s25fl008",         0x03, 0x08, 0x02, 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
+       FLASH_ID("sp s25fl016",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
+       FLASH_ID("sp s25fl116k",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
+       FLASH_ID("sp s25fl032",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
+       FLASH_ID("sp s25fl132k",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
+       FLASH_ID("sp s25fl064",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
+       FLASH_ID("sp s25fl164k",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
+       FLASH_ID("sp s25fl128s",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("sp s25fl256s",        0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("sp s25fl512s",        0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00200201, 0x200, 0x40000, 0x4000000),
+       FLASH_ID("cyp s25fl064l",       0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00176001, 0x100, 0x10000, 0x800000),
+       FLASH_ID("cyp s25fl128l",       0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00186001, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("cyp s25fl256l",       0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00196001, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("atmel 25f512",        0x03, 0x00, 0x02, 0x52, 0xc7, 0x0065001f, 0x80,  0x8000,  0x10000),
+       FLASH_ID("atmel 25f1024",       0x03, 0x00, 0x02, 0x52, 0x62, 0x0060001f, 0x100, 0x8000,  0x20000),
+       FLASH_ID("atmel 25f2048",       0x03, 0x00, 0x02, 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
+       FLASH_ID("atmel 25f4096",       0x03, 0x00, 0x02, 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
+       FLASH_ID("atmel 25fs040",       0x03, 0x00, 0x02, 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
+       FLASH_ID("mac 25l512",          0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
+       FLASH_ID("mac 25l1005",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
+       FLASH_ID("mac 25l2005",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
+       FLASH_ID("mac 25l4005",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
+       FLASH_ID("mac 25l8005",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
+       FLASH_ID("mac 25l1605",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
+       FLASH_ID("mac 25l3205",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
+       FLASH_ID("mac 25l6405",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
+       FLASH_ID("mac 25l12845",        0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001820c2, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("mac 25l25645",        0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001920c2, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("mac 25l51245",        0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a20c2, 0x100, 0x10000, 0x4000000),
+       FLASH_ID("mac 25lm51245",       0x13, 0xec, 0x12, 0xdc, 0xc7, 0x003a85c2, 0x100, 0x10000, 0x4000000),
+       FLASH_ID("mac 25r512f",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001028c2, 0x100, 0x10000, 0x10000),
+       FLASH_ID("mac 25r1035f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001128c2, 0x100, 0x10000, 0x20000),
+       FLASH_ID("mac 25r2035f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001228c2, 0x100, 0x10000, 0x40000),
+       FLASH_ID("mac 25r4035f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001328c2, 0x100, 0x10000, 0x80000),
+       FLASH_ID("mac 25r8035f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001428c2, 0x100, 0x10000, 0x100000),
+       FLASH_ID("mac 25r1635f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001528c2, 0x100, 0x10000, 0x200000),
+       FLASH_ID("mac 25r3235f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001628c2, 0x100, 0x10000, 0x400000),
+       FLASH_ID("mac 25r6435f",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001728c2, 0x100, 0x10000, 0x800000),
+       FLASH_ID("micron n25q064",      0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
+       FLASH_ID("micron n25q128",      0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("micron n25q256 3v",   0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019ba20, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("micron n25q256 1.8v", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019bb20, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("micron mt25ql512",    0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0020ba20, 0x100, 0x10000, 0x4000000),
+       FLASH_ID("micron mt25ql01",     0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0021ba20, 0x100, 0x10000, 0x8000000),
+       FLASH_ID("micron mt25ql02",     0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0022ba20, 0x100, 0x10000, 0x10000000),
+       FLASH_ID("win w25q80bv",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
+       FLASH_ID("win w25q16jv",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001540ef, 0x100, 0x10000, 0x200000),
+       FLASH_ID("win w25q16jv",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001570ef, 0x100, 0x10000, 0x200000), /* QPI / DTR */
+       FLASH_ID("win w25q32fv/jv",     0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
+       FLASH_ID("win w25q32fv",        0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000), /* QPI mode */
+       FLASH_ID("win w25q32jv",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001670ef, 0x100, 0x10000, 0x400000),
+       FLASH_ID("win w25q64fv/jv",     0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
+       FLASH_ID("win w25q64fv",        0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001760ef, 0x100, 0x10000, 0x800000), /* QPI mode */
+       FLASH_ID("win w25q64jv",        0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001770ef, 0x100, 0x10000, 0x800000),
+       FLASH_ID("win w25q128fv/jv",    0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("win w25q128fv",       0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001860ef, 0x100, 0x10000, 0x1000000), /* QPI mode */
+       FLASH_ID("win w25q128jv",       0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001870ef, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("win w25q256fv/jv",    0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001940ef, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("win w25q256fv",       0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001960ef, 0x100, 0x10000, 0x2000000), /* QPI mode */
+       FLASH_ID("win w25q256jv",       0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001970ef, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("gd gd25q512",         0x03, 0x00, 0x02, 0x20, 0xc7, 0x001040c8, 0x100, 0x1000,  0x10000),
+       FLASH_ID("gd gd25q10",          0x03, 0x00, 0x02, 0x20, 0xc7, 0x001140c8, 0x100, 0x1000,  0x20000),
+       FLASH_ID("gd gd25q20",          0x03, 0x00, 0x02, 0x20, 0xc7, 0x001240c8, 0x100, 0x1000,  0x40000),
+       FLASH_ID("gd gd25q40",          0x03, 0x00, 0x02, 0x20, 0xc7, 0x001340c8, 0x100, 0x1000,  0x80000),
+       FLASH_ID("gd gd25q16c",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
+       FLASH_ID("gd gd25q32c",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
+       FLASH_ID("gd gd25q64c",         0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001740c8, 0x100, 0x10000, 0x800000),
+       FLASH_ID("gd gd25q128c",        0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("gd gd25q256c",        0x13, 0x00, 0x12, 0xdc, 0xc7, 0x001940c8, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("gd gd25q512mc",       0x13, 0x00, 0x12, 0xdc, 0xc7, 0x002040c8, 0x100, 0x10000, 0x4000000),
+       FLASH_ID("issi is25lp032",      0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0016609d, 0x100, 0x10000, 0x400000),
+       FLASH_ID("issi is25lp064",      0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0017609d, 0x100, 0x10000, 0x800000),
+       FLASH_ID("issi is25lp128d",     0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("issi is25wp128d",     0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018709d, 0x100, 0x10000, 0x1000000),
+       FLASH_ID("issi is25lp256d",     0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019609d, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("issi is25wp256d",     0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
+       FLASH_ID("issi is25lp512m",     0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a609d, 0x100, 0x10000, 0x4000000),
+       FLASH_ID("issi is25wp512m",     0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a709d, 0x100, 0x10000, 0x4000000),
+
+       /* FRAM, no erase commands, no write page or sectors */
+       FRAM_ID("fu mb85rs16n",         0x03, 0,    0x02, 0x00010104, 0x800),
+       FRAM_ID("fu mb85rs32v",         0x03, 0,    0x02, 0x00010204, 0x1000), /* exists ? */
+       FRAM_ID("fu mb85rs64v",         0x03, 0,    0x02, 0x00020304, 0x2000),
+       FRAM_ID("fu mb85rs128b",        0x03, 0,    0x02, 0x00090404, 0x4000),
+       FRAM_ID("fu mb85rs256b",        0x03, 0,    0x02, 0x00090504, 0x8000),
+       FRAM_ID("fu mb85rs512t",        0x03, 0,    0x02, 0x00032604, 0x10000),
+       FRAM_ID("fu mb85rs1mt",         0x03, 0,    0x02, 0x00032704, 0x20000),
+       FRAM_ID("fu mb85rs2mta",        0x03, 0,    0x02, 0x00034804, 0x40000),
+       FRAM_ID("cyp fm25v01a",         0x03, 0,    0x02, 0x000821c2, 0x4000),
+       FRAM_ID("cyp fm25v02",          0x03, 0,    0x02, 0x000022c2, 0x8000),
+       FRAM_ID("cyp fm25v02a",         0x03, 0,    0x02, 0x000822c2, 0x8000),
+       FRAM_ID("cyp fm25v05",          0x03, 0,    0x02, 0x000023c2, 0x10000),
+       FRAM_ID("cyp fm25v10",          0x03, 0,    0x02, 0x000024c2, 0x20000),
+       FRAM_ID("cyp fm25v20a",         0x03, 0,    0x02, 0x000825c2, 0x40000),
+       FRAM_ID("cyp fm25v40",          0x03, 0,    0x02, 0x004026c2, 0x80000),
+
+       FLASH_ID(NULL,                  0,    0,    0,    0,    0,    0,          0,     0,       0)
 };
index a1849983f26db9e16603cb22dfdfc2ad6d3a7a0b..11c381fbd2ee7cbe9573c8a7c8c4d3937068ed7e 100644 (file)
@@ -1,4 +1,7 @@
 /***************************************************************************
+ *   Copyright (C) 2018 by Andreas Bolsch                                  *
+ *   andreas.bolsch@mni.thm.de                                             *
+ *                                                                         *
  *   Copyright (C) 2012 by George Harris                                   *
  *   george@luminairecoffee.com                                            *
  *                                                                         *
 #ifndef OPENOCD_FLASH_NOR_SPI_H
 #define OPENOCD_FLASH_NOR_SPI_H
 
+#ifndef __ASSEMBLER__
+
 /* data structure to maintain flash ids from different vendors */
 struct flash_device {
        char *name;
+       uint8_t read_cmd;
+       uint8_t qread_cmd;
+       uint8_t pprog_cmd;
        uint8_t erase_cmd;
        uint8_t chip_erase_cmd;
        uint32_t device_id;
        uint32_t pagesize;
-       unsigned long sectorsize;
-       unsigned long size_in_bytes;
+       uint32_t sectorsize;
+       uint32_t size_in_bytes;
 };
 
-#define FLASH_ID(n, es, ces, id, psize, ssize, size) \
-{                              \
-       .name = n,              \
-       .erase_cmd = es,        \
-       .chip_erase_cmd = ces,  \
-       .device_id = id,        \
-       .pagesize = psize,      \
-       .sectorsize = ssize,    \
-       .size_in_bytes = size   \
+#define FLASH_ID(n, re, qr, pp, es, ces, id, psize, ssize, size) \
+{                                      \
+       .name = n,                      \
+       .read_cmd = re,                 \
+       .qread_cmd = qr,                \
+       .pprog_cmd = pp,                \
+       .erase_cmd = es,                \
+       .chip_erase_cmd = ces,          \
+       .device_id = id,                \
+       .pagesize = psize,              \
+       .sectorsize = ssize,            \
+       .size_in_bytes = size,          \
+}
+
+#define FRAM_ID(n, re, qr, pp, id, size) \
+{                                      \
+       .name = n,                      \
+       .read_cmd = re,                 \
+       .qread_cmd = qr,                \
+       .pprog_cmd = pp,                \
+       .erase_cmd = 0x00,              \
+       .chip_erase_cmd = 0x00,         \
+       .device_id = id,                \
+       .pagesize = 0,                  \
+       .sectorsize = 0,                \
+       .size_in_bytes = size,          \
 }
 
 extern const struct flash_device flash_devices[];
 
+#endif
+
 /* fields in SPI flash status register */
-#define SPIFLASH_BSY_BIT               0x00000001 /* WIP Bit of SPI SR on SMI SR */
-#define SPIFLASH_WE_BIT                        0x00000002 /* WEL Bit of SPI SR on SMI SR */
+#define        SPIFLASH_BSY            0
+#define SPIFLASH_BSY_BIT       (1 << SPIFLASH_BSY)     /* WIP Bit of SPI SR */
+#define        SPIFLASH_WE                     1
+#define SPIFLASH_WE_BIT                (1 << SPIFLASH_WE)      /* WEL Bit of SPI SR */
 
 /* SPI Flash Commands */
 #define SPIFLASH_READ_ID               0x9F /* Read Flash Identification */
+#define SPIFLASH_READ_MID              0xAF /* Read Flash Identification, multi-io */
 #define SPIFLASH_READ_STATUS   0x05 /* Read Status Register */
 #define SPIFLASH_WRITE_ENABLE  0x06 /* Write Enable */
 #define SPIFLASH_PAGE_PROGRAM  0x02 /* Page Program */
 #define SPIFLASH_FAST_READ             0x0B /* Fast Read */
 #define SPIFLASH_READ                  0x03 /* Normal Read */
 
+#define SPIFLASH_DEF_PAGESIZE  256  /* default for non-page-oriented devices (FRAMs) */
+
 #endif /* OPENOCD_FLASH_NOR_SPI_H */
index c839bf74cb2ef625b28123e9bde58d78caff51be..922561002585f3826f1dc16f9853200211680579 100644 (file)
@@ -348,6 +348,9 @@ static int stmsmi_erase(struct flash_bank *bank, int first, int last)
                }
        }
 
+       if (stmsmi_info->dev->erase_cmd == 0x00)
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+
        for (sector = first; sector <= last; sector++) {
                retval = smi_erase_sector(bank, sector);
                if (retval != ERROR_OK)
@@ -431,7 +434,9 @@ static int stmsmi_write(struct flash_bank *bank, const uint8_t *buffer,
                }
        }
 
-       page_size = stmsmi_info->dev->pagesize;
+       /* if no valid page_size, use reasonable default */
+       page_size = stmsmi_info->dev->pagesize ?
+               stmsmi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
 
        /* unaligned buffer head */
        if (count > 0 && (offset & 3) != 0) {
@@ -524,7 +529,7 @@ static int stmsmi_probe(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
-       uint32_t io_base;
+       uint32_t io_base, sectorsize;
        struct flash_sector *sectors;
        uint32_t id = 0; /* silence uninitialized warning */
        const struct stmsmi_target *target_device;
@@ -589,10 +594,18 @@ static int stmsmi_probe(struct flash_bank *bank)
 
        /* Set correct size value */
        bank->size = stmsmi_info->dev->size_in_bytes;
+       if (bank->size <= (1UL << 16))
+               LOG_WARNING("device needs 2-byte addresses - not implemented");
+       if (bank->size > (1UL << 24))
+               LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
+
+       /* if no sectors, treat whole bank as single sector */
+       sectorsize = stmsmi_info->dev->sectorsize ?
+               stmsmi_info->dev->sectorsize : stmsmi_info->dev->size_in_bytes;
 
        /* create and fill sectors array */
        bank->num_sectors =
-               stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
+               stmsmi_info->dev->size_in_bytes / sectorsize;
        sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
        if (sectors == NULL) {
                LOG_ERROR("not enough memory");
@@ -600,8 +613,8 @@ static int stmsmi_probe(struct flash_bank *bank)
        }
 
        for (int sector = 0; sector < bank->num_sectors; sector++) {
-               sectors[sector].offset = sector * stmsmi_info->dev->sectorsize;
-               sectors[sector].size = stmsmi_info->dev->sectorsize;
+               sectors[sector].offset = sector * sectorsize;
+               sectors[sector].size = sectorsize;
                sectors[sector].is_erased = -1;
                sectors[sector].is_protected = 1;
        }

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)