openocd: remove recently added CamelCase symbols
[fw/openocd] / src / flash / nor / stm32l4x.c
index 06d4ac1eaaf6c98048da083bc62d1054e06b4dfc..a1108b5fd2a42f4b1c0802ca4dd549521333dc57 100644 (file)
@@ -1,22 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2015 by Uwe Bonnes                                      *
  *   bon@elektron.ikp.physik.tu-darmstadt.de                               *
  *                                                                         *
  *   Copyright (C) 2019 by Tarek Bochkati for STMicroelectronics           *
  *   tarek.bouchkati@gmail.com                                             *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "imp.h"
 #include <helper/align.h>
 #include <helper/binarybuffer.h>
+#include <helper/bits.h>
 #include <target/algorithm.h>
-#include <target/armv7m.h>
-#include "bits.h"
+#include <target/arm_adi_v5.h>
+#include <target/cortex_m.h>
 #include "stm32l4x.h"
 
 /* STM32L4xxx series for reference.
  *  - for STM32L4P5/Q5x
  *    In 1M FLASH devices bit 22 (DBANK) controls Dual Bank mode.
  *    In 512K FLASH devices bit 21 (DB512K) controls Dual Bank mode.
- *
  */
 
 /* STM32WBxxx series for reference.
  *
- * RM0434 (STM32WB55)
+ * RM0434 (STM32WB55/WB35x)
  * http://www.st.com/resource/en/reference_manual/dm00318631.pdf
  *
- * RM0471 (STM32WB50)
+ * RM0471 (STM32WB50/WB30x)
  * http://www.st.com/resource/en/reference_manual/dm00622834.pdf
+ *
+ * RM0473 (STM32WB15x)
+ * http://www.st.com/resource/en/reference_manual/dm00649196.pdf
+ *
+ * RM0478 (STM32WB10x)
+ * http://www.st.com/resource/en/reference_manual/dm00689203.pdf
  */
 
 /* STM32WLxxx series for reference.
  *
  * RM0461 (STM32WLEx)
  * http://www.st.com/resource/en/reference_manual/dm00530369.pdf
+ *
+ * RM0453 (STM32WL5x)
+ * http://www.st.com/resource/en/reference_manual/dm00451556.pdf
  */
 
 /* STM32G0xxx series for reference.
 /* Erase time can be as high as 25ms, 10x this and assume it's toast... */
 
 #define FLASH_ERASE_TIMEOUT 250
+#define FLASH_WRITE_TIMEOUT 50
 
 
 /* relevant STM32L4 flags ****************************************************/
 #define F_USE_ALL_WRPXX     BIT(1)
 /* this flag indicates if the device embeds a TrustZone security feature */
 #define F_HAS_TZ            BIT(2)
+/* this flag indicates if the device has the same flash registers as STM32L5 */
+#define F_HAS_L5_FLASH_REGS BIT(3)
+/* this flag indicates that programming should be done in quad-word
+ * the default programming word size is double-word */
+#define F_QUAD_WORD_PROG    BIT(4)
 /* end of STM32L4 flags ******************************************************/
 
 
