mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 01:11:14 +00:00
b9d58f7e06
generic: Add/rename patches for upstream consistency ipq40xx: generic-level patch replaces same-source patches-4.19/ 082-v4.20-mtd-spinand-winbond-Add-support-for-W25N01GV.patch The SPI-NAND framework from Linux uses common driver code that is then "tuned" by a tiny struct of chip-specific data that describes available commands, timing, and layout (data and OOB data). Several manufacturers and chips have been added since 4.19, several of which are used in devices already supported by OpenWrt (typically with no or "legacy" access to their NAND memory). This commit catches up the supported-chip definitions through Linux 5.2-rc6 and linux/next. The driver is only compiled for platforms with CONFIG_MTD_SPI_NAND=y. This presently includes ipq40xx and pistachio, with the addition of ath79-nand in these commits (and not ath79-generic or ath79-tiny). Upstream patches refreshed against 4.19.75 Build-tested-on: ipq40xx Run-tested-on: ath79-nand Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
204 lines
5.9 KiB
Diff
204 lines
5.9 KiB
Diff
From 3552691616c940a7c4125c2678ba816653cd725e Mon Sep 17 00:00:00 2001
|
|
From: Jeff Kletsky <git-commits@allycomm.com>
|
|
Date: Tue, 18 Jun 2019 10:08:05 -0700
|
|
Subject: [PATCH] mtd: spinand: Add initial support for Paragon PN26G0xA
|
|
|
|
Add initial support for Paragon Technology
|
|
PN26G01Axxxxx and PN26G02Axxxxx SPI NAND
|
|
|
|
Datasheets available at
|
|
http://www.xtxtech.com/upfile/2016082517274590.pdf
|
|
http://www.xtxtech.com/upfile/2016082517282329.pdf
|
|
|
|
Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
|
|
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
|
|
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
|
|
|
ADOPTED FROM UPSTREAM due to upstream commit 377e517b5fa5 in Linux 5.2
|
|
which added another parameter to NAND_MEMORG
|
|
---
|
|
drivers/mtd/nand/spi/Makefile | 2 +-
|
|
drivers/mtd/nand/spi/core.c | 1 +
|
|
drivers/mtd/nand/spi/paragon.c | 147 +++++++++++++++++++++++++++++++++
|
|
include/linux/mtd/spinand.h | 1 +
|
|
4 files changed, 150 insertions(+), 1 deletion(-)
|
|
create mode 100644 drivers/mtd/nand/spi/paragon.c
|
|
|
|
--- 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 gigadevice.o macronix.o micron.o toshiba.o winbond.o
|
|
+spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
|
|
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
|
--- a/drivers/mtd/nand/spi/core.c
|
|
+++ b/drivers/mtd/nand/spi/core.c
|
|
@@ -765,6 +765,7 @@ static const struct spinand_manufacturer
|
|
&gigadevice_spinand_manufacturer,
|
|
¯onix_spinand_manufacturer,
|
|
µn_spinand_manufacturer,
|
|
+ ¶gon_spinand_manufacturer,
|
|
&toshiba_spinand_manufacturer,
|
|
&winbond_spinand_manufacturer,
|
|
};
|
|
--- /dev/null
|
|
+++ b/drivers/mtd/nand/spi/paragon.c
|
|
@@ -0,0 +1,147 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+/*
|
|
+ * Copyright (C) 2019 Jeff Kletsky
|
|
+ *
|
|
+ * Author: Jeff Kletsky <git-commits@allycomm.com>
|
|
+ */
|
|
+
|
|
+#include <linux/device.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/mtd/spinand.h>
|
|
+
|
|
+
|
|
+#define SPINAND_MFR_PARAGON 0xa1
|
|
+
|
|
+
|
|
+#define PN26G0XA_STATUS_ECC_BITMASK (3 << 4)
|
|
+
|
|
+#define PN26G0XA_STATUS_ECC_NONE_DETECTED (0 << 4)
|
|
+#define PN26G0XA_STATUS_ECC_1_7_CORRECTED (1 << 4)
|
|
+#define PN26G0XA_STATUS_ECC_ERRORED (2 << 4)
|
|
+#define PN26G0XA_STATUS_ECC_8_CORRECTED (3 << 4)
|
|
+
|
|
+
|
|
+static SPINAND_OP_VARIANTS(read_cache_variants,
|
|
+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, 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 pn26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
|
|
+ struct mtd_oob_region *region)
|
|
+{
|
|
+ if (section > 3)
|
|
+ return -ERANGE;
|
|
+
|
|
+ region->offset = 6 + (15 * section); /* 4 BBM + 2 user bytes */
|
|
+ region->length = 13;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int pn26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
|
|
+ struct mtd_oob_region *region)
|
|
+{
|
|
+ if (section > 4)
|
|
+ return -ERANGE;
|
|
+
|
|
+ if (section == 4) {
|
|
+ region->offset = 64;
|
|
+ region->length = 64;
|
|
+ } else {
|
|
+ region->offset = 4 + (15 * section);
|
|
+ region->length = 2;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int pn26g0xa_ecc_get_status(struct spinand_device *spinand,
|
|
+ u8 status)
|
|
+{
|
|
+ switch (status & PN26G0XA_STATUS_ECC_BITMASK) {
|
|
+ case PN26G0XA_STATUS_ECC_NONE_DETECTED:
|
|
+ return 0;
|
|
+
|
|
+ case PN26G0XA_STATUS_ECC_1_7_CORRECTED:
|
|
+ return 7; /* Return upper limit by convention */
|
|
+
|
|
+ case PN26G0XA_STATUS_ECC_8_CORRECTED:
|
|
+ return 8;
|
|
+
|
|
+ case PN26G0XA_STATUS_ECC_ERRORED:
|
|
+ return -EBADMSG;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
|
|
+ .ecc = pn26g0xa_ooblayout_ecc,
|
|
+ .free = pn26g0xa_ooblayout_free,
|
|
+};
|
|
+
|
|
+
|
|
+static const struct spinand_info paragon_spinand_table[] = {
|
|
+ SPINAND_INFO("PN26G01A", 0xe1,
|
|
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
|
|
+ NAND_ECCREQ(8, 512),
|
|
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
|
+ &write_cache_variants,
|
|
+ &update_cache_variants),
|
|
+ 0,
|
|
+ SPINAND_ECCINFO(&pn26g0xa_ooblayout,
|
|
+ pn26g0xa_ecc_get_status)),
|
|
+ SPINAND_INFO("PN26G02A", 0xe2,
|
|
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
|
|
+ NAND_ECCREQ(8, 512),
|
|
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
|
+ &write_cache_variants,
|
|
+ &update_cache_variants),
|
|
+ 0,
|
|
+ SPINAND_ECCINFO(&pn26g0xa_ooblayout,
|
|
+ pn26g0xa_ecc_get_status)),
|
|
+};
|
|
+
|
|
+static int paragon_spinand_detect(struct spinand_device *spinand)
|
|
+{
|
|
+ u8 *id = spinand->id.data;
|
|
+ int ret;
|
|
+
|
|
+ /* Read ID returns [0][MID][DID] */
|
|
+
|
|
+ if (id[1] != SPINAND_MFR_PARAGON)
|
|
+ return 0;
|
|
+
|
|
+ ret = spinand_match_and_init(spinand, paragon_spinand_table,
|
|
+ ARRAY_SIZE(paragon_spinand_table),
|
|
+ id[2]);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
|
|
+ .detect = paragon_spinand_detect,
|
|
+};
|
|
+
|
|
+const struct spinand_manufacturer paragon_spinand_manufacturer = {
|
|
+ .id = SPINAND_MFR_PARAGON,
|
|
+ .name = "Paragon",
|
|
+ .ops = ¶gon_spinand_manuf_ops,
|
|
+};
|
|
--- a/include/linux/mtd/spinand.h
|
|
+++ b/include/linux/mtd/spinand.h
|
|
@@ -227,6 +227,7 @@ struct 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;
|
|
+extern const struct spinand_manufacturer paragon_spinand_manufacturer;
|
|
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
|
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
|
|