Просмотр исходного кода

kernel: mtd: spinand: add support for SkyHigh S35ML-3

This introduces support for the SkyHigh S35ML-3 series SPI NAND flash
devices by importing two key patches:
 - 430-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch
 - 431-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch

Additionally, refresh all existing patches.

Co-authored-by: Mieczyslaw Nalewaj <[email protected]>
Signed-off-by: Rongzeng Cai <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/21808
Signed-off-by: Hauke Mehrtens <[email protected]>
Rongzeng Cai 1 неделя назад
Родитель
Сommit
3a795bd100

+ 81 - 0
target/linux/generic/backport-6.12/430-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch

@@ -0,0 +1,81 @@
+From 6d9d6ab3a82af50e36e13e7bc8e2d1b970e39f79 Mon Sep 17 00:00:00 2001
+From: Takahiro Kuwano <[email protected]>
+Date: Tue, 3 Dec 2024 11:46:49 +0900
+Subject: [PATCH 1/1] mtd: spinand: Introduce a way to avoid raw access
+
+SkyHigh spinand device has ECC enable bit in configuration register but
+it must be always enabled. If ECC is disabled, read and write ops
+results in undetermined state. For such devices, a way to avoid raw
+access is needed.
+
+Introduce SPINAND_NO_RAW_ACCESS flag to advertise the device does not
+support raw access. In such devices, the on-die ECC engine ops returns
+error to I/O request in raw mode.
+
+Checking and marking BBM need to be cared as special case, by adding
+fallback mechanism that tries read/write OOB with ECC enabled.
+
+Signed-off-by: Takahiro Kuwano <[email protected]>
+Signed-off-by: Miquel Raynal <[email protected]>
+---
+ drivers/mtd/nand/spi/core.c | 22 ++++++++++++++++++++--
+ include/linux/mtd/spinand.h |  1 +
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -294,6 +294,9 @@ static int spinand_ondie_ecc_prepare_io_
+ 	struct spinand_device *spinand = nand_to_spinand(nand);
+ 	bool enable = (req->mode != MTD_OPS_RAW);
+ 
++	if (!enable && spinand->flags & SPINAND_NO_RAW_ACCESS)
++		return -EOPNOTSUPP;
++
+ 	memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand));
+ 
+ 	/* Only enable or disable the engine */
+@@ -921,9 +924,17 @@ static bool spinand_isbad(struct nand_de
+ 		.oobbuf.in = marker,
+ 		.mode = MTD_OPS_RAW,
+ 	};
++	int ret;
+ 
+ 	spinand_select_target(spinand, pos->target);
+-	spinand_read_page(spinand, &req);
++
++	ret = spinand_read_page(spinand, &req);
++	if (ret == -EOPNOTSUPP) {
++		/* Retry with ECC in case raw access is not supported */
++		req.mode = MTD_OPS_PLACE_OOB;
++		spinand_read_page(spinand, &req);
++	}
++
+ 	if (marker[0] != 0xff || marker[1] != 0xff)
+ 		return true;
+ 
+@@ -966,7 +977,14 @@ static int spinand_markbad(struct nand_d
+ 	if (ret)
+ 		return ret;
+ 
+-	return spinand_write_page(spinand, &req);
++	ret = spinand_write_page(spinand, &req);
++	if (ret == -EOPNOTSUPP) {
++		/* Retry with ECC in case raw access is not supported */
++		req.mode = MTD_OPS_PLACE_OOB;
++		ret = spinand_write_page(spinand, &req);
++	}
++
++	return ret;
+ }
+ 
+ static int spinand_mtd_block_markbad(struct mtd_info *mtd, loff_t offs)
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -315,6 +315,7 @@ struct spinand_ecc_info {
+ #define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
+ #define SPINAND_HAS_PROG_PLANE_SELECT_BIT		BIT(2)
+ #define SPINAND_HAS_READ_PLANE_SELECT_BIT		BIT(3)
++#define SPINAND_NO_RAW_ACCESS				BIT(4)
+ 
+ /**
+  * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure

+ 201 - 0
target/linux/generic/backport-6.12/431-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch

@@ -0,0 +1,201 @@
+From 1a50e3612de9187857f55ee14a573f7f8e7d4ebc Mon Sep 17 00:00:00 2001
+From: Takahiro Kuwano <[email protected]>
+Date: Tue, 3 Dec 2024 11:46:50 +0900
+Subject: [PATCH] mtd: spinand: Add support for SkyHigh S35ML-3 family
+
+SkyHigh S35ML01G300, S35ML01G301, S35ML02G300, and S35ML04G300 are 1Gb,
+2Gb, and 4Gb SLC SPI NAND flash family. This family of devices has
+on-die ECC which parity bits are stored to hidden area. In this family
+the on-die ECC cannot be disabled so raw access needs to be prevented.
+
+Link: https://www.skyhighmemory.com/download/SPI_S35ML01_04G3_002_19205.pdf?v=P
+Co-developed-by: KR Kim <[email protected]>
+Signed-off-by: KR Kim <[email protected]>
+Signed-off-by: Takahiro Kuwano <[email protected]>
+Signed-off-by: Miquel Raynal <[email protected]>
+---
+ drivers/mtd/nand/spi/Makefile  |   2 +-
+ drivers/mtd/nand/spi/core.c    |   1 +
+ drivers/mtd/nand/spi/skyhigh.c | 147 +++++++++++++++++++++++++++++++++
+ include/linux/mtd/spinand.h    |   1 +
+ 4 files changed, 150 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/mtd/nand/spi/skyhigh.c
+
+--- a/drivers/mtd/nand/spi/Makefile
++++ b/drivers/mtd/nand/spi/Makefile
+@@ -1,4 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0
+ spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o
+-spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o
++spinand-objs += micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o
+ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -1183,6 +1183,7 @@ static const struct spinand_manufacturer
+ 	&macronix_spinand_manufacturer,
+ 	&micron_spinand_manufacturer,
+ 	&paragon_spinand_manufacturer,
++	&skyhigh_spinand_manufacturer,
+ 	&toshiba_spinand_manufacturer,
+ 	&winbond_spinand_manufacturer,
+ 	&xtx_spinand_manufacturer,
+--- /dev/null
++++ b/drivers/mtd/nand/spi/skyhigh.c
+@@ -0,0 +1,147 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2024 SkyHigh Memory Limited
++ *
++ * Author: Takahiro Kuwano <[email protected]>
++ * Co-Author: KR Kim <[email protected]>
++ */
++
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/mtd/spinand.h>
++
++#define SPINAND_MFR_SKYHIGH			0x01
++#define SKYHIGH_STATUS_ECC_1TO2_BITFLIPS	(1 << 4)
++#define SKYHIGH_STATUS_ECC_3TO6_BITFLIPS	(2 << 4)
++#define SKYHIGH_STATUS_ECC_UNCOR_ERROR		(3 << 4)
++#define SKYHIGH_CONFIG_PROTECT_EN		BIT(1)
++
++static SPINAND_OP_VARIANTS(read_cache_variants,
++		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(write_cache_variants,
++		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
++		SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(update_cache_variants,
++		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
++		SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++static int skyhigh_spinand_ooblayout_ecc(struct mtd_info *mtd, int section,
++					 struct mtd_oob_region *region)
++{
++	/* ECC bytes are stored in hidden area. */
++	return -ERANGE;
++}
++
++static int skyhigh_spinand_ooblayout_free(struct mtd_info *mtd, int section,
++					  struct mtd_oob_region *region)
++{
++	if (section)
++		return -ERANGE;
++
++	/* ECC bytes are stored in hidden area. Reserve 2 bytes for the BBM. */
++	region->offset = 2;
++	region->length = mtd->oobsize - 2;
++
++	return 0;
++}
++
++static const struct mtd_ooblayout_ops skyhigh_spinand_ooblayout = {
++	.ecc = skyhigh_spinand_ooblayout_ecc,
++	.free = skyhigh_spinand_ooblayout_free,
++};
++
++static int skyhigh_spinand_ecc_get_status(struct spinand_device *spinand,
++					  u8 status)
++{
++	switch (status & STATUS_ECC_MASK) {
++	case STATUS_ECC_NO_BITFLIPS:
++		return 0;
++
++	case SKYHIGH_STATUS_ECC_UNCOR_ERROR:
++		return -EBADMSG;
++
++	case SKYHIGH_STATUS_ECC_1TO2_BITFLIPS:
++		return 2;
++
++	case SKYHIGH_STATUS_ECC_3TO6_BITFLIPS:
++		return 6;
++
++	default:
++		break;
++	}
++
++	return -EINVAL;
++}
++
++static const struct spinand_info skyhigh_spinand_table[] = {
++	SPINAND_INFO("S35ML01G301",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
++		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(6, 32),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_NO_RAW_ACCESS,
++		     SPINAND_ECCINFO(&skyhigh_spinand_ooblayout,
++				     skyhigh_spinand_ecc_get_status)),
++	SPINAND_INFO("S35ML01G300",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
++		     NAND_ECCREQ(6, 32),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_NO_RAW_ACCESS,
++		     SPINAND_ECCINFO(&skyhigh_spinand_ooblayout,
++				     skyhigh_spinand_ecc_get_status)),
++	SPINAND_INFO("S35ML02G300",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25),
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
++		     NAND_ECCREQ(6, 32),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_NO_RAW_ACCESS,
++		     SPINAND_ECCINFO(&skyhigh_spinand_ooblayout,
++				     skyhigh_spinand_ecc_get_status)),
++	SPINAND_INFO("S35ML04G300",
++		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
++		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 2, 1, 1),
++		     NAND_ECCREQ(6, 32),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_NO_RAW_ACCESS,
++		     SPINAND_ECCINFO(&skyhigh_spinand_ooblayout,
++				     skyhigh_spinand_ecc_get_status)),
++};
++
++static int skyhigh_spinand_init(struct spinand_device *spinand)
++{
++	/*
++	 * Config_Protect_En (bit 1 in Block Lock register) must be set to 1
++	 * before writing other bits. Do it here before core unlocks all blocks
++	 * by writing block protection bits.
++	 */
++	return spinand_write_reg_op(spinand, REG_BLOCK_LOCK,
++				    SKYHIGH_CONFIG_PROTECT_EN);
++}
++
++static const struct spinand_manufacturer_ops skyhigh_spinand_manuf_ops = {
++	.init = skyhigh_spinand_init,
++};
++
++const struct spinand_manufacturer skyhigh_spinand_manufacturer = {
++	.id = SPINAND_MFR_SKYHIGH,
++	.name = "SkyHigh",
++	.chips = skyhigh_spinand_table,
++	.nchips = ARRAY_SIZE(skyhigh_spinand_table),
++	.ops = &skyhigh_spinand_manuf_ops,
++};
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -269,6 +269,7 @@ extern const struct spinand_manufacturer
+ extern const struct spinand_manufacturer macronix_spinand_manufacturer;
+ extern const struct spinand_manufacturer micron_spinand_manufacturer;
+ extern const struct spinand_manufacturer paragon_spinand_manufacturer;
++extern const struct spinand_manufacturer skyhigh_spinand_manufacturer;
+ extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
+ extern const struct spinand_manufacturer winbond_spinand_manufacturer;
+ extern const struct spinand_manufacturer xtx_spinand_manufacturer;

+ 1 - 1
target/linux/generic/backport-6.12/434-v6.19-mtd-spinand-esmt-add-support-for-F50L1G41LC.patch

@@ -19,7 +19,7 @@ Signed-off-by: Miquel Raynal <[email protected]>
 
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -1158,6 +1158,7 @@ static const struct nand_ops spinand_ops
+@@ -1176,6 +1176,7 @@ static const struct nand_ops spinand_ops
  static const struct spinand_manufacturer *spinand_manufacturers[] = {
  	&alliancememory_spinand_manufacturer,
  	&ato_spinand_manufacturer,

+ 3 - 3
target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch

@@ -43,13 +43,13 @@ Submitted-by: Daniel Danzberger <[email protected]>
 @@ -1,4 +1,4 @@
  # SPDX-License-Identifier: GPL-2.0
 -spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o
--spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o
+-spinand-objs += micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o
 +spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o
-+spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
++spinand-objs += macronix.o micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o
  obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -1160,6 +1160,7 @@ static const struct spinand_manufacturer
+@@ -1178,6 +1178,7 @@ static const struct spinand_manufacturer
  	&ato_spinand_manufacturer,
  	&esmt_8c_spinand_manufacturer,
  	&esmt_c8_spinand_manufacturer,

+ 4 - 4
target/linux/mediatek/patches-6.12/121-hack-spi-nand-1b-bbm.patch

@@ -1,6 +1,6 @@
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -913,7 +913,7 @@ static int spinand_mtd_write(struct mtd_
+@@ -916,7 +916,7 @@ static int spinand_mtd_write(struct mtd_
  static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos)
  {
  	struct spinand_device *spinand = nand_to_spinand(nand);
@@ -9,10 +9,10 @@
  	struct nand_page_io_req req = {
  		.pos = *pos,
  		.ooblen = sizeof(marker),
-@@ -924,7 +924,7 @@ static bool spinand_isbad(struct nand_de
+@@ -935,7 +935,7 @@ static bool spinand_isbad(struct nand_de
+ 		spinand_read_page(spinand, &req);
+ 	}
  
- 	spinand_select_target(spinand, pos->target);
- 	spinand_read_page(spinand, &req);
 -	if (marker[0] != 0xff || marker[1] != 0xff)
 +	if (marker[0] != 0xff)
  		return true;

+ 3 - 3
target/linux/mediatek/patches-6.12/330-snand-mtk-bmt-support.patch

@@ -8,7 +8,7 @@
  
  static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
  {
-@@ -1577,6 +1578,7 @@ static int spinand_probe(struct spi_mem
+@@ -1596,6 +1597,7 @@ static int spinand_probe(struct spi_mem
  	if (ret)
  		return ret;
  
@@ -16,7 +16,7 @@
  	ret = mtd_device_register(mtd, NULL, 0);
  	if (ret)
  		goto err_spinand_cleanup;
-@@ -1584,6 +1586,7 @@ static int spinand_probe(struct spi_mem
+@@ -1603,6 +1605,7 @@ static int spinand_probe(struct spi_mem
  	return 0;
  
  err_spinand_cleanup:
@@ -24,7 +24,7 @@
  	spinand_cleanup(spinand);
  
  	return ret;
-@@ -1602,6 +1605,7 @@ static int spinand_remove(struct spi_mem
+@@ -1621,6 +1624,7 @@ static int spinand_remove(struct spi_mem
  	if (ret)
  		return ret;
  

+ 2 - 2
target/linux/mediatek/patches-6.12/340-mtd-spinand-Add-support-for-the-Fidelix-FM35X1GA.patch

@@ -20,11 +20,11 @@ Signed-off-by: Davide Fioravanti <[email protected]>
  # SPDX-License-Identifier: GPL-2.0
 -spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o
 +spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fidelix.o fmsh.o foresee.o gigadevice.o
- spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
+ spinand-objs += macronix.o micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o
  obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -1163,6 +1163,7 @@ static const struct spinand_manufacturer
+@@ -1181,6 +1181,7 @@ static const struct spinand_manufacturer
  	&esmt_c8_spinand_manufacturer,
  	&etron_spinand_manufacturer,
  	&fmsh_spinand_manufacturer,

+ 2 - 2
target/linux/mediatek/patches-6.12/435-drivers-mtd-spinand-Add-calibration-support-for-spin.patch

@@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang <[email protected]>
 
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -1201,6 +1201,56 @@ static int spinand_manufacturer_match(st
+@@ -1220,6 +1220,56 @@ static int spinand_manufacturer_match(st
  	return -EOPNOTSUPP;
  }
  
@@ -68,7 +68,7 @@ Signed-off-by: SkyLake.Huang <[email protected]>
  static int spinand_id_detect(struct spinand_device *spinand)
  {
  	u8 *id = spinand->id.data;
-@@ -1454,6 +1504,10 @@ static int spinand_init(struct spinand_d
+@@ -1473,6 +1523,10 @@ static int spinand_init(struct spinand_d
  	if (!spinand->scratchbuf)
  		return -ENOMEM;
  

+ 1 - 1
target/linux/mediatek/patches-6.12/436-drivers-mtd-spi-nor-Add-calibration-support-for-spi-.patch

@@ -12,7 +12,7 @@ Signed-off-by: SkyLake.Huang <[email protected]>
 
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -1242,7 +1242,10 @@ static int spinand_cal_read(void *priv,
+@@ -1261,7 +1261,10 @@ static int spinand_cal_read(void *priv,
  	if (ret)
  		return ret;
  

+ 2 - 2
target/linux/mediatek/patches-6.12/960-asus-hack-u-boot-ignore-mtdparts.patch

@@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
-@@ -1671,6 +1671,7 @@ static int spinand_remove(struct spi_mem
+@@ -1690,6 +1690,7 @@ static int spinand_remove(struct spi_mem
  
  static const struct spi_device_id spinand_ids[] = {
  	{ .name = "spi-nand" },
@@ -37,7 +37,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  	{ /* sentinel */ },
  };
  MODULE_DEVICE_TABLE(spi, spinand_ids);
-@@ -1678,6 +1679,7 @@ MODULE_DEVICE_TABLE(spi, spinand_ids);
+@@ -1697,6 +1698,7 @@ MODULE_DEVICE_TABLE(spi, spinand_ids);
  #ifdef CONFIG_OF
  static const struct of_device_id spinand_of_ids[] = {
  	{ .compatible = "spi-nand" },