@@ -136,6 +140,9 @@ enum stm32l4_flash_reg_index {
        STM32_FLASH_OPTKEYR_INDEX,
        STM32_FLASH_SR_INDEX,
        STM32_FLASH_CR_INDEX,
+       /* for some devices like STM32WL5x, the CPU2 have a dedicated C2CR register w/o LOCKs,
+        * so it uses the C2CR for flash operations and CR for checking locks and locking */
+       STM32_FLASH_CR_WLK_INDEX, /* FLASH_CR_WITH_LOCK */
        STM32_FLASH_OPTR_INDEX,
        STM32_FLASH_WRP1AR_INDEX,
        STM32_FLASH_WRP1BR_INDEX,
@@ -164,12 +171,37 @@ 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] = {
+static const uint32_t stm32wl_cpu2_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_SR_INDEX]       = 0x060,
+       [STM32_FLASH_CR_INDEX]       = 0x064,
+       [STM32_FLASH_CR_WLK_INDEX]   = 0x014,
+       [STM32_FLASH_OPTR_INDEX]     = 0x020,
+       [STM32_FLASH_WRP1AR_INDEX]   = 0x02C,
+       [STM32_FLASH_WRP1BR_INDEX]   = 0x030,
+};
+
+static const uint32_t stm32l5_ns_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
+       [STM32_FLASH_ACR_INDEX]      = 0x000,
+       [STM32_FLASH_KEYR_INDEX]     = 0x008, /* NSKEYR */
+       [STM32_FLASH_OPTKEYR_INDEX]  = 0x010,
+       [STM32_FLASH_SR_INDEX]       = 0x020, /* NSSR */
+       [STM32_FLASH_CR_INDEX]       = 0x028, /* NSCR */
+       [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,
+};
+
+static const uint32_t stm32l5_s_flash_regs[STM32_FLASH_REG_INDEX_NUM] = {
+       [STM32_FLASH_ACR_INDEX]      = 0x000,
+       [STM32_FLASH_KEYR_INDEX]     = 0x00C, /* SECKEYR */
+       [STM32_FLASH_OPTKEYR_INDEX]  = 0x010,
+       [STM32_FLASH_SR_INDEX]       = 0x024, /* SECSR */
+       [STM32_FLASH_CR_INDEX]       = 0x02C, /* SECCR */
        [STM32_FLASH_OPTR_INDEX]     = 0x040,
        [STM32_FLASH_WRP1AR_INDEX]   = 0x058,
        [STM32_FLASH_WRP1BR_INDEX]   = 0x05C,
@@ -190,7 +222,6 @@ struct stm32l4_part_info {
        const uint16_t max_flash_size_kb;
        const uint32_t flags; /* one bit per feature, see STM32L4 flags: macros F_XXX */
        const uint32_t flash_regs_base;
-       const uint32_t *default_flash_regs;
        const uint32_t fsize_addr;
        const uint32_t otp_base;
        const uint32_t otp_size;
@@ -203,8 +234,12 @@ struct stm32l4_flash_bank {
        bool dual_bank_mode;
        int hole_sectors;
        uint32_t user_bank_size;
+       uint32_t data_width;
+       uint32_t cr_bker_mask;
+       uint32_t sr_bsy_mask;
        uint32_t wrpxxr_mask;
        const struct stm32l4_part_info *part_info;
+       uint32_t flash_regs_base;
        const uint32_t *flash_regs;
        bool otp_enabled;
        enum stm32l4_rdp rdp;
@@ -228,277 +263,325 @@ struct stm32l4_wrp {
 };
 
 /* human readable list of families this drivers supports (sorted alphabetically) */
-static const char *device_families = "STM32G0/G4/L4/L4+/L5/WB/WL";
+static const char *device_families = "STM32G0/G4/L4/L4+/L5/U5/WB/WL";
 
-static const struct stm32l4_rev stm32_415_revs[] = {
+static const struct stm32l4_rev stm32l47_l48xx_revs[] = {
        { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" }
 };
 
-static const struct stm32l4_rev stm32_435_revs[] = {
+static const struct stm32l4_rev stm32l43_l44xx_revs[] = {
        { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" },
 };
 
-static const struct stm32l4_rev stm32_460_revs[] = {
+static const struct stm32l4_rev stm32g05_g06xx_revs[] = {
+       { 0x1000, "A" },
+};
+
+static const struct stm32l4_rev stm32_g07_g08xx_revs[] = {
        { 0x1000, "A/Z" } /* A and Z, no typo in RM! */, { 0x2000, "B" },
 };
 
-static const struct stm32l4_rev stm32_461_revs[] = {
+static const struct stm32l4_rev stm32l49_l4axx_revs[] = {
        { 0x1000, "A" }, { 0x2000, "B" },
 };
 
-static const struct stm32l4_rev stm32_462_revs[] = {
+static const struct stm32l4_rev stm32l45_l46xx_revs[] = {
        { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" },
 };
 
-static const struct stm32l4_rev stm32_464_revs[] = {
+static const struct stm32l4_rev stm32l41_l42xx_revs[] = {
        { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" },
 };
 
-static const struct stm32l4_rev stm32_466_revs[] = {
+static const struct stm32l4_rev stm32g03_g04xx_revs[] = {
        { 0x1000, "A" }, { 0x1001, "Z" }, { 0x2000, "B" },
 };
 
-static const struct stm32l4_rev stm32_468_revs[] = {
+static const struct stm32l4_rev stm32g0b_g0cxx_revs[] = {
+       { 0x1000, "A" },
+};
+
+static const struct stm32l4_rev stm32g43_g44xx_revs[] = {
        { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" },
 };
 
-static const struct stm32l4_rev stm32_469_revs[] = {
+static const struct stm32l4_rev stm32g47_g48xx_revs[] = {
        { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" },
 };
 
-static const struct stm32l4_rev stm32_470_revs[] = {
+static const struct stm32l4_rev stm32l4r_l4sxx_revs[] = {
        { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" },
 };
 
-static const struct stm32l4_rev stm32_471_revs[] = {
+static const struct stm32l4_rev stm32l4p_l4qxx_revs[] = {
        { 0x1001, "Z" },
 };
 
-static const struct stm32l4_rev stm32_472_revs[] = {
+static const struct stm32l4_rev stm32l55_l56xx_revs[] = {
        { 0x1000, "A" }, { 0x2000, "B" },
 };
 
-static const struct stm32l4_rev stm32_479_revs[] = {
+static const struct stm32l4_rev stm32g49_g4axx_revs[] = {
        { 0x1000, "A" },
 };
 
-static const struct stm32l4_rev stm32_495_revs[] = {
+static const struct stm32l4_rev stm32u57_u58xx_revs[] = {
+       { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" },
+};
+
+static const struct stm32l4_rev stm32wb1xx_revs[] = {
+       { 0x1000, "A" }, { 0x2000, "B" },
+};
+
+static const struct stm32l4_rev stm32wb5xx_revs[] = {
        { 0x2001, "2.1" },
 };
 
-static const struct stm32l4_rev stm32_496_revs[] = {
+static const struct stm32l4_rev stm32wb3xx_revs[] = {
        { 0x1000, "A" },
 };
 
-static const struct stm32l4_rev stm32_497_revs[] = {
+static const struct stm32l4_rev stm32wle_wl5xx_revs[] = {
        { 0x1000, "1.0" },
 };
 
 static const struct stm32l4_part_info stm32l4_parts[] = {
        {
-         .id                    = 0x415,
-         .revs                  = stm32_415_revs,
-         .num_revs              = ARRAY_SIZE(stm32_415_revs),
+         .id                    = DEVID_STM32L47_L48XX,
+         .revs                  = stm32l47_l48xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l47_l48xx_revs),
          .device_str            = "STM32L47/L48xx",
          .max_flash_size_kb     = 1024,
          .flags                 = F_HAS_DUAL_BANK,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x435,
-         .revs                  = stm32_435_revs,
-         .num_revs              = ARRAY_SIZE(stm32_435_revs),
+         .id                    = DEVID_STM32L43_L44XX,
+         .revs                  = stm32l43_l44xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l43_l44xx_revs),
          .device_str            = "STM32L43/L44xx",
          .max_flash_size_kb     = 256,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x460,
-         .revs                  = stm32_460_revs,
-         .num_revs              = ARRAY_SIZE(stm32_460_revs),
+         .id                    = DEVID_STM32G05_G06XX,
+         .revs                  = stm32g05_g06xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32g05_g06xx_revs),
+         .device_str            = "STM32G05/G06xx",
+         .max_flash_size_kb     = 64,
+         .flags                 = F_NONE,
+         .flash_regs_base       = 0x40022000,
+         .fsize_addr            = 0x1FFF75E0,
+         .otp_base              = 0x1FFF7000,
+         .otp_size              = 1024,
+       },
+       {
+         .id                    = DEVID_STM32G07_G08XX,
+         .revs                  = stm32_g07_g08xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32_g07_g08xx_revs),
          .device_str            = "STM32G07/G08xx",
          .max_flash_size_kb     = 128,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x461,
-         .revs                  = stm32_461_revs,
-         .num_revs              = ARRAY_SIZE(stm32_461_revs),
+         .id                    = DEVID_STM32L49_L4AXX,
+         .revs                  = stm32l49_l4axx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l49_l4axx_revs),
          .device_str            = "STM32L49/L4Axx",
          .max_flash_size_kb     = 1024,
          .flags                 = F_HAS_DUAL_BANK,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x462,
-         .revs                  = stm32_462_revs,
-         .num_revs              = ARRAY_SIZE(stm32_462_revs),
+         .id                    = DEVID_STM32L45_L46XX,
+         .revs                  = stm32l45_l46xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l45_l46xx_revs),
          .device_str            = "STM32L45/L46xx",
          .max_flash_size_kb     = 512,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x464,
-         .revs                  = stm32_464_revs,
-         .num_revs              = ARRAY_SIZE(stm32_464_revs),
+         .id                    = DEVID_STM32L41_L42XX,
+         .revs                  = stm32l41_l42xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l41_l42xx_revs),
          .device_str            = "STM32L41/L42xx",
          .max_flash_size_kb     = 128,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x466,
-         .revs                  = stm32_466_revs,
-         .num_revs              = ARRAY_SIZE(stm32_466_revs),
-         .device_str            = "STM32G03/G04xx",
+         .id                    = DEVID_STM32G03_G04XX,
+         .revs                  = stm32g03_g04xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32g03_g04xx_revs),
+         .device_str            = "STM32G03x/G04xx",
          .max_flash_size_kb     = 64,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x468,
-         .revs                  = stm32_468_revs,
-         .num_revs              = ARRAY_SIZE(stm32_468_revs),
+         .id                    = DEVID_STM32G0B_G0CXX,
+         .revs                  = stm32g0b_g0cxx_revs,
+         .num_revs              = ARRAY_SIZE(stm32g0b_g0cxx_revs),
+         .device_str            = "STM32G0B/G0Cx",
+         .max_flash_size_kb     = 512,
+         .flags                 = F_HAS_DUAL_BANK,
+         .flash_regs_base       = 0x40022000,
+         .fsize_addr            = 0x1FFF75E0,
+         .otp_base              = 0x1FFF7000,
+         .otp_size              = 1024,
+       },
+       {
+         .id                    = DEVID_STM32G43_G44XX,
+         .revs                  = stm32g43_g44xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32g43_g44xx_revs),
          .device_str            = "STM32G43/G44xx",
          .max_flash_size_kb     = 128,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x469,
-         .revs                  = stm32_469_revs,
-         .num_revs              = ARRAY_SIZE(stm32_469_revs),
+         .id                    = DEVID_STM32G47_G48XX,
+         .revs                  = stm32g47_g48xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32g47_g48xx_revs),
          .device_str            = "STM32G47/G48xx",
          .max_flash_size_kb     = 512,
          .flags                 = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x470,
-         .revs                  = stm32_470_revs,
-         .num_revs              = ARRAY_SIZE(stm32_470_revs),
+         .id                    = DEVID_STM32L4R_L4SXX,
+         .revs                  = stm32l4r_l4sxx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l4r_l4sxx_revs),
          .device_str            = "STM32L4R/L4Sxx",
          .max_flash_size_kb     = 2048,
          .flags                 = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x471,
-         .revs                  = stm32_471_revs,
-         .num_revs              = ARRAY_SIZE(stm32_471_revs),
-         .device_str            = "STM32L4P5/L4Q5x",
+         .id                    = DEVID_STM32L4P_L4QXX,
+         .revs                  = stm32l4p_l4qxx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l4p_l4qxx_revs),
+         .device_str            = "STM32L4P/L4Qxx",
          .max_flash_size_kb     = 1024,
          .flags                 = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x472,
-         .revs                  = stm32_472_revs,
-         .num_revs              = ARRAY_SIZE(stm32_472_revs),
+         .id                    = DEVID_STM32L55_L56XX,
+         .revs                  = stm32l55_l56xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32l55_l56xx_revs),
          .device_str            = "STM32L55/L56xx",
          .max_flash_size_kb     = 512,
-         .flags                 = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX | F_HAS_TZ,
+         .flags                 = F_HAS_DUAL_BANK | F_USE_ALL_WRPXX | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l5_ns_flash_regs,
          .fsize_addr            = 0x0BFA05E0,
          .otp_base              = 0x0BFA0000,
          .otp_size              = 512,
        },
        {
-         .id                    = 0x479,
-         .revs                  = stm32_479_revs,
-         .num_revs              = ARRAY_SIZE(stm32_479_revs),
+         .id                    = DEVID_STM32G49_G4AXX,
+         .revs                  = stm32g49_g4axx_revs,
+         .num_revs              = ARRAY_SIZE(stm32g49_g4axx_revs),
          .device_str            = "STM32G49/G4Axx",
          .max_flash_size_kb     = 512,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x40022000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x495,
-         .revs                  = stm32_495_revs,
-         .num_revs              = ARRAY_SIZE(stm32_495_revs),
+         .id                    = DEVID_STM32U57_U58XX,
+         .revs                  = stm32u57_u58xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32u57_u58xx_revs),
+         .device_str            = "STM32U57/U58xx",
+         .max_flash_size_kb     = 2048,
+         .flags                 = F_HAS_DUAL_BANK | F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
+         .flash_regs_base       = 0x40022000,
+         .fsize_addr            = 0x0BFA07A0,
+         .otp_base              = 0x0BFA0000,
+         .otp_size              = 512,
+       },
+       {
+         .id                    = DEVID_STM32WB1XX,
+         .revs                  = stm32wb1xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32wb1xx_revs),
+         .device_str            = "STM32WB1x",
+         .max_flash_size_kb     = 320,
+         .flags                 = F_NONE,
+         .flash_regs_base       = 0x58004000,
+         .fsize_addr            = 0x1FFF75E0,
+         .otp_base              = 0x1FFF7000,
+         .otp_size              = 1024,
+       },
+       {
+         .id                    = DEVID_STM32WB5XX,
+         .revs                  = stm32wb5xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32wb5xx_revs),
          .device_str            = "STM32WB5x",
          .max_flash_size_kb     = 1024,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x58004000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x496,
-         .revs                  = stm32_496_revs,
-         .num_revs              = ARRAY_SIZE(stm32_496_revs),
+         .id                    = DEVID_STM32WB3XX,
+         .revs                  = stm32wb3xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32wb3xx_revs),
          .device_str            = "STM32WB3x",
          .max_flash_size_kb     = 512,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x58004000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
        },
        {
-         .id                    = 0x497,
-         .revs                  = stm32_497_revs,
-         .num_revs              = ARRAY_SIZE(stm32_497_revs),
-         .device_str            = "STM32WLEx",
+         .id                    = DEVID_STM32WLE_WL5XX,
+         .revs                  = stm32wle_wl5xx_revs,
+         .num_revs              = ARRAY_SIZE(stm32wle_wl5xx_revs),
+         .device_str            = "STM32WLE/WL5x",
          .max_flash_size_kb     = 256,
          .flags                 = F_NONE,
          .flash_regs_base       = 0x58004000,
-         .default_flash_regs    = stm32l4_flash_regs,
          .fsize_addr            = 0x1FFF75E0,
          .otp_base              = 0x1FFF7000,
          .otp_size              = 1024,
@@ -522,10 +605,6 @@ FLASH_BANK_COMMAND_HANDLER(stm32l4_flash_bank_command)
                return ERROR_FAIL; /* Checkme: What better error to use?*/
        bank->driver_priv = stm32l4_info;
 
-       /* The flash write must be aligned to a double word (8-bytes) boundary.
-        * Ask the flash infrastructure to ensure required alignment */
-       bank->write_start_alignment = bank->write_end_alignment = 8;
-
        stm32l4_info->probed = false;
        stm32l4_info->otp_enabled = false;
        stm32l4_info->user_bank_size = bank->size;
@@ -653,7 +732,7 @@ static void stm32l4_sync_rdp_tzen(struct flash_bank *bank)
 static inline uint32_t stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
 {
        struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
-       return stm32l4_info->part_info->flash_regs_base + reg_offset;
+       return stm32l4_info->flash_regs_base + reg_offset;
 }
 
 static inline uint32_t stm32l4_get_flash_reg_by_index(struct flash_bank *bank,
@@ -689,6 +768,7 @@ static inline int stm32l4_write_flash_reg_by_index(struct flash_bank *bank,
 
 static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
 {
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        uint32_t status;
        int retval = ERROR_OK;
 
@@ -698,7 +778,7 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
                if (retval != ERROR_OK)
                        return retval;
                LOG_DEBUG("status: 0x%" PRIx32 "", status);
-               if ((status & FLASH_BSY) == 0)
+               if ((status & stm32l4_info->sr_bsy_mask) == 0)
                        break;
                if (timeout-- <= 0) {
                        LOG_ERROR("timed out waiting for flash");
@@ -725,14 +805,65 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
        return retval;
 }
 
+/** set all FLASH_SECBB registers to the same value */
+static int stm32l4_set_secbb(struct flash_bank *bank, uint32_t value)
+{
+       /* This function should be used only with device with TrustZone, do just a security check */
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+       assert(stm32l4_info->part_info->flags & F_HAS_TZ);
+
+       /* based on RM0438 Rev6 for STM32L5x devices:
+        * to modify a page block-based security attribution, it is recommended to
+        *  1- check that no flash operation is ongoing on the related page
+        *  2- add ISB instruction after modifying the page security attribute in SECBBxRy
+        *     this step is not need in case of JTAG direct access
+        */
+       int retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* write SECBBxRy registers */
+       LOG_DEBUG("setting secure block-based areas registers (SECBBxRy) to 0x%08x", value);
+
+       const uint8_t secbb_regs[] = {
+                       FLASH_SECBB1(1), FLASH_SECBB1(2), FLASH_SECBB1(3), FLASH_SECBB1(4), /* bank 1 SECBB register offsets */
+                       FLASH_SECBB2(1), FLASH_SECBB2(2), FLASH_SECBB2(3), FLASH_SECBB2(4)  /* bank 2 SECBB register offsets */
+       };
+
+
+       unsigned int num_secbb_regs = ARRAY_SIZE(secbb_regs);
+
+       /* in single bank mode, it's useless to modify FLASH_SECBB2Rx registers
+        * then consider only the first half of secbb_regs
+        */
+       if (!stm32l4_info->dual_bank_mode)
+               num_secbb_regs /= 2;
+
+       for (unsigned int i = 0; i < num_secbb_regs; i++) {
+               retval = stm32l4_write_flash_reg(bank, secbb_regs[i], value);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static inline int stm32l4_get_flash_cr_with_lock_index(struct flash_bank *bank)
+{
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+       return (stm32l4_info->flash_regs[STM32_FLASH_CR_WLK_INDEX]) ?
+               STM32_FLASH_CR_WLK_INDEX : STM32_FLASH_CR_INDEX;
+}
+
 static int stm32l4_unlock_reg(struct flash_bank *bank)
 {
+       const uint32_t flash_cr_index = stm32l4_get_flash_cr_with_lock_index(bank);
        uint32_t ctrl;
 
        /* first check if not already unlocked
         * otherwise writing on STM32_FLASH_KEYR will fail
         */
-       int retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl);
+       int retval = stm32l4_read_flash_reg_by_index(bank, flash_cr_index, &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -748,7 +879,7 @@ static int stm32l4_unlock_reg(struct flash_bank *bank)
        if (retval != ERROR_OK)
                return retval;
 
-       retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl);
+       retval = stm32l4_read_flash_reg_by_index(bank, flash_cr_index, &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -762,9 +893,10 @@ static int stm32l4_unlock_reg(struct flash_bank *bank)
 
 static int stm32l4_unlock_option_reg(struct flash_bank *bank)
 {
+       const uint32_t flash_cr_index = stm32l4_get_flash_cr_with_lock_index(bank);
        uint32_t ctrl;
 
-       int retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl);
+       int retval = stm32l4_read_flash_reg_by_index(bank, flash_cr_index, &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -780,7 +912,7 @@ static int stm32l4_unlock_option_reg(struct flash_bank *bank)
        if (retval != ERROR_OK)
                return retval;
 
-       retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl);
+       retval = stm32l4_read_flash_reg_by_index(bank, flash_cr_index, &ctrl);
        if (retval != ERROR_OK)
                return retval;
 
@@ -820,7 +952,8 @@ static int stm32l4_perform_obl_launch(struct flash_bank *bank)
        stm32l4_info->probed = false;
 
 err_lock:
-       retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK | FLASH_OPTLOCK);
+       retval2 = stm32l4_write_flash_reg_by_index(bank, stm32l4_get_flash_cr_with_lock_index(bank),
+                       FLASH_LOCK | FLASH_OPTLOCK);
 
        if (retval != ERROR_OK)
                return retval;
@@ -831,6 +964,7 @@ err_lock:
 static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset,
        uint32_t value, uint32_t mask)
 {
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        uint32_t optiondata;
        int retval, retval2;
 
@@ -838,6 +972,12 @@ static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset,
        if (retval != ERROR_OK)
                return retval;
 
+       /* for STM32L5 and similar devices, use always non-secure
+        * registers for option bytes programming */
+       const uint32_t *saved_flash_regs = stm32l4_info->flash_regs;
+       if (stm32l4_info->part_info->flags & F_HAS_L5_FLASH_REGS)
+               stm32l4_info->flash_regs = stm32l5_ns_flash_regs;
+
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                goto err_lock;
@@ -859,7 +999,9 @@ static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset,
        retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
 
 err_lock:
-       retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK | FLASH_OPTLOCK);
+       retval2 = stm32l4_write_flash_reg_by_index(bank, stm32l4_get_flash_cr_with_lock_index(bank),
+                       FLASH_LOCK | FLASH_OPTLOCK);
+       stm32l4_info->flash_regs = saved_flash_regs;
 
        if (retval != ERROR_OK)
                return retval;
@@ -925,7 +1067,7 @@ static int stm32l4_get_all_wrpxy(struct flash_bank *bank, enum stm32_bank_id dev
        if (dev_bank_id != STM32_BANK1 && stm32l4_info->dual_bank_mode)
                wrp2y_sectors_offset = stm32l4_info->bank1_sectors;
 
-       if (wrp2y_sectors_offset > -1) {
+       if (wrp2y_sectors_offset >= 0) {
                /* get WRP2AR */
                ret = stm32l4_get_one_wrpxy(bank, &wrpxy[(*n_wrp)++], STM32_FLASH_WRP2AR_INDEX, wrp2y_sectors_offset);
                if (ret != ERROR_OK)
@@ -1007,6 +1149,16 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first,
                return ERROR_TARGET_NOT_HALTED;
        }
 
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               /* set all FLASH pages as secure */
+               retval = stm32l4_set_secbb(bank, FLASH_SECBB_SECURE);
+               if (retval != ERROR_OK) {
+                       /* restore all FLASH pages as non-secure */
+                       stm32l4_set_secbb(bank, FLASH_SECBB_NON_SECURE); /* ignore the return value */
+                       return retval;
+               }
+       }
+
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                goto err_lock;
@@ -1029,7 +1181,7 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first,
                if (i >= stm32l4_info->bank1_sectors) {
                        uint8_t snb;
                        snb = i - stm32l4_info->bank1_sectors;
-                       erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER;
+                       erase_flags |= snb << FLASH_PAGE_SHIFT | stm32l4_info->cr_bker_mask;
                } else
                        erase_flags |= i << FLASH_PAGE_SHIFT;
                retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, erase_flags);
@@ -1042,7 +1194,14 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first,
        }
 
 err_lock:
-       retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK);
+       retval2 = stm32l4_write_flash_reg_by_index(bank, stm32l4_get_flash_cr_with_lock_index(bank), FLASH_LOCK);
+
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               /* restore all FLASH pages as non-secure */
+               int retval3 = stm32l4_set_secbb(bank, FLASH_SECBB_NON_SECURE);
+               if (retval3 != ERROR_OK)
+                       return retval3;
+       }
 
        if (retval != ERROR_OK)
                return retval;
@@ -1050,49 +1209,11 @@ err_lock:
        return retval2;
 }
 
-static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
+static int stm32l4_protect_same_bank(struct flash_bank *bank, enum stm32_bank_id bank_id, int set,
+               unsigned int first, unsigned int last)
 {
-       struct target *target = bank->target;
-       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
-       int ret = ERROR_OK;
        unsigned int i;
 
-       if (stm32l4_is_otp(bank)) {
-               LOG_ERROR("cannot protect/unprotect OTP memory");
-               return ERROR_FLASH_OPER_UNSUPPORTED;
-       }
-
-       if (target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       /* the requested sectors could be located into bank1 and/or bank2 */
-       bool use_bank2 = false;
-       if (last >= stm32l4_info->bank1_sectors) {
-               if (first < stm32l4_info->bank1_sectors) {
-                       /* the requested sectors for (un)protection are shared between
-                        * bank 1 and 2, then split the operation */
-
-                       /*  1- deal with bank 1 sectors */
-                       LOG_DEBUG("The requested sectors for %s are shared between bank 1 and 2",
-                                       set ? "protection" : "unprotection");
-                       ret = stm32l4_protect(bank, set, first, stm32l4_info->bank1_sectors - 1);
-                       if (ret != ERROR_OK)
-                               return ret;
-
-                       /*  2- then continue with bank 2 sectors */
-                       first = stm32l4_info->bank1_sectors;
-               }
-
-               use_bank2 = true;
-       }
-
-       /* refresh the sectors' protection */
-       ret = stm32l4_protect_check(bank);
-       if (ret != ERROR_OK)
-               return ret;
-
        /* check if the desired protection is already configured */
        for (i = first; i <= last; i++) {
                if (bank->sectors[i].is_protected != set)
@@ -1108,7 +1229,7 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first,
        unsigned int n_wrp;
        struct stm32l4_wrp wrpxy[4];
 
-       ret = stm32l4_get_all_wrpxy(bank, use_bank2 ? STM32_BANK2 : STM32_BANK1, wrpxy, &n_wrp);
+       int ret = stm32l4_get_all_wrpxy(bank, bank_id, wrpxy, &n_wrp);
        if (ret != ERROR_OK)
                return ret;
 
@@ -1179,16 +1300,50 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first,
        return stm32l4_write_all_wrpxy(bank, wrpxy, n_wrp);
 }
 
-/* Count is in double-words */
+static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
+{
+       struct target *target = bank->target;
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+
+       if (stm32l4_is_otp(bank)) {
+               LOG_ERROR("cannot protect/unprotect OTP memory");
+               return ERROR_FLASH_OPER_UNSUPPORTED;
+       }
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* refresh the sectors' protection */
+       int ret = stm32l4_protect_check(bank);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* the requested sectors could be located into bank1 and/or bank2 */
+       if (last < stm32l4_info->bank1_sectors) {
+               return stm32l4_protect_same_bank(bank, STM32_BANK1, set, first, last);
+       } else if (first >= stm32l4_info->bank1_sectors) {
+               return stm32l4_protect_same_bank(bank, STM32_BANK2, set, first, last);
+       } else {
+               ret = stm32l4_protect_same_bank(bank, STM32_BANK1, set, first, stm32l4_info->bank1_sectors - 1);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               return stm32l4_protect_same_bank(bank, STM32_BANK2, set, stm32l4_info->bank1_sectors, last);
+       }
+}
+
+/* count is the size divided by stm32l4_info->data_width */
 static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
        uint32_t offset, uint32_t count)
 {
        struct target *target = bank->target;
-       uint32_t buffer_size;
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        struct working_area *write_algorithm;
        struct working_area *source;
        uint32_t address = bank->base + offset;
-       struct reg_param reg_params[6];
+       struct reg_param reg_params[5];
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
 
@@ -1210,17 +1365,23 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
                return retval;
        }
 
-       /* memory buffer, size *must* be multiple of dword plus one dword for rp and one for wp */
-       buffer_size = target_get_working_area_avail(target) & ~(2 * sizeof(uint32_t) - 1);
+       /* data_width should be multiple of double-word */
+       assert(stm32l4_info->data_width % 8 == 0);
+       const size_t extra_size = sizeof(struct stm32l4_work_area);
+       uint32_t buffer_size = target_get_working_area_avail(target) - extra_size;
+       /* buffer_size should be multiple of stm32l4_info->data_width */
+       buffer_size &= ~(stm32l4_info->data_width - 1);
+
        if (buffer_size < 256) {
                LOG_WARNING("large enough working area not available, can't do block memory writes");
+               target_free_working_area(target, write_algorithm);
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        } else if (buffer_size > 16384) {
                /* probably won't benefit from more than 16k ... */
                buffer_size = 16384;
        }
 
-       if (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
+       if (target_alloc_working_area_try(target, buffer_size + extra_size, &source) != ERROR_OK) {
                LOG_ERROR("allocating working area failed");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
@@ -1228,31 +1389,52 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
        armv7m_info.core_mode = ARM_MODE_THREAD;
 
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
+       /* contrib/loaders/flash/stm32/stm32l4x.c:write() arguments */
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* stm32l4_work_area ptr , status (out) */
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* buffer end */
        init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* target address */
-       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* count (double word-64bit) */
-       init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);    /* flash status register */
-       init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);    /* flash control register */
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);    /* count (of stm32l4_info->data_width) */
 
        buf_set_u32(reg_params[0].value, 0, 32, source->address);
        buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
        buf_set_u32(reg_params[2].value, 0, 32, address);
        buf_set_u32(reg_params[3].value, 0, 32, count);
-       buf_set_u32(reg_params[4].value, 0, 32, stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX));
-       buf_set_u32(reg_params[5].value, 0, 32, stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX));
 
-       retval = target_run_flash_async_algorithm(target, buffer, count, 8,
+       /* write algo stack pointer */
+       init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
+       buf_set_u32(reg_params[4].value, 0, 32, source->address +
+                       offsetof(struct stm32l4_work_area, stack) + LDR_STACK_SIZE);
+
+       struct stm32l4_loader_params loader_extra_params;
+
+       target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_sr_addr,
+                       stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX));
+       target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_cr_addr,
+                       stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX));
+       target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_word_size,
+                       stm32l4_info->data_width);
+       target_buffer_set_u32(target, (uint8_t *) &loader_extra_params.flash_sr_bsy_mask,
+                       stm32l4_info->sr_bsy_mask);
+
+       retval = target_write_buffer(target, source->address, sizeof(loader_extra_params),
+                       (uint8_t *) &loader_extra_params);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = target_run_flash_async_algorithm(target, buffer, count, stm32l4_info->data_width,
                        0, NULL,
                        ARRAY_SIZE(reg_params), reg_params,
-                       source->address, source->size,
+                       source->address + offsetof(struct stm32l4_work_area, fifo),
+                       source->size - offsetof(struct stm32l4_work_area, fifo),
                        write_algorithm->address, 0,
                        &armv7m_info);
 
        if (retval == ERROR_FLASH_OPERATION_FAILED) {
                LOG_ERROR("error executing stm32l4 flash write algorithm");
 
-               uint32_t error = buf_get_u32(reg_params[0].value, 0, 32) & FLASH_ERROR;
+               uint32_t error;
+               stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, &error);
+               error &= FLASH_ERROR;
 
                if (error & FLASH_WRPERR)
                        LOG_ERROR("flash memory write protected");
@@ -1273,7 +1455,51 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
        destroy_reg_param(&reg_params[2]);
        destroy_reg_param(&reg_params[3]);
        destroy_reg_param(&reg_params[4]);
-       destroy_reg_param(&reg_params[5]);
+
+       return retval;
+}
+
+/* count is the size divided by stm32l4_info->data_width */
+static int stm32l4_write_block_without_loader(struct flash_bank *bank, const uint8_t *buffer,
+                               uint32_t offset, uint32_t count)
+{
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+       struct target *target = bank->target;
+       uint32_t address = bank->base + offset;
+       int retval = ERROR_OK;
+
+       /* wait for BSY bit */
+       retval = stm32l4_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* set PG in FLASH_CR */
+       retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_PG);
+       if (retval != ERROR_OK)
+               return retval;
+
+
+       /* write directly to flash memory */
+       const uint8_t *src = buffer;
+       const uint32_t data_width_in_words = stm32l4_info->data_width / 4;
+       while (count--) {
+               retval = target_write_memory(target, address, 4, data_width_in_words, src);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* wait for BSY bit */
+               retval = stm32l4_wait_status_busy(bank, FLASH_WRITE_TIMEOUT);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               src += stm32l4_info->data_width;
+               address += stm32l4_info->data_width;
+       }
+
+       /* reset PG in FLASH_CR */
+       retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, 0);
+       if (retval != ERROR_OK)
+               return retval;
 
        return retval;
 }
@@ -1281,6 +1507,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
 static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
        uint32_t offset, uint32_t count)
 {
+       struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
        int retval = ERROR_OK, retval2;
 
        if (stm32l4_is_otp(bank) && !stm32l4_otp_is_enabled(bank)) {
@@ -1293,10 +1520,13 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       /* The flash write must be aligned to a double word (8-bytes) boundary.
+       /* ensure that stm32l4_info->data_width is 'at least' a multiple of dword */
+       assert(stm32l4_info->data_width % 8 == 0);
+
+       /* The flash write must be aligned to the 'stm32l4_info->data_width' boundary.
         * The flash infrastructure ensures it, do just a security check */
-       assert(offset % 8 == 0);
-       assert(count % 8 == 0);
+       assert(offset % stm32l4_info->data_width == 0);
+       assert(count % stm32l4_info->data_width == 0);
 
        /* STM32G4xxx Cat. 3 devices may have gaps between banks, check whether
         * data to be written does not go into a gap:
@@ -1335,14 +1565,48 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer,
        if (retval != ERROR_OK)
                return retval;
 
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               /* set all FLASH pages as secure */
+               retval = stm32l4_set_secbb(bank, FLASH_SECBB_SECURE);
+               if (retval != ERROR_OK) {
+                       /* restore all FLASH pages as non-secure */
+                       stm32l4_set_secbb(bank, FLASH_SECBB_NON_SECURE); /* ignore the return value */
+                       return retval;
+               }
+       }
+
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                goto err_lock;
 
-       retval = stm32l4_write_block(bank, buffer, offset, count / 8);
+
+       /* For TrustZone enabled devices, when TZEN is set and RDP level is 0.5,
+        * the debug is possible only in non-secure state.
+        * Thus means the flashloader will run in non-secure mode,
+        * and the workarea need to be in non-secure RAM */
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0_5))
+               LOG_WARNING("RDP = 0x55, the work-area should be in non-secure RAM (check SAU partitioning)");
+
+       /* first try to write using the loader, for better performance */
+       retval = stm32l4_write_block(bank, buffer, offset,
+                       count / stm32l4_info->data_width);
+
+       /* if resources are not available write without a loader */
+       if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
+               LOG_WARNING("falling back to programming without a flash loader (slower)");
+               retval = stm32l4_write_block_without_loader(bank, buffer, offset,
+                               count / stm32l4_info->data_width);
+       }
 
 err_lock:
