--- a/src/flash/nor/stm32l4x.c
+++ b/src/flash/nor/stm32l4x.c
@@ -60,36 +60,34 @@
 
 #define FLASH_ERASE_TIMEOUT 250
 
-#define STM32_FLASH_BASE    0x40022000
-#define STM32_FLASH_ACR     0x40022000
-#define STM32_FLASH_KEYR    0x40022008
-#define STM32_FLASH_OPTKEYR 0x4002200c
-#define STM32_FLASH_SR      0x40022010
-#define STM32_FLASH_CR      0x40022014
-#define STM32_FLASH_OPTR    0x40022020
-#define STM32_FLASH_WRP1AR  0x4002202c
-#define STM32_FLASH_WRP1BR  0x40022030
-#define STM32_FLASH_WRP2AR  0x4002204c
-#define STM32_FLASH_WRP2BR  0x40022050
+/* Flash registers offsets */
+#define STM32_FLASH_ACR     0x00
+#define STM32_FLASH_KEYR    0x08
+#define STM32_FLASH_OPTKEYR 0x0c
+#define STM32_FLASH_SR      0x10
+#define STM32_FLASH_CR      0x14
+#define STM32_FLASH_OPTR    0x20
+#define STM32_FLASH_WRP1AR  0x2c
+#define STM32_FLASH_WRP1BR  0x30
+#define STM32_FLASH_WRP2AR  0x4c
+#define STM32_FLASH_WRP2BR  0x50
 
 /* FLASH_CR register bits */
-
-#define FLASH_PG       (1 << 0)
-#define FLASH_PER      (1 << 1)
-#define FLASH_MER1     (1 << 2)
-#define FLASH_PAGE_SHIFT     3
-#define FLASH_CR_BKER  (1 << 11)
-#define FLASH_MER2     (1 << 15)
-#define FLASH_STRT     (1 << 16)
-#define FLASH_OPTSTRT  (1 << 17)
-#define FLASH_EOPIE    (1 << 24)
-#define FLASH_ERRIE    (1 << 25)
+#define FLASH_PG        (1 << 0)
+#define FLASH_PER       (1 << 1)
+#define FLASH_MER1      (1 << 2)
+#define FLASH_PAGE_SHIFT      3
+#define FLASH_CR_BKER   (1 << 11)
+#define FLASH_MER2      (1 << 15)
+#define FLASH_STRT      (1 << 16)
+#define FLASH_OPTSTRT   (1 << 17)
+#define FLASH_EOPIE     (1 << 24)
+#define FLASH_ERRIE     (1 << 25)
 #define FLASH_OBLLAUNCH (1 << 27)
-#define FLASH_OPTLOCK  (1 << 30)
-#define FLASH_LOCK     (1 << 31)
+#define FLASH_OPTLOCK   (1 << 30)
+#define FLASH_LOCK      (1 << 31)
 
 /* FLASH_SR register bits */
-
 #define FLASH_BSY      (1 << 16)
 /* Fast programming not used => related errors not used*/
 #define FLASH_PGSERR   (1 << 7) /* Programming sequence error */
@@ -99,16 +97,13 @@
 #define FLASH_PROGERR  (1 << 3) /* Programming error */
 #define FLASH_OPERR    (1 << 1) /* Operation error */
 #define FLASH_EOP      (1 << 0) /* End of operation */
-
 #define FLASH_ERROR (FLASH_PGSERR | FLASH_PGSERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR)
 
 /* STM32_FLASH_OBR bit definitions (reading) */
-
-#define OPT_DBANK_LE_1M (1 << 21)	/* dual bank for devices up to 1M flash */
-#define OPT_DBANK_GE_2M (1 << 22)	/* dual bank for devices with 2M flash */
+#define OPT_DB1M  (1 << 21)	/* dual bank for devices up to 1M flash */
+#define OPT_DBANK (1 << 22)	/* dual bank for devices with 2M flash, like 0x470 */
 
 /* register unlock keys */
-
 #define KEY1           0x45670123
 #define KEY2           0xCDEF89AB
 
@@ -123,11 +118,121 @@
 
 /* other registers */
 #define DBGMCU_IDCODE	0xE0042000
