[RFC PATCH] mtd: nand: raw: Add ONFI NAND unique id read support.
Michael Nazzareno Trimarchi
michael at amarulasolutions.com
Fri Nov 7 11:45:28 CET 2025
Hi all
On Fri, Nov 7, 2025 at 11:41 AM Eugen Hristev <eugen.hristev at linaro.org> wrote:
>
>
>
> On 11/6/25 19:01, Zixun LI wrote:
> > This patch adds support for reading the unique ID from ONFI-compliant NAND
> > flash devices.
> >
> > The unique ID is a 32 bytes long identifier that is useful for device
> > identification and tracking.
> >
> > Tested on SAM9G25-EK with Macronix MX60LF8G18AC flash.
> >
> > Signed-off-by: Zixun LI <admin at hifiphile.com>
> > ---
> > drivers/mtd/nand/raw/nand_base.c | 69 ++++++++++++++++++++++++++++++++
> > include/linux/mtd/rawnand.h | 8 ++++
> > 2 files changed, 77 insertions(+)
> >
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 48e3685d995..30aa578e074 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -991,6 +991,75 @@ static int nand_onfi_set_timings(struct mtd_info *mtd, struct nand_chip *chip)
> > tmode_param);
> > }
> >
> > +/**
> > + * nand_onfi_read_unique_id - read the ONFI unique ID sequence
> > + * @chip: NAND chip descriptor
> > + * @buf: destination buffer
> > + * @len: size of the destination buffer
> > + *
> > + * Issues the ONFI UNIQUE_ID command sequence, validates the unique ID and
> > + * copies it into @buf.
> > + *
> > + * Return: 0 on success or negative error code otherwise.
> > + */
> > +int nand_onfi_read_unique_id(struct nand_chip *chip, void *buf,
> > + unsigned int len)
> > +{
> > + struct mtd_info *mtd;
> > + unsigned int copy;
> > + unsigned int byte;
> > + unsigned int copy_len;
> > + u8 raw_id[ONFI_UNIQUE_ID_LEN * 2];
> > + u8 *out = buf;
> > + int ret = -EIO;
> > +
> > + if (!chip)
> > + return -EINVAL;
> > +
> > + if (len && !buf)
> > + return -EINVAL;
> > +
> > + if (len > ONFI_UNIQUE_ID_LEN)
> > + return -EINVAL;
> > +
> > + if (!chip->onfi_version)
> > + return -EOPNOTSUPP;
> > +
> > + mtd = nand_to_mtd(chip);
> > + nand_get_device(mtd, FL_READING);
> > + chip->select_chip(mtd, 0);
> > +
> > + chip->cmdfunc(mtd, NAND_CMD_UNIQUE_ID, 0, -1);
> > +
> > + for (copy = 0; copy < ONFI_UNIQUE_ID_COPIES; copy++) {
> > + for (byte = 0; byte < ONFI_UNIQUE_ID_LEN * 2; byte++)
> > + raw_id[byte] = chip->read_byte(mtd);
> > +
> > + for (byte = 0; byte < ONFI_UNIQUE_ID_LEN; byte++) {
> > + u8 lo = raw_id[byte];
> > + u8 hi = raw_id[byte + ONFI_UNIQUE_ID_LEN];
> > +
> > + if ((lo ^ hi) != 0xff)
> > + break;
> > + }
> > +
> > + if (byte == ONFI_UNIQUE_ID_LEN) {
> > + copy_len = min_t(unsigned int, len, ONFI_UNIQUE_ID_LEN);
> > +
> > + if (len)
> > + memcpy(out, raw_id, copy_len);
> > +
> > + ret = 0;
> > + goto out;
> > + }
> > + }
> > +
> > +out:
> > + nand_release_device(mtd);
> > + return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(nand_onfi_read_unique_id);
> > +
> > /**
> > * nand_setup_data_interface - Setup the best data interface and timings
> > * @chip: The NAND chip
> > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > index 3e80b134063..87083c34aed 100644
> > --- a/include/linux/mtd/rawnand.h
> > +++ b/include/linux/mtd/rawnand.h
> > @@ -88,6 +88,7 @@ void nand_wait_ready(struct mtd_info *mtd);
> > #define NAND_CMD_READID 0x90
> > #define NAND_CMD_ERASE2 0xd0
> > #define NAND_CMD_PARAM 0xec
> > +#define NAND_CMD_UNIQUE_ID 0xed
> > #define NAND_CMD_GET_FEATURES 0xee
> > #define NAND_CMD_SET_FEATURES 0xef
> > #define NAND_CMD_RESET 0xff
> > @@ -409,6 +410,10 @@ struct onfi_ext_param_page {
> > */
> > } __packed;
> >
> > +/* ONFI unique ID */
> > +#define ONFI_UNIQUE_ID_LEN 16
> > +#define ONFI_UNIQUE_ID_COPIES 16
> > +
> > struct jedec_ecc_info {
> > u8 ecc_bits;
> > u8 codeword_size;
> > @@ -1385,4 +1390,7 @@ int nand_write_data_op(struct nand_chip *chip, const void *buf,
> > /* Default extended ID decoding function */
> > void nand_decode_ext_id(struct nand_chip *chip);
> >
> > +int nand_onfi_read_unique_id(struct nand_chip *chip, void *buf,
> > + unsigned int len);
> > +
>
> Something appears to be missing. Where is this function called ?
>
I prefer to apply if we have a use case and a consumer of this patch.
Michael
> Eugen> #endif /* __LINUX_MTD_RAWNAND_H */
>
--
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael at amarulasolutions.com
__________________________________
Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info at amarulasolutions.com
www.amarulasolutions.com
More information about the U-Boot
mailing list