-       retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK);
+       retval2 = stm32l4_write_flash_reg_by_index(bank, stm32l4_get_flash_cr_with_lock_index(bank), FLASH_LOCK);
+
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               /* restore all FLASH pages as non-secure */
+               int retval3 = stm32l4_set_secbb(bank, FLASH_SECBB_NON_SECURE);
+               if (retval3 != ERROR_OK)
+                       return retval3;
+       }
 
        if (retval != ERROR_OK) {
                LOG_ERROR("block write failed");
@@ -1353,17 +1617,49 @@ err_lock:
 
 static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
 {
-       int retval;
+       int retval = ERROR_OK;
+       struct target *target = bank->target;
 
        /* 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);
+               retval = target_read_u32(target, dbgmcu_idcode[i], id);
                if ((retval == ERROR_OK) && ((*id & 0xfff) != 0) && ((*id & 0xfff) != 0xfff))
                        return ERROR_OK;
        }
 
+       /* Workaround for STM32WL5x devices:
+        * DBGMCU_IDCODE cannot be read using CPU1 (Cortex-M0+) at AP1,
+        * to solve this read the UID64 (IEEE 64-bit unique device ID register) */
+
+       struct armv7m_common *armv7m = target_to_armv7m_safe(target);
+       if (!armv7m) {
+               LOG_ERROR("Flash requires Cortex-M target");
+               return ERROR_TARGET_INVALID;
+       }
+
+       /* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1.
+        * Using HLA adapters armv7m.debug_ap is null, and checking ap_num triggers a segfault */
+       if (cortex_m_get_partno_safe(target) == CORTEX_M0P_PARTNO &&
+                       armv7m->debug_ap && armv7m->debug_ap->ap_num == 1) {
+               uint32_t uid64_ids;
+
+               /* UID64 is contains
+                *  - Bits 63:32 : DEVNUM (unique device number, different for each individual device)
+                *  - Bits 31:08 : STID (company ID) = 0x0080E1
+                *  - Bits 07:00 : DEVID (device ID) = 0x15
+                *
+                *  read only the fixed values {STID,DEVID} from UID64_IDS to identify the device as STM32WLx
+                */
+               retval = target_read_u32(target, UID64_IDS, &uid64_ids);
+               if (retval == ERROR_OK && uid64_ids == UID64_IDS_STM32WL) {
+                       /* force the DEV_ID to DEVID_STM32WLE_WL5XX and the REV_ID to unknown */
+                       *id = DEVID_STM32WLE_WL5XX;
+                       return ERROR_OK;
+               }
+       }
+
        LOG_ERROR("can't get the device id");
        return (retval == ERROR_OK) ? ERROR_FAIL : retval;
 }
@@ -1398,6 +1694,17 @@ static int stm32l4_probe(struct flash_bank *bank)
        const struct stm32l4_part_info *part_info;
        uint16_t flash_size_kb = 0xffff;
 
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_TARGET_NOT_EXAMINED;
+       }
+
+       struct armv7m_common *armv7m = target_to_armv7m_safe(target);
+       if (!armv7m) {
+               LOG_ERROR("Flash requires Cortex-M target");
+               return ERROR_TARGET_INVALID;
+       }
+
        stm32l4_info->probed = false;
 
        /* read stm32 device id registers */
