diff --git a/doc/openocd.texi b/doc/openocd.texi
index 7ebe45788a93c5dc87398583fb12e546dd208745..107441d2d5cd2dd9f068ca5b6e869afd61190581 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -3537,7 +3537,7 @@ The @var{num} parameter is a value shown by @command{flash banks}.
 @end deffn
 
 @anchor{flash write_image}
-@deffn Command {flash write_image} [erase] filename [offset] [type]
+@deffn Command {flash write_image} [erase] [unlock] filename [offset] [type]
 Write the image @file{filename} to the current target's flash bank(s).
 A relocation @var{offset} may be specified, in which case it is added
 to the base address for each section in the image.
@@ -3546,8 +3546,9 @@ explicitly as @option{bin} (binary), @option{ihex} (Intel hex),
 @option{elf} (ELF file), @option{s19} (Motorola s19).
 @option{mem}, or @option{builder}.
 The relevant flash sectors will be erased prior to programming
-if the @option{erase} parameter is given.
-The flash bank to use is inferred from the @var{address} of
+if the @option{erase} parameter is given. If @option{unlock} is
+provided, then the flash banks are unlocked before erase and
+program. The flash bank to use is inferred from the @var{address} of
 each image segment.
 @end deffn
 
diff --git a/src/flash/flash.c b/src/flash/flash.c
index d1b023c55b28e11dd369599f553e133510b6842d..87eec6e4d07089bfd502bda4f2b31071d623216e 100644
--- a/src/flash/flash.c
+++ b/src/flash/flash.c
@@ -43,6 +43,7 @@ static int handle_flash_write_bank_command(struct command_context_s *cmd_ctx, ch
 static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_flash_fill_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int flash_write_unlock(target_t *target, image_t *image, uint32_t *written, int erase, bool unlock);
 
 /* flash drivers
  */
@@ -199,7 +200,7 @@ int flash_init_drivers(struct command_context_s *cmd_ctx)
 		register_command(cmd_ctx, flash_cmd, "write_bank", handle_flash_write_bank_command, COMMAND_EXEC,
 						 "write binary data to <bank> <file> <offset>");
 		register_command(cmd_ctx, flash_cmd, "write_image", handle_flash_write_image_command, COMMAND_EXEC,
-						 "write_image [erase] <file> [offset] [type]");
+						 "write_image [erase] [unlock] <file> [offset] [type]");
 		register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC,
 						 "set protection of sectors at <bank> <first> <last> <on | off>");
 	}
@@ -697,13 +698,26 @@ static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, c
 
 	/* flash auto-erase is disabled by default*/
 	int auto_erase = 0;
+	bool auto_unlock = false;
 
-	if (strcmp(args[0], "erase") == 0)
+	for (;;)
 	{
-		auto_erase = 1;
-		args++;
-		argc--;
-		command_print(cmd_ctx, "auto erase enabled");
+		if (strcmp(args[0], "erase") == 0)
+		{
+			auto_erase = 1;
+			args++;
+			argc--;
+			command_print(cmd_ctx, "auto erase enabled");
+		} else if (strcmp(args[0], "unlock") == 0)
+		{
+			auto_unlock = true;
+			args++;
+			argc--;
+			command_print(cmd_ctx, "auto unlock enabled");
+		} else
+		{
+			break;
+		}
 	}
 
 	if (argc < 1)
@@ -738,7 +752,7 @@ static int handle_flash_write_image_command(struct command_context_s *cmd_ctx, c
 		return retval;
 	}
 
-	retval = flash_write(target, &image, &written, auto_erase);
+	retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
 	if (retval != ERROR_OK)
 	{
 		image_close(&image);
@@ -994,7 +1008,8 @@ flash_bank_t *get_flash_bank_by_addr(target_t *target, uint32_t addr)
 }
 
 /* erase given flash region, selects proper bank according to target and address */
-int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
+static int flash_iterate_address_range(target_t *target, uint32_t addr, uint32_t length,
+		int (*callback)(struct flash_bank_s *bank, int first, int last))
 {
 	flash_bank_t *c;
 	int first = -1;
@@ -1016,7 +1031,7 @@ int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
 		if (addr != c->base)
 			return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
 
-		return flash_driver_erase(c, 0, c->num_sectors - 1);
+		return callback(c, 0, c->num_sectors - 1);
 	}
 
 	/* check whether it fits */
@@ -1039,11 +1054,29 @@ int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
 	if (first == -1 || last == -1)
 		return ERROR_OK;
 
-	return flash_driver_erase(c, first, last);
+	return callback(c, first, last);
+}
+
+
+
+int flash_erase_address_range(target_t *target, uint32_t addr, uint32_t length)
+{
+	return flash_iterate_address_range(target, addr, length, &flash_driver_erase);
+}
+
+static int flash_driver_unprotect(struct flash_bank_s *bank, int first, int last)
+{
+	return flash_driver_protect(bank, 0, first, last);
 }
 
+static int flash_unlock_address_range(target_t *target, uint32_t addr, uint32_t length)
+{
+	return flash_iterate_address_range(target, addr, length, &flash_driver_unprotect);
+}
+
+
 /* write (optional verify) an image to flash memory of the given target */
-int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
+static int flash_write_unlock(target_t *target, image_t *image, uint32_t *written, int erase, bool unlock)
 {
 	int retval = ERROR_OK;
 
@@ -1166,10 +1199,17 @@ int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
 
 		retval = ERROR_OK;
 
-		if (erase)
+		if (unlock)
+		{
+			retval = flash_unlock_address_range(target, run_address, run_size);
+		}
+		if (retval == ERROR_OK)
 		{
-			/* calculate and erase sectors */
-			retval = flash_erase_address_range(target, run_address, run_size);
+			if (erase)
+			{
+				/* calculate and erase sectors */
+				retval = flash_erase_address_range(target, run_address, run_size);
+			}
 		}
 
 		if (retval == ERROR_OK)
@@ -1195,6 +1235,11 @@ int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
 	return retval;
 }
 
+int flash_write(target_t *target, image_t *image, uint32_t *written, int erase)
+{
+	return flash_write_unlock(target, image, written, erase, false);
+}
+
 int default_flash_mem_blank_check(struct flash_bank_s *bank)
 {
 	target_t *target = bank->target;