* [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-10-20 13:27 ` Sky Huang
0 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router platforms
chips, we have to quality lots of SPI-NAND devices and are eager for
a standard so that we don't need to maintain trivial flash ID table
anymore. I also noticed a talk in 2019 Embedded Linux Conference,
Memory Technology Devices: what's new, which mentioned "ONFI for
SPI-NANDs? Maybe, maybe not".
So earlier this year, I proposed a bold idea, CASN page (Common Attributes
for SPI-NAND). I worked together with top 3 SPI-NAND market share flash
vendors and other vendors to integrate CASN page on their SPI-NAND devices
including but not limited to:
[ESMT]
F50L1G41LB
F50L2G41KA
[Etron]
EM73C044VCF-H
EM73D044VCO-H
EM73E044VCE-H
EM73F044VCA-H
[GigaDevice]
GD5F1GM7UE
GD5F1GQ5UEYIG
GD5F2GM7UE
GD5F2GQ5UEYIG
GD5F4GM8UE
GD5F4GQ6UEYIG
[Macronix (MXIC)]
MX35LF1GE4ABZ4IG
[Winbond]
W25N01GV
W25N01KV
W25N02KV
W25N04KV
A document of CASN is hosted on github(https://github.com/mtk-openwrt/
doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep it
simple here.
With CASN page, we don't need to maintain SPI-NAND flash ID table anymore.
Currently, it's integrated in 3.3V SPI-NANDs of small density and it's not
JEDEC standard yet. But it should be able to handle 1.8V and can be easily
integrated by flash vendors.
I believe this idea and implementation have room for improvement. Hope to
hear you open source community's comments soon.
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
Sky Huang (4):
mtd: nand: Create param.c to do CRC check and bitwise majority for
Parameter & CASN page
include: mtd: Add CASN page definition and related structs.
include: mtd: spinand: Add CASN page related macros and flags.
mtd: nand: spi: Add CASN page support
drivers/mtd/nand/Makefile | 2 +-
drivers/mtd/nand/param.c | 52 +++
drivers/mtd/nand/raw/nand_onfi.c | 43 +-
drivers/mtd/nand/spi/core.c | 741 ++++++++++++++++++++++++++++++-
include/linux/mtd/casn.h | 191 ++++++++
include/linux/mtd/param.h | 20 +
include/linux/mtd/spinand.h | 100 ++++-
7 files changed, 1094 insertions(+), 55 deletions(-)
create mode 100644 drivers/mtd/nand/param.c
create mode 100644 include/linux/mtd/casn.h
create mode 100644 include/linux/mtd/param.h
--
2.45.2
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-10-20 13:27 ` Sky Huang
0 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router platforms
chips, we have to quality lots of SPI-NAND devices and are eager for
a standard so that we don't need to maintain trivial flash ID table
anymore. I also noticed a talk in 2019 Embedded Linux Conference,
Memory Technology Devices: what's new, which mentioned "ONFI for
SPI-NANDs? Maybe, maybe not".
So earlier this year, I proposed a bold idea, CASN page (Common Attributes
for SPI-NAND). I worked together with top 3 SPI-NAND market share flash
vendors and other vendors to integrate CASN page on their SPI-NAND devices
including but not limited to:
[ESMT]
F50L1G41LB
F50L2G41KA
[Etron]
EM73C044VCF-H
EM73D044VCO-H
EM73E044VCE-H
EM73F044VCA-H
[GigaDevice]
GD5F1GM7UE
GD5F1GQ5UEYIG
GD5F2GM7UE
GD5F2GQ5UEYIG
GD5F4GM8UE
GD5F4GQ6UEYIG
[Macronix (MXIC)]
MX35LF1GE4ABZ4IG
[Winbond]
W25N01GV
W25N01KV
W25N02KV
W25N04KV
A document of CASN is hosted on github(https://github.com/mtk-openwrt/
doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep it
simple here.
With CASN page, we don't need to maintain SPI-NAND flash ID table anymore.
Currently, it's integrated in 3.3V SPI-NANDs of small density and it's not
JEDEC standard yet. But it should be able to handle 1.8V and can be easily
integrated by flash vendors.
I believe this idea and implementation have room for improvement. Hope to
hear you open source community's comments soon.
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
Sky Huang (4):
mtd: nand: Create param.c to do CRC check and bitwise majority for
Parameter & CASN page
include: mtd: Add CASN page definition and related structs.
include: mtd: spinand: Add CASN page related macros and flags.
mtd: nand: spi: Add CASN page support
drivers/mtd/nand/Makefile | 2 +-
drivers/mtd/nand/param.c | 52 +++
drivers/mtd/nand/raw/nand_onfi.c | 43 +-
drivers/mtd/nand/spi/core.c | 741 ++++++++++++++++++++++++++++++-
include/linux/mtd/casn.h | 191 ++++++++
include/linux/mtd/param.h | 20 +
include/linux/mtd/spinand.h | 100 ++++-
7 files changed, 1094 insertions(+), 55 deletions(-)
create mode 100644 drivers/mtd/nand/param.c
create mode 100644 include/linux/mtd/casn.h
create mode 100644 include/linux/mtd/param.h
--
2.45.2
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page
2024-10-20 13:27 ` Sky Huang
@ 2024-10-20 13:27 ` Sky Huang
-1 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky.Huang
From: "Sky.Huang" <skylake.huang@mediatek.com>
Create drivers/mtd/nand/param.c so ONFI parameter page & CASN page
can both use nanddev_crc16() and nanddev_bit_wise_majority() directly
like this:
* For ONFI Parameter page:
onfi_crc16() -> nanddev_crc16()
* For CASN page: nanddev_crc16()
nanddev_bit_wise_majority() is same as nand_bit_wise_majority().
nanddev_crc16() is same as onfi_crc16(). But there are lots of
onfi_crc16() call, so keep onfi_crc16() there and hook it to
nanddev_crc16().
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
drivers/mtd/nand/Makefile | 2 +-
drivers/mtd/nand/param.c | 52 ++++++++++++++++++++++++++++++++
drivers/mtd/nand/raw/nand_onfi.c | 43 ++------------------------
include/linux/mtd/param.h | 20 ++++++++++++
4 files changed, 76 insertions(+), 41 deletions(-)
create mode 100644 drivers/mtd/nand/param.c
create mode 100644 include/linux/mtd/param.h
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 19e1291ac4d5..790bde0148d1 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-nandcore-objs := core.o bbt.o
+nandcore-objs := core.o bbt.o param.o
obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o
diff --git a/drivers/mtd/nand/param.c b/drivers/mtd/nand/param.c
new file mode 100644
index 000000000000..f67b9fe633d9
--- /dev/null
+++ b/drivers/mtd/nand/param.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 - Mediatek
+ *
+ * Author: Sky Huang <SkyLake.Huang@mediatek.com>
+ */
+
+#include <linux/mtd/param.h>
+
+u16 nanddev_crc16(u16 crc, u8 const *p, size_t len)
+{
+ int i;
+
+ while (len--) {
+ crc ^= *p++ << 8;
+ for (i = 0; i < 8; i++)
+ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+ }
+
+ return crc;
+}
+
+/*
+ * Recover data with bit-wise majority
+ */
+void nanddev_bit_wise_majority(const void **srcbufs,
+ unsigned int nsrcbufs,
+ void *dstbuf,
+ unsigned int bufsize)
+{
+ int i, j, k;
+
+ for (i = 0; i < bufsize; i++) {
+ u8 val = 0;
+
+ for (j = 0; j < 8; j++) {
+ unsigned int cnt = 0;
+
+ for (k = 0; k < nsrcbufs; k++) {
+ const u8 *srcbuf = srcbufs[k];
+
+ if (srcbuf[i] & BIT(j))
+ cnt++;
+ }
+
+ if (cnt > nsrcbufs / 2)
+ val |= BIT(j);
+ }
+
+ ((u8 *)dstbuf)[i] = val;
+ }
+}
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
index 861975e44b55..5d330dd53e8f 100644
--- a/drivers/mtd/nand/raw/nand_onfi.c
+++ b/drivers/mtd/nand/raw/nand_onfi.c
@@ -12,6 +12,7 @@
* This file contains all ONFI helpers.
*/
+#include <linux/mtd/param.h>
#include <linux/slab.h>
#include "internals.h"
@@ -20,14 +21,7 @@
u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
{
- int i;
- while (len--) {
- crc ^= *p++ << 8;
- for (i = 0; i < 8; i++)
- crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
- }
-
- return crc;
+ return nanddev_crc16(crc, p, len);
}
/* Parse the Extended Parameter Page. */
@@ -107,37 +101,6 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
return ret;
}
-/*
- * Recover data with bit-wise majority
- */
-static void nand_bit_wise_majority(const void **srcbufs,
- unsigned int nsrcbufs,
- void *dstbuf,
- unsigned int bufsize)
-{
- int i, j, k;
-
- for (i = 0; i < bufsize; i++) {
- u8 val = 0;
-
- for (j = 0; j < 8; j++) {
- unsigned int cnt = 0;
-
- for (k = 0; k < nsrcbufs; k++) {
- const u8 *srcbuf = srcbufs[k];
-
- if (srcbuf[i] & BIT(j))
- cnt++;
- }
-
- if (cnt > nsrcbufs / 2)
- val |= BIT(j);
- }
-
- ((u8 *)dstbuf)[i] = val;
- }
-}
-
/*
* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
*/
@@ -200,7 +163,7 @@ int nand_onfi_detect(struct nand_chip *chip)
srcbufs[j] = pbuf + j;
pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n");
- nand_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, pbuf,
+ nanddev_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, pbuf,
sizeof(*pbuf));
crc = onfi_crc16(ONFI_CRC_BASE, (u8 *)pbuf, 254);
diff --git a/include/linux/mtd/param.h b/include/linux/mtd/param.h
new file mode 100644
index 000000000000..39636f66f1b4
--- /dev/null
+++ b/include/linux/mtd/param.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 - Mediatek
+ *
+ * Author: Sky Huang <SkyLake.Huang@mediatek.com>
+ */
+
+#ifndef __LINUX_NAND_PARAM
+#define __LINUX_NAND_PARAM
+
+#include <linux/io.h>
+
+u16 nanddev_crc16(u16 crc, u8 const *p, size_t len);
+void nanddev_bit_wise_majority(const void **srcbufs,
+ unsigned int nsrcbufs,
+ void *dstbuf,
+ unsigned int bufsize);
+
+#endif /* __LINUX_NAND_PARAM */
+
--
2.45.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page
@ 2024-10-20 13:27 ` Sky Huang
0 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky.Huang
From: "Sky.Huang" <skylake.huang@mediatek.com>
Create drivers/mtd/nand/param.c so ONFI parameter page & CASN page
can both use nanddev_crc16() and nanddev_bit_wise_majority() directly
like this:
* For ONFI Parameter page:
onfi_crc16() -> nanddev_crc16()
* For CASN page: nanddev_crc16()
nanddev_bit_wise_majority() is same as nand_bit_wise_majority().
nanddev_crc16() is same as onfi_crc16(). But there are lots of
onfi_crc16() call, so keep onfi_crc16() there and hook it to
nanddev_crc16().
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
drivers/mtd/nand/Makefile | 2 +-
drivers/mtd/nand/param.c | 52 ++++++++++++++++++++++++++++++++
drivers/mtd/nand/raw/nand_onfi.c | 43 ++------------------------
include/linux/mtd/param.h | 20 ++++++++++++
4 files changed, 76 insertions(+), 41 deletions(-)
create mode 100644 drivers/mtd/nand/param.c
create mode 100644 include/linux/mtd/param.h
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 19e1291ac4d5..790bde0148d1 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-nandcore-objs := core.o bbt.o
+nandcore-objs := core.o bbt.o param.o
obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o
diff --git a/drivers/mtd/nand/param.c b/drivers/mtd/nand/param.c
new file mode 100644
index 000000000000..f67b9fe633d9
--- /dev/null
+++ b/drivers/mtd/nand/param.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 - Mediatek
+ *
+ * Author: Sky Huang <SkyLake.Huang@mediatek.com>
+ */
+
+#include <linux/mtd/param.h>
+
+u16 nanddev_crc16(u16 crc, u8 const *p, size_t len)
+{
+ int i;
+
+ while (len--) {
+ crc ^= *p++ << 8;
+ for (i = 0; i < 8; i++)
+ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+ }
+
+ return crc;
+}
+
+/*
+ * Recover data with bit-wise majority
+ */
+void nanddev_bit_wise_majority(const void **srcbufs,
+ unsigned int nsrcbufs,
+ void *dstbuf,
+ unsigned int bufsize)
+{
+ int i, j, k;
+
+ for (i = 0; i < bufsize; i++) {
+ u8 val = 0;
+
+ for (j = 0; j < 8; j++) {
+ unsigned int cnt = 0;
+
+ for (k = 0; k < nsrcbufs; k++) {
+ const u8 *srcbuf = srcbufs[k];
+
+ if (srcbuf[i] & BIT(j))
+ cnt++;
+ }
+
+ if (cnt > nsrcbufs / 2)
+ val |= BIT(j);
+ }
+
+ ((u8 *)dstbuf)[i] = val;
+ }
+}
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
index 861975e44b55..5d330dd53e8f 100644
--- a/drivers/mtd/nand/raw/nand_onfi.c
+++ b/drivers/mtd/nand/raw/nand_onfi.c
@@ -12,6 +12,7 @@
* This file contains all ONFI helpers.
*/
+#include <linux/mtd/param.h>
#include <linux/slab.h>
#include "internals.h"
@@ -20,14 +21,7 @@
u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
{
- int i;
- while (len--) {
- crc ^= *p++ << 8;
- for (i = 0; i < 8; i++)
- crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
- }
-
- return crc;
+ return nanddev_crc16(crc, p, len);
}
/* Parse the Extended Parameter Page. */
@@ -107,37 +101,6 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
return ret;
}
-/*
- * Recover data with bit-wise majority
- */
-static void nand_bit_wise_majority(const void **srcbufs,
- unsigned int nsrcbufs,
- void *dstbuf,
- unsigned int bufsize)
-{
- int i, j, k;
-
- for (i = 0; i < bufsize; i++) {
- u8 val = 0;
-
- for (j = 0; j < 8; j++) {
- unsigned int cnt = 0;
-
- for (k = 0; k < nsrcbufs; k++) {
- const u8 *srcbuf = srcbufs[k];
-
- if (srcbuf[i] & BIT(j))
- cnt++;
- }
-
- if (cnt > nsrcbufs / 2)
- val |= BIT(j);
- }
-
- ((u8 *)dstbuf)[i] = val;
- }
-}
-
/*
* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
*/
@@ -200,7 +163,7 @@ int nand_onfi_detect(struct nand_chip *chip)
srcbufs[j] = pbuf + j;
pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n");
- nand_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, pbuf,
+ nanddev_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, pbuf,
sizeof(*pbuf));
crc = onfi_crc16(ONFI_CRC_BASE, (u8 *)pbuf, 254);
diff --git a/include/linux/mtd/param.h b/include/linux/mtd/param.h
new file mode 100644
index 000000000000..39636f66f1b4
--- /dev/null
+++ b/include/linux/mtd/param.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 - Mediatek
+ *
+ * Author: Sky Huang <SkyLake.Huang@mediatek.com>
+ */
+
+#ifndef __LINUX_NAND_PARAM
+#define __LINUX_NAND_PARAM
+
+#include <linux/io.h>
+
+u16 nanddev_crc16(u16 crc, u8 const *p, size_t len);
+void nanddev_bit_wise_majority(const void **srcbufs,
+ unsigned int nsrcbufs,
+ void *dstbuf,
+ unsigned int bufsize);
+
+#endif /* __LINUX_NAND_PARAM */
+
--
2.45.2
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 2/4] include: mtd: Add CASN page definition and related structs.
2024-10-20 13:27 ` Sky Huang
@ 2024-10-20 13:27 ` Sky Huang
-1 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
This patch adds CASN page definition. You can see corresponding
table in CASN page application note referred in cover letter.
(https://github.com/mtk-openwrt/doc/blob/
main/CASN%20Page%20Introduction.pdf)
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
include/linux/mtd/casn.h | 191 +++++++++++++++++++++++++++++++++++++++
1 file changed, 191 insertions(+)
create mode 100644 include/linux/mtd/casn.h
diff --git a/include/linux/mtd/casn.h b/include/linux/mtd/casn.h
new file mode 100644
index 000000000000..65ebd23c17c1
--- /dev/null
+++ b/include/linux/mtd/casn.h
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 - Mediatek
+ *
+ * Author: Sky Huang <SkyLake.Huang@mediatek.com>
+ */
+
+#ifndef __LINUX_MTD_CASN_H
+#define __LINUX_MTD_CASN_H
+
+#define CASN_CRC_BASE 0x4341
+#define CASN_SIGNATURE 0x4341534EU
+#define SPINAND_CASN_V1_CRC_OFS (254)
+#define CASN_PAGE_V1_COPIES (3)
+
+#define SDR_READ_1_1_1 BIT(0)
+#define SDR_READ_1_1_1_FAST BIT(1)
+#define SDR_READ_1_1_2 BIT(2)
+#define SDR_READ_1_2_2 BIT(3)
+#define SDR_READ_1_1_4 BIT(4)
+#define SDR_READ_1_4_4 BIT(5)
+#define SDR_READ_1_1_8 BIT(6)
+#define SDR_READ_1_8_8 BIT(7)
+
+#define SDR_WRITE_1_1_1 BIT(0)
+#define SDR_WRITE_1_1_4 BIT(1)
+
+#define SDR_UPDATE_1_1_1 BIT(0)
+#define SDR_UPDATE_1_1_4 BIT(1)
+
+struct op_slice {
+ u8 cmd_opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 dummy_nbytes : 4;
+ u8 addr_nbytes : 4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ u8 addr_nbytes : 4;
+ u8 dummy_nbytes : 4;
+#endif
+};
+
+struct SPINAND_FLAGS {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 has_qe_bit : 1;
+ u8 has_cr_feat_bit : 1;
+ u8 conti_read_cap : 1;
+ u8 on_die_ecc : 1;
+ u8 legacy_ecc_status : 1;
+ u8 adv_ecc_status : 1;
+ u8 ecc_parity_readable : 1;
+ u8 ecc_alg : 1; /* ECC algorithm */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ u8 ecc_alg : 1; /* ECC algorithm */
+ u8 ecc_parity_readable : 1;
+ u8 adv_ecc_status : 1;
+ u8 legacy_ecc_status : 1;
+ u8 on_die_ecc : 1;
+ u8 conti_read_cap : 1;
+ u8 has_cr_feat_bit : 1;
+ u8 has_qe_bit : 1;
+#endif
+};
+
+struct ADV_ECC_STATUS {
+ u8 cmd;
+ u8 addr;
+ u8 addr_nbytes;
+ u8 addr_buswidth;
+ u8 dummy_nbytes;
+ u8 dummy_buswidth;
+ u8 status_nbytes;
+ u16 status_mask;
+ u8 pre_op; /* pre-process operator */
+ u8 pre_mask; /* pre-process mask */
+} __packed;
+
+struct CASN_OOB {
+ u8 layout_type;
+
+ /* OOB free layout */
+ u8 free_start;
+ u8 free_length;
+ u8 bbm_length;
+
+ /* ECC parity layout */
+ u8 ecc_parity_start;
+ u8 ecc_parity_space;
+ u8 ecc_parity_real_length;
+};
+
+enum oob_overall {
+ OOB_DISCRETE = 0,
+ OOB_CONTINUOUS,
+};
+
+struct nand_casn {
+ /* CASN signature must be 4 chars: 'C','A','S','N' */
+ union {
+ u8 sig[4];
+ u32 signature;
+ };
+
+ u8 version;
+ char manufacturer[13];
+ char model[16];
+
+ __be32 bits_per_cell;
+ __be32 bytes_per_page;
+ __be32 spare_bytes_per_page;
+ __be32 pages_per_block;
+ __be32 blocks_per_lun;
+ __be32 max_bb_per_lun;
+ __be32 planes_per_lun;
+ __be32 luns_per_target;
+ __be32 total_target;
+
+ __be32 ecc_strength;
+ __be32 ecc_step_size;
+
+ u8 flags;
+ u8 reserved1;
+
+ __be16 sdr_read_cap;
+ struct op_slice sdr_read_1_1_1;
+ struct op_slice sdr_read_1_1_1_fast;
+ struct op_slice sdr_read_1_1_2;
+ struct op_slice sdr_read_1_2_2;
+ struct op_slice sdr_read_1_1_4;
+ struct op_slice sdr_read_1_4_4;
+ struct op_slice sdr_read_1_1_8;
+ struct op_slice sdr_read_1_8_8;
+
+ struct op_slice sdr_cont_read_1_1_1;
+ struct op_slice sdr_cont_read_1_1_1_fast;
+ struct op_slice sdr_cont_read_1_1_2;
+ struct op_slice sdr_cont_read_1_2_2;
+ struct op_slice sdr_cont_read_1_1_4;
+ struct op_slice sdr_cont_read_1_4_4;
+ struct op_slice sdr_cont_read_1_1_8;
+ struct op_slice sdr_cont_read_1_8_8;
+
+ __be16 ddr_read_cap;
+ struct op_slice ddr_read_1_1_1;
+ struct op_slice ddr_read_1_1_1_fast;
+ struct op_slice ddr_read_1_1_2;
+ struct op_slice ddr_read_1_2_2;
+ struct op_slice ddr_read_1_1_4;
+ struct op_slice ddr_read_1_4_4;
+ struct op_slice ddr_read_1_1_8;
+ struct op_slice ddr_read_1_8_8;
+
+ struct op_slice ddr_cont_read_1_1_1;
+ struct op_slice ddr_cont_read_1_1_1_fast;
+ struct op_slice ddr_cont_read_1_1_2;
+ struct op_slice ddr_cont_read_1_2_2;
+ struct op_slice ddr_cont_read_1_1_4;
+ struct op_slice ddr_cont_read_1_4_4;
+ struct op_slice ddr_cont_read_1_1_8;
+ struct op_slice ddr_cont_read_1_8_8;
+
+ u8 sdr_write_cap;
+ struct op_slice sdr_write_1_1_1;
+ struct op_slice sdr_write_1_1_4;
+ struct op_slice reserved2[6];
+ u8 ddr_write_cap;
+ struct op_slice reserved3[8];
+
+ u8 sdr_update_cap;
+ struct op_slice sdr_update_1_1_1;
+ struct op_slice sdr_update_1_1_4;
+ struct op_slice reserved4[6];
+ u8 ddr_update_cap;
+ struct op_slice reserved5[8];
+
+ struct CASN_OOB casn_oob;
+
+ /* Advanced ECC status CMD0 (higher bits) */
+ struct ADV_ECC_STATUS ecc_status_high;
+ /* Advanced ECC status CMD1 (lower bits) */
+ struct ADV_ECC_STATUS ecc_status_low;
+
+ u8 advecc_noerr_status;
+ u8 advecc_uncor_status;
+ u8 advecc_post_op;
+ u8 advecc_post_mask;
+
+ u8 reserved6[5];
+ __be16 crc;
+} __packed;
+
+#endif /* __LINUX_MTD_CASN_H */
--
2.45.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 2/4] include: mtd: Add CASN page definition and related structs.
@ 2024-10-20 13:27 ` Sky Huang
0 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
This patch adds CASN page definition. You can see corresponding
table in CASN page application note referred in cover letter.
(https://github.com/mtk-openwrt/doc/blob/
main/CASN%20Page%20Introduction.pdf)
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
include/linux/mtd/casn.h | 191 +++++++++++++++++++++++++++++++++++++++
1 file changed, 191 insertions(+)
create mode 100644 include/linux/mtd/casn.h
diff --git a/include/linux/mtd/casn.h b/include/linux/mtd/casn.h
new file mode 100644
index 000000000000..65ebd23c17c1
--- /dev/null
+++ b/include/linux/mtd/casn.h
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 - Mediatek
+ *
+ * Author: Sky Huang <SkyLake.Huang@mediatek.com>
+ */
+
+#ifndef __LINUX_MTD_CASN_H
+#define __LINUX_MTD_CASN_H
+
+#define CASN_CRC_BASE 0x4341
+#define CASN_SIGNATURE 0x4341534EU
+#define SPINAND_CASN_V1_CRC_OFS (254)
+#define CASN_PAGE_V1_COPIES (3)
+
+#define SDR_READ_1_1_1 BIT(0)
+#define SDR_READ_1_1_1_FAST BIT(1)
+#define SDR_READ_1_1_2 BIT(2)
+#define SDR_READ_1_2_2 BIT(3)
+#define SDR_READ_1_1_4 BIT(4)
+#define SDR_READ_1_4_4 BIT(5)
+#define SDR_READ_1_1_8 BIT(6)
+#define SDR_READ_1_8_8 BIT(7)
+
+#define SDR_WRITE_1_1_1 BIT(0)
+#define SDR_WRITE_1_1_4 BIT(1)
+
+#define SDR_UPDATE_1_1_1 BIT(0)
+#define SDR_UPDATE_1_1_4 BIT(1)
+
+struct op_slice {
+ u8 cmd_opcode;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 dummy_nbytes : 4;
+ u8 addr_nbytes : 4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ u8 addr_nbytes : 4;
+ u8 dummy_nbytes : 4;
+#endif
+};
+
+struct SPINAND_FLAGS {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 has_qe_bit : 1;
+ u8 has_cr_feat_bit : 1;
+ u8 conti_read_cap : 1;
+ u8 on_die_ecc : 1;
+ u8 legacy_ecc_status : 1;
+ u8 adv_ecc_status : 1;
+ u8 ecc_parity_readable : 1;
+ u8 ecc_alg : 1; /* ECC algorithm */
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ u8 ecc_alg : 1; /* ECC algorithm */
+ u8 ecc_parity_readable : 1;
+ u8 adv_ecc_status : 1;
+ u8 legacy_ecc_status : 1;
+ u8 on_die_ecc : 1;
+ u8 conti_read_cap : 1;
+ u8 has_cr_feat_bit : 1;
+ u8 has_qe_bit : 1;
+#endif
+};
+
+struct ADV_ECC_STATUS {
+ u8 cmd;
+ u8 addr;
+ u8 addr_nbytes;
+ u8 addr_buswidth;
+ u8 dummy_nbytes;
+ u8 dummy_buswidth;
+ u8 status_nbytes;
+ u16 status_mask;
+ u8 pre_op; /* pre-process operator */
+ u8 pre_mask; /* pre-process mask */
+} __packed;
+
+struct CASN_OOB {
+ u8 layout_type;
+
+ /* OOB free layout */
+ u8 free_start;
+ u8 free_length;
+ u8 bbm_length;
+
+ /* ECC parity layout */
+ u8 ecc_parity_start;
+ u8 ecc_parity_space;
+ u8 ecc_parity_real_length;
+};
+
+enum oob_overall {
+ OOB_DISCRETE = 0,
+ OOB_CONTINUOUS,
+};
+
+struct nand_casn {
+ /* CASN signature must be 4 chars: 'C','A','S','N' */
+ union {
+ u8 sig[4];
+ u32 signature;
+ };
+
+ u8 version;
+ char manufacturer[13];
+ char model[16];
+
+ __be32 bits_per_cell;
+ __be32 bytes_per_page;
+ __be32 spare_bytes_per_page;
+ __be32 pages_per_block;
+ __be32 blocks_per_lun;
+ __be32 max_bb_per_lun;
+ __be32 planes_per_lun;
+ __be32 luns_per_target;
+ __be32 total_target;
+
+ __be32 ecc_strength;
+ __be32 ecc_step_size;
+
+ u8 flags;
+ u8 reserved1;
+
+ __be16 sdr_read_cap;
+ struct op_slice sdr_read_1_1_1;
+ struct op_slice sdr_read_1_1_1_fast;
+ struct op_slice sdr_read_1_1_2;
+ struct op_slice sdr_read_1_2_2;
+ struct op_slice sdr_read_1_1_4;
+ struct op_slice sdr_read_1_4_4;
+ struct op_slice sdr_read_1_1_8;
+ struct op_slice sdr_read_1_8_8;
+
+ struct op_slice sdr_cont_read_1_1_1;
+ struct op_slice sdr_cont_read_1_1_1_fast;
+ struct op_slice sdr_cont_read_1_1_2;
+ struct op_slice sdr_cont_read_1_2_2;
+ struct op_slice sdr_cont_read_1_1_4;
+ struct op_slice sdr_cont_read_1_4_4;
+ struct op_slice sdr_cont_read_1_1_8;
+ struct op_slice sdr_cont_read_1_8_8;
+
+ __be16 ddr_read_cap;
+ struct op_slice ddr_read_1_1_1;
+ struct op_slice ddr_read_1_1_1_fast;
+ struct op_slice ddr_read_1_1_2;
+ struct op_slice ddr_read_1_2_2;
+ struct op_slice ddr_read_1_1_4;
+ struct op_slice ddr_read_1_4_4;
+ struct op_slice ddr_read_1_1_8;
+ struct op_slice ddr_read_1_8_8;
+
+ struct op_slice ddr_cont_read_1_1_1;
+ struct op_slice ddr_cont_read_1_1_1_fast;
+ struct op_slice ddr_cont_read_1_1_2;
+ struct op_slice ddr_cont_read_1_2_2;
+ struct op_slice ddr_cont_read_1_1_4;
+ struct op_slice ddr_cont_read_1_4_4;
+ struct op_slice ddr_cont_read_1_1_8;
+ struct op_slice ddr_cont_read_1_8_8;
+
+ u8 sdr_write_cap;
+ struct op_slice sdr_write_1_1_1;
+ struct op_slice sdr_write_1_1_4;
+ struct op_slice reserved2[6];
+ u8 ddr_write_cap;
+ struct op_slice reserved3[8];
+
+ u8 sdr_update_cap;
+ struct op_slice sdr_update_1_1_1;
+ struct op_slice sdr_update_1_1_4;
+ struct op_slice reserved4[6];
+ u8 ddr_update_cap;
+ struct op_slice reserved5[8];
+
+ struct CASN_OOB casn_oob;
+
+ /* Advanced ECC status CMD0 (higher bits) */
+ struct ADV_ECC_STATUS ecc_status_high;
+ /* Advanced ECC status CMD1 (lower bits) */
+ struct ADV_ECC_STATUS ecc_status_low;
+
+ u8 advecc_noerr_status;
+ u8 advecc_uncor_status;
+ u8 advecc_post_op;
+ u8 advecc_post_mask;
+
+ u8 reserved6[5];
+ __be16 crc;
+} __packed;
+
+#endif /* __LINUX_MTD_CASN_H */
--
2.45.2
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
2024-10-20 13:27 ` Sky Huang
@ 2024-10-20 13:27 ` Sky Huang
-1 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
This patch adds SPINAND CASN page manipulation macros for
SPI-NAND driver to use. Also, some important flag bits, like
SPINAND_SUPR_CR(continuous read), are added to show the
SPI-NAND device's capability.
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
include/linux/mtd/spinand.h | 100 +++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 2 deletions(-)
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 702e5fb13dae..de97994c357b 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -62,6 +62,59 @@
SPI_MEM_OP_NO_DUMMY, \
SPI_MEM_OP_NO_DATA)
+/* Macros for CASN */
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(fast, naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 1))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X2_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_DUALIO_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 2), \
+ SPI_MEM_OP_DUMMY(ndummy, 2), \
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X4_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_QUADIO_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 4), \
+ SPI_MEM_OP_DUMMY(ndummy, 4), \
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
+
+#define SPINAND_CASN_PROG_LOAD(reset, naddr, addr, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_DATA_OUT(len, buf, 1))
+
+#define SPINAND_CASN_PROG_LOAD_X4(reset, naddr, addr, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x32 : 0x34, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_DATA_OUT(len, buf, 4))
+
+#define SPINAND_CASN_ADVECC_OP(casn_adv_ecc_status, buf) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(casn_adv_ecc_status.cmd, 1), \
+ SPI_MEM_OP_ADDR(casn_adv_ecc_status.addr_nbytes, \
+ casn_adv_ecc_status.addr, \
+ casn_adv_ecc_status.addr_buswidth), \
+ SPI_MEM_OP_DUMMY(casn_adv_ecc_status.dummy_nbytes, \
+ casn_adv_ecc_status.dummy_buswidth), \
+ SPI_MEM_OP_DATA_IN(casn_adv_ecc_status.status_nbytes, buf, 1))
+/* Macros for CASN end */
+
#define SPINAND_PAGE_READ_FROM_CACHE_OP(fast, addr, ndummy, buf, len) \
SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
SPI_MEM_OP_ADDR(2, addr, 1), \
@@ -312,8 +365,11 @@ struct spinand_ecc_info {
#define SPINAND_HAS_QE_BIT BIT(0)
#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_SUP_CR BIT(2)
+#define SPINAND_SUP_ON_DIE_ECC BIT(3)
+#define SPINAND_SUP_LEGACY_ECC_STATUS BIT(4)
+#define SPINAND_SUP_ADV_ECC_STATUS BIT(5)
+#define SPINAND_ECC_PARITY_READABLE BIT(6)
/**
* struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
@@ -406,6 +462,28 @@ struct spinand_dirmap {
struct spi_mem_dirmap_desc *rdesc_ecc;
};
+/**
+ * struct CASN_ADVECC - CASN's advanced ECC description
+ * @cmd: Command to access SPI-NAND on-chip ECC status registers
+ * @mask: Mask to access SPI-NAND on-chip ECC status registers.
+ * ADV_ECC_STATUS->status_nbytes | CASN_ADVECC->mask
+ * 1 | 0 to 0xff
+ * 2 | 0 to 0xffff
+ * @shift: How many bits to shift to get on-chip ECC status
+ * @pre_op: This comes from CASN page's ADV_ECC_STATUS's pre_op.
+ * After reading on-chip ECC status, we need to do some math
+ * operations if this is specified.
+ * @pre_mask: This comes from CASN page's ADV_ECC_STATUS's pre_mask.
+ * This is used in companion with pre_op above.
+ */
+struct CASN_ADVECC {
+ u8 cmd;
+ u16 mask;
+ u8 shift;
+ u8 pre_op;
+ u8 pre_mask;
+};
+
/**
* struct spinand_device - SPI NAND device instance
* @base: NAND device instance
@@ -464,6 +542,23 @@ struct spinand_device {
u8 *oobbuf;
u8 *scratchbuf;
const struct spinand_manufacturer *manufacturer;
+
+ bool use_casn;
+ struct nand_casn *casn;
+ struct spi_mem_op *advecc_high_ops; /* ops to read higher part of advanced ECC status*/
+ struct spi_mem_op *advecc_low_ops;
+ struct CASN_OOB *casn_oob;
+ struct CASN_ADVECC *advecc_high;
+ struct CASN_ADVECC *advecc_low;
+
+ u8 advecc_low_bitcnt;
+ u8 advecc_noerr_status;
+ u8 advecc_uncor_status;
+ u8 advecc_post_op;
+ u8 advecc_post_mask;
+
+ size_t (*eccsr_math_op[4])(size_t, size_t);
+
void *priv;
bool cont_read_possible;
@@ -539,3 +634,4 @@ int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val);
int spinand_select_target(struct spinand_device *spinand, unsigned int target);
#endif /* __LINUX_MTD_SPINAND_H */
+
--
2.45.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
@ 2024-10-20 13:27 ` Sky Huang
0 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
This patch adds SPINAND CASN page manipulation macros for
SPI-NAND driver to use. Also, some important flag bits, like
SPINAND_SUPR_CR(continuous read), are added to show the
SPI-NAND device's capability.
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
include/linux/mtd/spinand.h | 100 +++++++++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 2 deletions(-)
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 702e5fb13dae..de97994c357b 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -62,6 +62,59 @@
SPI_MEM_OP_NO_DUMMY, \
SPI_MEM_OP_NO_DATA)
+/* Macros for CASN */
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(fast, naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 1))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X2_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_DUALIO_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 2), \
+ SPI_MEM_OP_DUMMY(ndummy, 2), \
+ SPI_MEM_OP_DATA_IN(len, buf, 2))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X4_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_DUMMY(ndummy, 1), \
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
+
+#define SPINAND_CASN_PAGE_READ_FROM_CACHE_QUADIO_OP(naddr, addr, ndummy, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 4), \
+ SPI_MEM_OP_DUMMY(ndummy, 4), \
+ SPI_MEM_OP_DATA_IN(len, buf, 4))
+
+#define SPINAND_CASN_PROG_LOAD(reset, naddr, addr, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_DATA_OUT(len, buf, 1))
+
+#define SPINAND_CASN_PROG_LOAD_X4(reset, naddr, addr, buf, len) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x32 : 0x34, 1), \
+ SPI_MEM_OP_ADDR(naddr, addr, 1), \
+ SPI_MEM_OP_NO_DUMMY, \
+ SPI_MEM_OP_DATA_OUT(len, buf, 4))
+
+#define SPINAND_CASN_ADVECC_OP(casn_adv_ecc_status, buf) \
+ SPI_MEM_OP(SPI_MEM_OP_CMD(casn_adv_ecc_status.cmd, 1), \
+ SPI_MEM_OP_ADDR(casn_adv_ecc_status.addr_nbytes, \
+ casn_adv_ecc_status.addr, \
+ casn_adv_ecc_status.addr_buswidth), \
+ SPI_MEM_OP_DUMMY(casn_adv_ecc_status.dummy_nbytes, \
+ casn_adv_ecc_status.dummy_buswidth), \
+ SPI_MEM_OP_DATA_IN(casn_adv_ecc_status.status_nbytes, buf, 1))
+/* Macros for CASN end */
+
#define SPINAND_PAGE_READ_FROM_CACHE_OP(fast, addr, ndummy, buf, len) \
SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
SPI_MEM_OP_ADDR(2, addr, 1), \
@@ -312,8 +365,11 @@ struct spinand_ecc_info {
#define SPINAND_HAS_QE_BIT BIT(0)
#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_SUP_CR BIT(2)
+#define SPINAND_SUP_ON_DIE_ECC BIT(3)
+#define SPINAND_SUP_LEGACY_ECC_STATUS BIT(4)
+#define SPINAND_SUP_ADV_ECC_STATUS BIT(5)
+#define SPINAND_ECC_PARITY_READABLE BIT(6)
/**
* struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
@@ -406,6 +462,28 @@ struct spinand_dirmap {
struct spi_mem_dirmap_desc *rdesc_ecc;
};
+/**
+ * struct CASN_ADVECC - CASN's advanced ECC description
+ * @cmd: Command to access SPI-NAND on-chip ECC status registers
+ * @mask: Mask to access SPI-NAND on-chip ECC status registers.
+ * ADV_ECC_STATUS->status_nbytes | CASN_ADVECC->mask
+ * 1 | 0 to 0xff
+ * 2 | 0 to 0xffff
+ * @shift: How many bits to shift to get on-chip ECC status
+ * @pre_op: This comes from CASN page's ADV_ECC_STATUS's pre_op.
+ * After reading on-chip ECC status, we need to do some math
+ * operations if this is specified.
+ * @pre_mask: This comes from CASN page's ADV_ECC_STATUS's pre_mask.
+ * This is used in companion with pre_op above.
+ */
+struct CASN_ADVECC {
+ u8 cmd;
+ u16 mask;
+ u8 shift;
+ u8 pre_op;
+ u8 pre_mask;
+};
+
/**
* struct spinand_device - SPI NAND device instance
* @base: NAND device instance
@@ -464,6 +542,23 @@ struct spinand_device {
u8 *oobbuf;
u8 *scratchbuf;
const struct spinand_manufacturer *manufacturer;
+
+ bool use_casn;
+ struct nand_casn *casn;
+ struct spi_mem_op *advecc_high_ops; /* ops to read higher part of advanced ECC status*/
+ struct spi_mem_op *advecc_low_ops;
+ struct CASN_OOB *casn_oob;
+ struct CASN_ADVECC *advecc_high;
+ struct CASN_ADVECC *advecc_low;
+
+ u8 advecc_low_bitcnt;
+ u8 advecc_noerr_status;
+ u8 advecc_uncor_status;
+ u8 advecc_post_op;
+ u8 advecc_post_mask;
+
+ size_t (*eccsr_math_op[4])(size_t, size_t);
+
void *priv;
bool cont_read_possible;
@@ -539,3 +634,4 @@ int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val);
int spinand_select_target(struct spinand_device *spinand, unsigned int target);
#endif /* __LINUX_MTD_SPINAND_H */
+
--
2.45.2
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 4/4] mtd: nand: spi: Add CASN page support
2024-10-20 13:27 ` Sky Huang
@ 2024-10-20 13:27 ` Sky Huang
-1 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
This patch implements how CASN page detection works for
SPI-NAND and how CASN page interprets ECC information
of all SPI-NAND flash vendors.
Probe flow will become like this:
* If CASN page exists, check its validity.
--> If a certain CASN page is valid, we will know the SPI-NAND
device's information, including memory organization, flash
on-chip ECC engine's design, etc.
* If CASN page doesn't exist, switch to reading ID
spinand_dump_casn() can be moved to sysfs, debugfs or something
else later, I guess.
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
drivers/mtd/nand/spi/core.c | 741 +++++++++++++++++++++++++++++++++++-
1 file changed, 729 insertions(+), 12 deletions(-)
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 4d76f9f71a0e..7d7408e00b5e 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -9,10 +9,13 @@
#define pr_fmt(fmt) "spi-nand: " fmt
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mtd/casn.h>
+#include <linux/mtd/param.h>
#include <linux/mtd/spinand.h>
#include <linux/of.h>
#include <linux/slab.h>
@@ -20,6 +23,8 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
+extern void sanitize_string(uint8_t *s, size_t len);
+
static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
{
struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
@@ -200,6 +205,63 @@ static int spinand_ecc_enable(struct spinand_device *spinand,
enable ? CFG_ECC_ENABLE : 0);
}
+static size_t eccsr_none_op(size_t val, size_t mask) { return val; }
+static size_t eccsr_and_op(size_t val, size_t mask) { return val & mask; }
+static size_t eccsr_add_op(size_t val, size_t mask) { return val + mask; }
+static size_t eccsr_minus_op(size_t val, size_t mask) { return val - mask; }
+static size_t eccsr_mul_op(size_t val, size_t mask) { return val * mask; }
+
+static void spinand_read_adv_ecc(struct spinand_device *spinand,
+ struct spi_mem_op *ops, u16 *eccsr,
+ u16 mask, u8 shift,
+ u8 pre_op, u8 pre_mask)
+{
+ u8 *p = spinand->scratchbuf;
+
+ spi_mem_exec_op(spinand->spimem, ops);
+
+ if (likely(mask <= 0xff))
+ *eccsr += (*p & mask) >> shift;
+ else
+ *eccsr += (((*p << 8) | (*p+1)) & mask) >> shift;
+
+ *eccsr = spinand->eccsr_math_op[pre_op](*eccsr, pre_mask);
+}
+
+static int spinand_casn_get_ecc_status(struct spinand_device *spinand,
+ u8 status)
+{
+ struct mtd_info *mtd = spinand_to_mtd(spinand);
+ struct CASN_ADVECC *ah = spinand->advecc_high;
+ struct CASN_ADVECC *al = spinand->advecc_low;
+ u16 eccsr_high = 0;
+ u16 eccsr_low = 0;
+ u32 eccsr = 0;
+
+ if (al->cmd) {
+ spinand_read_adv_ecc(spinand,
+ spinand->advecc_low_ops, &eccsr_low,
+ al->mask, al->shift,
+ al->pre_op, al->pre_mask);
+ eccsr += eccsr_low;
+ }
+ if (ah->cmd) {
+ spinand_read_adv_ecc(spinand,
+ spinand->advecc_high_ops, &eccsr_high,
+ ah->mask, ah->shift,
+ ah->pre_op, ah->pre_mask);
+ eccsr += eccsr_high << spinand->advecc_low_bitcnt;
+ }
+
+ if (eccsr == spinand->advecc_noerr_status)
+ return 0;
+ else if (eccsr == spinand->advecc_uncor_status)
+ return -EBADMSG;
+ eccsr = spinand->eccsr_math_op[spinand->advecc_post_op](eccsr, spinand->advecc_post_mask);
+
+ return eccsr > mtd->ecc_strength ? mtd->ecc_strength : eccsr;
+}
+
static int spinand_cont_read_enable(struct spinand_device *spinand,
bool enable)
{
@@ -1149,6 +1211,242 @@ static int spinand_manufacturer_match(struct spinand_device *spinand,
return -EOPNOTSUPP;
}
+static int spinand_check_casn_validity(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct device *dev = &spinand->spimem->spi->dev;
+
+ if (be32_to_cpu(casn->bits_per_cell) != 1) {
+ dev_err(dev, "[CASN] bits-per-cell must be 1\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->bytes_per_page)) {
+ case 2048:
+ case 4096:
+ break;
+ default:
+ dev_err(dev, "[CASN] page size must be 2048/4096\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->spare_bytes_per_page)) {
+ case 64:
+ case 96:
+ case 128:
+ case 256:
+ break;
+ default:
+ dev_err(dev, "[CASN] spare size must be 64/128/256\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->pages_per_block)) {
+ case 64:
+ case 128:
+ break;
+ default:
+ dev_err(dev, "[CASN] pages_per_block must be 64/128\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->blocks_per_lun)) {
+ case 1024:
+ if (be32_to_cpu(casn->max_bb_per_lun) != 20) {
+ dev_err(dev, "[CASN] max_bb_per_lun must be 20 when blocks_per_lun is 1024\n");
+ return -EINVAL;
+ }
+ break;
+ case 2048:
+ if (be32_to_cpu(casn->max_bb_per_lun) != 40) {
+ dev_err(dev, "[CASN] max_bb_per_lun must be 40 when blocks_per_lun is 2048\n");
+ return -EINVAL;
+ }
+ break;
+ case 4096:
+ if (be32_to_cpu(casn->max_bb_per_lun) != 80) {
+ dev_err(dev, "[CASN] max_bb_per_lun must be 80 when blocks_per_lun is 4096\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(dev, "[CASN] blocks_per_lun must be 1024/2048/4096\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->planes_per_lun)) {
+ case 1:
+ case 2:
+ break;
+ default:
+ dev_err(dev, "[CASN] planes_per_lun must be 1/2\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->luns_per_target)) {
+ case 1:
+ case 2:
+ break;
+ default:
+ dev_err(dev, "[CASN] luns_per_target must be 1/2\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->total_target)) {
+ case 1:
+ case 2:
+ break;
+ default:
+ dev_err(dev, "[CASN] ntargets must be 1/2\n");
+ return -EINVAL;
+ }
+
+ if (casn->casn_oob.layout_type != OOB_CONTINUOUS &&
+ casn->casn_oob.layout_type != OOB_DISCRETE) {
+ dev_err(dev, "[CASN] OOB layout type isn't correct.\n");
+ return -EINVAL;
+ }
+
+ if (casn->ecc_status_high.status_nbytes > 2 ||
+ casn->ecc_status_low.status_nbytes > 2) {
+ dev_err(dev, "[CASN] ADVECC status nbytes must be no more than 2\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int spinand_check_casn(struct spinand_device *spinand,
+ struct nand_casn *casn, unsigned int *sel)
+{
+ struct device *dev = &spinand->spimem->spi->dev;
+ uint16_t crc = be16_to_cpu(casn->crc);
+ uint16_t crc_compute;
+ int ret = 0;
+ int i;
+
+ /* There are 3 copies of CASN Pages V1. Choose one avabilable copy
+ * first. If none of the copies is available, try to recover.
+ */
+ for (i = 0; i < CASN_PAGE_V1_COPIES; i++) {
+ if (be32_to_cpu(casn[i].signature) != CASN_SIGNATURE) {
+ ret = -EINVAL;
+ continue;
+ }
+ crc_compute = nanddev_crc16(CASN_CRC_BASE, (u8 *)(casn + i),
+ SPINAND_CASN_V1_CRC_OFS);
+ dev_dbg(dev, "CASN COPY %d CRC read: 0x%x, compute: 0x%x\n",
+ i, crc, crc_compute);
+ if (crc != crc_compute) {
+ ret = -EBADMSG;
+ continue;
+ }
+ ret = spinand_check_casn_validity(spinand, casn + i);
+ if (ret < 0)
+ continue;
+ *sel = i;
+ break;
+ }
+
+ if (i == CASN_PAGE_V1_COPIES && ret == -EBADMSG) {
+ const void *srcbufs[CASN_PAGE_V1_COPIES];
+ int j;
+
+ for (j = 0; j < CASN_PAGE_V1_COPIES; j++)
+ srcbufs[j] = casn + j;
+ dev_info(dev, "Couldn't find a valid CASN page, try bitwise majority to recover it\n");
+ nanddev_bit_wise_majority(srcbufs, CASN_PAGE_V1_COPIES, casn,
+ sizeof(*casn));
+ crc_compute = nanddev_crc16(CASN_CRC_BASE, (uint8_t *)casn,
+ SPINAND_CASN_V1_CRC_OFS);
+ if (crc_compute != crc) {
+ dev_err(dev, "CASN page recovery failed, aborting\n");
+ return -EBADMSG;
+ }
+ ret = spinand_check_casn_validity(spinand, casn + i);
+ if (ret < 0)
+ return ret;
+ dev_info(dev, "CASN page recovery succeeded\n");
+ *sel = 0;
+ }
+
+ return ret;
+}
+
+static int spinand_casn_detect(struct spinand_device *spinand,
+ struct nand_casn *casn, unsigned int *sel)
+{
+ struct device *dev = &spinand->spimem->spi->dev;
+ uint8_t casn_offset[3] = {0x0, 0x1, 0x4};
+ struct nand_page_io_req req;
+ struct spi_mem_op op;
+ struct nand_pos pos;
+ int check_ret = 0;
+ uint8_t status;
+ int final_ret;
+ int ret = 0;
+ u8 cfg_reg;
+ int i;
+
+ ret = spinand_read_reg_op(spinand, REG_CFG, &cfg_reg);
+ if (ret)
+ return ret;
+
+ ret = spinand_write_reg_op(spinand, REG_CFG, cfg_reg | BIT(6));
+ if (ret)
+ return ret;
+
+ memset(&pos, 0, sizeof(pos));
+
+ req = (struct nand_page_io_req){
+ .pos = pos,
+ .dataoffs = 0,
+ .datalen = 256 * CASN_PAGE_V1_COPIES,
+ .databuf.in = (u8 *)casn,
+ .mode = MTD_OPS_AUTO_OOB,
+ };
+
+ for (i = 0; i < sizeof(casn_offset)/sizeof(uint8_t); i++) {
+ req.pos.page = casn_offset[i];
+ ret = spinand_load_page_op(spinand, &req);
+ if (ret)
+ goto finish;
+
+ ret = spinand_wait(spinand,
+ SPINAND_READ_INITIAL_DELAY_US,
+ SPINAND_READ_POLL_DELAY_US,
+ &status);
+ if (ret < 0)
+ goto finish;
+
+ op = (struct spi_mem_op) SPINAND_PAGE_READ_FROM_CACHE_OP(
+ false, 768, 1, (u8 *)casn, 256 * CASN_PAGE_V1_COPIES);
+ ret = spi_mem_exec_op(spinand->spimem, &op);
+ if (ret < 0)
+ goto finish;
+
+ check_ret = spinand_check_casn(spinand, casn, sel);
+ if (!check_ret)
+ break;
+ }
+
+finish:
+ /* We need to restore configuration register. */
+ final_ret = spinand_write_reg_op(spinand, REG_CFG, cfg_reg);
+ if (final_ret)
+ return final_ret;
+
+ if (check_ret) {
+ dev_err(dev, "CASN page check failed\n");
+ return check_ret;
+ }
+
+ if (ret)
+ dev_err(dev, "CASN page read failed\n");
+
+ return ret;
+}
+
static int spinand_id_detect(struct spinand_device *spinand)
{
u8 *id = spinand->id.data;
@@ -1180,7 +1478,7 @@ static int spinand_id_detect(struct spinand_device *spinand)
static int spinand_manufacturer_init(struct spinand_device *spinand)
{
- if (spinand->manufacturer->ops->init)
+ if (!spinand->use_casn && spinand->manufacturer->ops->init)
return spinand->manufacturer->ops->init(spinand);
return 0;
@@ -1189,7 +1487,7 @@ static int spinand_manufacturer_init(struct spinand_device *spinand)
static void spinand_manufacturer_cleanup(struct spinand_device *spinand)
{
/* Release manufacturer private data */
- if (spinand->manufacturer->ops->cleanup)
+ if (!spinand->use_casn && spinand->manufacturer->ops->cleanup)
return spinand->manufacturer->ops->cleanup(spinand);
}
@@ -1293,37 +1591,456 @@ int spinand_match_and_init(struct spinand_device *spinand,
return -ENOTSUPP;
}
+static int spinand_casn_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ struct spinand_device *spinand = mtd_to_spinand(mtd);
+ int sectionp;
+ struct CASN_OOB *co = spinand->casn_oob;
+
+ sectionp = spinand->base.memorg.pagesize/mtd->ecc_step_size;
+ if (section >= sectionp)
+ return -ERANGE;
+
+ if (co->layout_type == OOB_DISCRETE) {
+ region->offset = co->ecc_parity_start +
+ (co->free_length + co->ecc_parity_space)
+ * section;
+ } else if (co->layout_type == OOB_CONTINUOUS) {
+ region->offset = co->ecc_parity_start + co->ecc_parity_space * section;
+ }
+ region->length = co->ecc_parity_real_length;
+
+ return 0;
+}
+
+static int spinand_casn_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ struct spinand_device *spinand = mtd_to_spinand(mtd);
+ int sectionp;
+ struct CASN_OOB *co = spinand->casn_oob;
+
+ sectionp = spinand->base.memorg.pagesize/mtd->ecc_step_size;
+ if (section >= sectionp)
+ return -ERANGE;
+
+ if (!section) {
+ region->offset = co->free_start + co->bbm_length;
+ region->length = co->free_length - co->bbm_length;
+ } else {
+ if (co->layout_type == OOB_DISCRETE) {
+ region->offset = co->free_start +
+ (co->free_length +
+ co->ecc_parity_space) * section;
+ } else if (co->layout_type == OOB_CONTINUOUS) {
+ region->offset = co->free_start +
+ co->free_length * section;
+ }
+ region->length = co->free_length;
+ }
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops spinand_casn_ooblayout = {
+ .ecc = spinand_casn_ooblayout_ecc,
+ .free = spinand_casn_ooblayout_free,
+};
+
+static int spinand_set_read_op_variants(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct spinand_op_variants casn_read_cache_variants;
+ u16 sdr_read_cap = be16_to_cpu(casn->sdr_read_cap);
+ struct spi_mem_op *read_ops;
+ const struct spi_mem_op *op;
+ int i = 0;
+
+ read_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op) *
+ hweight16(sdr_read_cap),
+ GFP_KERNEL);
+ if (!read_ops)
+ return -ENOMEM;
+
+ if (FIELD_GET(SDR_READ_1_4_4, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_QUADIO_OP(
+ casn->sdr_read_1_4_4.addr_nbytes, 0,
+ casn->sdr_read_1_4_4.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_4, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_X4_OP(
+ casn->sdr_read_1_1_4.addr_nbytes, 0,
+ casn->sdr_read_1_1_4.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_2_2, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_DUALIO_OP(
+ casn->sdr_read_1_2_2.addr_nbytes, 0,
+ casn->sdr_read_1_2_2.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_2, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_X2_OP(
+ casn->sdr_read_1_1_2.addr_nbytes, 0,
+ casn->sdr_read_1_1_2.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_1_FAST, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(
+ true, casn->sdr_read_1_1_1_fast.addr_nbytes, 0,
+ casn->sdr_read_1_1_1_fast.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_1, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(
+ false, casn->sdr_read_1_1_1.addr_nbytes, 0,
+ casn->sdr_read_1_1_1.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+
+ casn_read_cache_variants = (struct spinand_op_variants){
+ .ops = read_ops,
+ .nops = hweight16(sdr_read_cap),
+ };
+
+ op = spinand_select_op_variant(spinand, &casn_read_cache_variants);
+ if (!op) {
+ devm_kfree(&spinand->spimem->spi->dev, read_ops);
+ return -EOPNOTSUPP;
+ }
+ spinand->op_templates.read_cache = op;
+
+ return 0;
+}
+
+static int spinand_set_write_op_variants(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct spinand_op_variants casn_write_cache_variants;
+ struct spi_mem_op *write_ops;
+ const struct spi_mem_op *op;
+ int i = 0;
+
+ write_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op) *
+ hweight8(casn->sdr_write_cap),
+ GFP_KERNEL);
+ if (!write_ops)
+ return -ENOMEM;
+
+ if (FIELD_GET(SDR_WRITE_1_1_4, casn->sdr_write_cap)) {
+ write_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD_X4(
+ true, casn->sdr_write_1_1_4.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+ if (FIELD_GET(SDR_WRITE_1_1_1, casn->sdr_write_cap)) {
+ write_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD(
+ true, casn->sdr_write_1_1_1.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+
+ casn_write_cache_variants = (struct spinand_op_variants){
+ .ops = write_ops,
+ .nops = hweight8(casn->sdr_write_cap),
+ };
+
+ op = spinand_select_op_variant(spinand, &casn_write_cache_variants);
+ if (!op) {
+ devm_kfree(&spinand->spimem->spi->dev, write_ops);
+ return -EOPNOTSUPP;
+ }
+ spinand->op_templates.write_cache = op;
+
+ return 0;
+}
+
+static int spinand_set_update_op_variants(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct spinand_op_variants casn_update_cache_variants;
+ struct spi_mem_op *update_ops;
+ const struct spi_mem_op *op;
+ int i = 0;
+
+ update_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op) *
+ hweight8(casn->sdr_update_cap),
+ GFP_KERNEL);
+ if (!update_ops)
+ return -ENOMEM;
+
+ if (FIELD_GET(SDR_UPDATE_1_1_4, casn->sdr_update_cap)) {
+ update_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD_X4(
+ false, casn->sdr_update_1_1_4.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+ if (FIELD_GET(SDR_UPDATE_1_1_1, casn->sdr_update_cap)) {
+ update_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD(
+ false, casn->sdr_update_1_1_1.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+
+ casn_update_cache_variants = (struct spinand_op_variants){
+ .ops = update_ops,
+ .nops = hweight8(casn->sdr_update_cap),
+ };
+
+ op = spinand_select_op_variant(spinand, &casn_update_cache_variants);
+ if (!op) {
+ devm_kfree(&spinand->spimem->spi->dev, update_ops);
+ return -EOPNOTSUPP;
+ }
+ spinand->op_templates.update_cache = op;
+
+ return 0;
+}
+
+static int spinand_init_via_casn(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct nand_device *nand = spinand_to_nand(spinand);
+ u32 val;
+ int ret;
+ int i;
+
+ /* Set members of nand->memorg via CASN. */
+ for (i = 0; i < 9; i++) {
+ val = be32_to_cpu(*(&casn->bits_per_cell + i));
+ memcpy((u32 *)&nand->memorg.bits_per_cell + i, &val, sizeof(u32));
+ }
+ nand->ecc.requirements.strength = be32_to_cpu(casn->ecc_strength);
+ nand->ecc.requirements.step_size = be32_to_cpu(casn->ecc_step_size);
+ spinand->flags = casn->flags;
+
+ if (spinand->flags & SPINAND_SUP_ADV_ECC_STATUS) {
+ spinand->eccinfo = (struct spinand_ecc_info) {
+ &spinand_casn_get_ecc_status, &spinand_casn_ooblayout};
+ } else {
+ spinand->eccinfo = (struct spinand_ecc_info) {
+ NULL, &spinand_casn_ooblayout };
+ }
+
+ spinand->advecc_high_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op),
+ GFP_KERNEL);
+ if (!spinand->advecc_high_ops)
+ return -ENOMEM;
+ spinand->advecc_low_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op),
+ GFP_KERNEL);
+ if (!spinand->advecc_low_ops)
+ return -ENOMEM;
+ spinand->casn_oob = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct CASN_OOB),
+ GFP_KERNEL);
+ if (!spinand->casn_oob)
+ return -ENOMEM;
+ spinand->advecc_high = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct CASN_ADVECC),
+ GFP_KERNEL);
+ if (!spinand->advecc_high)
+ return -ENOMEM;
+ spinand->advecc_low = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct CASN_ADVECC),
+ GFP_KERNEL);
+ if (!spinand->advecc_low)
+ return -ENOMEM;
+
+ *spinand->advecc_high_ops = (struct spi_mem_op)
+ SPINAND_CASN_ADVECC_OP(casn->ecc_status_high, spinand->scratchbuf);
+ *spinand->advecc_low_ops = (struct spi_mem_op)
+ SPINAND_CASN_ADVECC_OP(casn->ecc_status_low, spinand->scratchbuf);
+
+ memcpy(spinand->casn_oob, &casn->casn_oob, sizeof(struct CASN_OOB));
+
+ spinand->advecc_high->cmd = casn->ecc_status_high.cmd;
+ spinand->advecc_high->mask = be16_to_cpu(casn->ecc_status_high.status_mask);
+ spinand->advecc_high->shift = spinand->advecc_high->mask ?
+ ffs(spinand->advecc_high->mask)-1 : 0;
+ spinand->advecc_high->pre_op = casn->ecc_status_high.pre_op;
+ spinand->advecc_high->pre_mask = casn->ecc_status_high.pre_mask;
+
+ spinand->advecc_low->cmd = casn->ecc_status_low.cmd;
+ spinand->advecc_low->mask = be16_to_cpu(casn->ecc_status_low.status_mask);
+ spinand->advecc_low->shift = spinand->advecc_low->mask ?
+ ffs(spinand->advecc_low->mask)-1 : 0;
+ spinand->advecc_low->pre_op = casn->ecc_status_low.pre_op;
+ spinand->advecc_low->pre_mask = casn->ecc_status_low.pre_mask;
+
+ spinand->advecc_low_bitcnt = hweight16(spinand->advecc_low->mask);
+
+ spinand->advecc_noerr_status = casn->advecc_noerr_status;
+ spinand->advecc_uncor_status = casn->advecc_uncor_status;
+ spinand->advecc_post_op = casn->advecc_post_op;
+ spinand->advecc_post_mask = casn->advecc_post_mask;
+ spinand->eccsr_math_op[0] = eccsr_none_op;
+ spinand->eccsr_math_op[1] = eccsr_and_op;
+ spinand->eccsr_math_op[2] = eccsr_add_op;
+ spinand->eccsr_math_op[3] = eccsr_minus_op;
+ spinand->eccsr_math_op[4] = eccsr_mul_op;
+
+ ret = spinand_set_read_op_variants(spinand, casn);
+ if (ret < 0)
+ return ret;
+ ret = spinand_set_write_op_variants(spinand, casn);
+ if (ret < 0)
+ return ret;
+ ret = spinand_set_update_op_variants(spinand, casn);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void spinand_dump_casn(struct spinand_device *spinand, struct nand_casn *casn)
+{
+ int i;
+
+ dev_dbg(&spinand->spimem->spi->dev,
+ "---Start dumping full CASN page---\n");
+ for (i = 0; i < 64; i++)
+ pr_debug("0x%08x", *((u32 *)casn + i));
+
+ pr_debug("** Dump critical fields **\n");
+ pr_debug("signature: 0x%04x\n", be32_to_cpu(casn->signature));
+ pr_debug("version: v%u.%u\n", casn->version >> 4, casn->version & 0xf);
+ pr_debug("[Memory Organization]\n");
+ pr_debug(" bits_per_cell: %d\n", be32_to_cpu(casn->bits_per_cell));
+ pr_debug(" bytes_per_page: %d\n", be32_to_cpu(casn->bytes_per_page));
+ pr_debug(" spare_bytes_per_page: %d\n",
+ be32_to_cpu(casn->spare_bytes_per_page));
+ pr_debug(" pages_per_block: %d\n",
+ be32_to_cpu(casn->pages_per_block));
+ pr_debug(" blocks_per_lun: %d\n", be32_to_cpu(casn->blocks_per_lun));
+ pr_debug(" max_bb_per_lun: %d\n", be32_to_cpu(casn->max_bb_per_lun));
+ pr_debug(" planes_per_lun: %d\n", be32_to_cpu(casn->planes_per_lun));
+ pr_debug(" luns_per_target: %d\n",
+ be32_to_cpu(casn->luns_per_target));
+ pr_debug(" total_target: %d\n", be32_to_cpu(casn->total_target));
+ pr_debug("[flags]\n");
+ pr_debug(" 0. Have QE bit? %s\n",
+ casn->flags & SPINAND_HAS_QE_BIT ? "Yes" : "No");
+ pr_debug(" 1. Have continuous read feature bit? %s\n",
+ casn->flags & SPINAND_HAS_CR_FEAT_BIT ? "Yes" : "No");
+ pr_debug(" 2. Support continuous read? %s\n",
+ casn->flags & SPINAND_SUP_CR ? "Yes" : "No");
+ pr_debug(" 3. Support on-die ECC? %s\n",
+ casn->flags & SPINAND_SUP_ON_DIE_ECC ? "Yes" : "No");
+ pr_debug(" 4. Support legacy ECC status? %s\n",
+ casn->flags & SPINAND_SUP_LEGACY_ECC_STATUS ? "Yes" : "No");
+ pr_debug(" 5. Support advanced ECC status? %s\n",
+ casn->flags & SPINAND_SUP_ADV_ECC_STATUS ? "Yes" : "No");
+ pr_debug(" 6. ECC parity readable? %s\n",
+ casn->flags & SPINAND_ECC_PARITY_READABLE ? "Yes" : "No");
+ pr_debug("[R/W ability]\n");
+ pr_debug(" read ability: %x\n", be16_to_cpu(casn->sdr_read_cap));
+ pr_debug(" write ability: %x\n", casn->sdr_write_cap);
+ pr_debug(" update ability: %x\n", casn->sdr_update_cap);
+ pr_debug("advanced ECC no error state: %x\n",
+ casn->advecc_noerr_status);
+ pr_debug("advecced ECC uncorrectable state: %x\n",
+ casn->advecc_uncor_status);
+ pr_debug("CRC: 0x%04x\n", be16_to_cpu(casn->crc));
+
+ dev_dbg(&spinand->spimem->spi->dev,
+ "---Dumping full CASN page ends here.---\n");
+}
+
static int spinand_detect(struct spinand_device *spinand)
{
- struct device *dev = &spinand->spimem->spi->dev;
struct nand_device *nand = spinand_to_nand(spinand);
+ struct device *dev = &spinand->spimem->spi->dev;
+ struct nand_casn *casn;
+ char manufacturer[14];
+ unsigned int sel = 0;
+ char model[17];
int ret;
ret = spinand_reset_op(spinand);
if (ret)
return ret;
- ret = spinand_id_detect(spinand);
- if (ret) {
- dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
- spinand->id.data);
- return ret;
+ spinand->use_casn = false;
+ casn = kzalloc((sizeof(struct nand_casn) * CASN_PAGE_V1_COPIES), GFP_KERNEL);
+ if (!casn)
+ return -ENOMEM;
+
+ ret = spinand_casn_detect(spinand, casn, &sel);
+ if (!ret) {
+ spinand->use_casn = true;
+ strscpy(manufacturer, casn[sel].manufacturer, sizeof(manufacturer)-1);
+ sanitize_string(manufacturer, sizeof(manufacturer));
+ strscpy(model, casn[sel].model, sizeof(model)-1);
+ sanitize_string(model, sizeof(model));
+
+ spinand_dump_casn(spinand, casn + sel);
+
+ ret = spinand_init_via_casn(spinand, casn + sel);
+ if (ret)
+ dev_err(dev, "Initializing spinand via CASN fails: %d\n", ret);
+ }
+
+ if (ret < 0) {
+ dev_warn(dev, "Fallback to read ID\n");
+
+ ret = spinand_reset_op(spinand);
+ if (ret)
+ goto free_casn;
+ ret = spinand_id_detect(spinand);
+ if (ret) {
+ dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
+ spinand->id.data);
+ goto free_casn;
+ }
}
if (nand->memorg.ntargets > 1 && !spinand->select_target) {
dev_err(dev,
"SPI NANDs with more than one die must implement ->select_target()\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto free_casn;
+ }
+
+ if (spinand->use_casn) {
+ dev_info(&spinand->spimem->spi->dev,
+ "%s %s SPI NAND was found.\n", manufacturer, model);
+ } else {
+ dev_info(&spinand->spimem->spi->dev,
+ "%s SPI NAND was found.\n", spinand->manufacturer->name);
}
- dev_info(&spinand->spimem->spi->dev,
- "%s SPI NAND was found.\n", spinand->manufacturer->name);
dev_info(&spinand->spimem->spi->dev,
"%llu MiB, block size: %zu KiB, page size: %zu, OOB size: %u\n",
nanddev_size(nand) >> 20, nanddev_eraseblock_size(nand) >> 10,
nanddev_page_size(nand), nanddev_per_page_oobsize(nand));
- return 0;
+free_casn:
+ kfree(casn);
+
+ return ret;
}
static int spinand_init_flash(struct spinand_device *spinand)
--
2.45.2
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [RFC PATCH nand/next 4/4] mtd: nand: spi: Add CASN page support
@ 2024-10-20 13:27 ` Sky Huang
0 siblings, 0 replies; 29+ messages in thread
From: Sky Huang @ 2024-10-20 13:27 UTC (permalink / raw)
To: Matthias Brugger, Miquel Raynal, AngeloGioacchino Del Regno,
Richard Weinberger, Vignesh Raghavendra, Daniel Golle,
Chia-Lin Kao, Mika Westerberg, Cheng Ming Lin, linux-kernel,
linux-mtd, linux-arm-kernel, linux-mediatek
Cc: Steven Liu, Sky Huang
From: "Sky Huang" <skylake.huang@mediatek.com>
This patch implements how CASN page detection works for
SPI-NAND and how CASN page interprets ECC information
of all SPI-NAND flash vendors.
Probe flow will become like this:
* If CASN page exists, check its validity.
--> If a certain CASN page is valid, we will know the SPI-NAND
device's information, including memory organization, flash
on-chip ECC engine's design, etc.
* If CASN page doesn't exist, switch to reading ID
spinand_dump_casn() can be moved to sysfs, debugfs or something
else later, I guess.
Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
---
drivers/mtd/nand/spi/core.c | 741 +++++++++++++++++++++++++++++++++++-
1 file changed, 729 insertions(+), 12 deletions(-)
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 4d76f9f71a0e..7d7408e00b5e 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -9,10 +9,13 @@
#define pr_fmt(fmt) "spi-nand: " fmt
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mtd/casn.h>
+#include <linux/mtd/param.h>
#include <linux/mtd/spinand.h>
#include <linux/of.h>
#include <linux/slab.h>
@@ -20,6 +23,8 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
+extern void sanitize_string(uint8_t *s, size_t len);
+
static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
{
struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
@@ -200,6 +205,63 @@ static int spinand_ecc_enable(struct spinand_device *spinand,
enable ? CFG_ECC_ENABLE : 0);
}
+static size_t eccsr_none_op(size_t val, size_t mask) { return val; }
+static size_t eccsr_and_op(size_t val, size_t mask) { return val & mask; }
+static size_t eccsr_add_op(size_t val, size_t mask) { return val + mask; }
+static size_t eccsr_minus_op(size_t val, size_t mask) { return val - mask; }
+static size_t eccsr_mul_op(size_t val, size_t mask) { return val * mask; }
+
+static void spinand_read_adv_ecc(struct spinand_device *spinand,
+ struct spi_mem_op *ops, u16 *eccsr,
+ u16 mask, u8 shift,
+ u8 pre_op, u8 pre_mask)
+{
+ u8 *p = spinand->scratchbuf;
+
+ spi_mem_exec_op(spinand->spimem, ops);
+
+ if (likely(mask <= 0xff))
+ *eccsr += (*p & mask) >> shift;
+ else
+ *eccsr += (((*p << 8) | (*p+1)) & mask) >> shift;
+
+ *eccsr = spinand->eccsr_math_op[pre_op](*eccsr, pre_mask);
+}
+
+static int spinand_casn_get_ecc_status(struct spinand_device *spinand,
+ u8 status)
+{
+ struct mtd_info *mtd = spinand_to_mtd(spinand);
+ struct CASN_ADVECC *ah = spinand->advecc_high;
+ struct CASN_ADVECC *al = spinand->advecc_low;
+ u16 eccsr_high = 0;
+ u16 eccsr_low = 0;
+ u32 eccsr = 0;
+
+ if (al->cmd) {
+ spinand_read_adv_ecc(spinand,
+ spinand->advecc_low_ops, &eccsr_low,
+ al->mask, al->shift,
+ al->pre_op, al->pre_mask);
+ eccsr += eccsr_low;
+ }
+ if (ah->cmd) {
+ spinand_read_adv_ecc(spinand,
+ spinand->advecc_high_ops, &eccsr_high,
+ ah->mask, ah->shift,
+ ah->pre_op, ah->pre_mask);
+ eccsr += eccsr_high << spinand->advecc_low_bitcnt;
+ }
+
+ if (eccsr == spinand->advecc_noerr_status)
+ return 0;
+ else if (eccsr == spinand->advecc_uncor_status)
+ return -EBADMSG;
+ eccsr = spinand->eccsr_math_op[spinand->advecc_post_op](eccsr, spinand->advecc_post_mask);
+
+ return eccsr > mtd->ecc_strength ? mtd->ecc_strength : eccsr;
+}
+
static int spinand_cont_read_enable(struct spinand_device *spinand,
bool enable)
{
@@ -1149,6 +1211,242 @@ static int spinand_manufacturer_match(struct spinand_device *spinand,
return -EOPNOTSUPP;
}
+static int spinand_check_casn_validity(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct device *dev = &spinand->spimem->spi->dev;
+
+ if (be32_to_cpu(casn->bits_per_cell) != 1) {
+ dev_err(dev, "[CASN] bits-per-cell must be 1\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->bytes_per_page)) {
+ case 2048:
+ case 4096:
+ break;
+ default:
+ dev_err(dev, "[CASN] page size must be 2048/4096\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->spare_bytes_per_page)) {
+ case 64:
+ case 96:
+ case 128:
+ case 256:
+ break;
+ default:
+ dev_err(dev, "[CASN] spare size must be 64/128/256\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->pages_per_block)) {
+ case 64:
+ case 128:
+ break;
+ default:
+ dev_err(dev, "[CASN] pages_per_block must be 64/128\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->blocks_per_lun)) {
+ case 1024:
+ if (be32_to_cpu(casn->max_bb_per_lun) != 20) {
+ dev_err(dev, "[CASN] max_bb_per_lun must be 20 when blocks_per_lun is 1024\n");
+ return -EINVAL;
+ }
+ break;
+ case 2048:
+ if (be32_to_cpu(casn->max_bb_per_lun) != 40) {
+ dev_err(dev, "[CASN] max_bb_per_lun must be 40 when blocks_per_lun is 2048\n");
+ return -EINVAL;
+ }
+ break;
+ case 4096:
+ if (be32_to_cpu(casn->max_bb_per_lun) != 80) {
+ dev_err(dev, "[CASN] max_bb_per_lun must be 80 when blocks_per_lun is 4096\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(dev, "[CASN] blocks_per_lun must be 1024/2048/4096\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->planes_per_lun)) {
+ case 1:
+ case 2:
+ break;
+ default:
+ dev_err(dev, "[CASN] planes_per_lun must be 1/2\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->luns_per_target)) {
+ case 1:
+ case 2:
+ break;
+ default:
+ dev_err(dev, "[CASN] luns_per_target must be 1/2\n");
+ return -EINVAL;
+ }
+
+ switch (be32_to_cpu(casn->total_target)) {
+ case 1:
+ case 2:
+ break;
+ default:
+ dev_err(dev, "[CASN] ntargets must be 1/2\n");
+ return -EINVAL;
+ }
+
+ if (casn->casn_oob.layout_type != OOB_CONTINUOUS &&
+ casn->casn_oob.layout_type != OOB_DISCRETE) {
+ dev_err(dev, "[CASN] OOB layout type isn't correct.\n");
+ return -EINVAL;
+ }
+
+ if (casn->ecc_status_high.status_nbytes > 2 ||
+ casn->ecc_status_low.status_nbytes > 2) {
+ dev_err(dev, "[CASN] ADVECC status nbytes must be no more than 2\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int spinand_check_casn(struct spinand_device *spinand,
+ struct nand_casn *casn, unsigned int *sel)
+{
+ struct device *dev = &spinand->spimem->spi->dev;
+ uint16_t crc = be16_to_cpu(casn->crc);
+ uint16_t crc_compute;
+ int ret = 0;
+ int i;
+
+ /* There are 3 copies of CASN Pages V1. Choose one avabilable copy
+ * first. If none of the copies is available, try to recover.
+ */
+ for (i = 0; i < CASN_PAGE_V1_COPIES; i++) {
+ if (be32_to_cpu(casn[i].signature) != CASN_SIGNATURE) {
+ ret = -EINVAL;
+ continue;
+ }
+ crc_compute = nanddev_crc16(CASN_CRC_BASE, (u8 *)(casn + i),
+ SPINAND_CASN_V1_CRC_OFS);
+ dev_dbg(dev, "CASN COPY %d CRC read: 0x%x, compute: 0x%x\n",
+ i, crc, crc_compute);
+ if (crc != crc_compute) {
+ ret = -EBADMSG;
+ continue;
+ }
+ ret = spinand_check_casn_validity(spinand, casn + i);
+ if (ret < 0)
+ continue;
+ *sel = i;
+ break;
+ }
+
+ if (i == CASN_PAGE_V1_COPIES && ret == -EBADMSG) {
+ const void *srcbufs[CASN_PAGE_V1_COPIES];
+ int j;
+
+ for (j = 0; j < CASN_PAGE_V1_COPIES; j++)
+ srcbufs[j] = casn + j;
+ dev_info(dev, "Couldn't find a valid CASN page, try bitwise majority to recover it\n");
+ nanddev_bit_wise_majority(srcbufs, CASN_PAGE_V1_COPIES, casn,
+ sizeof(*casn));
+ crc_compute = nanddev_crc16(CASN_CRC_BASE, (uint8_t *)casn,
+ SPINAND_CASN_V1_CRC_OFS);
+ if (crc_compute != crc) {
+ dev_err(dev, "CASN page recovery failed, aborting\n");
+ return -EBADMSG;
+ }
+ ret = spinand_check_casn_validity(spinand, casn + i);
+ if (ret < 0)
+ return ret;
+ dev_info(dev, "CASN page recovery succeeded\n");
+ *sel = 0;
+ }
+
+ return ret;
+}
+
+static int spinand_casn_detect(struct spinand_device *spinand,
+ struct nand_casn *casn, unsigned int *sel)
+{
+ struct device *dev = &spinand->spimem->spi->dev;
+ uint8_t casn_offset[3] = {0x0, 0x1, 0x4};
+ struct nand_page_io_req req;
+ struct spi_mem_op op;
+ struct nand_pos pos;
+ int check_ret = 0;
+ uint8_t status;
+ int final_ret;
+ int ret = 0;
+ u8 cfg_reg;
+ int i;
+
+ ret = spinand_read_reg_op(spinand, REG_CFG, &cfg_reg);
+ if (ret)
+ return ret;
+
+ ret = spinand_write_reg_op(spinand, REG_CFG, cfg_reg | BIT(6));
+ if (ret)
+ return ret;
+
+ memset(&pos, 0, sizeof(pos));
+
+ req = (struct nand_page_io_req){
+ .pos = pos,
+ .dataoffs = 0,
+ .datalen = 256 * CASN_PAGE_V1_COPIES,
+ .databuf.in = (u8 *)casn,
+ .mode = MTD_OPS_AUTO_OOB,
+ };
+
+ for (i = 0; i < sizeof(casn_offset)/sizeof(uint8_t); i++) {
+ req.pos.page = casn_offset[i];
+ ret = spinand_load_page_op(spinand, &req);
+ if (ret)
+ goto finish;
+
+ ret = spinand_wait(spinand,
+ SPINAND_READ_INITIAL_DELAY_US,
+ SPINAND_READ_POLL_DELAY_US,
+ &status);
+ if (ret < 0)
+ goto finish;
+
+ op = (struct spi_mem_op) SPINAND_PAGE_READ_FROM_CACHE_OP(
+ false, 768, 1, (u8 *)casn, 256 * CASN_PAGE_V1_COPIES);
+ ret = spi_mem_exec_op(spinand->spimem, &op);
+ if (ret < 0)
+ goto finish;
+
+ check_ret = spinand_check_casn(spinand, casn, sel);
+ if (!check_ret)
+ break;
+ }
+
+finish:
+ /* We need to restore configuration register. */
+ final_ret = spinand_write_reg_op(spinand, REG_CFG, cfg_reg);
+ if (final_ret)
+ return final_ret;
+
+ if (check_ret) {
+ dev_err(dev, "CASN page check failed\n");
+ return check_ret;
+ }
+
+ if (ret)
+ dev_err(dev, "CASN page read failed\n");
+
+ return ret;
+}
+
static int spinand_id_detect(struct spinand_device *spinand)
{
u8 *id = spinand->id.data;
@@ -1180,7 +1478,7 @@ static int spinand_id_detect(struct spinand_device *spinand)
static int spinand_manufacturer_init(struct spinand_device *spinand)
{
- if (spinand->manufacturer->ops->init)
+ if (!spinand->use_casn && spinand->manufacturer->ops->init)
return spinand->manufacturer->ops->init(spinand);
return 0;
@@ -1189,7 +1487,7 @@ static int spinand_manufacturer_init(struct spinand_device *spinand)
static void spinand_manufacturer_cleanup(struct spinand_device *spinand)
{
/* Release manufacturer private data */
- if (spinand->manufacturer->ops->cleanup)
+ if (!spinand->use_casn && spinand->manufacturer->ops->cleanup)
return spinand->manufacturer->ops->cleanup(spinand);
}
@@ -1293,37 +1591,456 @@ int spinand_match_and_init(struct spinand_device *spinand,
return -ENOTSUPP;
}
+static int spinand_casn_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ struct spinand_device *spinand = mtd_to_spinand(mtd);
+ int sectionp;
+ struct CASN_OOB *co = spinand->casn_oob;
+
+ sectionp = spinand->base.memorg.pagesize/mtd->ecc_step_size;
+ if (section >= sectionp)
+ return -ERANGE;
+
+ if (co->layout_type == OOB_DISCRETE) {
+ region->offset = co->ecc_parity_start +
+ (co->free_length + co->ecc_parity_space)
+ * section;
+ } else if (co->layout_type == OOB_CONTINUOUS) {
+ region->offset = co->ecc_parity_start + co->ecc_parity_space * section;
+ }
+ region->length = co->ecc_parity_real_length;
+
+ return 0;
+}
+
+static int spinand_casn_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+ struct spinand_device *spinand = mtd_to_spinand(mtd);
+ int sectionp;
+ struct CASN_OOB *co = spinand->casn_oob;
+
+ sectionp = spinand->base.memorg.pagesize/mtd->ecc_step_size;
+ if (section >= sectionp)
+ return -ERANGE;
+
+ if (!section) {
+ region->offset = co->free_start + co->bbm_length;
+ region->length = co->free_length - co->bbm_length;
+ } else {
+ if (co->layout_type == OOB_DISCRETE) {
+ region->offset = co->free_start +
+ (co->free_length +
+ co->ecc_parity_space) * section;
+ } else if (co->layout_type == OOB_CONTINUOUS) {
+ region->offset = co->free_start +
+ co->free_length * section;
+ }
+ region->length = co->free_length;
+ }
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops spinand_casn_ooblayout = {
+ .ecc = spinand_casn_ooblayout_ecc,
+ .free = spinand_casn_ooblayout_free,
+};
+
+static int spinand_set_read_op_variants(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct spinand_op_variants casn_read_cache_variants;
+ u16 sdr_read_cap = be16_to_cpu(casn->sdr_read_cap);
+ struct spi_mem_op *read_ops;
+ const struct spi_mem_op *op;
+ int i = 0;
+
+ read_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op) *
+ hweight16(sdr_read_cap),
+ GFP_KERNEL);
+ if (!read_ops)
+ return -ENOMEM;
+
+ if (FIELD_GET(SDR_READ_1_4_4, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_QUADIO_OP(
+ casn->sdr_read_1_4_4.addr_nbytes, 0,
+ casn->sdr_read_1_4_4.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_4, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_X4_OP(
+ casn->sdr_read_1_1_4.addr_nbytes, 0,
+ casn->sdr_read_1_1_4.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_2_2, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_DUALIO_OP(
+ casn->sdr_read_1_2_2.addr_nbytes, 0,
+ casn->sdr_read_1_2_2.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_2, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_X2_OP(
+ casn->sdr_read_1_1_2.addr_nbytes, 0,
+ casn->sdr_read_1_1_2.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_1_FAST, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(
+ true, casn->sdr_read_1_1_1_fast.addr_nbytes, 0,
+ casn->sdr_read_1_1_1_fast.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+ if (FIELD_GET(SDR_READ_1_1_1, sdr_read_cap)) {
+ read_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(
+ false, casn->sdr_read_1_1_1.addr_nbytes, 0,
+ casn->sdr_read_1_1_1.dummy_nbytes, NULL, 0
+ );
+ i++;
+ }
+
+ casn_read_cache_variants = (struct spinand_op_variants){
+ .ops = read_ops,
+ .nops = hweight16(sdr_read_cap),
+ };
+
+ op = spinand_select_op_variant(spinand, &casn_read_cache_variants);
+ if (!op) {
+ devm_kfree(&spinand->spimem->spi->dev, read_ops);
+ return -EOPNOTSUPP;
+ }
+ spinand->op_templates.read_cache = op;
+
+ return 0;
+}
+
+static int spinand_set_write_op_variants(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct spinand_op_variants casn_write_cache_variants;
+ struct spi_mem_op *write_ops;
+ const struct spi_mem_op *op;
+ int i = 0;
+
+ write_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op) *
+ hweight8(casn->sdr_write_cap),
+ GFP_KERNEL);
+ if (!write_ops)
+ return -ENOMEM;
+
+ if (FIELD_GET(SDR_WRITE_1_1_4, casn->sdr_write_cap)) {
+ write_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD_X4(
+ true, casn->sdr_write_1_1_4.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+ if (FIELD_GET(SDR_WRITE_1_1_1, casn->sdr_write_cap)) {
+ write_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD(
+ true, casn->sdr_write_1_1_1.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+
+ casn_write_cache_variants = (struct spinand_op_variants){
+ .ops = write_ops,
+ .nops = hweight8(casn->sdr_write_cap),
+ };
+
+ op = spinand_select_op_variant(spinand, &casn_write_cache_variants);
+ if (!op) {
+ devm_kfree(&spinand->spimem->spi->dev, write_ops);
+ return -EOPNOTSUPP;
+ }
+ spinand->op_templates.write_cache = op;
+
+ return 0;
+}
+
+static int spinand_set_update_op_variants(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct spinand_op_variants casn_update_cache_variants;
+ struct spi_mem_op *update_ops;
+ const struct spi_mem_op *op;
+ int i = 0;
+
+ update_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op) *
+ hweight8(casn->sdr_update_cap),
+ GFP_KERNEL);
+ if (!update_ops)
+ return -ENOMEM;
+
+ if (FIELD_GET(SDR_UPDATE_1_1_4, casn->sdr_update_cap)) {
+ update_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD_X4(
+ false, casn->sdr_update_1_1_4.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+ if (FIELD_GET(SDR_UPDATE_1_1_1, casn->sdr_update_cap)) {
+ update_ops[i] = (struct spi_mem_op)
+ SPINAND_CASN_PROG_LOAD(
+ false, casn->sdr_update_1_1_1.addr_nbytes, 0,
+ NULL, 0);
+ i++;
+ }
+
+ casn_update_cache_variants = (struct spinand_op_variants){
+ .ops = update_ops,
+ .nops = hweight8(casn->sdr_update_cap),
+ };
+
+ op = spinand_select_op_variant(spinand, &casn_update_cache_variants);
+ if (!op) {
+ devm_kfree(&spinand->spimem->spi->dev, update_ops);
+ return -EOPNOTSUPP;
+ }
+ spinand->op_templates.update_cache = op;
+
+ return 0;
+}
+
+static int spinand_init_via_casn(struct spinand_device *spinand,
+ struct nand_casn *casn)
+{
+ struct nand_device *nand = spinand_to_nand(spinand);
+ u32 val;
+ int ret;
+ int i;
+
+ /* Set members of nand->memorg via CASN. */
+ for (i = 0; i < 9; i++) {
+ val = be32_to_cpu(*(&casn->bits_per_cell + i));
+ memcpy((u32 *)&nand->memorg.bits_per_cell + i, &val, sizeof(u32));
+ }
+ nand->ecc.requirements.strength = be32_to_cpu(casn->ecc_strength);
+ nand->ecc.requirements.step_size = be32_to_cpu(casn->ecc_step_size);
+ spinand->flags = casn->flags;
+
+ if (spinand->flags & SPINAND_SUP_ADV_ECC_STATUS) {
+ spinand->eccinfo = (struct spinand_ecc_info) {
+ &spinand_casn_get_ecc_status, &spinand_casn_ooblayout};
+ } else {
+ spinand->eccinfo = (struct spinand_ecc_info) {
+ NULL, &spinand_casn_ooblayout };
+ }
+
+ spinand->advecc_high_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op),
+ GFP_KERNEL);
+ if (!spinand->advecc_high_ops)
+ return -ENOMEM;
+ spinand->advecc_low_ops = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct spi_mem_op),
+ GFP_KERNEL);
+ if (!spinand->advecc_low_ops)
+ return -ENOMEM;
+ spinand->casn_oob = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct CASN_OOB),
+ GFP_KERNEL);
+ if (!spinand->casn_oob)
+ return -ENOMEM;
+ spinand->advecc_high = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct CASN_ADVECC),
+ GFP_KERNEL);
+ if (!spinand->advecc_high)
+ return -ENOMEM;
+ spinand->advecc_low = devm_kzalloc(&spinand->spimem->spi->dev,
+ sizeof(struct CASN_ADVECC),
+ GFP_KERNEL);
+ if (!spinand->advecc_low)
+ return -ENOMEM;
+
+ *spinand->advecc_high_ops = (struct spi_mem_op)
+ SPINAND_CASN_ADVECC_OP(casn->ecc_status_high, spinand->scratchbuf);
+ *spinand->advecc_low_ops = (struct spi_mem_op)
+ SPINAND_CASN_ADVECC_OP(casn->ecc_status_low, spinand->scratchbuf);
+
+ memcpy(spinand->casn_oob, &casn->casn_oob, sizeof(struct CASN_OOB));
+
+ spinand->advecc_high->cmd = casn->ecc_status_high.cmd;
+ spinand->advecc_high->mask = be16_to_cpu(casn->ecc_status_high.status_mask);
+ spinand->advecc_high->shift = spinand->advecc_high->mask ?
+ ffs(spinand->advecc_high->mask)-1 : 0;
+ spinand->advecc_high->pre_op = casn->ecc_status_high.pre_op;
+ spinand->advecc_high->pre_mask = casn->ecc_status_high.pre_mask;
+
+ spinand->advecc_low->cmd = casn->ecc_status_low.cmd;
+ spinand->advecc_low->mask = be16_to_cpu(casn->ecc_status_low.status_mask);
+ spinand->advecc_low->shift = spinand->advecc_low->mask ?
+ ffs(spinand->advecc_low->mask)-1 : 0;
+ spinand->advecc_low->pre_op = casn->ecc_status_low.pre_op;
+ spinand->advecc_low->pre_mask = casn->ecc_status_low.pre_mask;
+
+ spinand->advecc_low_bitcnt = hweight16(spinand->advecc_low->mask);
+
+ spinand->advecc_noerr_status = casn->advecc_noerr_status;
+ spinand->advecc_uncor_status = casn->advecc_uncor_status;
+ spinand->advecc_post_op = casn->advecc_post_op;
+ spinand->advecc_post_mask = casn->advecc_post_mask;
+ spinand->eccsr_math_op[0] = eccsr_none_op;
+ spinand->eccsr_math_op[1] = eccsr_and_op;
+ spinand->eccsr_math_op[2] = eccsr_add_op;
+ spinand->eccsr_math_op[3] = eccsr_minus_op;
+ spinand->eccsr_math_op[4] = eccsr_mul_op;
+
+ ret = spinand_set_read_op_variants(spinand, casn);
+ if (ret < 0)
+ return ret;
+ ret = spinand_set_write_op_variants(spinand, casn);
+ if (ret < 0)
+ return ret;
+ ret = spinand_set_update_op_variants(spinand, casn);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void spinand_dump_casn(struct spinand_device *spinand, struct nand_casn *casn)
+{
+ int i;
+
+ dev_dbg(&spinand->spimem->spi->dev,
+ "---Start dumping full CASN page---\n");
+ for (i = 0; i < 64; i++)
+ pr_debug("0x%08x", *((u32 *)casn + i));
+
+ pr_debug("** Dump critical fields **\n");
+ pr_debug("signature: 0x%04x\n", be32_to_cpu(casn->signature));
+ pr_debug("version: v%u.%u\n", casn->version >> 4, casn->version & 0xf);
+ pr_debug("[Memory Organization]\n");
+ pr_debug(" bits_per_cell: %d\n", be32_to_cpu(casn->bits_per_cell));
+ pr_debug(" bytes_per_page: %d\n", be32_to_cpu(casn->bytes_per_page));
+ pr_debug(" spare_bytes_per_page: %d\n",
+ be32_to_cpu(casn->spare_bytes_per_page));
+ pr_debug(" pages_per_block: %d\n",
+ be32_to_cpu(casn->pages_per_block));
+ pr_debug(" blocks_per_lun: %d\n", be32_to_cpu(casn->blocks_per_lun));
+ pr_debug(" max_bb_per_lun: %d\n", be32_to_cpu(casn->max_bb_per_lun));
+ pr_debug(" planes_per_lun: %d\n", be32_to_cpu(casn->planes_per_lun));
+ pr_debug(" luns_per_target: %d\n",
+ be32_to_cpu(casn->luns_per_target));
+ pr_debug(" total_target: %d\n", be32_to_cpu(casn->total_target));
+ pr_debug("[flags]\n");
+ pr_debug(" 0. Have QE bit? %s\n",
+ casn->flags & SPINAND_HAS_QE_BIT ? "Yes" : "No");
+ pr_debug(" 1. Have continuous read feature bit? %s\n",
+ casn->flags & SPINAND_HAS_CR_FEAT_BIT ? "Yes" : "No");
+ pr_debug(" 2. Support continuous read? %s\n",
+ casn->flags & SPINAND_SUP_CR ? "Yes" : "No");
+ pr_debug(" 3. Support on-die ECC? %s\n",
+ casn->flags & SPINAND_SUP_ON_DIE_ECC ? "Yes" : "No");
+ pr_debug(" 4. Support legacy ECC status? %s\n",
+ casn->flags & SPINAND_SUP_LEGACY_ECC_STATUS ? "Yes" : "No");
+ pr_debug(" 5. Support advanced ECC status? %s\n",
+ casn->flags & SPINAND_SUP_ADV_ECC_STATUS ? "Yes" : "No");
+ pr_debug(" 6. ECC parity readable? %s\n",
+ casn->flags & SPINAND_ECC_PARITY_READABLE ? "Yes" : "No");
+ pr_debug("[R/W ability]\n");
+ pr_debug(" read ability: %x\n", be16_to_cpu(casn->sdr_read_cap));
+ pr_debug(" write ability: %x\n", casn->sdr_write_cap);
+ pr_debug(" update ability: %x\n", casn->sdr_update_cap);
+ pr_debug("advanced ECC no error state: %x\n",
+ casn->advecc_noerr_status);
+ pr_debug("advecced ECC uncorrectable state: %x\n",
+ casn->advecc_uncor_status);
+ pr_debug("CRC: 0x%04x\n", be16_to_cpu(casn->crc));
+
+ dev_dbg(&spinand->spimem->spi->dev,
+ "---Dumping full CASN page ends here.---\n");
+}
+
static int spinand_detect(struct spinand_device *spinand)
{
- struct device *dev = &spinand->spimem->spi->dev;
struct nand_device *nand = spinand_to_nand(spinand);
+ struct device *dev = &spinand->spimem->spi->dev;
+ struct nand_casn *casn;
+ char manufacturer[14];
+ unsigned int sel = 0;
+ char model[17];
int ret;
ret = spinand_reset_op(spinand);
if (ret)
return ret;
- ret = spinand_id_detect(spinand);
- if (ret) {
- dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
- spinand->id.data);
- return ret;
+ spinand->use_casn = false;
+ casn = kzalloc((sizeof(struct nand_casn) * CASN_PAGE_V1_COPIES), GFP_KERNEL);
+ if (!casn)
+ return -ENOMEM;
+
+ ret = spinand_casn_detect(spinand, casn, &sel);
+ if (!ret) {
+ spinand->use_casn = true;
+ strscpy(manufacturer, casn[sel].manufacturer, sizeof(manufacturer)-1);
+ sanitize_string(manufacturer, sizeof(manufacturer));
+ strscpy(model, casn[sel].model, sizeof(model)-1);
+ sanitize_string(model, sizeof(model));
+
+ spinand_dump_casn(spinand, casn + sel);
+
+ ret = spinand_init_via_casn(spinand, casn + sel);
+ if (ret)
+ dev_err(dev, "Initializing spinand via CASN fails: %d\n", ret);
+ }
+
+ if (ret < 0) {
+ dev_warn(dev, "Fallback to read ID\n");
+
+ ret = spinand_reset_op(spinand);
+ if (ret)
+ goto free_casn;
+ ret = spinand_id_detect(spinand);
+ if (ret) {
+ dev_err(dev, "unknown raw ID %*phN\n", SPINAND_MAX_ID_LEN,
+ spinand->id.data);
+ goto free_casn;
+ }
}
if (nand->memorg.ntargets > 1 && !spinand->select_target) {
dev_err(dev,
"SPI NANDs with more than one die must implement ->select_target()\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto free_casn;
+ }
+
+ if (spinand->use_casn) {
+ dev_info(&spinand->spimem->spi->dev,
+ "%s %s SPI NAND was found.\n", manufacturer, model);
+ } else {
+ dev_info(&spinand->spimem->spi->dev,
+ "%s SPI NAND was found.\n", spinand->manufacturer->name);
}
- dev_info(&spinand->spimem->spi->dev,
- "%s SPI NAND was found.\n", spinand->manufacturer->name);
dev_info(&spinand->spimem->spi->dev,
"%llu MiB, block size: %zu KiB, page size: %zu, OOB size: %u\n",
nanddev_size(nand) >> 20, nanddev_eraseblock_size(nand) >> 10,
nanddev_page_size(nand), nanddev_per_page_oobsize(nand));
- return 0;
+free_casn:
+ kfree(casn);
+
+ return ret;
}
static int spinand_init_flash(struct spinand_device *spinand)
--
2.45.2
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
2024-10-20 13:27 ` Sky Huang
(?)
@ 2024-10-23 5:22 ` kernel test robot
-1 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2024-10-23 5:22 UTC (permalink / raw)
To: Sky Huang; +Cc: oe-kbuild-all
Hi Sky,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on mtd/nand/next]
[also build test ERROR on mtd/mtd/next mtd/mtd/fixes linus/master v6.12-rc4 next-20241022]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sky-Huang/mtd-nand-Create-param-c-to-do-CRC-check-and-bitwise-majority-for-Parameter-CASN-page/20241020-212938
base: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
patch link: https://lore.kernel.org/r/20241020132722.20565-4-SkyLake.Huang%40mediatek.com
patch subject: [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20241023/202410231223.S7qRiG54-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241023/202410231223.S7qRiG54-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410231223.S7qRiG54-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/mtd/nand/spi/core.c: In function 'spinand_read_from_cache_op':
>> drivers/mtd/nand/spi/core.c:411:30: error: 'SPINAND_HAS_READ_PLANE_SELECT_BIT' undeclared (first use in this function)
411 | if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/mtd/nand/spi/core.c:411:30: note: each undeclared identifier is reported only once for each function it appears in
drivers/mtd/nand/spi/core.c: In function 'spinand_write_to_cache_op':
>> drivers/mtd/nand/spi/core.c:495:30: error: 'SPINAND_HAS_PROG_PLANE_SELECT_BIT' undeclared (first use in this function)
495 | if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
In file included from drivers/mtd/nand/spi/macronix.c:11:
>> drivers/mtd/nand/spi/macronix.c:158:22: error: 'SPINAND_HAS_PROG_PLANE_SELECT_BIT' undeclared here (not in a function)
158 | SPINAND_HAS_PROG_PLANE_SELECT_BIT |
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mtd/spinand.h:454:26: note: in definition of macro 'SPINAND_INFO'
454 | .flags = __flags, \
| ^~~~~~~
>> drivers/mtd/nand/spi/macronix.c:159:22: error: 'SPINAND_HAS_READ_PLANE_SELECT_BIT' undeclared here (not in a function)
159 | SPINAND_HAS_READ_PLANE_SELECT_BIT,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/mtd/spinand.h:454:26: note: in definition of macro 'SPINAND_INFO'
454 | .flags = __flags, \
| ^~~~~~~
vim +/SPINAND_HAS_READ_PLANE_SELECT_BIT +411 drivers/mtd/nand/spi/core.c
7529df4652482c Peter Pan 2018-06-22 376
7529df4652482c Peter Pan 2018-06-22 377 static int spinand_read_from_cache_op(struct spinand_device *spinand,
7529df4652482c Peter Pan 2018-06-22 378 const struct nand_page_io_req *req)
7529df4652482c Peter Pan 2018-06-22 379 {
7529df4652482c Peter Pan 2018-06-22 380 struct nand_device *nand = spinand_to_nand(spinand);
e708789c4a8798 Miquel Raynal 2021-01-07 381 struct mtd_info *mtd = spinand_to_mtd(spinand);
981d1aa0697ce1 Boris Brezillon 2019-01-24 382 struct spi_mem_dirmap_desc *rdesc;
7529df4652482c Peter Pan 2018-06-22 383 unsigned int nbytes = 0;
7529df4652482c Peter Pan 2018-06-22 384 void *buf = NULL;
7529df4652482c Peter Pan 2018-06-22 385 u16 column = 0;
981d1aa0697ce1 Boris Brezillon 2019-01-24 386 ssize_t ret;
7529df4652482c Peter Pan 2018-06-22 387
7529df4652482c Peter Pan 2018-06-22 388 if (req->datalen) {
7529df4652482c Peter Pan 2018-06-22 389 buf = spinand->databuf;
631cfdd0520d19 Miquel Raynal 2024-08-26 390 if (!req->continuous)
981d1aa0697ce1 Boris Brezillon 2019-01-24 391 nbytes = nanddev_page_size(nand);
631cfdd0520d19 Miquel Raynal 2024-08-26 392 else
631cfdd0520d19 Miquel Raynal 2024-08-26 393 nbytes = round_up(req->dataoffs + req->datalen,
631cfdd0520d19 Miquel Raynal 2024-08-26 394 nanddev_page_size(nand));
981d1aa0697ce1 Boris Brezillon 2019-01-24 395 column = 0;
7529df4652482c Peter Pan 2018-06-22 396 }
7529df4652482c Peter Pan 2018-06-22 397
7529df4652482c Peter Pan 2018-06-22 398 if (req->ooblen) {
7529df4652482c Peter Pan 2018-06-22 399 nbytes += nanddev_per_page_oobsize(nand);
7529df4652482c Peter Pan 2018-06-22 400 if (!buf) {
7529df4652482c Peter Pan 2018-06-22 401 buf = spinand->oobbuf;
7529df4652482c Peter Pan 2018-06-22 402 column = nanddev_page_size(nand);
7529df4652482c Peter Pan 2018-06-22 403 }
7529df4652482c Peter Pan 2018-06-22 404 }
7529df4652482c Peter Pan 2018-06-22 405
f9d7c7265bcff7 Miquel Raynal 2022-01-27 406 if (req->mode == MTD_OPS_RAW)
981d1aa0697ce1 Boris Brezillon 2019-01-24 407 rdesc = spinand->dirmaps[req->pos.plane].rdesc;
f9d7c7265bcff7 Miquel Raynal 2022-01-27 408 else
f9d7c7265bcff7 Miquel Raynal 2022-01-27 409 rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc;
7529df4652482c Peter Pan 2018-06-22 410
ca229bdbef29be Cheng Ming Lin 2024-09-09 @411 if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT)
ca229bdbef29be Cheng Ming Lin 2024-09-09 412 column |= req->pos.plane << fls(nanddev_page_size(nand));
ca229bdbef29be Cheng Ming Lin 2024-09-09 413
7529df4652482c Peter Pan 2018-06-22 414 while (nbytes) {
981d1aa0697ce1 Boris Brezillon 2019-01-24 415 ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf);
981d1aa0697ce1 Boris Brezillon 2019-01-24 416 if (ret < 0)
7529df4652482c Peter Pan 2018-06-22 417 return ret;
7529df4652482c Peter Pan 2018-06-22 418
981d1aa0697ce1 Boris Brezillon 2019-01-24 419 if (!ret || ret > nbytes)
981d1aa0697ce1 Boris Brezillon 2019-01-24 420 return -EIO;
7529df4652482c Peter Pan 2018-06-22 421
981d1aa0697ce1 Boris Brezillon 2019-01-24 422 nbytes -= ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 423 column += ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 424 buf += ret;
631cfdd0520d19 Miquel Raynal 2024-08-26 425
631cfdd0520d19 Miquel Raynal 2024-08-26 426 /*
631cfdd0520d19 Miquel Raynal 2024-08-26 427 * Dirmap accesses are allowed to toggle the CS.
631cfdd0520d19 Miquel Raynal 2024-08-26 428 * Toggling the CS during a continuous read is forbidden.
631cfdd0520d19 Miquel Raynal 2024-08-26 429 */
631cfdd0520d19 Miquel Raynal 2024-08-26 430 if (nbytes && req->continuous)
631cfdd0520d19 Miquel Raynal 2024-08-26 431 return -EIO;
7529df4652482c Peter Pan 2018-06-22 432 }
7529df4652482c Peter Pan 2018-06-22 433
7529df4652482c Peter Pan 2018-06-22 434 if (req->datalen)
7529df4652482c Peter Pan 2018-06-22 435 memcpy(req->databuf.in, spinand->databuf + req->dataoffs,
7529df4652482c Peter Pan 2018-06-22 436 req->datalen);
7529df4652482c Peter Pan 2018-06-22 437
e708789c4a8798 Miquel Raynal 2021-01-07 438 if (req->ooblen) {
e708789c4a8798 Miquel Raynal 2021-01-07 439 if (req->mode == MTD_OPS_AUTO_OOB)
e708789c4a8798 Miquel Raynal 2021-01-07 440 mtd_ooblayout_get_databytes(mtd, req->oobbuf.in,
e708789c4a8798 Miquel Raynal 2021-01-07 441 spinand->oobbuf,
e708789c4a8798 Miquel Raynal 2021-01-07 442 req->ooboffs,
e708789c4a8798 Miquel Raynal 2021-01-07 443 req->ooblen);
e708789c4a8798 Miquel Raynal 2021-01-07 444 else
868cbe2a6dcee4 Miquel Raynal 2020-10-01 445 memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs,
868cbe2a6dcee4 Miquel Raynal 2020-10-01 446 req->ooblen);
e708789c4a8798 Miquel Raynal 2021-01-07 447 }
868cbe2a6dcee4 Miquel Raynal 2020-10-01 448
7529df4652482c Peter Pan 2018-06-22 449 return 0;
7529df4652482c Peter Pan 2018-06-22 450 }
7529df4652482c Peter Pan 2018-06-22 451
7529df4652482c Peter Pan 2018-06-22 452 static int spinand_write_to_cache_op(struct spinand_device *spinand,
7529df4652482c Peter Pan 2018-06-22 453 const struct nand_page_io_req *req)
7529df4652482c Peter Pan 2018-06-22 454 {
7529df4652482c Peter Pan 2018-06-22 455 struct nand_device *nand = spinand_to_nand(spinand);
3d1f08b032dc4e Miquel Raynal 2020-10-01 456 struct mtd_info *mtd = spinand_to_mtd(spinand);
981d1aa0697ce1 Boris Brezillon 2019-01-24 457 struct spi_mem_dirmap_desc *wdesc;
981d1aa0697ce1 Boris Brezillon 2019-01-24 458 unsigned int nbytes, column = 0;
13c15e07eedf26 Boris Brezillon 2019-01-24 459 void *buf = spinand->databuf;
981d1aa0697ce1 Boris Brezillon 2019-01-24 460 ssize_t ret;
7529df4652482c Peter Pan 2018-06-22 461
13c15e07eedf26 Boris Brezillon 2019-01-24 462 /*
13c15e07eedf26 Boris Brezillon 2019-01-24 463 * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
13c15e07eedf26 Boris Brezillon 2019-01-24 464 * the cache content to 0xFF (depends on vendor implementation), so we
13c15e07eedf26 Boris Brezillon 2019-01-24 465 * must fill the page cache entirely even if we only want to program
13c15e07eedf26 Boris Brezillon 2019-01-24 466 * the data portion of the page, otherwise we might corrupt the BBM or
13c15e07eedf26 Boris Brezillon 2019-01-24 467 * user data previously programmed in OOB area.
3d1f08b032dc4e Miquel Raynal 2020-10-01 468 *
3d1f08b032dc4e Miquel Raynal 2020-10-01 469 * Only reset the data buffer manually, the OOB buffer is prepared by
3d1f08b032dc4e Miquel Raynal 2020-10-01 470 * ECC engines ->prepare_io_req() callback.
13c15e07eedf26 Boris Brezillon 2019-01-24 471 */
13c15e07eedf26 Boris Brezillon 2019-01-24 472 nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
3d1f08b032dc4e Miquel Raynal 2020-10-01 473 memset(spinand->databuf, 0xff, nanddev_page_size(nand));
13c15e07eedf26 Boris Brezillon 2019-01-24 474
13c15e07eedf26 Boris Brezillon 2019-01-24 475 if (req->datalen)
13c15e07eedf26 Boris Brezillon 2019-01-24 476 memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
13c15e07eedf26 Boris Brezillon 2019-01-24 477 req->datalen);
7529df4652482c Peter Pan 2018-06-22 478
7529df4652482c Peter Pan 2018-06-22 479 if (req->ooblen) {
7529df4652482c Peter Pan 2018-06-22 480 if (req->mode == MTD_OPS_AUTO_OOB)
7529df4652482c Peter Pan 2018-06-22 481 mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
7529df4652482c Peter Pan 2018-06-22 482 spinand->oobbuf,
7529df4652482c Peter Pan 2018-06-22 483 req->ooboffs,
7529df4652482c Peter Pan 2018-06-22 484 req->ooblen);
7529df4652482c Peter Pan 2018-06-22 485 else
7529df4652482c Peter Pan 2018-06-22 486 memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
7529df4652482c Peter Pan 2018-06-22 487 req->ooblen);
7529df4652482c Peter Pan 2018-06-22 488 }
7529df4652482c Peter Pan 2018-06-22 489
f9d7c7265bcff7 Miquel Raynal 2022-01-27 490 if (req->mode == MTD_OPS_RAW)
981d1aa0697ce1 Boris Brezillon 2019-01-24 491 wdesc = spinand->dirmaps[req->pos.plane].wdesc;
f9d7c7265bcff7 Miquel Raynal 2022-01-27 492 else
f9d7c7265bcff7 Miquel Raynal 2022-01-27 493 wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc;
7529df4652482c Peter Pan 2018-06-22 494
ca229bdbef29be Cheng Ming Lin 2024-09-09 @495 if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT)
ca229bdbef29be Cheng Ming Lin 2024-09-09 496 column |= req->pos.plane << fls(nanddev_page_size(nand));
ca229bdbef29be Cheng Ming Lin 2024-09-09 497
7529df4652482c Peter Pan 2018-06-22 498 while (nbytes) {
981d1aa0697ce1 Boris Brezillon 2019-01-24 499 ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf);
981d1aa0697ce1 Boris Brezillon 2019-01-24 500 if (ret < 0)
7529df4652482c Peter Pan 2018-06-22 501 return ret;
7529df4652482c Peter Pan 2018-06-22 502
981d1aa0697ce1 Boris Brezillon 2019-01-24 503 if (!ret || ret > nbytes)
981d1aa0697ce1 Boris Brezillon 2019-01-24 504 return -EIO;
7529df4652482c Peter Pan 2018-06-22 505
981d1aa0697ce1 Boris Brezillon 2019-01-24 506 nbytes -= ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 507 column += ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 508 buf += ret;
7529df4652482c Peter Pan 2018-06-22 509 }
7529df4652482c Peter Pan 2018-06-22 510
7529df4652482c Peter Pan 2018-06-22 511 return 0;
7529df4652482c Peter Pan 2018-06-22 512 }
7529df4652482c Peter Pan 2018-06-22 513
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
2024-10-20 13:27 ` Sky Huang
(?)
(?)
@ 2024-10-23 5:23 ` kernel test robot
-1 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2024-10-23 5:23 UTC (permalink / raw)
To: Sky Huang; +Cc: llvm, oe-kbuild-all
Hi Sky,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on mtd/nand/next]
[also build test ERROR on mtd/mtd/next mtd/mtd/fixes linus/master v6.12-rc4 next-20241022]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sky-Huang/mtd-nand-Create-param-c-to-do-CRC-check-and-bitwise-majority-for-Parameter-CASN-page/20241020-212938
base: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
patch link: https://lore.kernel.org/r/20241020132722.20565-4-SkyLake.Huang%40mediatek.com
patch subject: [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20241023/202410231353.YRTCHb8J-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241023/202410231353.YRTCHb8J-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410231353.YRTCHb8J-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/mtd/nand/spi/core.c:411:23: error: use of undeclared identifier 'SPINAND_HAS_READ_PLANE_SELECT_BIT'
411 | if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT)
| ^
>> drivers/mtd/nand/spi/core.c:495:23: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
495 | if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT)
| ^
2 errors generated.
--
>> drivers/mtd/nand/spi/macronix.c:158:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
158 | SPINAND_HAS_PROG_PLANE_SELECT_BIT |
| ^
>> drivers/mtd/nand/spi/macronix.c:159:8: error: use of undeclared identifier 'SPINAND_HAS_READ_PLANE_SELECT_BIT'
159 | SPINAND_HAS_READ_PLANE_SELECT_BIT,
| ^
drivers/mtd/nand/spi/macronix.c:200:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
200 | SPINAND_HAS_PROG_PLANE_SELECT_BIT,
| ^
drivers/mtd/nand/spi/macronix.c:219:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
219 | SPINAND_HAS_PROG_PLANE_SELECT_BIT,
| ^
drivers/mtd/nand/spi/macronix.c:259:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
259 | SPINAND_HAS_PROG_PLANE_SELECT_BIT |
| ^
drivers/mtd/nand/spi/macronix.c:260:8: error: use of undeclared identifier 'SPINAND_HAS_READ_PLANE_SELECT_BIT'
260 | SPINAND_HAS_READ_PLANE_SELECT_BIT,
| ^
drivers/mtd/nand/spi/macronix.c:271:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
271 | SPINAND_HAS_PROG_PLANE_SELECT_BIT,
| ^
drivers/mtd/nand/spi/macronix.c:303:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
303 | SPINAND_HAS_PROG_PLANE_SELECT_BIT |
| ^
drivers/mtd/nand/spi/macronix.c:304:8: error: use of undeclared identifier 'SPINAND_HAS_READ_PLANE_SELECT_BIT'
304 | SPINAND_HAS_READ_PLANE_SELECT_BIT,
| ^
drivers/mtd/nand/spi/macronix.c:315:8: error: use of undeclared identifier 'SPINAND_HAS_PROG_PLANE_SELECT_BIT'
315 | SPINAND_HAS_PROG_PLANE_SELECT_BIT,
| ^
>> drivers/mtd/nand/spi/macronix.c:441:12: error: invalid application of 'sizeof' to an incomplete type 'const struct spinand_info[]'
441 | .nchips = ARRAY_SIZE(macronix_spinand_table),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/array_size.h:11:32: note: expanded from macro 'ARRAY_SIZE'
11 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
| ^~~~~
11 errors generated.
vim +/SPINAND_HAS_READ_PLANE_SELECT_BIT +411 drivers/mtd/nand/spi/core.c
7529df4652482c Peter Pan 2018-06-22 376
7529df4652482c Peter Pan 2018-06-22 377 static int spinand_read_from_cache_op(struct spinand_device *spinand,
7529df4652482c Peter Pan 2018-06-22 378 const struct nand_page_io_req *req)
7529df4652482c Peter Pan 2018-06-22 379 {
7529df4652482c Peter Pan 2018-06-22 380 struct nand_device *nand = spinand_to_nand(spinand);
e708789c4a8798 Miquel Raynal 2021-01-07 381 struct mtd_info *mtd = spinand_to_mtd(spinand);
981d1aa0697ce1 Boris Brezillon 2019-01-24 382 struct spi_mem_dirmap_desc *rdesc;
7529df4652482c Peter Pan 2018-06-22 383 unsigned int nbytes = 0;
7529df4652482c Peter Pan 2018-06-22 384 void *buf = NULL;
7529df4652482c Peter Pan 2018-06-22 385 u16 column = 0;
981d1aa0697ce1 Boris Brezillon 2019-01-24 386 ssize_t ret;
7529df4652482c Peter Pan 2018-06-22 387
7529df4652482c Peter Pan 2018-06-22 388 if (req->datalen) {
7529df4652482c Peter Pan 2018-06-22 389 buf = spinand->databuf;
631cfdd0520d19 Miquel Raynal 2024-08-26 390 if (!req->continuous)
981d1aa0697ce1 Boris Brezillon 2019-01-24 391 nbytes = nanddev_page_size(nand);
631cfdd0520d19 Miquel Raynal 2024-08-26 392 else
631cfdd0520d19 Miquel Raynal 2024-08-26 393 nbytes = round_up(req->dataoffs + req->datalen,
631cfdd0520d19 Miquel Raynal 2024-08-26 394 nanddev_page_size(nand));
981d1aa0697ce1 Boris Brezillon 2019-01-24 395 column = 0;
7529df4652482c Peter Pan 2018-06-22 396 }
7529df4652482c Peter Pan 2018-06-22 397
7529df4652482c Peter Pan 2018-06-22 398 if (req->ooblen) {
7529df4652482c Peter Pan 2018-06-22 399 nbytes += nanddev_per_page_oobsize(nand);
7529df4652482c Peter Pan 2018-06-22 400 if (!buf) {
7529df4652482c Peter Pan 2018-06-22 401 buf = spinand->oobbuf;
7529df4652482c Peter Pan 2018-06-22 402 column = nanddev_page_size(nand);
7529df4652482c Peter Pan 2018-06-22 403 }
7529df4652482c Peter Pan 2018-06-22 404 }
7529df4652482c Peter Pan 2018-06-22 405
f9d7c7265bcff7 Miquel Raynal 2022-01-27 406 if (req->mode == MTD_OPS_RAW)
981d1aa0697ce1 Boris Brezillon 2019-01-24 407 rdesc = spinand->dirmaps[req->pos.plane].rdesc;
f9d7c7265bcff7 Miquel Raynal 2022-01-27 408 else
f9d7c7265bcff7 Miquel Raynal 2022-01-27 409 rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc;
7529df4652482c Peter Pan 2018-06-22 410
ca229bdbef29be Cheng Ming Lin 2024-09-09 @411 if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT)
ca229bdbef29be Cheng Ming Lin 2024-09-09 412 column |= req->pos.plane << fls(nanddev_page_size(nand));
ca229bdbef29be Cheng Ming Lin 2024-09-09 413
7529df4652482c Peter Pan 2018-06-22 414 while (nbytes) {
981d1aa0697ce1 Boris Brezillon 2019-01-24 415 ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf);
981d1aa0697ce1 Boris Brezillon 2019-01-24 416 if (ret < 0)
7529df4652482c Peter Pan 2018-06-22 417 return ret;
7529df4652482c Peter Pan 2018-06-22 418
981d1aa0697ce1 Boris Brezillon 2019-01-24 419 if (!ret || ret > nbytes)
981d1aa0697ce1 Boris Brezillon 2019-01-24 420 return -EIO;
7529df4652482c Peter Pan 2018-06-22 421
981d1aa0697ce1 Boris Brezillon 2019-01-24 422 nbytes -= ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 423 column += ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 424 buf += ret;
631cfdd0520d19 Miquel Raynal 2024-08-26 425
631cfdd0520d19 Miquel Raynal 2024-08-26 426 /*
631cfdd0520d19 Miquel Raynal 2024-08-26 427 * Dirmap accesses are allowed to toggle the CS.
631cfdd0520d19 Miquel Raynal 2024-08-26 428 * Toggling the CS during a continuous read is forbidden.
631cfdd0520d19 Miquel Raynal 2024-08-26 429 */
631cfdd0520d19 Miquel Raynal 2024-08-26 430 if (nbytes && req->continuous)
631cfdd0520d19 Miquel Raynal 2024-08-26 431 return -EIO;
7529df4652482c Peter Pan 2018-06-22 432 }
7529df4652482c Peter Pan 2018-06-22 433
7529df4652482c Peter Pan 2018-06-22 434 if (req->datalen)
7529df4652482c Peter Pan 2018-06-22 435 memcpy(req->databuf.in, spinand->databuf + req->dataoffs,
7529df4652482c Peter Pan 2018-06-22 436 req->datalen);
7529df4652482c Peter Pan 2018-06-22 437
e708789c4a8798 Miquel Raynal 2021-01-07 438 if (req->ooblen) {
e708789c4a8798 Miquel Raynal 2021-01-07 439 if (req->mode == MTD_OPS_AUTO_OOB)
e708789c4a8798 Miquel Raynal 2021-01-07 440 mtd_ooblayout_get_databytes(mtd, req->oobbuf.in,
e708789c4a8798 Miquel Raynal 2021-01-07 441 spinand->oobbuf,
e708789c4a8798 Miquel Raynal 2021-01-07 442 req->ooboffs,
e708789c4a8798 Miquel Raynal 2021-01-07 443 req->ooblen);
e708789c4a8798 Miquel Raynal 2021-01-07 444 else
868cbe2a6dcee4 Miquel Raynal 2020-10-01 445 memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs,
868cbe2a6dcee4 Miquel Raynal 2020-10-01 446 req->ooblen);
e708789c4a8798 Miquel Raynal 2021-01-07 447 }
868cbe2a6dcee4 Miquel Raynal 2020-10-01 448
7529df4652482c Peter Pan 2018-06-22 449 return 0;
7529df4652482c Peter Pan 2018-06-22 450 }
7529df4652482c Peter Pan 2018-06-22 451
7529df4652482c Peter Pan 2018-06-22 452 static int spinand_write_to_cache_op(struct spinand_device *spinand,
7529df4652482c Peter Pan 2018-06-22 453 const struct nand_page_io_req *req)
7529df4652482c Peter Pan 2018-06-22 454 {
7529df4652482c Peter Pan 2018-06-22 455 struct nand_device *nand = spinand_to_nand(spinand);
3d1f08b032dc4e Miquel Raynal 2020-10-01 456 struct mtd_info *mtd = spinand_to_mtd(spinand);
981d1aa0697ce1 Boris Brezillon 2019-01-24 457 struct spi_mem_dirmap_desc *wdesc;
981d1aa0697ce1 Boris Brezillon 2019-01-24 458 unsigned int nbytes, column = 0;
13c15e07eedf26 Boris Brezillon 2019-01-24 459 void *buf = spinand->databuf;
981d1aa0697ce1 Boris Brezillon 2019-01-24 460 ssize_t ret;
7529df4652482c Peter Pan 2018-06-22 461
13c15e07eedf26 Boris Brezillon 2019-01-24 462 /*
13c15e07eedf26 Boris Brezillon 2019-01-24 463 * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
13c15e07eedf26 Boris Brezillon 2019-01-24 464 * the cache content to 0xFF (depends on vendor implementation), so we
13c15e07eedf26 Boris Brezillon 2019-01-24 465 * must fill the page cache entirely even if we only want to program
13c15e07eedf26 Boris Brezillon 2019-01-24 466 * the data portion of the page, otherwise we might corrupt the BBM or
13c15e07eedf26 Boris Brezillon 2019-01-24 467 * user data previously programmed in OOB area.
3d1f08b032dc4e Miquel Raynal 2020-10-01 468 *
3d1f08b032dc4e Miquel Raynal 2020-10-01 469 * Only reset the data buffer manually, the OOB buffer is prepared by
3d1f08b032dc4e Miquel Raynal 2020-10-01 470 * ECC engines ->prepare_io_req() callback.
13c15e07eedf26 Boris Brezillon 2019-01-24 471 */
13c15e07eedf26 Boris Brezillon 2019-01-24 472 nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
3d1f08b032dc4e Miquel Raynal 2020-10-01 473 memset(spinand->databuf, 0xff, nanddev_page_size(nand));
13c15e07eedf26 Boris Brezillon 2019-01-24 474
13c15e07eedf26 Boris Brezillon 2019-01-24 475 if (req->datalen)
13c15e07eedf26 Boris Brezillon 2019-01-24 476 memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
13c15e07eedf26 Boris Brezillon 2019-01-24 477 req->datalen);
7529df4652482c Peter Pan 2018-06-22 478
7529df4652482c Peter Pan 2018-06-22 479 if (req->ooblen) {
7529df4652482c Peter Pan 2018-06-22 480 if (req->mode == MTD_OPS_AUTO_OOB)
7529df4652482c Peter Pan 2018-06-22 481 mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
7529df4652482c Peter Pan 2018-06-22 482 spinand->oobbuf,
7529df4652482c Peter Pan 2018-06-22 483 req->ooboffs,
7529df4652482c Peter Pan 2018-06-22 484 req->ooblen);
7529df4652482c Peter Pan 2018-06-22 485 else
7529df4652482c Peter Pan 2018-06-22 486 memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
7529df4652482c Peter Pan 2018-06-22 487 req->ooblen);
7529df4652482c Peter Pan 2018-06-22 488 }
7529df4652482c Peter Pan 2018-06-22 489
f9d7c7265bcff7 Miquel Raynal 2022-01-27 490 if (req->mode == MTD_OPS_RAW)
981d1aa0697ce1 Boris Brezillon 2019-01-24 491 wdesc = spinand->dirmaps[req->pos.plane].wdesc;
f9d7c7265bcff7 Miquel Raynal 2022-01-27 492 else
f9d7c7265bcff7 Miquel Raynal 2022-01-27 493 wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc;
7529df4652482c Peter Pan 2018-06-22 494
ca229bdbef29be Cheng Ming Lin 2024-09-09 @495 if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT)
ca229bdbef29be Cheng Ming Lin 2024-09-09 496 column |= req->pos.plane << fls(nanddev_page_size(nand));
ca229bdbef29be Cheng Ming Lin 2024-09-09 497
7529df4652482c Peter Pan 2018-06-22 498 while (nbytes) {
981d1aa0697ce1 Boris Brezillon 2019-01-24 499 ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf);
981d1aa0697ce1 Boris Brezillon 2019-01-24 500 if (ret < 0)
7529df4652482c Peter Pan 2018-06-22 501 return ret;
7529df4652482c Peter Pan 2018-06-22 502
981d1aa0697ce1 Boris Brezillon 2019-01-24 503 if (!ret || ret > nbytes)
981d1aa0697ce1 Boris Brezillon 2019-01-24 504 return -EIO;
7529df4652482c Peter Pan 2018-06-22 505
981d1aa0697ce1 Boris Brezillon 2019-01-24 506 nbytes -= ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 507 column += ret;
981d1aa0697ce1 Boris Brezillon 2019-01-24 508 buf += ret;
7529df4652482c Peter Pan 2018-06-22 509 }
7529df4652482c Peter Pan 2018-06-22 510
7529df4652482c Peter Pan 2018-06-22 511 return 0;
7529df4652482c Peter Pan 2018-06-22 512 }
7529df4652482c Peter Pan 2018-06-22 513
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page
2024-10-20 13:27 ` Sky Huang
(?)
@ 2024-10-23 15:03 ` kernel test robot
-1 siblings, 0 replies; 29+ messages in thread
From: kernel test robot @ 2024-10-23 15:03 UTC (permalink / raw)
To: Sky Huang; +Cc: oe-kbuild-all
Hi Sky,
[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:
[auto build test ERROR on mtd/nand/next]
[also build test ERROR on mtd/mtd/next mtd/mtd/fixes linus/master v6.12-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sky-Huang/mtd-nand-Create-param-c-to-do-CRC-check-and-bitwise-majority-for-Parameter-CASN-page/20241020-212938
base: https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
patch link: https://lore.kernel.org/r/20241020132722.20565-2-SkyLake.Huang%40mediatek.com
patch subject: [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page
config: i386-randconfig-012-20241023 (https://download.01.org/0day-ci/archive/20241023/202410232209.VNMcFcd5-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241023/202410232209.VNMcFcd5-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410232209.VNMcFcd5-lkp@intel.com/
All errors (new ones prefixed by >>, old ones prefixed by <<):
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/devfreq/governor_powersave.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/fsi/fsi-master-gpio.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/fpga/tests/fpga-mgr-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/fpga/tests/fpga-bridge-test.o
WARNING: modpost: missing MODULE_DESCRIPTION() in drivers/fpga/tests/fpga-region-test.o
>> ERROR: modpost: "nanddev_crc16" [drivers/mtd/nand/raw/nand.ko] undefined!
>> ERROR: modpost: "nanddev_bit_wise_majority" [drivers/mtd/nand/raw/nand.ko] undefined!
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
2024-10-20 13:27 ` Sky Huang
@ 2024-10-28 15:25 ` SkyLake Huang (黃啟澤)
-1 siblings, 0 replies; 29+ messages in thread
From: SkyLake Huang (黃啟澤) @ 2024-10-28 15:25 UTC (permalink / raw)
To: miquel.raynal@bootlin.com, linux-kernel@vger.kernel.org,
linux-mtd@lists.infradead.org, linux-mediatek@lists.infradead.org,
acelan.kao@canonical.com, chengminglin@mxic.com.tw,
mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
On Sun, 2024-10-20 at 21:27 +0800, Sky Huang wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
> platforms
> chips, we have to quality lots of SPI-NAND devices and are eager for
> a standard so that we don't need to maintain trivial flash ID table
> anymore. I also noticed a talk in 2019 Embedded Linux Conference,
> Memory Technology Devices: what's new, which mentioned "ONFI for
> SPI-NANDs? Maybe, maybe not".
>
> So earlier this year, I proposed a bold idea, CASN page (Common
> Attributes
> for SPI-NAND). I worked together with top 3 SPI-NAND market share
> flash
> vendors and other vendors to integrate CASN page on their SPI-NAND
> devices
> including but not limited to:
>
gentle ping
BRs,
Sky
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-10-28 15:25 ` SkyLake Huang (黃啟澤)
0 siblings, 0 replies; 29+ messages in thread
From: SkyLake Huang (黃啟澤) @ 2024-10-28 15:25 UTC (permalink / raw)
To: miquel.raynal@bootlin.com, linux-kernel@vger.kernel.org,
linux-mtd@lists.infradead.org, linux-mediatek@lists.infradead.org,
acelan.kao@canonical.com, chengminglin@mxic.com.tw,
mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
On Sun, 2024-10-20 at 21:27 +0800, Sky Huang wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
> platforms
> chips, we have to quality lots of SPI-NAND devices and are eager for
> a standard so that we don't need to maintain trivial flash ID table
> anymore. I also noticed a talk in 2019 Embedded Linux Conference,
> Memory Technology Devices: what's new, which mentioned "ONFI for
> SPI-NANDs? Maybe, maybe not".
>
> So earlier this year, I proposed a bold idea, CASN page (Common
> Attributes
> for SPI-NAND). I worked together with top 3 SPI-NAND market share
> flash
> vendors and other vendors to integrate CASN page on their SPI-NAND
> devices
> including but not limited to:
>
gentle ping
BRs,
Sky
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
2024-10-28 15:25 ` SkyLake Huang (黃啟澤)
@ 2024-11-06 15:20 ` Miquel Raynal
-1 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-06 15:20 UTC (permalink / raw)
To: SkyLake Huang
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-mediatek@lists.infradead.org, acelan.kao@canonical.com,
chengminglin@mxic.com.tw, mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
Hello,
On 28/10/2024 at 15:25:59 GMT, SkyLake Huang (黃啟澤) <SkyLake.Huang@mediatek.com> wrote:
> On Sun, 2024-10-20 at 21:27 +0800, Sky Huang wrote:
>> From: "Sky Huang" <skylake.huang@mediatek.com>
>>
>> Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
>> platforms
>> chips, we have to quality lots of SPI-NAND devices and are eager for
>> a standard so that we don't need to maintain trivial flash ID table
>> anymore. I also noticed a talk in 2019 Embedded Linux Conference,
>> Memory Technology Devices: what's new, which mentioned "ONFI for
>> SPI-NANDs? Maybe, maybe not".
>>
>> So earlier this year, I proposed a bold idea, CASN page (Common
>> Attributes
>> for SPI-NAND). I worked together with top 3 SPI-NAND market share
>> flash
>> vendors and other vendors to integrate CASN page on their SPI-NAND
>> devices
>> including but not limited to:
>>
> gentle ping
I had a look at it, it is interesting but I have some questions and need
to come back to it. Unfortunately I was a bit busy these days. Sorry for
the delay.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-11-06 15:20 ` Miquel Raynal
0 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-06 15:20 UTC (permalink / raw)
To: SkyLake Huang
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-mediatek@lists.infradead.org, acelan.kao@canonical.com,
chengminglin@mxic.com.tw, mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
Hello,
On 28/10/2024 at 15:25:59 GMT, SkyLake Huang (黃啟澤) <SkyLake.Huang@mediatek.com> wrote:
> On Sun, 2024-10-20 at 21:27 +0800, Sky Huang wrote:
>> From: "Sky Huang" <skylake.huang@mediatek.com>
>>
>> Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
>> platforms
>> chips, we have to quality lots of SPI-NAND devices and are eager for
>> a standard so that we don't need to maintain trivial flash ID table
>> anymore. I also noticed a talk in 2019 Embedded Linux Conference,
>> Memory Technology Devices: what's new, which mentioned "ONFI for
>> SPI-NANDs? Maybe, maybe not".
>>
>> So earlier this year, I proposed a bold idea, CASN page (Common
>> Attributes
>> for SPI-NAND). I worked together with top 3 SPI-NAND market share
>> flash
>> vendors and other vendors to integrate CASN page on their SPI-NAND
>> devices
>> including but not limited to:
>>
> gentle ping
I had a look at it, it is interesting but I have some questions and need
to come back to it. Unfortunately I was a bit busy these days. Sorry for
the delay.
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
2024-10-20 13:27 ` Sky Huang
@ 2024-11-18 10:53 ` Miquel Raynal
-1 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 10:53 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:18 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router platforms
> chips, we have to quality lots of SPI-NAND devices and are eager for
> a standard so that we don't need to maintain trivial flash ID table
> anymore. I also noticed a talk in 2019 Embedded Linux Conference,
> Memory Technology Devices: what's new, which mentioned "ONFI for
> SPI-NANDs? Maybe, maybe not".
>
> So earlier this year, I proposed a bold idea, CASN page (Common Attributes
> for SPI-NAND). I worked together with top 3 SPI-NAND market share flash
> vendors and other vendors to integrate CASN page on their SPI-NAND devices
> including but not limited to:
> [ESMT]
> F50L1G41LB
> F50L2G41KA
>
> [Etron]
> EM73C044VCF-H
> EM73D044VCO-H
> EM73E044VCE-H
> EM73F044VCA-H
>
> [GigaDevice]
> GD5F1GM7UE
> GD5F1GQ5UEYIG
> GD5F2GM7UE
> GD5F2GQ5UEYIG
> GD5F4GM8UE
> GD5F4GQ6UEYIG
>
> [Macronix (MXIC)]
> MX35LF1GE4ABZ4IG
>
> [Winbond]
> W25N01GV
> W25N01KV
> W25N02KV
> W25N04KV
>
> A document of CASN is hosted on github(https://github.com/mtk-openwrt/
> doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep it
> simple here.
>
> With CASN page, we don't need to maintain SPI-NAND flash ID table anymore.
> Currently, it's integrated in 3.3V SPI-NANDs of small density and it's not
> JEDEC standard yet. But it should be able to handle 1.8V and can be easily
> integrated by flash vendors.
>
> I believe this idea and implementation have room for improvement. Hope to
> hear you open source community's comments soon.
I think this is a bright initiative. I'd welcome some standardisation on
the discovery indeed.
But to be really useful, I believe this table must be really complete,
otherwise ID's will remain. For instance SDR/DDR modes are not entirely
defined as we already have mixed modes. There is also no information
about what maximum frequencies can be used with each operation. As
another example, there is no read retry information. Nor anything about
the fact that the on-die ECC engine might not be disabled.
Overall I think this is an interesting initiative but I would like it to
be more advanced. Is there a plan on getting this standardized through
eg. a JEDEC spec?
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-11-18 10:53 ` Miquel Raynal
0 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 10:53 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:18 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router platforms
> chips, we have to quality lots of SPI-NAND devices and are eager for
> a standard so that we don't need to maintain trivial flash ID table
> anymore. I also noticed a talk in 2019 Embedded Linux Conference,
> Memory Technology Devices: what's new, which mentioned "ONFI for
> SPI-NANDs? Maybe, maybe not".
>
> So earlier this year, I proposed a bold idea, CASN page (Common Attributes
> for SPI-NAND). I worked together with top 3 SPI-NAND market share flash
> vendors and other vendors to integrate CASN page on their SPI-NAND devices
> including but not limited to:
> [ESMT]
> F50L1G41LB
> F50L2G41KA
>
> [Etron]
> EM73C044VCF-H
> EM73D044VCO-H
> EM73E044VCE-H
> EM73F044VCA-H
>
> [GigaDevice]
> GD5F1GM7UE
> GD5F1GQ5UEYIG
> GD5F2GM7UE
> GD5F2GQ5UEYIG
> GD5F4GM8UE
> GD5F4GQ6UEYIG
>
> [Macronix (MXIC)]
> MX35LF1GE4ABZ4IG
>
> [Winbond]
> W25N01GV
> W25N01KV
> W25N02KV
> W25N04KV
>
> A document of CASN is hosted on github(https://github.com/mtk-openwrt/
> doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep it
> simple here.
>
> With CASN page, we don't need to maintain SPI-NAND flash ID table anymore.
> Currently, it's integrated in 3.3V SPI-NANDs of small density and it's not
> JEDEC standard yet. But it should be able to handle 1.8V and can be easily
> integrated by flash vendors.
>
> I believe this idea and implementation have room for improvement. Hope to
> hear you open source community's comments soon.
I think this is a bright initiative. I'd welcome some standardisation on
the discovery indeed.
But to be really useful, I believe this table must be really complete,
otherwise ID's will remain. For instance SDR/DDR modes are not entirely
defined as we already have mixed modes. There is also no information
about what maximum frequencies can be used with each operation. As
another example, there is no read retry information. Nor anything about
the fact that the on-die ECC engine might not be disabled.
Overall I think this is an interesting initiative but I would like it to
be more advanced. Is there a plan on getting this standardized through
eg. a JEDEC spec?
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page
2024-10-20 13:27 ` Sky Huang
@ 2024-11-18 10:55 ` Miquel Raynal
-1 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 10:55 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:19 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky.Huang" <skylake.huang@mediatek.com>
>
> Create drivers/mtd/nand/param.c so ONFI parameter page & CASN page
> can both use nanddev_crc16() and nanddev_bit_wise_majority() directly
> like this:
> * For ONFI Parameter page:
> onfi_crc16() -> nanddev_crc16()
> * For CASN page: nanddev_crc16()
>
> nanddev_bit_wise_majority() is same as nand_bit_wise_majority().
Please use the same nanddev_ prefix.
> nanddev_crc16() is same as onfi_crc16(). But there are lots of
> onfi_crc16() call, so keep onfi_crc16() there and hook it to
> nanddev_crc16().
>
> Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page
@ 2024-11-18 10:55 ` Miquel Raynal
0 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 10:55 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:19 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky.Huang" <skylake.huang@mediatek.com>
>
> Create drivers/mtd/nand/param.c so ONFI parameter page & CASN page
> can both use nanddev_crc16() and nanddev_bit_wise_majority() directly
> like this:
> * For ONFI Parameter page:
> onfi_crc16() -> nanddev_crc16()
> * For CASN page: nanddev_crc16()
>
> nanddev_bit_wise_majority() is same as nand_bit_wise_majority().
Please use the same nanddev_ prefix.
> nanddev_crc16() is same as onfi_crc16(). But there are lots of
> onfi_crc16() call, so keep onfi_crc16() there and hook it to
> nanddev_crc16().
>
> Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 2/4] include: mtd: Add CASN page definition and related structs.
2024-10-20 13:27 ` Sky Huang
@ 2024-11-18 10:58 ` Miquel Raynal
-1 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 10:58 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:20 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> This patch adds CASN page definition. You can see corresponding
> table in CASN page application note referred in cover letter.
> (https://github.com/mtk-openwrt/doc/blob/
> main/CASN%20Page%20Introduction.pdf)
Please don't break URLs. They become no longer clickable.
>
> +
> +struct SPINAND_FLAGS {
No upper case struct type please.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 2/4] include: mtd: Add CASN page definition and related structs.
@ 2024-11-18 10:58 ` Miquel Raynal
0 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 10:58 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:20 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> This patch adds CASN page definition. You can see corresponding
> table in CASN page application note referred in cover letter.
> (https://github.com/mtk-openwrt/doc/blob/
> main/CASN%20Page%20Introduction.pdf)
Please don't break URLs. They become no longer clickable.
>
> +
> +struct SPINAND_FLAGS {
No upper case struct type please.
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
2024-10-20 13:27 ` Sky Huang
@ 2024-11-18 13:06 ` Miquel Raynal
-1 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 13:06 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:21 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> This patch adds SPINAND CASN page manipulation macros for
> SPI-NAND driver to use. Also, some important flag bits, like
> SPINAND_SUPR_CR(continuous read), are added to show the
> SPI-NAND device's capability.
>
> Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
> ---
> include/linux/mtd/spinand.h | 100 +++++++++++++++++++++++++++++++++++-
> 1 file changed, 98 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index 702e5fb13dae..de97994c357b 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -62,6 +62,59 @@
> SPI_MEM_OP_NO_DUMMY, \
> SPI_MEM_OP_NO_DATA)
>
> +/* Macros for CASN */
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(fast, naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_DUMMY(ndummy, 1), \
> + SPI_MEM_OP_DATA_IN(len, buf, 1))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X2_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_DUMMY(ndummy, 1), \
> + SPI_MEM_OP_DATA_IN(len, buf, 2))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_DUALIO_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 2), \
> + SPI_MEM_OP_DUMMY(ndummy, 2), \
> + SPI_MEM_OP_DATA_IN(len, buf, 2))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X4_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_DUMMY(ndummy, 1), \
> + SPI_MEM_OP_DATA_IN(len, buf, 4))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_QUADIO_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 4), \
> + SPI_MEM_OP_DUMMY(ndummy, 4), \
> + SPI_MEM_OP_DATA_IN(len, buf, 4))
> +
> +#define SPINAND_CASN_PROG_LOAD(reset, naddr, addr, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_NO_DUMMY, \
> + SPI_MEM_OP_DATA_OUT(len, buf, 1))
> +
> +#define SPINAND_CASN_PROG_LOAD_X4(reset, naddr, addr, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x32 : 0x34, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_NO_DUMMY, \
> + SPI_MEM_OP_DATA_OUT(len, buf, 4))
Why would you need to redefine all these?
> +
> +#define SPINAND_CASN_ADVECC_OP(casn_adv_ecc_status, buf) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(casn_adv_ecc_status.cmd, 1), \
> + SPI_MEM_OP_ADDR(casn_adv_ecc_status.addr_nbytes, \
> + casn_adv_ecc_status.addr, \
> + casn_adv_ecc_status.addr_buswidth), \
> + SPI_MEM_OP_DUMMY(casn_adv_ecc_status.dummy_nbytes, \
> + casn_adv_ecc_status.dummy_buswidth), \
> + SPI_MEM_OP_DATA_IN(casn_adv_ecc_status.status_nbytes, buf, 1))
> +/* Macros for CASN end */
> +
> #define SPINAND_PAGE_READ_FROM_CACHE_OP(fast, addr, ndummy, buf, len) \
> SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
> SPI_MEM_OP_ADDR(2, addr, 1), \
> @@ -312,8 +365,11 @@ struct spinand_ecc_info {
>
> #define SPINAND_HAS_QE_BIT BIT(0)
> #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)
Why do you remove that?
> +#define SPINAND_SUP_CR BIT(2)
> +#define SPINAND_SUP_ON_DIE_ECC BIT(3)
> +#define SPINAND_SUP_LEGACY_ECC_STATUS BIT(4)
> +#define SPINAND_SUP_ADV_ECC_STATUS BIT(5)
> +#define SPINAND_ECC_PARITY_READABLE BIT(6)
>
> /**
> * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
> @@ -406,6 +462,28 @@ struct spinand_dirmap {
> struct spi_mem_dirmap_desc *rdesc_ecc;
> };
>
> +/**
> + * struct CASN_ADVECC - CASN's advanced ECC description
> + * @cmd: Command to access SPI-NAND on-chip ECC status registers
> + * @mask: Mask to access SPI-NAND on-chip ECC status registers.
> + * ADV_ECC_STATUS->status_nbytes | CASN_ADVECC->mask
> + * 1 | 0 to 0xff
> + * 2 | 0 to 0xffff
> + * @shift: How many bits to shift to get on-chip ECC status
> + * @pre_op: This comes from CASN page's ADV_ECC_STATUS's pre_op.
> + * After reading on-chip ECC status, we need to do some math
> + * operations if this is specified.
I'm not sure I understand how you'll encode a math operation there.
> + * @pre_mask: This comes from CASN page's ADV_ECC_STATUS's pre_mask.
> + * This is used in companion with pre_op above.
> + */
> +struct CASN_ADVECC {
This is usually changing when continuous reads are enabled, it would
need to be handled.
> + u8 cmd;
> + u16 mask;
> + u8 shift;
> + u8 pre_op;
> + u8 pre_mask;
> +};
> +
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags.
@ 2024-11-18 13:06 ` Miquel Raynal
0 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-18 13:06 UTC (permalink / raw)
To: Sky Huang
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Richard Weinberger,
Vignesh Raghavendra, Daniel Golle, Chia-Lin Kao, Mika Westerberg,
Cheng Ming Lin, linux-kernel, linux-mtd, linux-arm-kernel,
linux-mediatek, Steven Liu
On 20/10/2024 at 21:27:21 +08, Sky Huang <SkyLake.Huang@mediatek.com> wrote:
> From: "Sky Huang" <skylake.huang@mediatek.com>
>
> This patch adds SPINAND CASN page manipulation macros for
> SPI-NAND driver to use. Also, some important flag bits, like
> SPINAND_SUPR_CR(continuous read), are added to show the
> SPI-NAND device's capability.
>
> Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
> ---
> include/linux/mtd/spinand.h | 100 +++++++++++++++++++++++++++++++++++-
> 1 file changed, 98 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index 702e5fb13dae..de97994c357b 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -62,6 +62,59 @@
> SPI_MEM_OP_NO_DUMMY, \
> SPI_MEM_OP_NO_DATA)
>
> +/* Macros for CASN */
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_OP(fast, naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_DUMMY(ndummy, 1), \
> + SPI_MEM_OP_DATA_IN(len, buf, 1))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X2_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_DUMMY(ndummy, 1), \
> + SPI_MEM_OP_DATA_IN(len, buf, 2))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_DUALIO_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 2), \
> + SPI_MEM_OP_DUMMY(ndummy, 2), \
> + SPI_MEM_OP_DATA_IN(len, buf, 2))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_X4_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_DUMMY(ndummy, 1), \
> + SPI_MEM_OP_DATA_IN(len, buf, 4))
> +
> +#define SPINAND_CASN_PAGE_READ_FROM_CACHE_QUADIO_OP(naddr, addr, ndummy, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 4), \
> + SPI_MEM_OP_DUMMY(ndummy, 4), \
> + SPI_MEM_OP_DATA_IN(len, buf, 4))
> +
> +#define SPINAND_CASN_PROG_LOAD(reset, naddr, addr, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_NO_DUMMY, \
> + SPI_MEM_OP_DATA_OUT(len, buf, 1))
> +
> +#define SPINAND_CASN_PROG_LOAD_X4(reset, naddr, addr, buf, len) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x32 : 0x34, 1), \
> + SPI_MEM_OP_ADDR(naddr, addr, 1), \
> + SPI_MEM_OP_NO_DUMMY, \
> + SPI_MEM_OP_DATA_OUT(len, buf, 4))
Why would you need to redefine all these?
> +
> +#define SPINAND_CASN_ADVECC_OP(casn_adv_ecc_status, buf) \
> + SPI_MEM_OP(SPI_MEM_OP_CMD(casn_adv_ecc_status.cmd, 1), \
> + SPI_MEM_OP_ADDR(casn_adv_ecc_status.addr_nbytes, \
> + casn_adv_ecc_status.addr, \
> + casn_adv_ecc_status.addr_buswidth), \
> + SPI_MEM_OP_DUMMY(casn_adv_ecc_status.dummy_nbytes, \
> + casn_adv_ecc_status.dummy_buswidth), \
> + SPI_MEM_OP_DATA_IN(casn_adv_ecc_status.status_nbytes, buf, 1))
> +/* Macros for CASN end */
> +
> #define SPINAND_PAGE_READ_FROM_CACHE_OP(fast, addr, ndummy, buf, len) \
> SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \
> SPI_MEM_OP_ADDR(2, addr, 1), \
> @@ -312,8 +365,11 @@ struct spinand_ecc_info {
>
> #define SPINAND_HAS_QE_BIT BIT(0)
> #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)
Why do you remove that?
> +#define SPINAND_SUP_CR BIT(2)
> +#define SPINAND_SUP_ON_DIE_ECC BIT(3)
> +#define SPINAND_SUP_LEGACY_ECC_STATUS BIT(4)
> +#define SPINAND_SUP_ADV_ECC_STATUS BIT(5)
> +#define SPINAND_ECC_PARITY_READABLE BIT(6)
>
> /**
> * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
> @@ -406,6 +462,28 @@ struct spinand_dirmap {
> struct spi_mem_dirmap_desc *rdesc_ecc;
> };
>
> +/**
> + * struct CASN_ADVECC - CASN's advanced ECC description
> + * @cmd: Command to access SPI-NAND on-chip ECC status registers
> + * @mask: Mask to access SPI-NAND on-chip ECC status registers.
> + * ADV_ECC_STATUS->status_nbytes | CASN_ADVECC->mask
> + * 1 | 0 to 0xff
> + * 2 | 0 to 0xffff
> + * @shift: How many bits to shift to get on-chip ECC status
> + * @pre_op: This comes from CASN page's ADV_ECC_STATUS's pre_op.
> + * After reading on-chip ECC status, we need to do some math
> + * operations if this is specified.
I'm not sure I understand how you'll encode a math operation there.
> + * @pre_mask: This comes from CASN page's ADV_ECC_STATUS's pre_mask.
> + * This is used in companion with pre_op above.
> + */
> +struct CASN_ADVECC {
This is usually changing when continuous reads are enabled, it would
need to be handled.
> + u8 cmd;
> + u16 mask;
> + u8 shift;
> + u8 pre_op;
> + u8 pre_mask;
> +};
> +
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
2024-11-18 10:53 ` Miquel Raynal
@ 2024-11-20 7:24 ` SkyLake Huang (黃啟澤)
-1 siblings, 0 replies; 29+ messages in thread
From: SkyLake Huang (黃啟澤) @ 2024-11-20 7:24 UTC (permalink / raw)
To: miquel.raynal@bootlin.com
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-mediatek@lists.infradead.org, acelan.kao@canonical.com,
chengminglin@mxic.com.tw, mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org,
Steven Liu (劉人豪), matthias.bgg@gmail.com,
daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
On Mon, 2024-11-18 at 11:53 +0100, Miquel Raynal wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On 20/10/2024 at 21:27:18 +08, Sky Huang <SkyLake.Huang@mediatek.com>
> wrote:
>
> > From: "Sky Huang" <skylake.huang@mediatek.com>
> >
> > Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
> > platforms
> > chips, we have to quality lots of SPI-NAND devices and are eager
> > for
> > a standard so that we don't need to maintain trivial flash ID table
> > anymore. I also noticed a talk in 2019 Embedded Linux Conference,
> > Memory Technology Devices: what's new, which mentioned "ONFI for
> > SPI-NANDs? Maybe, maybe not".
> >
> > So earlier this year, I proposed a bold idea, CASN page (Common
> > Attributes
> > for SPI-NAND). I worked together with top 3 SPI-NAND market share
> > flash
> > vendors and other vendors to integrate CASN page on their SPI-NAND
> > devices
> > including but not limited to:
> > [ESMT]
> > F50L1G41LB
> > F50L2G41KA
> >
> > [Etron]
> > EM73C044VCF-H
> > EM73D044VCO-H
> > EM73E044VCE-H
> > EM73F044VCA-H
> >
> > [GigaDevice]
> > GD5F1GM7UE
> > GD5F1GQ5UEYIG
> > GD5F2GM7UE
> > GD5F2GQ5UEYIG
> > GD5F4GM8UE
> > GD5F4GQ6UEYIG
> >
> > [Macronix (MXIC)]
> > MX35LF1GE4ABZ4IG
> >
> > [Winbond]
> > W25N01GV
> > W25N01KV
> > W25N02KV
> > W25N04KV
> >
> > A document of CASN is hosted on github(
> > https://urldefense.com/v3/__https://github.com/mtk-openwrt/__;!!CTRNKA9wMg0ARbw!j_TES7dJ_An-9wtyQqWgGBE9ovPnUA-tDNlZ-pGpUdYv4gphzW4v54Fal8i_nLwSmPAzK9ApgSBG1XQ_mREdTS0ZwrBWRA$
> > doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep
> > it
> > simple here.
> >
> > With CASN page, we don't need to maintain SPI-NAND flash ID table
> > anymore.
> > Currently, it's integrated in 3.3V SPI-NANDs of small density and
> > it's not
> > JEDEC standard yet. But it should be able to handle 1.8V and can be
> > easily
> > integrated by flash vendors.
> >
> > I believe this idea and implementation have room for improvement.
> > Hope to
> > hear you open source community's comments soon.
>
> I think this is a bright initiative. I'd welcome some standardisation
> on
> the discovery indeed.
>
> But to be really useful, I believe this table must be really
> complete,
> otherwise ID's will remain. For instance SDR/DDR modes are not
> entirely
> defined as we already have mixed modes. There is also no information
> about what maximum frequencies can be used with each operation.
Maximum frequencies are limited by SPI controller's max freq now, I
guess?
> As
> another example, there is no read retry information.
What will retry information look like?
> Nor anything about
> the fact that the on-die ECC engine might not be disabled.
As far as I know, only SkyHigh's SPI-NAND's ECC engine can't be
disabled since its on-die ECC engine contains randomizer.
There are some reserved fields. We can handle above requirements in
CASN V1.2 or V2. But may I ask what's the purpose of involving above
information in CASN? Are there any practical application scenarios?
>
> Overall I think this is an interesting initiative but I would like it
> to
> be more advanced.
Agree.
> Is there a plan on getting this standardized through
> eg. a JEDEC spec?
>
> Thanks,
> Miquèl
Yes. We're working on it. But it will take some time. Your opinions
mean a lot to CASN page standardisation.
BRs,
Sky
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-11-20 7:24 ` SkyLake Huang (黃啟澤)
0 siblings, 0 replies; 29+ messages in thread
From: SkyLake Huang (黃啟澤) @ 2024-11-20 7:24 UTC (permalink / raw)
To: miquel.raynal@bootlin.com
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-mediatek@lists.infradead.org, acelan.kao@canonical.com,
chengminglin@mxic.com.tw, mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org,
Steven Liu (劉人豪), matthias.bgg@gmail.com,
daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
On Mon, 2024-11-18 at 11:53 +0100, Miquel Raynal wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> On 20/10/2024 at 21:27:18 +08, Sky Huang <SkyLake.Huang@mediatek.com>
> wrote:
>
> > From: "Sky Huang" <skylake.huang@mediatek.com>
> >
> > Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
> > platforms
> > chips, we have to quality lots of SPI-NAND devices and are eager
> > for
> > a standard so that we don't need to maintain trivial flash ID table
> > anymore. I also noticed a talk in 2019 Embedded Linux Conference,
> > Memory Technology Devices: what's new, which mentioned "ONFI for
> > SPI-NANDs? Maybe, maybe not".
> >
> > So earlier this year, I proposed a bold idea, CASN page (Common
> > Attributes
> > for SPI-NAND). I worked together with top 3 SPI-NAND market share
> > flash
> > vendors and other vendors to integrate CASN page on their SPI-NAND
> > devices
> > including but not limited to:
> > [ESMT]
> > F50L1G41LB
> > F50L2G41KA
> >
> > [Etron]
> > EM73C044VCF-H
> > EM73D044VCO-H
> > EM73E044VCE-H
> > EM73F044VCA-H
> >
> > [GigaDevice]
> > GD5F1GM7UE
> > GD5F1GQ5UEYIG
> > GD5F2GM7UE
> > GD5F2GQ5UEYIG
> > GD5F4GM8UE
> > GD5F4GQ6UEYIG
> >
> > [Macronix (MXIC)]
> > MX35LF1GE4ABZ4IG
> >
> > [Winbond]
> > W25N01GV
> > W25N01KV
> > W25N02KV
> > W25N04KV
> >
> > A document of CASN is hosted on github(
> > https://urldefense.com/v3/__https://github.com/mtk-openwrt/__;!!CTRNKA9wMg0ARbw!j_TES7dJ_An-9wtyQqWgGBE9ovPnUA-tDNlZ-pGpUdYv4gphzW4v54Fal8i_nLwSmPAzK9ApgSBG1XQ_mREdTS0ZwrBWRA$
> > doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep
> > it
> > simple here.
> >
> > With CASN page, we don't need to maintain SPI-NAND flash ID table
> > anymore.
> > Currently, it's integrated in 3.3V SPI-NANDs of small density and
> > it's not
> > JEDEC standard yet. But it should be able to handle 1.8V and can be
> > easily
> > integrated by flash vendors.
> >
> > I believe this idea and implementation have room for improvement.
> > Hope to
> > hear you open source community's comments soon.
>
> I think this is a bright initiative. I'd welcome some standardisation
> on
> the discovery indeed.
>
> But to be really useful, I believe this table must be really
> complete,
> otherwise ID's will remain. For instance SDR/DDR modes are not
> entirely
> defined as we already have mixed modes. There is also no information
> about what maximum frequencies can be used with each operation.
Maximum frequencies are limited by SPI controller's max freq now, I
guess?
> As
> another example, there is no read retry information.
What will retry information look like?
> Nor anything about
> the fact that the on-die ECC engine might not be disabled.
As far as I know, only SkyHigh's SPI-NAND's ECC engine can't be
disabled since its on-die ECC engine contains randomizer.
There are some reserved fields. We can handle above requirements in
CASN V1.2 or V2. But may I ask what's the purpose of involving above
information in CASN? Are there any practical application scenarios?
>
> Overall I think this is an interesting initiative but I would like it
> to
> be more advanced.
Agree.
> Is there a plan on getting this standardized through
> eg. a JEDEC spec?
>
> Thanks,
> Miquèl
Yes. We're working on it. But it will take some time. Your opinions
mean a lot to CASN page standardisation.
BRs,
Sky
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
2024-11-20 7:24 ` SkyLake Huang (黃啟澤)
@ 2024-11-20 10:13 ` Miquel Raynal
-1 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-20 10:13 UTC (permalink / raw)
To: SkyLake Huang
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-mediatek@lists.infradead.org, acelan.kao@canonical.com,
chengminglin@mxic.com.tw, mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org, Steven Liu,
matthias.bgg@gmail.com, daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
On 20/11/2024 at 07:24:28 GMT, SkyLake Huang (黃啟澤) <SkyLake.Huang@mediatek.com> wrote:
> On Mon, 2024-11-18 at 11:53 +0100, Miquel Raynal wrote:
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>
>>
>> On 20/10/2024 at 21:27:18 +08, Sky Huang <SkyLake.Huang@mediatek.com>
>> wrote:
>>
>> > From: "Sky Huang" <skylake.huang@mediatek.com>
>> >
>> > Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
>> > platforms
>> > chips, we have to quality lots of SPI-NAND devices and are eager
>> > for
>> > a standard so that we don't need to maintain trivial flash ID table
>> > anymore. I also noticed a talk in 2019 Embedded Linux Conference,
>> > Memory Technology Devices: what's new, which mentioned "ONFI for
>> > SPI-NANDs? Maybe, maybe not".
>> >
>> > So earlier this year, I proposed a bold idea, CASN page (Common
>> > Attributes
>> > for SPI-NAND). I worked together with top 3 SPI-NAND market share
>> > flash
>> > vendors and other vendors to integrate CASN page on their SPI-NAND
>> > devices
>> > including but not limited to:
>> > [ESMT]
>> > F50L1G41LB
>> > F50L2G41KA
>> >
>> > [Etron]
>> > EM73C044VCF-H
>> > EM73D044VCO-H
>> > EM73E044VCE-H
>> > EM73F044VCA-H
>> >
>> > [GigaDevice]
>> > GD5F1GM7UE
>> > GD5F1GQ5UEYIG
>> > GD5F2GM7UE
>> > GD5F2GQ5UEYIG
>> > GD5F4GM8UE
>> > GD5F4GQ6UEYIG
>> >
>> > [Macronix (MXIC)]
>> > MX35LF1GE4ABZ4IG
>> >
>> > [Winbond]
>> > W25N01GV
>> > W25N01KV
>> > W25N02KV
>> > W25N04KV
>> >
>> > A document of CASN is hosted on github(
>> > https://urldefense.com/v3/__https://github.com/mtk-openwrt/__;!!CTRNKA9wMg0ARbw!j_TES7dJ_An-9wtyQqWgGBE9ovPnUA-tDNlZ-pGpUdYv4gphzW4v54Fal8i_nLwSmPAzK9ApgSBG1XQ_mREdTS0ZwrBWRA$
>> > doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep
>> > it
>> > simple here.
>> >
>> > With CASN page, we don't need to maintain SPI-NAND flash ID table
>> > anymore.
>> > Currently, it's integrated in 3.3V SPI-NANDs of small density and
>> > it's not
>> > JEDEC standard yet. But it should be able to handle 1.8V and can be
>> > easily
>> > integrated by flash vendors.
>> >
>> > I believe this idea and implementation have room for improvement.
>> > Hope to
>> > hear you open source community's comments soon.
>>
>> I think this is a bright initiative. I'd welcome some standardisation
>> on
>> the discovery indeed.
>>
>> But to be really useful, I believe this table must be really
>> complete,
>> otherwise ID's will remain. For instance SDR/DDR modes are not
>> entirely
>> defined as we already have mixed modes. There is also no information
>> about what maximum frequencies can be used with each operation.
>
> Maximum frequencies are limited by SPI controller's max freq now, I
> guess?
No, this is just the PCB/controller limitation. But there are chips with
frequency limitations depending on the type of command (see for instance
Winbond AC timings tables for DDR capable devices).
>> As
>> another example, there is no read retry information.
> What will retry information look like?
Number of retry modes, how to enable retry mode (which is maybe
standardized per manufacturer, in this case we can just get the right
hook from the manufacturer information, but otherwise if there are
differences inside production lines from a single manufacturer, we'll
still need either a table or some extension of CASN.
>> Nor anything about
>> the fact that the on-die ECC engine might not be disabled.
> As far as I know, only SkyHigh's SPI-NAND's ECC engine can't be
> disabled since its on-die ECC engine contains randomizer.
Randomizer and ECC engine are two different things, there are many raw
NAND controllers with a programmable ECC engine *and* randomizer. They
just choose to hide the controls.
Today it is SkyHigh. What about tomorrow?
> There are some reserved fields. We can handle above requirements in
> CASN V1.2 or V2. But may I ask what's the purpose of involving above
> information in CASN? Are there any practical application scenarios?
You claim you want to replace the ID tables. These tables are filled
with all the relevant data to make the chips supported in Linux. If one
of these fields is missing from CASN, it means we need to keep the
tables. So it kind of defeats the CASN purpose. Yes we may have dynamic
vendor hooks to adapt these parameters "on the fly", but we still need
internal tables for that.
>> Overall I think this is an interesting initiative but I would like it
>> to
>> be more advanced.
> Agree.
>
>> Is there a plan on getting this standardized through
>> eg. a JEDEC spec?
>>
>> Thanks,
>> Miquèl
> Yes. We're working on it. But it will take some time. Your opinions
> mean a lot to CASN page standardisation.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support
@ 2024-11-20 10:13 ` Miquel Raynal
0 siblings, 0 replies; 29+ messages in thread
From: Miquel Raynal @ 2024-11-20 10:13 UTC (permalink / raw)
To: SkyLake Huang
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
linux-mediatek@lists.infradead.org, acelan.kao@canonical.com,
chengminglin@mxic.com.tw, mika.westerberg@linux.intel.com,
linux-arm-kernel@lists.infradead.org, Steven Liu,
matthias.bgg@gmail.com, daniel@makrotopia.org, vigneshr@ti.com,
AngeloGioacchino Del Regno, richard@nod.at
On 20/11/2024 at 07:24:28 GMT, SkyLake Huang (黃啟澤) <SkyLake.Huang@mediatek.com> wrote:
> On Mon, 2024-11-18 at 11:53 +0100, Miquel Raynal wrote:
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>
>>
>> On 20/10/2024 at 21:27:18 +08, Sky Huang <SkyLake.Huang@mediatek.com>
>> wrote:
>>
>> > From: "Sky Huang" <skylake.huang@mediatek.com>
>> >
>> > Hi, this is Qi-Ze Huang(Sky Huang) from MediaTek. On our router
>> > platforms
>> > chips, we have to quality lots of SPI-NAND devices and are eager
>> > for
>> > a standard so that we don't need to maintain trivial flash ID table
>> > anymore. I also noticed a talk in 2019 Embedded Linux Conference,
>> > Memory Technology Devices: what's new, which mentioned "ONFI for
>> > SPI-NANDs? Maybe, maybe not".
>> >
>> > So earlier this year, I proposed a bold idea, CASN page (Common
>> > Attributes
>> > for SPI-NAND). I worked together with top 3 SPI-NAND market share
>> > flash
>> > vendors and other vendors to integrate CASN page on their SPI-NAND
>> > devices
>> > including but not limited to:
>> > [ESMT]
>> > F50L1G41LB
>> > F50L2G41KA
>> >
>> > [Etron]
>> > EM73C044VCF-H
>> > EM73D044VCO-H
>> > EM73E044VCE-H
>> > EM73F044VCA-H
>> >
>> > [GigaDevice]
>> > GD5F1GM7UE
>> > GD5F1GQ5UEYIG
>> > GD5F2GM7UE
>> > GD5F2GQ5UEYIG
>> > GD5F4GM8UE
>> > GD5F4GQ6UEYIG
>> >
>> > [Macronix (MXIC)]
>> > MX35LF1GE4ABZ4IG
>> >
>> > [Winbond]
>> > W25N01GV
>> > W25N01KV
>> > W25N02KV
>> > W25N04KV
>> >
>> > A document of CASN is hosted on github(
>> > https://urldefense.com/v3/__https://github.com/mtk-openwrt/__;!!CTRNKA9wMg0ARbw!j_TES7dJ_An-9wtyQqWgGBE9ovPnUA-tDNlZ-pGpUdYv4gphzW4v54Fal8i_nLwSmPAzK9ApgSBG1XQ_mREdTS0ZwrBWRA$
>> > doc/blob/main/CASN%20Page%20Introduction.pdf) So I'll try to keep
>> > it
>> > simple here.
>> >
>> > With CASN page, we don't need to maintain SPI-NAND flash ID table
>> > anymore.
>> > Currently, it's integrated in 3.3V SPI-NANDs of small density and
>> > it's not
>> > JEDEC standard yet. But it should be able to handle 1.8V and can be
>> > easily
>> > integrated by flash vendors.
>> >
>> > I believe this idea and implementation have room for improvement.
>> > Hope to
>> > hear you open source community's comments soon.
>>
>> I think this is a bright initiative. I'd welcome some standardisation
>> on
>> the discovery indeed.
>>
>> But to be really useful, I believe this table must be really
>> complete,
>> otherwise ID's will remain. For instance SDR/DDR modes are not
>> entirely
>> defined as we already have mixed modes. There is also no information
>> about what maximum frequencies can be used with each operation.
>
> Maximum frequencies are limited by SPI controller's max freq now, I
> guess?
No, this is just the PCB/controller limitation. But there are chips with
frequency limitations depending on the type of command (see for instance
Winbond AC timings tables for DDR capable devices).
>> As
>> another example, there is no read retry information.
> What will retry information look like?
Number of retry modes, how to enable retry mode (which is maybe
standardized per manufacturer, in this case we can just get the right
hook from the manufacturer information, but otherwise if there are
differences inside production lines from a single manufacturer, we'll
still need either a table or some extension of CASN.
>> Nor anything about
>> the fact that the on-die ECC engine might not be disabled.
> As far as I know, only SkyHigh's SPI-NAND's ECC engine can't be
> disabled since its on-die ECC engine contains randomizer.
Randomizer and ECC engine are two different things, there are many raw
NAND controllers with a programmable ECC engine *and* randomizer. They
just choose to hide the controls.
Today it is SkyHigh. What about tomorrow?
> There are some reserved fields. We can handle above requirements in
> CASN V1.2 or V2. But may I ask what's the purpose of involving above
> information in CASN? Are there any practical application scenarios?
You claim you want to replace the ID tables. These tables are filled
with all the relevant data to make the chips supported in Linux. If one
of these fields is missing from CASN, it means we need to keep the
tables. So it kind of defeats the CASN purpose. Yes we may have dynamic
vendor hooks to adapt these parameters "on the fly", but we still need
internal tables for that.
>> Overall I think this is an interesting initiative but I would like it
>> to
>> be more advanced.
> Agree.
>
>> Is there a plan on getting this standardized through
>> eg. a JEDEC spec?
>>
>> Thanks,
>> Miquèl
> Yes. We're working on it. But it will take some time. Your opinions
> mean a lot to CASN page standardisation.
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2024-11-20 10:15 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-20 13:27 [RFC PATCH nand/next 0/4] mtd: nand: spi: Add CASN page support Sky Huang
2024-10-20 13:27 ` Sky Huang
2024-10-20 13:27 ` [RFC PATCH nand/next 1/4] mtd: nand: Create param.c to do CRC check and bitwise majority for Parameter & CASN page Sky Huang
2024-10-20 13:27 ` Sky Huang
2024-10-23 15:03 ` kernel test robot
2024-11-18 10:55 ` Miquel Raynal
2024-11-18 10:55 ` Miquel Raynal
2024-10-20 13:27 ` [RFC PATCH nand/next 2/4] include: mtd: Add CASN page definition and related structs Sky Huang
2024-10-20 13:27 ` Sky Huang
2024-11-18 10:58 ` Miquel Raynal
2024-11-18 10:58 ` Miquel Raynal
2024-10-20 13:27 ` [RFC PATCH nand/next 3/4] include: mtd: spinand: Add CASN page related macros and flags Sky Huang
2024-10-20 13:27 ` Sky Huang
2024-10-23 5:22 ` kernel test robot
2024-10-23 5:23 ` kernel test robot
2024-11-18 13:06 ` Miquel Raynal
2024-11-18 13:06 ` Miquel Raynal
2024-10-20 13:27 ` [RFC PATCH nand/next 4/4] mtd: nand: spi: Add CASN page support Sky Huang
2024-10-20 13:27 ` Sky Huang
2024-10-28 15:25 ` [RFC PATCH nand/next 0/4] " SkyLake Huang (黃啟澤)
2024-10-28 15:25 ` SkyLake Huang (黃啟澤)
2024-11-06 15:20 ` Miquel Raynal
2024-11-06 15:20 ` Miquel Raynal
2024-11-18 10:53 ` Miquel Raynal
2024-11-18 10:53 ` Miquel Raynal
2024-11-20 7:24 ` SkyLake Huang (黃啟澤)
2024-11-20 7:24 ` SkyLake Huang (黃啟澤)
2024-11-20 10:13 ` Miquel Raynal
2024-11-20 10:13 ` Miquel Raynal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.