@@ -1426,7 +1733,20 @@ static int stm32l4_probe(struct flash_bank *bank)
        LOG_INFO("device idcode = 0x%08" PRIx32 " (%s - Rev %s : 0x%04x)",
                        stm32l4_info->idcode, part_info->device_str, rev_str, rev_id);
 
-       stm32l4_info->flash_regs = stm32l4_info->part_info->default_flash_regs;
+       stm32l4_info->flash_regs_base = stm32l4_info->part_info->flash_regs_base;
+       stm32l4_info->data_width = (part_info->flags & F_QUAD_WORD_PROG) ? 16 : 8;
+       stm32l4_info->cr_bker_mask = FLASH_BKER;
+       stm32l4_info->sr_bsy_mask = FLASH_BSY;
+
+       /* Set flash write alignment boundaries.
+        * Ask the flash infrastructure to ensure required alignment */
+       bank->write_start_alignment = bank->write_end_alignment = stm32l4_info->data_width;
+
+       /* Initialize the flash registers layout */
+       if (part_info->flags & F_HAS_L5_FLASH_REGS)
+               stm32l4_info->flash_regs = stm32l5_ns_flash_regs;
+       else
+               stm32l4_info->flash_regs = stm32l4_flash_regs;
 
        /* read flash option register */
        retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_OPTR_INDEX, &stm32l4_info->optr);
