diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c
index ccb1a74aa66d9f9bd9ce13e4bb8f89e647f0dbf2..03f771c87e2a9a483c8d523f9c3d6d54e5ab8f08 100644
--- a/src/flash/nor/at91sam7.c
+++ b/src/flash/nor/at91sam7.c
@@ -661,7 +661,7 @@ static int at91sam7_erase_check(struct flash_bank *bank)
 		retval = target_blank_check_memory(target,
 				bank->base + bank->sectors[nSector].offset,
 				bank->sectors[nSector].size,
-				&blank);
+				&blank, bank->erased_value);
 		if (retval != ERROR_OK) {
 			fast_check = 0;
 			break;
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index 7a62ba1c76223d03f130d109ead872d7d6ff6a82..8f6306f2572be9d6c6b8658fc35e1e59ff7b2697 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -288,7 +288,7 @@ static int default_flash_mem_blank_check(struct flash_bank *bank)
 				goto done;
 
 			for (nBytes = 0; nBytes < chunk; nBytes++) {
-				if (buffer[nBytes] != 0xFF) {
+				if (buffer[nBytes] != bank->erased_value) {
 					bank->sectors[i].is_erased = 0;
 					break;
 				}
@@ -319,12 +319,12 @@ int default_flash_blank_check(struct flash_bank *bank)
 		uint32_t address = bank->base + bank->sectors[i].offset;
 		uint32_t size = bank->sectors[i].size;
 
-		retval = target_blank_check_memory(target, address, size, &blank);
+		retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value);
 		if (retval != ERROR_OK) {
 			fast_check = 0;
 			break;
 		}
-		if (blank == 0xFF)
+		if (blank == bank->erased_value)
 			bank->sectors[i].is_erased = 1;
 		else
 			bank->sectors[i].is_erased = 0;
diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h
index 60d4483ae5ed7bde99bd6fcbab8b00392a879703..338363e2acad9713bfeccb1b786ab686e84cb529 100644
--- a/src/flash/nor/core.h
+++ b/src/flash/nor/core.h
@@ -90,6 +90,9 @@ struct flash_bank {
 	int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */
 	int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */
 
+	/** Erased value. Defaults to 0xFF. */
+	uint8_t erased_value;
+
 	/** Default padded value used, normally this matches the  flash
 	 * erased value. Defaults to 0xFF. */
 	uint8_t default_padded_value;
diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c
index 376c0f839b928f6645194819caacaa40b8844461..0b392334fb2149c16407393c8aae0340d3d867ae 100644
--- a/src/flash/nor/stm32lx.c
+++ b/src/flash/nor/stm32lx.c
@@ -300,7 +300,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
 	stm32lx_info->user_bank_size = bank->size;
 
 	/* the stm32l erased value is 0x00 */
-	bank->default_padded_value = 0x00;
+	bank->default_padded_value = bank->erased_value = 0x00;
 
 	return ERROR_OK;
 }
@@ -884,56 +884,6 @@ static int stm32lx_auto_probe(struct flash_bank *bank)
 	return stm32lx_probe(bank);
 }
 
-static int stm32lx_erase_check(struct flash_bank *bank)
-{
-	struct target *target = bank->target;
-	const int buffer_size = 4096;
-	int i;
-	uint32_t nBytes;
-	int retval = ERROR_OK;
-
-	if (bank->target->state != TARGET_HALTED) {
-		LOG_ERROR("Target not halted");
-		return ERROR_TARGET_NOT_HALTED;
-	}
-
-	uint8_t *buffer = malloc(buffer_size);
-	if (buffer == NULL) {
-		LOG_ERROR("failed to allocate read buffer");
-		return ERROR_FAIL;
-	}
-
-	for (i = 0; i < bank->num_sectors; i++) {
-		uint32_t j;
-		bank->sectors[i].is_erased = 1;
-
-		/* Loop chunk by chunk over the sector */
-		for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
-			uint32_t chunk;
-			chunk = buffer_size;
-			if (chunk > (j - bank->sectors[i].size))
-				chunk = (j - bank->sectors[i].size);
-
-			retval = target_read_memory(target, bank->base
-					+ bank->sectors[i].offset + j, 4, chunk / 4, buffer);
-			if (retval != ERROR_OK)
-				break;
-
-			for (nBytes = 0; nBytes < chunk; nBytes++) {
-				if (buffer[nBytes] != 0x00) {
-					bank->sectors[i].is_erased = 0;
-					break;
-				}
-			}
-		}
-		if (retval != ERROR_OK)
-			break;
-	}
-	free(buffer);
-
-	return retval;
-}
-
 /* This method must return a string displaying information about the bank */
 static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
 {
@@ -1022,7 +972,7 @@ struct flash_driver stm32lx_flash = {
 		.read = default_flash_read,
 		.probe = stm32lx_probe,
 		.auto_probe = stm32lx_auto_probe,
-		.erase_check = stm32lx_erase_check,
+		.erase_check = default_flash_blank_check,
 		.protect_check = stm32lx_protect_check,
 		.info = stm32lx_get_info,
 };
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index 6dd21407e877d37bca938ce498683b0da7703d26..d62fa7462e43bd9b70914754ae498a4d3c6a9cbf 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -1012,7 +1012,7 @@ COMMAND_HANDLER(handle_flash_bank_command)
 	COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
 	COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
 	COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
-	c->default_padded_value = 0xff;
+	c->default_padded_value = c->erased_value = 0xff;
 	c->num_sectors = 0;
 	c->sectors = NULL;
 	c->num_prot_blocks = 0;
diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c
index 3cb793e306942e2a1090edc0866f5dd1d57a0dd8..06981f4f4b762df21458777a01e3b82427146c5a 100644
--- a/src/flash/nor/virtual.c
+++ b/src/flash/nor/virtual.c
@@ -44,6 +44,7 @@ static void virtual_update_bank_info(struct flash_bank *bank)
 	bank->size = master_bank->size;
 	bank->chip_width = master_bank->chip_width;
 	bank->bus_width = master_bank->bus_width;
+	bank->erased_value = master_bank->erased_value;
 	bank->default_padded_value = master_bank->default_padded_value;
 	bank->num_sectors = master_bank->num_sectors;
 	bank->sectors = master_bank->sectors;
diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c
index 2a52269dc5b7f7288c80d333e517ff9f4a3d6244..f396ca3d573f48ab1e6e45db6013e8add663e733 100644
--- a/src/flash/nor/xmc4xxx.c
+++ b/src/flash/nor/xmc4xxx.c
@@ -319,8 +319,8 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank)
 	}
 
 	/* This part doesn't follow the typical standard of 0xff
-	 * being the default padding value.*/
-	bank->default_padded_value = 0x00;
+	 * being the erased value.*/
+	bank->default_padded_value = bank->erased_value = 0x00;
 
 	return ERROR_OK;
 }
