[PATCH] drivers: mtd: nand: Use Cadence-specific onfi_set_feature
dinesh.maniyam at altera.com
dinesh.maniyam at altera.com
Tue Jun 17 06:58:42 CEST 2025
From: Dinesh Maniyam <dinesh.maniyam at altera.com>
Implement Cadence-specific onfi_set_features and onfi_get_features ops
to support ONFI optional commands via standard NAND hooks. The Cadence
controller performs 32-bit writes per transaction, different from the
legacy single byte transaction for SET_FEATURES command.
Hence, using legacy byte-wise writes introduces redundant overhead
after a SET_FEATURES command. This specific implementation will use
the single-buffered write for SET_FEATURES cmd.
As ONFI_SUBFEATURE_PARAM_LEN also 4bytes, a single transaction
is enough to write the full timing parameter in SET_FEATURE cmd.
Matches Linux Cadence NAND implementation to ensure reliable and efficient
feature setting.
Signed-off-by: Dinesh Maniyam <dinesh.maniyam at altera.com>
---
drivers/mtd/nand/raw/cadence_nand.c | 55 +++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/drivers/mtd/nand/raw/cadence_nand.c b/drivers/mtd/nand/raw/cadence_nand.c
index 27aa7f97a45..7093343b7e3 100644
--- a/drivers/mtd/nand/raw/cadence_nand.c
+++ b/drivers/mtd/nand/raw/cadence_nand.c
@@ -2140,6 +2140,59 @@ static void cadence_nand_write_byte(struct mtd_info *mtd, u8 byte)
cadence_nand_write_buf(mtd, &byte, 1);
}
+static int cadence_set_features_op(struct nand_chip *chip, u8 feature,
+ const void *data)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ const u8 *params = data;
+ int status;
+
+ cadence_nand_cmdfunc(mtd, NAND_CMD_SET_FEATURES, feature, -1);
+ cadence_nand_write_buf(mtd, params, ONFI_SUBFEATURE_PARAM_LEN);
+
+ status = cadence_nand_waitfunc(mtd, chip);
+ if (status & NAND_STATUS_FAIL)
+ return -EIO;
+
+ return 0;
+}
+
+static int cadence_get_features_op(struct nand_chip *chip, u8 feature,
+ void *data)
+{
+ struct mtd_info *mtd = nand_to_mtd(chip);
+ u8 *params = data;
+
+ cadence_nand_cmdfunc(mtd, NAND_CMD_GET_FEATURES, feature, -1);
+ cadence_nand_read_buf(mtd, params, ONFI_SUBFEATURE_PARAM_LEN);
+
+ return 0;
+}
+
+static int cadence_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
+ int addr, uint8_t *subfeature_param)
+{
+ if (IS_ENABLED(CONFIG_SYS_NAND_ONFI_DETECTION))
+ if (!chip->onfi_version ||
+ !(le16_to_cpu(chip->onfi_params.opt_cmd)
+ & ONFI_OPT_CMD_SET_GET_FEATURES))
+ return -EOPNOTSUPP;
+
+ return cadence_set_features_op(chip, addr, subfeature_param);
+}
+
+static int cadence_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
+ int addr, uint8_t *subfeature_param)
+{
+ if (IS_ENABLED(CONFIG_SYS_NAND_ONFI_DETECTION))
+ if (!chip->onfi_version ||
+ !(le16_to_cpu(chip->onfi_params.opt_cmd)
+ & ONFI_OPT_CMD_SET_GET_FEATURES))
+ return -EOPNOTSUPP;
+
+ return cadence_get_features_op(chip, addr, subfeature_param);
+}
+
static int cadence_nand_chip_init(struct cadence_nand_info *cadence, ofnode node)
{
struct cdns_nand_chip *cdns_chip;
@@ -2208,6 +2261,8 @@ static int cadence_nand_chip_init(struct cadence_nand_info *cadence, ofnode node
chip->read_buf = cadence_nand_read_buf;
chip->write_buf = cadence_nand_write_buf;
chip->setup_data_interface = cadence_setup_data_interface;
+ chip->onfi_set_features = cadence_onfi_set_features;
+ chip->onfi_get_features = cadence_onfi_get_features;
ret = nand_scan_ident(mtd, 1, NULL);
if (ret) {
--
2.35.3
More information about the U-Boot
mailing list