@@ -1435,6 +1755,17 @@ static int stm32l4_probe(struct flash_bank *bank)
 
        stm32l4_sync_rdp_tzen(bank);
 
+       /* for devices with TrustZone, use flash secure registers when TZEN=1 and RDP is LEVEL_0 */
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               if (part_info->flags & F_HAS_L5_FLASH_REGS) {
+                       stm32l4_info->flash_regs_base |= STM32L5_REGS_SEC_OFFSET;
+                       stm32l4_info->flash_regs = stm32l5_s_flash_regs;
+               } else {
+                       LOG_ERROR("BUG: device supported incomplete");
+                       return ERROR_NOT_IMPLEMENTED;
+               }
+       }
+
        if (part_info->flags & F_HAS_TZ)
                LOG_INFO("TZEN = %d : TrustZone %s by option bytes",
                                stm32l4_info->tzen,
@@ -1461,7 +1792,7 @@ static int stm32l4_probe(struct flash_bank *bank)
 
                stm32l4_info->probed = true;
                return ERROR_OK;
-       } else if (bank->base != STM32_FLASH_BANK_BASE) {
+       } else if (bank->base != STM32_FLASH_BANK_BASE && bank->base != STM32_FLASH_S_BANK_BASE) {
                LOG_ERROR("invalid bank base address");
                return ERROR_FAIL;
        }