@@ -617,99 +617,6 @@ static int xmc4xxx_enter_page_mode(struct flash_bank *bank)
 	return res;
 }
 
-/* The logical erase value of an xmc4xxx memory cell is 0x00,
- * therefore, we cannot use the built in flash blank check and must
- * implement our own */
-
-/** Checks whether a memory region is zeroed. */
-static int xmc4xxx_blank_check_memory(struct target *target,
-	uint32_t address, uint32_t count, uint32_t *blank)
-{
-	struct working_area *erase_check_algorithm;
-	struct reg_param reg_params[3];
-	struct armv7m_algorithm armv7m_info;
-	int retval;
-
-	static const uint8_t erase_check_code[] = {
-#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
-	};
-
-	/* make sure we have a working area */
-	if (target_alloc_working_area(target, sizeof(erase_check_code),
-		&erase_check_algorithm) != ERROR_OK)
-		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
-	retval = target_write_buffer(target, erase_check_algorithm->address,
-			sizeof(erase_check_code), (uint8_t *)erase_check_code);
-	if (retval != ERROR_OK)
-		goto cleanup;
-
-	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-	armv7m_info.core_mode = ARM_MODE_THREAD;
-
-	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
-	buf_set_u32(reg_params[0].value, 0, 32, address);
-
-	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-	buf_set_u32(reg_params[1].value, 0, 32, count);
-
-	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
-	buf_set_u32(reg_params[2].value, 0, 32, 0x00);
-
-	retval = target_run_algorithm(target,
-				      0,
-				      NULL,
-				      3,
-				      reg_params,
-				      erase_check_algorithm->address,
-				      erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
-				      10000,
-				      &armv7m_info);
-
-	if (retval == ERROR_OK)
-		*blank = buf_get_u32(reg_params[2].value, 0, 32);
-
-	destroy_reg_param(&reg_params[0]);
-	destroy_reg_param(&reg_params[1]);
-	destroy_reg_param(&reg_params[2]);
-
-cleanup:
-	target_free_working_area(target, erase_check_algorithm);
-
-	return retval;
-}
-
-static int xmc4xxx_flash_blank_check(struct flash_bank *bank)
-{
-	struct target *target = bank->target;
-	int i;
-	int retval = ERROR_OK;
-	uint32_t blank;
-
-	if (bank->target->state != TARGET_HALTED) {
-		LOG_ERROR("Target not halted");
-		return ERROR_TARGET_NOT_HALTED;
-	}
-
-	for (i = 0; i < bank->num_sectors; i++) {
-		uint32_t address = bank->base + bank->sectors[i].offset;
-		uint32_t size = bank->sectors[i].size;
-
-		LOG_DEBUG("Erase checking 0x%08"PRIx32, address);
-		retval = xmc4xxx_blank_check_memory(target, address, size, &blank);
-
-		if (retval != ERROR_OK)
-			break;
-
-		if (blank == 0x00)
-			bank->sectors[i].is_erased = 1;
-		else
-			bank->sectors[i].is_erased = 0;
-	}
-
-	return retval;
-}
-
 static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf,
 			      uint32_t offset, bool user_config)
 {
@@ -1439,7 +1346,7 @@ struct flash_driver xmc4xxx_flash = {
 	.read = default_flash_read,
 	.probe = xmc4xxx_probe,
 	.auto_probe = xmc4xxx_probe,
-	.erase_check = xmc4xxx_flash_blank_check,
+	.erase_check = default_flash_blank_check,
 	.info = xmc4xxx_get_info_command,
 	.protect_check = xmc4xxx_protect_check,
 	.protect = xmc4xxx_protect,
diff --git a/src/target/arm.h b/src/target/arm.h
index 163db239a37867eb7bbf91610b06d4a7673b42ab..28022e3d2d905eb4c20550d060f72dad4c46ca7d 100644
--- a/src/target/arm.h
+++ b/src/target/arm.h
@@ -232,7 +232,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
 int arm_checksum_memory(struct target *target,
 		uint32_t address, uint32_t count, uint32_t *checksum);
 int arm_blank_check_memory(struct target *target,
-		uint32_t address, uint32_t count, uint32_t *blank);
+		uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
 
 void arm_set_cpsr(struct arm *arm, uint32_t cpsr);
 struct reg *arm_reg_current(struct arm *arm, unsigned regnum);
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index e6ecfc88467d73044e83cd4bf37c25cff3b02478..1a31d40ce24f51a923c0a136858c5ed474cf5f5d 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -1486,7 +1486,7 @@ cleanup:
  *
  */
 int arm_blank_check_memory(struct target *target,
-	uint32_t address, uint32_t count, uint32_t *blank)
+	uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
 {
 	struct working_area *check_algorithm;
 	struct reg_param reg_params[3];
@@ -1502,6 +1502,12 @@ int arm_blank_check_memory(struct target *target,
 
 	assert(sizeof(check_code_le) % 4 == 0);
 
+	if (erased_value != 0xff) {
+		LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for ARMv4/v5 targets",
+			erased_value);
+		return ERROR_FAIL;
+	}
+
 	/* make sure we have a working area */
 	retval = target_alloc_working_area(target,
 			sizeof(check_code_le), &check_algorithm);
@@ -1529,7 +1535,7 @@ int arm_blank_check_memory(struct target *target,
 	buf_set_u32(reg_params[1].value, 0, 32, count);
 
 	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
-	buf_set_u32(reg_params[2].value, 0, 32, 0xff);
+	buf_set_u32(reg_params[2].value, 0, 32, erased_value);
 
 	/* armv4 must exit using a hardware breakpoint */
 	if (arm->is_armv4)
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
index e2f710f147aeab260927253525d59982b18a0d17..60b244aae38b51a879a03ebaea6f148752a636f6 100644
--- a/src/target/armv7m.c
+++ b/src/target/armv7m.c
@@ -726,26 +726,42 @@ cleanup:
 	return retval;
 }
 
-/** Checks whether a memory region is zeroed. */
+/** Checks whether a memory region is erased. */
 int armv7m_blank_check_memory(struct target *target,
-	uint32_t address, uint32_t count, uint32_t *blank)
+	uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
 {
 	struct working_area *erase_check_algorithm;
 	struct reg_param reg_params[3];
 	struct armv7m_algorithm armv7m_info;
+	const uint8_t *code;
+	uint32_t code_size;
 	int retval;
 
 	static const uint8_t erase_check_code[] = {
 #include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
 	};
+	static const uint8_t zero_erase_check_code[] = {
+#include "../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
+	};
+
+	switch (erased_value) {
+	case 0x00:
+		code = zero_erase_check_code;
+		code_size = sizeof(zero_erase_check_code);
+		break;
+	case 0xff:
+	default:
+		code = erase_check_code;
+		code_size = sizeof(erase_check_code);
+	}
 
 	/* make sure we have a working area */
-	if (target_alloc_working_area(target, sizeof(erase_check_code),
+	if (target_alloc_working_area(target, code_size,
 		&erase_check_algorithm) != ERROR_OK)
 		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
 	retval = target_write_buffer(target, erase_check_algorithm->address,
-			sizeof(erase_check_code), (uint8_t *)erase_check_code);
+			code_size, code);
 	if (retval != ERROR_OK)
 		goto cleanup;
 
@@ -759,7 +775,7 @@ int armv7m_blank_check_memory(struct target *target,
 	buf_set_u32(reg_params[1].value, 0, 32, count);
 
 	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
-	buf_set_u32(reg_params[2].value, 0, 32, 0xff);
+	buf_set_u32(reg_params[2].value, 0, 32, erased_value);
 
 	retval = target_run_algorithm(target,
 			0,
@@ -767,7 +783,7 @@ int armv7m_blank_check_memory(struct target *target,
 			3,
 			reg_params,
 			erase_check_algorithm->address,
-			erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
+			erase_check_algorithm->address + (code_size - 2),
 			10000,
 			&armv7m_info);
 
diff --git a/src/target/armv7m.h b/src/target/armv7m.h
index 90cad00c2ab3d746c53b2aabdf5dc55315f67ac8..304c72d3f634fb5f7462f6656590789d7e6a787f 100644
--- a/src/target/armv7m.h
+++ b/src/target/armv7m.h
@@ -225,7 +225,7 @@ int armv7m_restore_context(struct target *target);
 int armv7m_checksum_memory(struct target *target,
 		uint32_t address, uint32_t count, uint32_t *checksum);
 int armv7m_blank_check_memory(struct target *target,
-		uint32_t address, uint32_t count, uint32_t *blank);
+		uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
 
 int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found);
 
diff --git a/src/target/mips32.c b/src/target/mips32.c
index 8c77986496fc4554586837fa3be23ad3fe4f1533..27caebee19d7c2b5c9514aa9b4aa0d11c04924c2 100644
--- a/src/target/mips32.c
+++ b/src/target/mips32.c
@@ -771,9 +771,9 @@ int mips32_checksum_memory(struct target *target, uint32_t address,
 	return retval;
 }
 
-/** Checks whether a memory region is zeroed. */
+/** Checks whether a memory region is erased. */
 int mips32_blank_check_memory(struct target *target,
-		uint32_t address, uint32_t count, uint32_t *blank)
+		uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
 {
 	struct working_area *erase_check_algorithm;
 	struct reg_param reg_params[3];
@@ -789,6 +789,12 @@ int mips32_blank_check_memory(struct target *target,
 		0x7000003F		/* sdbbp */
 	};
 
+	if (erased_value != 0xff) {
+		LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32",
+			erased_value);
+		return ERROR_FAIL;
+	}
+
 	/* make sure we have a working area */
 	if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
 		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -810,7 +816,7 @@ int mips32_blank_check_memory(struct target *target,
 	buf_set_u32(reg_params[1].value, 0, 32, count);
 
 	init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
-	buf_set_u32(reg_params[2].value, 0, 32, 0xff);
+	buf_set_u32(reg_params[2].value, 0, 32, erased_value);
 
 	int retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
 			erase_check_algorithm->address,
diff --git a/src/target/mips32.h b/src/target/mips32.h
index 8362f5e6b1323dee77d6d16427f398dbe508df06..d493b39ed23ec66e237b7d7fbc1352f43ea95824 100644
--- a/src/target/mips32.h
+++ b/src/target/mips32.h
@@ -249,6 +249,6 @@ int mips32_get_gdb_reg_list(struct target *target,
 int mips32_checksum_memory(struct target *target, uint32_t address,
 		uint32_t count, uint32_t *checksum);
 int mips32_blank_check_memory(struct target *target,
-		uint32_t address, uint32_t count, uint32_t *blank);
+		uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
 
 #endif /* OPENOCD_TARGET_MIPS32_H */
diff --git a/src/target/target.c b/src/target/target.c
index e3c81689d85271c4fdd3b2cbf23948bf3a7432fc..9fc9d20fcf5b8921e3526d6ec2b0458c56dff43f 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -2178,7 +2178,8 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
 	return retval;
 }
 
-int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank)
+int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank,
+	uint8_t erased_value)
 {
 	int retval;
 	if (!target_was_examined(target)) {
@@ -2189,7 +2190,7 @@ int target_blank_check_memory(struct target *target, uint32_t address, uint32_t
 	if (target->type->blank_check_memory == 0)
 		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-	retval = target->type->blank_check_memory(target, address, size, blank);
+	retval = target->type->blank_check_memory(target, address, size, blank, erased_value);
 
 	return retval;
 }
diff --git a/src/target/target.h b/src/target/target.h
index a1a30fff939d8926d24cee15ce61317ae17a3cc0..8f6a7d901abb93cd598aa7905667f4282f025175 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -579,7 +579,7 @@ int target_read_buffer(struct target *target,
 int target_checksum_memory(struct target *target,
 		uint32_t address, uint32_t size, uint32_t *crc);
 int target_blank_check_memory(struct target *target,
-		uint32_t address, uint32_t size, uint32_t *blank);
+		uint32_t address, uint32_t size, uint32_t *blank, uint8_t erased_value);
 int target_wait_state(struct target *target, enum target_state state, int ms);
 
 /**
diff --git a/src/target/target_type.h b/src/target/target_type.h
index eaa8a71cccd17f3557c074473f385020932b530f..2473c62cbeee8e88479576ba14e037edeaba389c 100644
--- a/src/target/target_type.h
+++ b/src/target/target_type.h
@@ -131,7 +131,7 @@ struct target_type {
 	int (*checksum_memory)(struct target *target, uint32_t address,
 			uint32_t count, uint32_t *checksum);
 	int (*blank_check_memory)(struct target *target, uint32_t address,
-			uint32_t count, uint32_t *blank);
+			uint32_t count, uint32_t *blank, uint8_t erased_value);
 
 	/*
 	 * target break-/watchpoint control