diff --git a/target/linux/generic/pending-5.4/499-0-mtd-spi-nor-allow-variable-erase.patch b/target/linux/generic/pending-5.4/499-0-mtd-spi-nor-allow-variable-erase.patch
new file mode 100644
index 0000000000..a7d727f2b0
--- /dev/null
+++ b/target/linux/generic/pending-5.4/499-0-mtd-spi-nor-allow-variable-erase.patch
@@ -0,0 +1,172 @@
+--- a/drivers/mtd/mtdpart.c
++++ b/drivers/mtd/mtdpart.c
+@@ -331,8 +331,9 @@ static struct mtd_part *allocate_partiti
+ {
+ 	int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize :
+ 							    parent->erasesize;
++	int wr_alignment_minor = parent->erasesize_minor;
+ 	struct mtd_part *slave;
+-	u32 remainder;
++	u32 remainder, remainder_minor;
+ 	char *name;
+ 	u64 tmp;
+ 
+@@ -433,6 +434,9 @@ static struct mtd_part *allocate_partiti
+ 	if (parent->_put_device)
+ 		slave->mtd._put_device = part_put_device;
+ 
++	if (parent->erasesize_minor)
++		slave->mtd.erasesize_minor = parent->erasesize_minor;
++
+ 	slave->mtd._erase = part_erase;
+ 	slave->parent = parent;
+ 	slave->offset = part->offset;
+@@ -523,21 +527,41 @@ static struct mtd_part *allocate_partiti
+ 
+ 	tmp = part_absolute_offset(parent) + slave->offset;
+ 	remainder = do_div(tmp, wr_alignment);
+-	if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
+-		/* Doesn't start on a boundary of major erase size */
+-		/* FIXME: Let it be writable if it is on a boundary of
+-		 * _minor_ erase size though */
+-		slave->mtd.flags &= ~MTD_WRITEABLE;
+-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
+-			part->name);
++	if (remainder && wr_alignment_minor) {
++		tmp = part_absolute_offset(parent) + slave->offset;
++		remainder_minor = do_div(tmp, wr_alignment_minor);
++	}
++	if (slave->mtd.flags & MTD_WRITEABLE){
++		if (!remainder){
++			/* Does start on a boundary of major erase size */
++		} else if (wr_alignment_minor && !remainder_minor){
++			/* Does start on a boundary of minor erase size */
++			slave->mtd.erasesize = parent->erasesize_minor;
++		} else {
++			slave->mtd.flags &= ~MTD_WRITEABLE;
++			printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
++				part->name);
++		}
+ 	}
+ 
+ 	tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size;
+ 	remainder = do_div(tmp, wr_alignment);
+-	if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
+-		slave->mtd.flags &= ~MTD_WRITEABLE;
+-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
+-			part->name);
++	if (remainder && wr_alignment_minor) {
++		tmp = part_absolute_offset(parent) +
++		      slave->offset + slave->mtd.size;
++		remainder_minor = do_div(tmp, wr_alignment_minor);
++	}
++	if (slave->mtd.flags & MTD_WRITEABLE){
++		if (!remainder){
++			/* Does end on a boundary of major erase size */
++		} else if (wr_alignment_minor && !remainder_minor){
++			/* Does end on a boundary of minor erase size */
++			slave->mtd.erasesize = parent->erasesize_minor;
++		} else {
++			slave->mtd.flags &= ~MTD_WRITEABLE;
++			printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
++				part->name);
++		}
+ 	}
+ 
+ 	mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops);
+--- a/drivers/mtd/spi-nor/Kconfig
++++ b/drivers/mtd/spi-nor/Kconfig
+@@ -24,6 +24,14 @@ config MTD_SPI_NOR_USE_4K_SECTORS
+ 	  Please note that some tools/drivers/filesystems may not work with
+ 	  4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
+ 
++config MTD_SPI_NOR_USE_VARIABLE_ERASE
++	bool "Disable uniform_erase"
++	default n
++	help
++	  Return false with spi_nor_has_uniform_erase,
++	  so that the multiple eraseregions code path is used.
++	  This allows an erase to use 4K erase where supported and needed.
++
+ config SPI_ASPEED_SMC
+ 	tristate "Aspeed flash controllers in SPI mode"
+ 	depends on ARCH_ASPEED || COMPILE_TEST
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -4346,6 +4346,7 @@ static int spi_nor_select_erase(struct s
+ {
+ 	struct spi_nor_erase_map *map = &nor->params.erase_map;
+ 	const struct spi_nor_erase_type *erase = NULL;
++	const struct spi_nor_erase_type *erase_minor = NULL;
+ 	struct mtd_info *mtd = &nor->mtd;
+ 	u32 wanted_size = nor->info->sector_size;
+ 	int i;
+@@ -4378,15 +4379,20 @@ static int spi_nor_select_erase(struct s
+ 	 */
+ 	for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
+ 		if (map->erase_type[i].size) {
+-			erase = &map->erase_type[i];
+-			break;
++			if (!erase)
++				erase = &map->erase_type[i];
++			erase_minor = &map->erase_type[i];
+ 		}
+ 	}
+ 
+ 	if (!erase)
+ 		return -EINVAL;
+ 
++	if (!erase_minor)
++		erase_minor = erase;
++
+ 	mtd->erasesize = erase->size;
++	mtd->erasesize_minor = erase_minor->size;
+ 	return 0;
+ }
+ 
+@@ -4522,12 +4528,20 @@ static void spi_nor_sfdp_init_params(str
+ 	struct spi_nor_flash_parameter sfdp_params;
+ 
+ 	memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
++	if (nor->params.erase_map.regions ==
++	    &nor->params.erase_map.uniform_region)
++		sfdp_params.erase_map.regions = (
++			&sfdp_params.erase_map.uniform_region);
+ 
+ 	if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
+ 		nor->addr_width = 0;
+ 		nor->flags &= ~SNOR_F_4B_OPCODES;
+ 	} else {
+ 		memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
++		if (sfdp_params.erase_map.regions ==
++		    &sfdp_params.erase_map.uniform_region)
++			nor->params.erase_map.regions = (
++				&nor->params.erase_map.uniform_region);
+ 	}
+ }
+ 
+--- a/include/linux/mtd/mtd.h
++++ b/include/linux/mtd/mtd.h
+@@ -205,6 +205,8 @@ struct mtd_info {
+ 	 * information below if they desire
+ 	 */
+ 	uint32_t erasesize;
++	/* "Minor" erase size supported by the whole device */
++	uint32_t erasesize_minor;
+ 	/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
+ 	 * though individual bits can be cleared), in case of NAND flash it is
+ 	 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
+--- a/include/linux/mtd/spi-nor.h
++++ b/include/linux/mtd/spi-nor.h
+@@ -631,7 +631,11 @@ spi_nor_region_mark_overlay(struct spi_n
+ 
+ static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
+ {
++#ifdef CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE
++	return false;
++#else
+ 	return !!nor->params.erase_map.uniform_erase_type;
++#endif
+ }
+ 
+ static inline void spi_nor_set_flash_node(struct spi_nor *nor,