@@ -1485,11 +1816,13 @@ static int stm32l4_probe(struct flash_bank *bank)
                flash_size_kb = stm32l4_info->user_bank_size / 1024;
        }
 
-       LOG_INFO("flash size = %dkbytes", flash_size_kb);
+       LOG_INFO("flash size = %d KiB", flash_size_kb);
 
        /* did we assign a flash size? */
        assert((flash_size_kb != 0xffff) && flash_size_kb);
 
+       const bool is_max_flash_size = flash_size_kb == stm32l4_info->part_info->max_flash_size_kb;
+
        stm32l4_info->bank1_sectors = 0;
        stm32l4_info->hole_sectors = 0;
 
@@ -1497,14 +1830,13 @@ 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 */
-       case 0x461: /* STM32L49/L4Axx */
+       case DEVID_STM32L47_L48XX:
+       case DEVID_STM32L49_L4AXX:
                /* if flash size is max (1M) the device is always dual bank
-                * 0x415: has variants with 512K
-                * 0x461: has variants with 512 and 256
+                * STM32L47/L48xx: has variants with 512K
+                * STM32L49/L4Axx: has variants with 512 and 256
                 * for these variants:
                 *   if DUAL_BANK = 0 -> single bank
                 *   else -> dual bank without gap
@@ -1514,26 +1846,41 @@ static int stm32l4_probe(struct flash_bank *bank)
                num_pages = flash_size_kb / page_size_kb;
                stm32l4_info->bank1_sectors = num_pages;
 
-               /* check DUAL_BANK bit[21] if the flash is less than 1M */
-               if (flash_size_kb == 1024 || (stm32l4_info->optr & BIT(21))) {
+               /* check DUAL_BANK option bit if the flash is less than 1M */
+               if (is_max_flash_size || (stm32l4_info->optr & FLASH_L4_DUAL_BANK)) {
                        stm32l4_info->dual_bank_mode = true;
                        stm32l4_info->bank1_sectors = num_pages / 2;
                }
                break;
-       case 0x435: /* STM32L43/L44xx */
-       case 0x460: /* STM32G07/G08xx */
-       case 0x462: /* STM32L45/L46xx */
-       case 0x464: /* STM32L41/L42xx */
-       case 0x466: /* STM32G03/G04xx */
-       case 0x468: /* STM32G43/G44xx */
-       case 0x479: /* STM32G49/G4Axx */
-       case 0x497: /* STM32WLEx */
+       case DEVID_STM32L43_L44XX:
+       case DEVID_STM32G05_G06XX:
+       case DEVID_STM32G07_G08XX:
+       case DEVID_STM32L45_L46XX:
+       case DEVID_STM32L41_L42XX:
+       case DEVID_STM32G03_G04XX:
+       case DEVID_STM32G43_G44XX:
+       case DEVID_STM32G49_G4AXX:
+       case DEVID_STM32WB1XX:
                /* single bank flash */
                page_size_kb = 2;
                num_pages = flash_size_kb / page_size_kb;
                stm32l4_info->bank1_sectors = num_pages;
                break;
-       case 0x469: /* STM32G47/G48xx */
+       case DEVID_STM32G0B_G0CXX:
+               /* single/dual bank depending on DUAL_BANK option bit */
+               page_size_kb = 2;
+               num_pages = flash_size_kb / page_size_kb;
+               stm32l4_info->bank1_sectors = num_pages;
+               stm32l4_info->cr_bker_mask = FLASH_BKER_G0;
+
+               /* check DUAL_BANK bit */
+               if (stm32l4_info->optr & FLASH_G0_DUAL_BANK) {
+                       stm32l4_info->sr_bsy_mask = FLASH_BSY | FLASH_BSY2;
+                       stm32l4_info->dual_bank_mode = true;
+                       stm32l4_info->bank1_sectors = num_pages / 2;
+               }
+               break;
+       case DEVID_STM32G47_G48XX:
                /* STM32G47/8 can be single/dual bank:
                 *   if DUAL_BANK = 0 -> single bank
                 *   else -> dual bank WITH gap
@@ -1541,7 +1888,7 @@ static int stm32l4_probe(struct flash_bank *bank)
                page_size_kb = 4;
                num_pages = flash_size_kb / page_size_kb;
                stm32l4_info->bank1_sectors = num_pages;
-               if (stm32l4_info->optr & BIT(22)) {
+               if (stm32l4_info->optr & FLASH_G4_DUAL_BANK) {
                        stm32l4_info->dual_bank_mode = true;
                        page_size_kb = 2;
                        num_pages = flash_size_kb / page_size_kb;
@@ -1552,56 +1899,88 @@ static int stm32l4_probe(struct flash_bank *bank)
                                (part_info->max_flash_size_kb - flash_size_kb) / (2 * page_size_kb);
                }
                break;
-       case 0x470: /* STM32L4R/L4Sxx */
-       case 0x471: /* STM32L4P5/L4Q5x */
+       case DEVID_STM32L4R_L4SXX:
+       case DEVID_STM32L4P_L4QXX:
                /* STM32L4R/S can be single/dual bank:
-                *   if size = 2M check DBANK bit(22)
-                *   if size = 1M check DB1M bit(21)
+                *   if size = 2M check DBANK bit
+                *   if size = 1M check DB1M bit
                 * STM32L4P/Q can be single/dual bank
-                *   if size = 1M check DBANK bit(22)
-                *   if size = 512K check DB512K bit(21)
+                *   if size = 1M check DBANK bit
+                *   if size = 512K check DB512K bit (same as DB1M bit)
                 */
                page_size_kb = 8;
                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 && (stm32l4_info->optr & BIT(22))) ||
