Files
openwrt/target/linux/generic/backport-6.12/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch
Hauke Mehrtens 3c821c19a8 kernel: move patches to backported
These formally pending patches were merged into upstream Linux some time
ago. Move them to the backports folder and add the kernel version they
were added to the file name.

Link: https://github.com/openwrt/openwrt/pull/21366
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-01-04 16:41:29 +01:00

116 lines
3.1 KiB
Diff

From f6dffe2a9ed1bdcee1879e2728310fb1e08602cf Mon Sep 17 00:00:00 2001
From: Mikhail Zhilkin <csharper2005@gmail.com>
Date: Thu, 27 Nov 2025 22:59:00 +0300
Subject: mtd: spinand: add support for FudanMicro FM25S01BI3
Add support for FudanMicro FM25S01BI3 SPI NAND.
Link: https://www.fmsh.com/nvm/FM25S01BI3_ds_eng.pdf
Signed-off-by: Mikhail Zhilkin <csharper2005@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
drivers/mtd/nand/spi/fmsh.c | 72 +++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
--- a/drivers/mtd/nand/spi/fmsh.c
+++ b/drivers/mtd/nand/spi/fmsh.c
@@ -9,6 +9,13 @@
#include <linux/kernel.h>
#include <linux/mtd/spinand.h>
+#define FM25S01BI3_STATUS_ECC_MASK (7 << 4)
+ #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4)
+ #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4)
+ #define FM25S01BI3_STATUS_ECC_UNCOR_ERROR (2 << 4)
+ #define FM25S01BI3_STATUS_ECC_4_6_BITFLIPS (3 << 4)
+ #define FM25S01BI3_STATUS_ECC_7_8_BITFLIPS (5 << 4)
+
#define SPINAND_MFR_FMSH 0xA1
static SPINAND_OP_VARIANTS(read_cache_variants,
@@ -45,11 +52,66 @@ static int fm25s01a_ooblayout_free(struc
return 0;
}
+static int fm25s01bi3_ecc_get_status(struct spinand_device *spinand,
+ u8 status)
+{
+ switch (status & FM25S01BI3_STATUS_ECC_MASK) {
+ case FM25S01BI3_STATUS_ECC_NO_BITFLIPS:
+ return 0;
+
+ case FM25S01BI3_STATUS_ECC_UNCOR_ERROR:
+ return -EBADMSG;
+
+ case FM25S01BI3_STATUS_ECC_1_3_BITFLIPS:
+ return 3;
+
+ case FM25S01BI3_STATUS_ECC_4_6_BITFLIPS:
+ return 6;
+
+ case FM25S01BI3_STATUS_ECC_7_8_BITFLIPS:
+ return 8;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int fm25s01bi3_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section)
+ return -ERANGE;
+
+ region->offset = 64;
+ region->length = 64;
+
+ return 0;
+}
+
+static int fm25s01bi3_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ if (section > 3)
+ return -ERANGE;
+
+ region->offset = (16 * section) + 4;
+ region->length = 12;
+
+ return 0;
+}
+
static const struct mtd_ooblayout_ops fm25s01a_ooblayout = {
.ecc = fm25s01a_ooblayout_ecc,
.free = fm25s01a_ooblayout_free,
};
+static const struct mtd_ooblayout_ops fm25s01bi3_ooblayout = {
+ .ecc = fm25s01bi3_ooblayout_ecc,
+ .free = fm25s01bi3_ooblayout_free,
+};
+
static const struct spinand_info fmsh_spinand_table[] = {
SPINAND_INFO("FM25S01A",
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
@@ -60,6 +122,16 @@ static const struct spinand_info fmsh_sp
&update_cache_variants),
0,
SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)),
+ SPINAND_INFO("FM25S01BI3",
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd4),
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ &write_cache_variants,
+ &update_cache_variants),
+ SPINAND_HAS_QE_BIT,
+ SPINAND_ECCINFO(&fm25s01bi3_ooblayout,
+ fm25s01bi3_ecc_get_status)),
};
static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = {