aboutsummaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/ath79.c39
-rw-r--r--src/flash/nor/jtagspi.c32
-rw-r--r--src/flash/nor/lpcspifi.c26
-rw-r--r--src/flash/nor/mrvlqspi.c28
-rw-r--r--src/flash/nor/spi.c167
-rw-r--r--src/flash/nor/spi.h58
-rw-r--r--src/flash/nor/stmsmi.c23
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;
}