From a8374683868634012ac873d628fa581fcc452e9c Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Tue, 16 Jun 2026 16:28:44 +0300 Subject: mtd: spinand: add support for HeYangTek HYF1GQ4UDACAE The HeYangTek HYF1GQ4UDACAE is a 1 Gbit (128 MiB) SLC SPI-NAND with 2048 + 64 byte pages and on-die 4-bit / 512-byte ECC; its JEDEC manufacturer ID is 0xc9. The die is GD5F1GQ4-compatible, so the OOB layout is taken from the in-tree gd5fxgq4xa. The die exposes only a coarse 2-bit ECC status with no fine-grained bitflip-count register, so the status is decoded into a representative number of corrected bitflips. It is found, among others, on some Keenetic KN-3411 (Buddy 6) units. Datasheet: https://www.heyangtek.cn/previewfile.jsp?file=ABUIABA9GAAgwsvRnwYo-eDpsgc Signed-off-by: Aleksei Sviridkin Signed-off-by: Miquel Raynal --- include/linux/mtd/spinand.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index ec6efcfeef83..5f4c00ae72a7 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -437,6 +437,7 @@ extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; extern const struct spinand_manufacturer fmsh_spinand_manufacturer; extern const struct spinand_manufacturer foresee_spinand_manufacturer; extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; +extern const struct spinand_manufacturer heyangtek_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; -- cgit v1.2.3 From 0732595d2f8cf846be3327c8c9453eb10b10ed39 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 7 Jul 2026 13:56:03 +0200 Subject: mtd: rawnand: qcom: Make has_onfi_read_op separate from qpic_version2 QPIC v1.5 requires using the OP_PAGE_READ_ONFI_READ command, but is missing the rest of the hardware changes that are currently covered by the QPIC v2 (qpic_version2) check in the driver. Split that into an extra has_onfi_read_op feature flag so it can be separately enabled. No functional change. Reviewed-by: Manivannan Sadhasivam Signed-off-by: Stephan Gerhold Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/qcom_nandc.c | 15 ++++++++------- include/linux/mtd/nand-qpic-common.h | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 0251dd591d40..9217e8de5512 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -1564,7 +1564,7 @@ static int qcom_op_cmd_mapping(struct nand_chip *chip, u8 opcode, cmd = OP_FETCH_ID; break; case NAND_CMD_PARAM: - if (nandc->props->qpic_version2) + if (nandc->props->has_onfi_read_op) cmd = OP_PAGE_READ_ONFI_READ; else cmd = OP_PAGE_READ; @@ -1903,7 +1903,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_ nandc->regs->ecc_buf_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE); /* configure CMD1 and VLD for ONFI param probing in QPIC v1 */ - if (!nandc->props->qpic_version2) { + if (!nandc->props->has_onfi_read_op) { nandc->regs->vld = cpu_to_le32((nandc->vld & ~READ_START_VLD)); nandc->regs->cmd1 = cpu_to_le32((nandc->cmd1 & ~READ_ADDR_MASK) | FIELD_PREP(READ_ADDR_MASK, NAND_CMD_PARAM)); @@ -1911,7 +1911,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_ nandc->regs->exec = cpu_to_le32(1); - if (!nandc->props->qpic_version2) { + if (!nandc->props->has_onfi_read_op) { nandc->regs->orig_cmd1 = cpu_to_le32(nandc->cmd1); nandc->regs->orig_vld = cpu_to_le32(nandc->vld); } @@ -1925,7 +1925,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_ else nandc_set_read_loc_first(chip, reg_base, 0, len, 1); - if (!nandc->props->qpic_version2) { + if (!nandc->props->has_onfi_read_op) { qcom_write_reg_dma(nandc, &nandc->regs->vld, NAND_DEV_CMD_VLD, 1, 0); qcom_write_reg_dma(nandc, &nandc->regs->cmd1, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL); } @@ -1939,7 +1939,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_ nandc->buf_count, 0); /* restore CMD1 and VLD regs */ - if (!nandc->props->qpic_version2) { + if (!nandc->props->has_onfi_read_op) { qcom_write_reg_dma(nandc, &nandc->regs->orig_cmd1, NAND_DEV_CMD1_RESTORE, 1, 0); qcom_write_reg_dma(nandc, &nandc->regs->orig_vld, NAND_DEV_CMD_VLD_RESTORE, 1, NAND_BAM_NEXT_SGL); @@ -2041,7 +2041,7 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) if (!nandc->props->nandc_part_of_qpic) nandc_write(nandc, SFLASHC_BURST_CFG, 0); - if (!nandc->props->qpic_version2) + if (!nandc->props->has_onfi_read_op) nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD), NAND_DEV_CMD_VLD_VAL); @@ -2063,7 +2063,7 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) } /* save the original values of these registers */ - if (!nandc->props->qpic_version2) { + if (!nandc->props->has_onfi_read_op) { nandc->cmd1 = nandc_read(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD1)); nandc->vld = NAND_DEV_CMD_VLD_VAL; } @@ -2385,6 +2385,7 @@ static const struct qcom_nandc_props sdx55_nandc_props = { .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), .supports_bam = true, .nandc_part_of_qpic = true, + .has_onfi_read_op = true, .qpic_version2 = true, .dev_cmd_reg_start = 0x7000, .bam_offset = 0x30000, diff --git a/include/linux/mtd/nand-qpic-common.h b/include/linux/mtd/nand-qpic-common.h index 006ca8c978a9..437448995187 100644 --- a/include/linux/mtd/nand-qpic-common.h +++ b/include/linux/mtd/nand-qpic-common.h @@ -443,6 +443,7 @@ struct qcom_nand_controller { * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset * @supports_bam - whether NAND controller is using BAM * @nandc_part_of_qpic - whether NAND controller is part of qpic IP + * @has_onfi_read_op - whether ONFI param page read command is supported * @qpic_version2 - flag to indicate QPIC IP version 2 * @use_codeword_fixup - whether NAND has different layout for boot partitions */ @@ -452,6 +453,7 @@ struct qcom_nandc_props { u32 bam_offset; bool supports_bam; bool nandc_part_of_qpic; + bool has_onfi_read_op; bool qpic_version2; bool use_codeword_fixup; }; -- cgit v1.2.3 From f97bdc8ec1dc7b33781a702eeba55326c206be56 Mon Sep 17 00:00:00 2001 From: "Uwe Kleine-König (The Capable Hub)" Date: Thu, 16 Jul 2026 21:25:23 +0200 Subject: mtd: nand-omap2: Move omap_nand_ids[] to raw nand driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Defining a static array in a header results in each .c file that includes the header (here: drivers/memory/omap-gpmc.c and drivers/mtd/nand/raw/omap2.c) to contain a copy of that array when compiled to an object file. With sizeof(struct of_device_id[3]) ≥ 588 having omap_nand_ids[] twice just to do two string comparisons is quite some bloat. So move omap_nand_ids[] to the nand driver which actually needs that array for its module meta data and do the compatible check by hand. bloat-o-meter reports for drivers/memory/omap-gpmc.o (ARCH=arm): add/remove: 1/2 grow/shrink: 1/0 up/down: 28/-588 (-560) Function old new delta gpmc_probe_generic_child 2108 2136 +28 omap_nand_ids 588 - -588 Total: Before=18114, After=17554, chg -3.09% (drivers/mtd/nand/raw/omap2.o doesn't change). This allows to drop from include/linux/platform_data/mtd-nand-omap2.h (which is my original motivation for this change). Note that this header isn't needed in the two drivers because omap-gpmc.c doesn't use any device id struct and for the nand driver omap2.c of_device_id is already provided via . Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Miquel Raynal --- drivers/memory/omap-gpmc.c | 9 ++++++++- drivers/mtd/nand/raw/omap2.c | 6 +++++- include/linux/platform_data/mtd-nand-omap2.h | 7 ------- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 958d2b0ea54a..48af31a54b55 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2129,6 +2129,13 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, of_property_read_bool(np, "gpmc,time-para-granularity"); } +static int gpmc_child_is_nand(struct device_node *child) +{ + /* This has to match drivers/mtd/nand/raw/omap2.c's omap_nand_ids[] */ + return of_device_is_compatible(child, "ti,omap2-nand") || + of_device_is_compatible(child, "ti,am64-nand"); +} + /** * gpmc_probe_generic_child - configures the gpmc for a child device * @pdev: pointer to gpmc platform device @@ -2220,7 +2227,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, goto err; } - if (of_match_node(omap_nand_ids, child)) { + if (gpmc_child_is_nand(child)) { /* NAND specific setup */ val = 8; of_property_read_u32(child, "nand-bus-width", &val); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 39e297486721..552f36da79fc 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2318,7 +2318,11 @@ static void omap_nand_remove(struct platform_device *pdev) nand_cleanup(nand_chip); } -/* omap_nand_ids defined in linux/platform_data/mtd-nand-omap2.h */ +static const struct of_device_id omap_nand_ids[] = { + { .compatible = "ti,omap2-nand" }, + { .compatible = "ti,am64-nand" }, + { } +}; MODULE_DEVICE_TABLE(of, omap_nand_ids); static struct platform_driver omap_nand_driver = { diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 8c2f1f185353..2ddb624b97fd 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -7,7 +7,6 @@ #define _MTD_NAND_OMAP2_H #include -#include #define GPMC_BCH_NUM_REMAINDER 8 @@ -63,10 +62,4 @@ struct gpmc_nand_regs { void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER]; }; -static const struct of_device_id omap_nand_ids[] = { - { .compatible = "ti,omap2-nand", }, - { .compatible = "ti,am64-nand", }, - {}, -}; - #endif /* _MTD_NAND_OMAP2_H */ -- cgit v1.2.3