-#define FLASH_SIZE_REG	0x1FFF75E0
+
+
+struct stm32l4_rev {
+	uint16_t rev;
+	const char *str;
+};
+
+struct stm32l4_part_info {
+	uint16_t id;
+	const char *device_str;
+	const struct stm32l4_rev *revs;
+	size_t num_revs;
+	unsigned int page_size; /* value will be corrected during probe */
+	uint16_t max_flash_size_kb;
+	bool has_dual_bank;
+	uint16_t bank1_sectors;
+	uint16_t hole_sectors; /* value will be set during probe */
+	uint32_t flash_base;
+	uint32_t fsize_base;
+};
 
 struct stm32l4_flash_bank {
-	uint16_t bank2_start;
 	int probed;
+	uint32_t idcode;
+	uint32_t user_bank_size;
+	uint32_t flash_base;
+	struct stm32l4_part_info *part_info;
+};
+
+static const struct stm32l4_rev stm32_415_revs[] = {
+	{ 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" }
+};
+
+static const struct stm32l4_rev stm32_435_revs[] = {
+	{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" },
+};
+
+static const struct stm32l4_rev stm32_461_revs[] = {
+	{ 0x1000, "A" }, { 0x2000, "B" },
+};
+
+static const struct stm32l4_rev stm32_462_revs[] = {
+		{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x2001, "Y" },
+};
+
+static const struct stm32l4_rev stm32_470_revs[] = {
+	{ 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x100F, "W" },
+};
+
+static struct stm32l4_part_info stm32l4_parts[] = {
+	{
+	  .id                   = 0x415,
+	  .revs                 = stm32_415_revs,
+	  .num_revs             = ARRAY_SIZE(stm32_415_revs),
+	  .device_str           = "STM32L47/L48xx",
+	  .page_size            = 2048,
+	  .max_flash_size_kb    = 1024,
+	  .has_dual_bank        = true,
+	  .bank1_sectors        = 256,
+	  .hole_sectors         = 0,
+	  .flash_base           = 0x40022000,
+	  .fsize_base           = 0x1FFF75E0,
+	},
+	{
+	  .id                   = 0x435,
+	  .revs                 = stm32_435_revs,
+	  .num_revs             = ARRAY_SIZE(stm32_435_revs),
+	  .device_str           = "STM32L43/L44xx",
+	  .page_size            = 2048,
+	  .max_flash_size_kb    = 256,
+	  .has_dual_bank        = false,
+	  .bank1_sectors        = 128,
+	  .hole_sectors         = 0,
+	  .flash_base           = 0x40022000,
+	  .fsize_base           = 0x1FFF75E0,
+	},
+	{
+	  .id                   = 0x461,
+	  .revs                 = stm32_461_revs,
+	  .num_revs             = ARRAY_SIZE(stm32_461_revs),
+	  .device_str           = "STM32L49/L4Axx",
+	  .page_size            = 2048,
+	  .max_flash_size_kb    = 1024,
+	  .has_dual_bank        = true,
+	  .bank1_sectors        = 256,
+	  .hole_sectors         = 0,
+	  .flash_base           = 0x40022000,
+	  .fsize_base           = 0x1FFF75E0,
+	},
+	{
+	  .id                   = 0x462,
+	  .revs                 = stm32_462_revs,
+	  .num_revs             = ARRAY_SIZE(stm32_462_revs),
+	  .device_str           = "STM32L45/L46xx",
+	  .page_size            = 2048,
+	  .max_flash_size_kb    = 512,
+	  .has_dual_bank        = false,
+	  .bank1_sectors        = 256,
+	  .hole_sectors         = 0,
+	  .flash_base           = 0x40022000,
+	  .fsize_base           = 0x1FFF75E0,
+	},
+	{
+	  .id                   = 0x470,
+	  .revs                 = stm32_470_revs,
+	  .num_revs             = ARRAY_SIZE(stm32_470_revs),
+	  .device_str           = "STM32L4R/L4Sxx",
+	  .page_size            = 4096, /* or 8192, depending on DBANK option bit */
+	  .max_flash_size_kb    = 2048,
+	  .has_dual_bank        = true,
+	  .bank1_sectors        = 256,
+	  .hole_sectors         = 0,
+	  .flash_base           = 0x40022000,
+	  .fsize_base           = 0x1FFF75E0,
+	},
 };
 
 /* flash bank stm32l4x <base> <size> 0 0 <target#>
@@ -145,20 +250,15 @@
 	bank->driver_priv = stm32l4_info;
 
 	stm32l4_info->probed = 0;
+	stm32l4_info->user_bank_size = bank->size;
 
 	return ERROR_OK;
 }
 
-static inline int stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t reg)
-{
-	return reg;
-}
-
-static inline int stm32l4_get_flash_status(struct flash_bank *bank, uint32_t *status)
-{
-	struct target *target = bank->target;
-	return target_read_u32(
-		target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR), status);
+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->flash_base + reg_offset;
 }
 
 static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout)
@@ -169,7 +269,7 @@
 
 	/* wait for busy to clear */
 	for (;;) {
-		retval = stm32l4_get_flash_status(bank, &status);
+		retval = target_read_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR), &status);
 		if (retval != ERROR_OK)
 			return retval;
 		LOG_DEBUG("status: 0x%" PRIx32 "", status);
@@ -201,14 +301,15 @@
 	return retval;
 }
 
