fa4dc86e98
MEMREAD is a new ioctl for MTD character devices that was first included in Linux 6.1. It allows userspace applications to use the Linux kernel's OOB autoplacement mechanism while reading data from NAND devices. The Yafut tool needs this ioctl to do its job. Signed-off-by: Michał Kępień <openwrt@kempniu.pl>
169 lines
5.1 KiB
Diff
169 lines
5.1 KiB
Diff
From f32085fc0b87049491b07e198d924d738a1a2834 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Danzberger <daniel@dd-wrt.com>
|
|
Date: Wed, 3 Aug 2022 17:31:03 +0200
|
|
Subject: [PATCH] mtd: spinand: Add support for Etron EM73D044VCx
|
|
|
|
Airoha is a new ARM platform based on Cortex-A53 which has recently been
|
|
merged into linux-next.
|
|
|
|
Due to BootROM limitations on this platform, the Cortex-A53 can't run in
|
|
Aarch64 mode and code must be compiled for 32-Bit ARM.
|
|
|
|
This support is based mostly on those linux-next commits backported
|
|
for kernel 5.15.
|
|
|
|
Patches:
|
|
1 - platform support = linux-next
|
|
2 - clock driver = linux-next
|
|
3 - gpio driver = linux-next
|
|
4 - linux,usable-memory-range dts support = linux-next
|
|
5 - mtd spinand driver
|
|
6 - spi driver
|
|
7 - pci driver (kconfig only, uses mediatek PCI) = linux-next
|
|
|
|
Still missing:
|
|
- Ethernet driver
|
|
- Sysupgrade support
|
|
|
|
A.t.m there exists one subtarget EN7523 with only one evaluation
|
|
board.
|
|
|
|
The initramfs can be run with the following commands from u-boot:
|
|
-
|
|
u-boot> setenv bootfile \
|
|
openwrt-airoha-airoha_en7523-evb-initramfs-kernel.bin
|
|
u-boot> tftpboot
|
|
u-boot> bootm 0x81800000
|
|
-
|
|
|
|
Submitted-by: Daniel Danzberger <daniel@dd-wrt.com>
|
|
|
|
--- a/drivers/mtd/nand/spi/Makefile
|
|
+++ b/drivers/mtd/nand/spi/Makefile
|
|
@@ -1,3 +1,3 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
-spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
|
|
+spinand-objs := core.o esmt.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o
|
|
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
|
--- a/drivers/mtd/nand/spi/core.c
|
|
+++ b/drivers/mtd/nand/spi/core.c
|
|
@@ -908,6 +908,7 @@ static const struct nand_ops spinand_ops
|
|
static const struct spinand_manufacturer *spinand_manufacturers[] = {
|
|
&esmt_c8_spinand_manufacturer,
|
|
&gigadevice_spinand_manufacturer,
|
|
+ &etron_spinand_manufacturer,
|
|
¯onix_spinand_manufacturer,
|
|
µn_spinand_manufacturer,
|
|
¶gon_spinand_manufacturer,
|
|
--- /dev/null
|
|
+++ b/drivers/mtd/nand/spi/etron.c
|
|
@@ -0,0 +1,98 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+
|
|
+#include <linux/device.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/mtd/spinand.h>
|
|
+
|
|
+#define SPINAND_MFR_ETRON 0xd5
|
|
+
|
|
+
|
|
+static SPINAND_OP_VARIANTS(read_cache_variants,
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
|
|
+
|
|
+static SPINAND_OP_VARIANTS(write_cache_variants,
|
|
+ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
|
|
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
|
|
+
|
|
+static SPINAND_OP_VARIANTS(update_cache_variants,
|
|
+ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
|
|
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
|
|
+
|
|
+static int etron_ooblayout_ecc(struct mtd_info *mtd, int section,
|
|
+ struct mtd_oob_region *oobregion)
|
|
+{
|
|
+ if (section)
|
|
+ return -ERANGE;
|
|
+
|
|
+ oobregion->offset = 72;
|
|
+ oobregion->length = 56;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int etron_ooblayout_free(struct mtd_info *mtd, int section,
|
|
+ struct mtd_oob_region *oobregion)
|
|
+{
|
|
+ if (section)
|
|
+ return -ERANGE;
|
|
+
|
|
+ oobregion->offset = 1;
|
|
+ oobregion->length = 71;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int etron_ecc_get_status(struct spinand_device *spinand, u8 status)
|
|
+{
|
|
+ switch (status & STATUS_ECC_MASK) {
|
|
+ case STATUS_ECC_NO_BITFLIPS:
|
|
+ return 0;
|
|
+
|
|
+ case STATUS_ECC_HAS_BITFLIPS:
|
|
+ /* Between 1-7 bitflips were corrected */
|
|
+ return 7;
|
|
+
|
|
+ case STATUS_ECC_MASK:
|
|
+ /* Maximum bitflips were corrected */
|
|
+ return 8;
|
|
+
|
|
+ case STATUS_ECC_UNCOR_ERROR:
|
|
+ return -EBADMSG;
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+static const struct mtd_ooblayout_ops etron_ooblayout = {
|
|
+ .ecc = etron_ooblayout_ecc,
|
|
+ .free = etron_ooblayout_free,
|
|
+};
|
|
+
|
|
+static const struct spinand_info etron_spinand_table[] = {
|
|
+ SPINAND_INFO("EM73D044VCx",
|
|
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x1f),
|
|
+ // bpc, pagesize, oobsize, pagesperblock, bperlun, maxbadplun, ppl, lpt, #t
|
|
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
|
+ NAND_ECCREQ(8, 512),
|
|
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
|
+ &write_cache_variants,
|
|
+ &update_cache_variants),
|
|
+ SPINAND_HAS_QE_BIT,
|
|
+ SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)),
|
|
+};
|
|
+
|
|
+static const struct spinand_manufacturer_ops etron_spinand_manuf_ops = {
|
|
+};
|
|
+
|
|
+const struct spinand_manufacturer etron_spinand_manufacturer = {
|
|
+ .id = SPINAND_MFR_ETRON,
|
|
+ .name = "Etron",
|
|
+ .chips = etron_spinand_table,
|
|
+ .nchips = ARRAY_SIZE(etron_spinand_table),
|
|
+ .ops = &etron_spinand_manuf_ops,
|
|
+};
|
|
--- a/include/linux/mtd/spinand.h
|
|
+++ b/include/linux/mtd/spinand.h
|
|
@@ -261,6 +261,7 @@ struct spinand_manufacturer {
|
|
|
|
/* SPI NAND manufacturers */
|
|
extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;
|
|
+extern const struct spinand_manufacturer etron_spinand_manufacturer;
|
|
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
|
|
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
|
|
extern const struct spinand_manufacturer micron_spinand_manufacturer;
|