-                       (!use_dbank_bit && (stm32l4_info->optr & BIT(21)))) {
+               if ((is_max_flash_size && (stm32l4_info->optr & FLASH_L4R_DBANK)) ||
+                       (!is_max_flash_size && (stm32l4_info->optr & FLASH_LRR_DB1M))) {
                        stm32l4_info->dual_bank_mode = true;
                        page_size_kb = 4;
                        num_pages = flash_size_kb / page_size_kb;
                        stm32l4_info->bank1_sectors = num_pages / 2;
                }
                break;
-       case 0x472: /* STM32L55/L56xx */
+       case DEVID_STM32L55_L56XX:
                /* STM32L55/L56xx can be single/dual bank:
-                *   if size = 512K check DBANK bit(22)
-                *   if size = 256K check DB256K bit(21)
+                *   if size = 512K check DBANK bit
+                *   if size = 256K check DB256K bit
+                *
+                * default page size is 4kb, if DBANK = 1, the page size is 2kb.
                 */
-               page_size_kb = 4;
+
+               page_size_kb = (stm32l4_info->optr & FLASH_L5_DBANK) ? 2 : 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 && (stm32l4_info->optr & BIT(22))) ||
-                       (!use_dbank_bit && (stm32l4_info->optr & BIT(21)))) {
+
+               if ((is_max_flash_size && (stm32l4_info->optr & FLASH_L5_DBANK)) ||
+                       (!is_max_flash_size && (stm32l4_info->optr & FLASH_L5_DB256))) {
+                       stm32l4_info->dual_bank_mode = true;
+                       stm32l4_info->bank1_sectors = num_pages / 2;
+               }
+               break;
+       case DEVID_STM32U57_U58XX:
+               /* if flash size is max (2M) the device is always dual bank
+                * otherwise check DUALBANK
+                */
+               page_size_kb = 8;
+               num_pages = flash_size_kb / page_size_kb;
+               stm32l4_info->bank1_sectors = num_pages;
+               if (is_max_flash_size || (stm32l4_info->optr & FLASH_U5_DUALBANK)) {
                        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 */
+       case DEVID_STM32WB5XX:
+       case DEVID_STM32WB3XX:
                /* single bank flash */
                page_size_kb = 4;
                num_pages = flash_size_kb / page_size_kb;
                stm32l4_info->bank1_sectors = num_pages;
                break;
+       case DEVID_STM32WLE_WL5XX:
+               /* single bank flash */
+               page_size_kb = 2;
+               num_pages = flash_size_kb / page_size_kb;
+               stm32l4_info->bank1_sectors = num_pages;
+
+               /* CPU2 (Cortex-M0+) is supported only with non-hla adapters because it is on AP1.
+                * Using HLA adapters armv7m->debug_ap is null, and checking ap_num triggers a segfault */
+               if (armv7m->debug_ap && armv7m->debug_ap->ap_num == 1)
+                       stm32l4_info->flash_regs = stm32wl_cpu2_flash_regs;
+               break;
        default:
                LOG_ERROR("unsupported device");
                return ERROR_FAIL;
        }
 
+       /* ensure that at least there is 1 flash sector / page */
+       if (num_pages == 0) {
+               if (stm32l4_info->user_bank_size)
+                       LOG_ERROR("The specified flash size is less than page size");
+
+               LOG_ERROR("Flash pages count cannot be zero");
+               return ERROR_FAIL;
+       }
+
        LOG_INFO("flash mode : %s-bank", stm32l4_info->dual_bank_mode ? "dual" : "single");
 
        const int gap_size_kb = stm32l4_info->hole_sectors * page_size_kb;
@@ -1622,10 +2001,8 @@ static int stm32l4_probe(struct flash_bank *bank)
 
        /* use *max_flash_size* instead of actual size as the trimmed versions
         * certainly use the same number of bits
-        * max_flash_size is always power of two, so max_pages too
         */
        uint32_t max_pages = stm32l4_info->part_info->max_flash_size_kb / page_size_kb;
-       assert(IS_PWR_OF_2(max_pages));
 
        /* in dual bank mode number of pages is doubled, but extra bit is bank selection */
        stm32l4_info->wrpxxr_mask = ((max_pages >> (stm32l4_info->dual_bank_mode ? 1 : 0)) - 1);
@@ -1663,8 +2040,19 @@ static int stm32l4_auto_probe(struct flash_bank *bank)
        if (stm32l4_info->probed) {
                uint32_t optr_cur;
 
+               /* save flash_regs_base */
+               uint32_t saved_flash_regs_base = stm32l4_info->flash_regs_base;
+
+               /* for devices with TrustZone, use NS flash registers to read OPTR */
+               if (stm32l4_info->part_info->flags & F_HAS_L5_FLASH_REGS)
+                       stm32l4_info->flash_regs_base &= ~STM32L5_REGS_SEC_OFFSET;
+
                /* read flash option register and re-probe if optr value is changed */
                int retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_OPTR_INDEX, &optr_cur);
+
+               /* restore saved flash_regs_base */
+               stm32l4_info->flash_regs_base = saved_flash_regs_base;
+
                if (retval != ERROR_OK)
                        return retval;
 
@@ -1714,6 +2102,16 @@ static int stm32l4_mass_erase(struct flash_bank *bank)
                return ERROR_TARGET_NOT_HALTED;
        }
 
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               /* set all FLASH pages as secure */
+               retval = stm32l4_set_secbb(bank, FLASH_SECBB_SECURE);
+               if (retval != ERROR_OK) {
+                       /* restore all FLASH pages as non-secure */
+                       stm32l4_set_secbb(bank, FLASH_SECBB_NON_SECURE); /* ignore the return value */
+                       return retval;
+               }
+       }
+
        retval = stm32l4_unlock_reg(bank);
        if (retval != ERROR_OK)
                goto err_lock;
@@ -1734,7 +2132,14 @@ static int stm32l4_mass_erase(struct flash_bank *bank)
        retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
 
 err_lock:
-       retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK);
+       retval2 = stm32l4_write_flash_reg_by_index(bank, stm32l4_get_flash_cr_with_lock_index(bank), FLASH_LOCK);
+
+       if (stm32l4_info->tzen && (stm32l4_info->rdp == RDP_LEVEL_0)) {
+               /* restore all FLASH pages as non-secure */
+               int retval3 = stm32l4_set_secbb(bank, FLASH_SECBB_NON_SECURE);
+               if (retval3 != ERROR_OK)
+                       return retval3;
+       }
 
        if (retval != ERROR_OK)
                return retval;