-static int stm32l4_unlock_reg(struct target *target)
-{
+static int stm32l4_unlock_reg(struct flash_bank *bank)
+{
+	struct target *target = bank->target;
 	uint32_t ctrl;
 
 	/* first check if not already unlocked
 	 * otherwise writing on STM32_FLASH_KEYR will fail
 	 */
-	int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+	int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), &ctrl);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -216,15 +317,15 @@
 		return ERROR_OK;
 
 	/* unlock flash registers */
-	retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1);
-	if (retval != ERROR_OK)
-		return retval;
-
-	retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2);
-	if (retval != ERROR_OK)
-		return retval;
-
-	retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+	retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_KEYR), KEY1);
+	if (retval != ERROR_OK)
+		return retval;
+
+	retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
+	if (retval != ERROR_OK)
+		return retval;
+
+	retval = target_read_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), &ctrl);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -236,11 +337,12 @@
 	return ERROR_OK;
 }
 
-static int stm32l4_unlock_option_reg(struct target *target)
-{
+static int stm32l4_unlock_option_reg(struct flash_bank *bank)
+{
+	struct target *target = bank->target;
 	uint32_t ctrl;
 
-	int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+	int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), &ctrl);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -248,15 +350,15 @@
 		return ERROR_OK;
 
 	/* unlock option registers */
-	retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1);
-	if (retval != ERROR_OK)
-		return retval;
-
-	retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2);
-	if (retval != ERROR_OK)
-		return retval;
-
-	retval = target_read_u32(target, STM32_FLASH_CR, &ctrl);
+	retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_OPTKEYR), OPTKEY1);
+	if (retval != ERROR_OK)
+		return retval;
+
+	retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_OPTKEYR), OPTKEY2);
+	if (retval != ERROR_OK)
+		return retval;
+
+	retval = target_read_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), &ctrl);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -268,32 +370,31 @@
 	return ERROR_OK;
 }
 
