diff options
-rw-r--r-- | src/flash/nor/ath79.c | 39 | ||||
-rw-r--r-- | src/flash/nor/jtagspi.c | 32 | ||||
-rw-r--r-- | src/flash/nor/lpcspifi.c | 26 | ||||
-rw-r--r-- | src/flash/nor/mrvlqspi.c | 28 | ||||
-rw-r--r-- | src/flash/nor/spi.c | 167 | ||||
-rw-r--r-- | src/flash/nor/spi.h | 58 | ||||
-rw-r--r-- | src/flash/nor/stmsmi.c | 23 |
7 files changed, 277 insertions, 96 deletions
diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c index c5f9eed5..d73a4916 100644 --- a/src/flash/nor/ath79.c +++ b/src/flash/nor/ath79.c @@ -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; } diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c index c5c565f2..0750fdfd 100644 --- a/src/flash/nor/jtagspi.c +++ b/src/flash/nor/jtagspi.c @@ -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; diff --git a/src/flash/nor/lpcspifi.c b/src/flash/nor/lpcspifi.c index 828c60ca..a50584f7 100644 --- a/src/flash/nor/lpcspifi.c +++ b/src/flash/nor/lpcspifi.c @@ -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; } diff --git a/src/flash/nor/mrvlqspi.c b/src/flash/nor/mrvlqspi.c index 132e5f36..cb2cfdbd 100644 --- a/src/flash/nor/mrvlqspi.c +++ b/src/flash/nor/mrvlqspi.c @@ -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; } diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c index 273e8508..e899fd07 100644 --- a/src/flash/nor/spi.c +++ b/src/flash/nor/spi.c @@ -1,4 +1,7 @@ /*************************************************************************** + * Copyright (C) 2018 by Andreas Bolsch * + * andreas.bolsch@mni.thm.de * + * * * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * @@ -30,55 +33,117 @@ /* 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) }; diff --git a/src/flash/nor/spi.h b/src/flash/nor/spi.h index a1849983..11c381fb 100644 --- a/src/flash/nor/spi.h +++ b/src/flash/nor/spi.h @@ -1,4 +1,7 @@ /*************************************************************************** + * Copyright (C) 2018 by Andreas Bolsch * + * andreas.bolsch@mni.thm.de * + * * * Copyright (C) 2012 by George Harris * * george@luminairecoffee.com * * * @@ -22,40 +25,69 @@ #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 */ diff --git a/src/flash/nor/stmsmi.c b/src/flash/nor/stmsmi.c index c839bf74..92256100 100644 --- a/src/flash/nor/stmsmi.c +++ b/src/flash/nor/stmsmi.c @@ -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; } |