aboutsummaryrefslogtreecommitdiff
path: root/src/flash/nor
diff options
context:
space:
mode:
authorTarek BOCHKATI <tarek.bouchkati@gmail.com>2020-03-25 16:33:30 +0100
committerTomas Vanek <vanekt@fbl.cz>2020-11-15 21:55:20 +0000
commit3d736e0488bc498358e3d49d7ce728b17955c8fe (patch)
tree94881dbfbc971328d7455c65200ec9e1ce9367b0 /src/flash/nor
parentdc43ecce5a7ee5722ea851707ad3acd08a42b5aa (diff)
downloadriscv-openocd-3d736e0488bc498358e3d49d7ce728b17955c8fe.zip
riscv-openocd-3d736e0488bc498358e3d49d7ce728b17955c8fe.tar.gz
riscv-openocd-3d736e0488bc498358e3d49d7ce728b17955c8fe.tar.bz2
flash/stm32l4x: STM32L55/L56xx basic support (non-secure mode)
STM32L5 have 512 Kbytes of Flash memory with dual bank architecture. STM32L5 flash is quite similar to L4 flash, mainly register names and offsets and some bits are changed. NON-SECURE flash is located at 0x8000000 like L4 devices, so no big change is needed (secure flash will be subject of another change). Note: flash driver name is set stm32l5x, in order to extend the commands with specific L5 commands (to manage TZEN for example ...) Note: this works only when TZEN=0 Change-Id: Ie758abb4aa19a3f29eeb0702d7dcb43992e4c639 Signed-off-by: Michael Jung <mijung@gmx.net> Signed-off-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com> Reviewed-on: http://openocd.zylin.com/5510 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Diffstat (limited to 'src/flash/nor')
-rw-r--r--src/flash/nor/stm32l4x.c75
1 files changed, 63 insertions, 12 deletions
diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
index ca8a3b8..2bf2913 100644
--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -106,6 +106,12 @@
* Cat. 4 devices have single bank only, page size is 2kByte.
*/
+/* STM32L5xxx series for reference.
+ *
+ * RM0428 (STM32L552xx/STM32L562xx)
+ * http://www.st.com/resource/en/reference_manual/dm00346336.pdf
+ */
+
/* Erase time can be as high as 25ms, 10x this and assume it's toast... */
#define FLASH_ERASE_TIMEOUT 250
@@ -137,6 +143,19 @@ static const uint32_t stm32l4_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
[STM32_FLASH_WRP2BR_INDEX] = 0x050,
};
+static const uint32_t stm32l5_ns_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
+ [STM32_FLASH_ACR_INDEX] = 0x000,
+ [STM32_FLASH_KEYR_INDEX] = 0x008,
+ [STM32_FLASH_OPTKEYR_INDEX] = 0x010,
+ [STM32_FLASH_SR_INDEX] = 0x020,
+ [STM32_FLASH_CR_INDEX] = 0x028,
+ [STM32_FLASH_OPTR_INDEX] = 0x040,
+ [STM32_FLASH_WRP1AR_INDEX] = 0x058,
+ [STM32_FLASH_WRP1BR_INDEX] = 0x05C,
+ [STM32_FLASH_WRP2AR_INDEX] = 0x068,
+ [STM32_FLASH_WRP2BR_INDEX] = 0x06C,
+};
+
struct stm32l4_rev {
const uint16_t rev;
const char *str;
@@ -167,7 +186,7 @@ struct stm32l4_flash_bank {
};
/* human readable list of families this drivers supports (sorted alphabetically) */
-static const char *device_families = "STM32G0/G4/L4/L4+/WB/WL";
+static const char *device_families = "STM32G0/G4/L4/L4+/L5/WB/WL";
static const struct stm32l4_rev stm32_415_revs[] = {
{ 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" }
@@ -213,6 +232,10 @@ static const struct stm32l4_rev stm32_471_revs[] = {
{ 0x1001, "Z" },
};
+static const struct stm32l4_rev stm32_472_revs[] = {
+ { 0x1000, "A" }, { 0x2000, "B" },
+};
+
static const struct stm32l4_rev stm32_479_revs[] = {
{ 0x1000, "A" },
};
@@ -352,6 +375,17 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
.fsize_addr = 0x1FFF75E0,
},
{
+ .id = 0x472,
+ .revs = stm32_472_revs,
+ .num_revs = ARRAY_SIZE(stm32_472_revs),
+ .device_str = "STM32L55/L56xx",
+ .max_flash_size_kb = 512,
+ .has_dual_bank = true,
+ .flash_regs_base = 0x40022000,
+ .default_flash_regs = stm32l5_ns_flash_regs,
+ .fsize_addr = 0x0BFA05E0,
+ },
+ {
.id = 0x479,
.revs = stm32_479_revs,
.num_revs = ARRAY_SIZE(stm32_479_revs),
@@ -477,7 +511,6 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
alive_sleep(1);
}
-
if (status & FLASH_WRPERR) {
LOG_ERROR("stm32x device protected");
retval = ERROR_FAIL;
@@ -917,17 +950,17 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
{
int retval;
- /* try stm32l4/l4+/wb/g4 id register first, then stm32g0 id register */
- retval = target_read_u32(bank->target, DBGMCU_IDCODE_L4_G4, id);
- if ((retval != ERROR_OK) || ((*id & 0xfff) == 0) || ((*id & 0xfff) == 0xfff)) {
- retval = target_read_u32(bank->target, DBGMCU_IDCODE_G0, id);
- if ((retval != ERROR_OK) || ((*id & 0xfff) == 0) || ((*id & 0xfff) == 0xfff)) {
- LOG_ERROR("can't get device id");
- return (retval == ERROR_OK) ? ERROR_FAIL : retval;
- }
+ /* try reading possible IDCODE registers, in the following order */
+ uint32_t DBGMCU_IDCODE[] = {DBGMCU_IDCODE_L4_G4, DBGMCU_IDCODE_G0, DBGMCU_IDCODE_L5};
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(DBGMCU_IDCODE); i++) {
+ retval = target_read_u32(bank->target, DBGMCU_IDCODE[i], id);
+ if ((retval == ERROR_OK) && ((*id & 0xfff) != 0) && ((*id & 0xfff) != 0xfff))
+ return ERROR_OK;
}
- return retval;
+ LOG_ERROR("can't get the device id");
+ return (retval == ERROR_OK) ? ERROR_FAIL : retval;
}
static int stm32l4_probe(struct flash_bank *bank)
@@ -1004,6 +1037,7 @@ static int stm32l4_probe(struct flash_bank *bank)
int page_size_kb = 0;
stm32l4_info->dual_bank_mode = false;
+ bool use_dbank_bit = false;
switch (device_id) {
case 0x415: /* STM32L47/L48xx */
@@ -1070,7 +1104,7 @@ static int stm32l4_probe(struct flash_bank *bank)
page_size_kb = 8;
num_pages = flash_size_kb / page_size_kb;
stm32l4_info->bank1_sectors = num_pages;
- const bool use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb;
+ use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb;
if ((use_dbank_bit && (options & BIT(22))) ||
(!use_dbank_bit && (options & BIT(21)))) {
stm32l4_info->dual_bank_mode = true;
@@ -1079,6 +1113,23 @@ static int stm32l4_probe(struct flash_bank *bank)
stm32l4_info->bank1_sectors = num_pages / 2;
}
break;
+ case 0x472: /* STM32L55/L56xx */
+ /* STM32L55/L56xx can be single/dual bank:
+ * if size = 512K check DBANK bit(22)
+ * if size = 256K check DB256K bit(21)
+ */
+ page_size_kb = 4;
+ num_pages = flash_size_kb / page_size_kb;
+ stm32l4_info->bank1_sectors = num_pages;
+ use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb;
+ if ((use_dbank_bit && (options & BIT(22))) ||
+ (!use_dbank_bit && (options & BIT(21)))) {
+ stm32l4_info->dual_bank_mode = true;
+ page_size_kb = 2;
+ num_pages = flash_size_kb / page_size_kb;
+ stm32l4_info->bank1_sectors = num_pages / 2;
+ }
+ break;
case 0x495: /* STM32WB5x */
case 0x496: /* STM32WB3x */
/* single bank flash */