mirror of
https://github.com/openwrt/openwrt.git
synced 2026-04-25 11:08:49 +04:00
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>
116 lines
3.1 KiB
Diff
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 = {
|