-static int stm32l4_read_option(struct flash_bank *bank, uint32_t address, uint32_t* value)
-{
-	struct target *target = bank->target;
-	return target_read_u32(target, address, value);
-}
-
-static int stm32l4_write_option(struct flash_bank *bank, uint32_t address, uint32_t value, uint32_t mask)
+static int stm32l4_read_option(struct flash_bank *bank, uint32_t reg_offset, uint32_t* value)
+{
+	return target_read_u32(bank->target, stm32l4_get_flash_reg(bank, reg_offset), value);
+}
+
+static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset, uint32_t value, uint32_t mask)
 {
 	struct target *target = bank->target;
 	uint32_t optiondata;
 
-	int retval = target_read_u32(target, address, &optiondata);
-	if (retval != ERROR_OK)
-		return retval;
-
-	retval = stm32l4_unlock_reg(target);
-	if (retval != ERROR_OK)
-		return retval;
-
-	retval = stm32l4_unlock_option_reg(target);
+	int retval = target_read_u32(target, stm32l4_get_flash_reg(bank, reg_offset), &optiondata);
+	if (retval != ERROR_OK)
+		return retval;
+
+	retval = stm32l4_unlock_reg(bank);
+	if (retval != ERROR_OK)
+		return retval;
+
+	retval = stm32l4_unlock_option_reg(bank);
 	if (retval != ERROR_OK)
 		return retval;
 
 	optiondata = (optiondata & ~mask) | (value & mask);
 
-	retval = target_write_u32(target, address, optiondata);
+	retval = target_write_u32(target, stm32l4_get_flash_reg(bank, reg_offset), optiondata);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -311,6 +412,8 @@
 static int stm32l4_protect_check(struct flash_bank *bank)
 {
 	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+	struct stm32l4_part_info *part_info = stm32l4_info->part_info;
+
 	uint32_t wrp1ar, wrp1br, wrp2ar, wrp2br;
 	stm32l4_read_option(bank, STM32_FLASH_WRP1AR, &wrp1ar);
 	stm32l4_read_option(bank, STM32_FLASH_WRP1BR, &wrp1br);
@@ -327,7 +430,7 @@
 	const uint8_t wrp2b_end = (wrp2br >> 16) & 0xFF;
 
 	for (int i = 0; i < bank->num_sectors; i++) {
-		if (i < stm32l4_info->bank2_start) {
+		if (i < part_info->bank1_sectors) {
 			if (((i >= wrp1a_start) &&
 				 (i <= wrp1a_end)) ||
 				((i >= wrp1b_start) &&
@@ -337,7 +440,7 @@
 				bank->sectors[i].is_protected = 0;
 		} else {
 			uint8_t snb;
-			snb = i - stm32l4_info->bank2_start;
+			snb = i - part_info->bank1_sectors;
 			if (((snb >= wrp2a_start) &&
 				 (snb <= wrp2a_end)) ||
 				((snb >= wrp2b_start) &&
@@ -353,7 +456,10 @@
 static int stm32l4_erase(struct flash_bank *bank, int first, int last)
 {
 	struct target *target = bank->target;
+	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+	struct stm32l4_part_info *part_info = stm32l4_info->part_info;
 	int i;
+	int retval;
 
 	assert(first < bank->num_sectors);
 	assert(last < bank->num_sectors);
@@ -363,8 +469,7 @@
 		return ERROR_TARGET_NOT_HALTED;
 	}
 
-	int retval;
-	retval = stm32l4_unlock_reg(target);
+	retval = stm32l4_unlock_reg(bank);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -378,20 +483,18 @@
 	3. Set the STRT bit in the FLASH_CR register
 	4. Wait for the BSY bit to be cleared
 	 */
-	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
 
 	for (i = first; i <= last; i++) {
 		uint32_t erase_flags;
 		erase_flags = FLASH_PER | FLASH_STRT;
 
-		if (i >= stm32l4_info->bank2_start) {
+		if (i >= part_info->bank1_sectors) {
 			uint8_t snb;
-			snb = i - stm32l4_info->bank2_start;
+			snb = i - part_info->bank1_sectors;
 			erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER;
 		} else
 			erase_flags |= i << FLASH_PAGE_SHIFT;
-		retval = target_write_u32(target,
-				stm32l4_get_flash_reg(bank, STM32_FLASH_CR), erase_flags);
+		retval =  target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), erase_flags);
 		if (retval != ERROR_OK)
 			return retval;
 
@@ -402,8 +505,7 @@
 		bank->sectors[i].is_erased = 1;
 	}
 
-	retval = target_write_u32(
-		target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
+	retval = target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -414,6 +516,7 @@
 {
 	struct target *target = bank->target;
 	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+	struct stm32l4_part_info *part_info = stm32l4_info->part_info;
 
 	if (target->state != TARGET_HALTED) {
 		LOG_ERROR("Target not halted");
@@ -423,9 +526,9 @@
 	int ret = ERROR_OK;
 	/* Bank 2 */
 	uint32_t reg_value = 0xFF; /* Default to bank un-protected */
-	if (last >= stm32l4_info->bank2_start) {
+	if (last >= part_info->bank1_sectors) {
 		if (set == 1) {
-			uint8_t begin = first > stm32l4_info->bank2_start ? first : 0x00;
+			uint8_t begin = first > part_info->bank1_sectors ? first : 0x00;
 			reg_value = ((last & 0xFF) << 16) | begin;
 		}
 
@@ -433,9 +536,9 @@
 	}
 	/* Bank 1 */
 	reg_value = 0xFF; /* Default to bank un-protected */
-	if (first < stm32l4_info->bank2_start) {
+	if (first < part_info->bank1_sectors) {
 		if (set == 1) {
-			uint8_t end = last >= stm32l4_info->bank2_start ? 0xFF : last;
+			uint8_t end = last >= part_info->bank1_sectors ? 0xFF : last;
 			reg_value = (end << 16) | (first & 0xFF);
 		}
 
@@ -450,6 +553,7 @@
 		uint32_t offset, uint32_t count)
 {
 	struct target *target = bank->target;
+	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
 	uint32_t buffer_size = 16384;
 	struct working_area *write_algorithm;
 	struct working_area *source;
@@ -503,7 +607,7 @@
 	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 / 4);
-	buf_set_u32(reg_params[4].value, 0, 32, STM32_FLASH_BASE);
+	buf_set_u32(reg_params[4].value, 0, 32, stm32l4_info->flash_base);
 
 	retval = target_run_flash_async_algorithm(target, buffer, count, 2,
 			0, NULL,
@@ -523,7 +627,7 @@
 		if (error != 0) {
 			LOG_ERROR("flash write failed = %08" PRIx32, error);
 			/* Clear but report errors */
-			target_write_u32(target, STM32_FLASH_SR, error);
+			target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_SR), error);
 			retval = ERROR_FAIL;
 		}
 	}
@@ -570,7 +674,7 @@
 		 */
 	}
 
-	retval = stm32l4_unlock_reg(target);
+	retval = stm32l4_unlock_reg(bank);
 	if (retval != ERROR_OK)
 		return retval;
 
@@ -579,60 +683,65 @@
 	if (retval != ERROR_OK) {
 		LOG_WARNING("block write failed");
 		return retval;
-		}
+	}
 
 	LOG_WARNING("block write succeeded");
-	return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
+	return target_write_u32(target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
+}
+
+static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id)
+{
+	int retval = target_read_u32(bank->target, DBGMCU_IDCODE, id);
+	if (retval != ERROR_OK)
+		return retval;
+
+	return retval;
 }
 
 static int stm32l4_probe(struct flash_bank *bank)
 {
 	struct target *target = bank->target;
 	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+	struct stm32l4_part_info *part_info;
 	int i;
 	uint16_t flash_size_in_kb = 0xffff;
-	uint16_t max_flash_size_in_kb;
 	uint32_t device_id;
 	uint32_t options;
-	uint32_t base_address = 0x08000000;
 
 	stm32l4_info->probed = 0;
 
 	/* read stm32 device id register */
-	int retval = target_read_u32(target, DBGMCU_IDCODE, &device_id);
-	if (retval != ERROR_OK)
-		return retval;
-	LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
-
-	/* set max flash size depending on family */
-	switch (device_id & 0xfff) {
-	case 0x470:
-		max_flash_size_in_kb = 2048;
-		break;
-	case 0x461:
-	case 0x415:
-		max_flash_size_in_kb = 1024;
-		break;
-	case 0x462:
-		max_flash_size_in_kb = 512;
-		break;
-	case 0x435:
-		max_flash_size_in_kb = 256;
-		break;
-	default:
+	int retval = stm32l4_read_idcode(bank, &stm32l4_info->idcode);
+	if (retval != ERROR_OK)
+		return retval;
+
+	LOG_INFO("device id = 0x%08" PRIx32 "", stm32l4_info->idcode);
+
+	device_id = stm32l4_info->idcode & 0xFFF;
+
+	for (unsigned int n = 0; n < ARRAY_SIZE(stm32l4_parts); n++) {
+		if (device_id == stm32l4_parts[n].id) {
+			stm32l4_info->part_info = &stm32l4_parts[n];
+			stm32l4_info->flash_base = stm32l4_info->part_info->flash_base;
+		}
+	}
+
+	if (!stm32l4_info->part_info) {
 		LOG_WARNING("Cannot identify target as an STM32L4 family device.");
 		return ERROR_FAIL;
 	}
 
+	part_info = stm32l4_info->part_info;
+
 	/* get flash size from target. */
-	retval = target_read_u16(target, FLASH_SIZE_REG, &flash_size_in_kb);
+	retval = target_read_u16(target, part_info->fsize_base, &flash_size_in_kb);
 
 	/* failed reading flash size or flash size invalid (early silicon),
 	 * default to max target family */
 	if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
 		LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash",
-			max_flash_size_in_kb);
-		flash_size_in_kb = max_flash_size_in_kb;
+			part_info->max_flash_size_kb);
+		flash_size_in_kb = part_info->max_flash_size_kb;
 	}
 
 	LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
@@ -640,91 +749,49 @@
 	/* did we assign a flash size? */
 	assert((flash_size_in_kb != 0xffff) && flash_size_in_kb);
 
-	/* get options for DUAL BANK. */
-	retval = target_read_u32(target, STM32_FLASH_OPTR, &options);
-
-	if (retval != ERROR_OK)
-		return retval;
-
-	int num_pages = 0;
-	int page_size = 0;
-
-	switch (device_id & 0xfff) {
-		case 0x470:
-			/* L4R/S have 1M or 2M FLASH and dual/single bank mode.
-			 * Page size is 4K or 8K.*/
-			if (flash_size_in_kb == 2048) {
-				stm32l4_info->bank2_start = 256;
-				if (options & OPT_DBANK_GE_2M) {
-					page_size = 4096;
-					num_pages = 512;
-				} else {
-					page_size = 8192;
-					num_pages = 256;
-				}
-				break;
-			}
-			if (flash_size_in_kb == 1024) {
-				stm32l4_info->bank2_start = 128;
-				if (options & OPT_DBANK_LE_1M) {
-					page_size = 4096;
-					num_pages = 256;
-				} else {
-					page_size = 8192;
-					num_pages = 128;
-				}
-				break;
-			}
-			/* Invalid FLASH size for this device. */
-			LOG_WARNING("Invalid flash size for STM32L4+ family device.");
-			return ERROR_FAIL;
-		case 0x461:
-		case 0x415:
-			/* These are dual-bank devices, we need to check the OPT_DBANK_LE_1M bit here */
-			page_size = 2048;
-			num_pages = flash_size_in_kb / 2;
-			/* check that calculation result makes sense */
-			assert(num_pages > 0);
-			if ((flash_size_in_kb == 1024) || !(options & OPT_DBANK_LE_1M))
-				stm32l4_info->bank2_start = 256;
-			else
-				stm32l4_info->bank2_start = num_pages / 2;
-			break;
-		case 0x462:
-		case 0x435:
-		default:
-			/* These are single-bank devices */
-			page_size = 2048;
-			num_pages = flash_size_in_kb / 2;
-			/* check that calculation result makes sense */
-			assert(num_pages > 0);
-			stm32l4_info->bank2_start = UINT16_MAX;
-			break;
-	}
-
-	/* Release sector table if allocated. */
+	if (part_info->has_dual_bank) {
+		/* get options for DUAL BANK. */
+		retval = stm32l4_read_option(bank, STM32_FLASH_OPTR, &options);
+		if (retval != ERROR_OK)
+			return retval;
+
+		/* OPT_DBANK is available only on 0x470 devices (STM32L4R/S) */
+		if ((device_id == 0x470) && ((options & OPT_DBANK) == 0)) {
+			part_info->page_size = 8192; /* single bank */
+		} else if ((options & OPT_DB1M) && (flash_size_in_kb < part_info->max_flash_size_kb)) {
+			part_info->bank1_sectors = ((flash_size_in_kb * 1024) / part_info->page_size) / 2;
+			part_info->hole_sectors = (((part_info->max_flash_size_kb * 1024) / part_info->page_size) / 2)
+					- part_info->bank1_sectors;
+		}
+	}
+
+	if (stm32l4_info->user_bank_size) {
+		flash_size_in_kb = stm32l4_info->user_bank_size / 1024;
+		LOG_INFO("ignoring flash probed value, using configured bank size: %d kbytes", flash_size_in_kb);
+	}
+
 	if (bank->sectors) {
 		free(bank->sectors);
 		bank->sectors = NULL;
 	}
 
-	/* Set bank configuration and construct sector table. */
-	bank->base = base_address;
-	bank->size = num_pages * page_size;
-	bank->num_sectors = num_pages;
-	bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
-	if (!bank->sectors)
-		return ERROR_FAIL; /* Checkme: What better error to use?*/
-
-	for (i = 0; i < num_pages; i++) {
-		bank->sectors[i].offset = i * page_size;
-		bank->sectors[i].size = page_size;
+	bank->size = flash_size_in_kb * 1024;
+	bank->base = 0x08000000;
+	bank->num_sectors = (flash_size_in_kb * 1024) / part_info->page_size;
+	bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+	if (bank->sectors == NULL) {
+		LOG_ERROR("failed to allocate bank sectors");
+		return ERROR_FAIL;
+	}
+
+	for (i = 0; i < bank->num_sectors; i++) {
+		bank->sectors[i].offset = i * part_info->page_size;
+		bank->sectors[i].size = part_info->page_size;
 		bank->sectors[i].is_erased = -1;
 		bank->sectors[i].is_protected = 1;
 	}
 
 	stm32l4_info->probed = 1;
-
 	return ERROR_OK;
 }
 
@@ -733,80 +800,75 @@
 	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
 	if (stm32l4_info->probed)
 		return ERROR_OK;
+
 	return stm32l4_probe(bank);
 }
 
 static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
 {
-	struct target *target = bank->target;
-	uint32_t dbgmcu_idcode;
-
-	/* read stm32 device id register */
-	int retval = target_read_u32(target, DBGMCU_IDCODE, &dbgmcu_idcode);
-	if (retval != ERROR_OK)
-		return retval;
-
-	uint16_t device_id = dbgmcu_idcode & 0xfff;
-	uint8_t rev_id = dbgmcu_idcode >> 28;
-	uint8_t rev_minor = 0;
-	int i;
-
-	for (i = 16; i < 28; i++) {
-		if (dbgmcu_idcode & (1 << i))
-			rev_minor++;
-		else
-			break;
-	}
-
-	const char *device_str;
-
-	switch (device_id) {
-	case 0x470:
-		device_str = "STM32L4R/4Sxx";
-		break;
-
-	case 0x461:
-		device_str = "STM32L496/4A6";
-		break;
-
-	case 0x415:
-		device_str = "STM32L475/476/486";
-		break;
-
-	case 0x462:
-		device_str = "STM32L45x/46x";
-		break;
-
-	case 0x435:
-		device_str = "STM32L43x/44x";
-		break;
-
-	default:
-		snprintf(buf, buf_size, "Cannot identify target as a STM32L4\n");
+	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+
+	if (!stm32l4_info->probed) {
+		int retval = stm32l4_probe(bank);
+		if (retval != ERROR_OK) {
+			snprintf(buf, buf_size, "Unable to find bank information.");
+			return retval;
+		}
+	}
+
+	struct stm32l4_part_info *part_info = stm32l4_info->part_info;
+
+	if (part_info) {
+		const char *rev_str = NULL;
+		uint16_t rev_id = stm32l4_info->idcode >> 16;
+		for (unsigned int i = 0; i < part_info->num_revs; i++) {
+			if (rev_id == part_info->revs[i].rev) {
+				rev_str = part_info->revs[i].str;
+
+				if (rev_str != NULL) {
+					snprintf(buf, buf_size, "%s - Rev: %s",
+							part_info->device_str, rev_str);
+					return ERROR_OK;
+				}
+			}
+		}
+
+		snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)",
+				part_info->device_str, rev_id);
+		return ERROR_OK;
+	} else {
+		snprintf(buf, buf_size, "Cannot identify target as a STM32L4x device");
 		return ERROR_FAIL;
 	}
 
-	snprintf(buf, buf_size, "%s - Rev: %1d.%02d",
-			 device_str, rev_id, rev_minor);
-
 	return ERROR_OK;
 }
 
-static int stm32l4_mass_erase(struct flash_bank *bank, uint32_t action)
+static int stm32l4_mass_erase(struct flash_bank *bank)
 {
 	int retval;
 	struct target *target = bank->target;
+
+	struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv;
+	uint32_t action = FLASH_MER1;
+
+	if (stm32l4_info->part_info->has_dual_bank)
+		action |= FLASH_MER2;
 
 	if (target->state != TARGET_HALTED) {
 		LOG_ERROR("Target not halted");
 		return ERROR_TARGET_NOT_HALTED;
 	}
 
-	retval = stm32l4_unlock_reg(target);
+	retval = stm32l4_unlock_reg(bank);
 	if (retval != ERROR_OK)
 		return retval;
 
 	/* mass erase flash memory */
+	retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT / 10);
+	if (retval != ERROR_OK)
+		return retval;
+
 	retval = target_write_u32(
 		target, stm32l4_get_flash_reg(bank, STM32_FLASH_CR), action);
 	if (retval != ERROR_OK)
@@ -832,7 +894,6 @@
 COMMAND_HANDLER(stm32l4_handle_mass_erase_command)
 {
 	int i;
-	uint32_t action;
 
 	if (CMD_ARGC < 1) {
 		command_print(CMD_CTX, "stm32l4x mass_erase <STM32L4 bank>");
@@ -844,8 +905,7 @@
 	if (ERROR_OK != retval)
 		return retval;
 
-	action =  FLASH_MER1 |  FLASH_MER2;
-	retval = stm32l4_mass_erase(bank, action);
+	retval = stm32l4_mass_erase(bank);
 	if (retval == ERROR_OK) {
 		/* set all sectors as erased */
 		for (i = 0; i < bank->num_sectors; i++)
@@ -871,12 +931,13 @@
 	if (ERROR_OK != retval)
 		return retval;
 
-	uint32_t reg_addr = STM32_FLASH_BASE;
+	uint32_t reg_offset, reg_addr;
 	uint32_t value = 0;
 
-	reg_addr += strtoul(CMD_ARGV[1], NULL, 16);
-
-	retval = stm32l4_read_option(bank, reg_addr, &value);
+	reg_offset = strtoul(CMD_ARGV[1], NULL, 16);
+	reg_addr = stm32l4_get_flash_reg(bank, reg_offset);
+
+	retval = stm32l4_read_option(bank, reg_offset, &value);
 	if (ERROR_OK != retval)
 		return retval;
 
@@ -897,11 +958,11 @@
 	if (ERROR_OK != retval)
 		return retval;
 
-	uint32_t reg_addr = STM32_FLASH_BASE;
+	uint32_t reg_offset;
 	uint32_t value = 0;
 	uint32_t mask = 0xFFFFFFFF;
 
-	reg_addr += strtoul(CMD_ARGV[1], NULL, 16);
+	reg_offset = strtoul(CMD_ARGV[1], NULL, 16);
 	value = strtoul(CMD_ARGV[2], NULL, 16);
 	if (CMD_ARGC > 3)
 		mask = strtoul(CMD_ARGV[3], NULL, 16);
@@ -910,7 +971,7 @@
 				"INFO: a reset or power cycle is required "
 				"for the new settings to take effect.", bank->driver->name);
 
-	retval = stm32l4_write_option(bank, reg_addr, value, mask);
+	retval = stm32l4_write_option(bank, reg_offset, value, mask);
 	return retval;
 }
 
@@ -926,11 +987,11 @@
 
 	struct target *target = bank->target;
 
-	retval = stm32l4_unlock_reg(target);
+	retval = stm32l4_unlock_reg(bank);
 	if (ERROR_OK != retval)
 		return retval;
 
-	retval = stm32l4_unlock_option_reg(target);
+	retval = stm32l4_unlock_option_reg(bank);
 	if (ERROR_OK != retval)
 		return retval;

